1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * winclip.c 12 * 13 * Routines for Win32 clipboard handling. 14 * Also used by Cygwin, using os_unix.c. 15 */ 16 17 #include "vimio.h" 18 #include "vim.h" 19 20 /* 21 * Compile only the clipboard handling features when compiling for cygwin 22 * posix environment. 23 */ 24 #ifdef FEAT_CYGWIN_WIN32_CLIPBOARD 25 # define WIN3264 26 # define WIN32_LEAN_AND_MEAN 27 # include <windows.h> 28 # include "winclip.pro" 29 #endif 30 31 /* 32 * When generating prototypes for Win32 on Unix, these lines make the syntax 33 * errors disappear. They do not need to be correct. 34 */ 35 #ifdef PROTO 36 #define WINAPI 37 #define WINBASEAPI 38 typedef int DWORD; 39 typedef int LPBOOL; 40 typedef int LPCSTR; 41 typedef int LPCWSTR; 42 typedef int LPSTR; 43 typedef int LPWSTR; 44 typedef int UINT; 45 #endif 46 47 #if defined(FEAT_MBYTE) || defined(PROTO) 48 /* 49 * Convert an UTF-8 string to UTF-16. 50 * "instr[inlen]" is the input. "inlen" is in bytes. 51 * When "outstr" is NULL only return the number of UTF-16 words produced. 52 * Otherwise "outstr" must be a buffer of sufficient size. 53 * Returns the number of UTF-16 words produced. 54 */ 55 int 56 utf8_to_utf16(char_u *instr, int inlen, short_u *outstr, int *unconvlenp) 57 { 58 int outlen = 0; 59 char_u *p = instr; 60 int todo = inlen; 61 int l; 62 int ch; 63 64 while (todo > 0) 65 { 66 /* Only convert if we have a complete sequence. */ 67 l = utf_ptr2len_len(p, todo); 68 if (l > todo) 69 { 70 /* Return length of incomplete sequence. */ 71 if (unconvlenp != NULL) 72 *unconvlenp = todo; 73 break; 74 } 75 76 ch = utf_ptr2char(p); 77 if (ch >= 0x10000) 78 { 79 /* non-BMP character, encoding with surrogate pairs */ 80 ++outlen; 81 if (outstr != NULL) 82 { 83 *outstr++ = (0xD800 - (0x10000 >> 10)) + (ch >> 10); 84 *outstr++ = 0xDC00 | (ch & 0x3FF); 85 } 86 } 87 else if (outstr != NULL) 88 *outstr++ = ch; 89 ++outlen; 90 p += l; 91 todo -= l; 92 } 93 94 return outlen; 95 } 96 97 /* 98 * Convert an UTF-16 string to UTF-8. 99 * The input is "instr[inlen]" with "inlen" in number of UTF-16 words. 100 * When "outstr" is NULL only return the required number of bytes. 101 * Otherwise "outstr" must be a buffer of sufficient size. 102 * Return the number of bytes produced. 103 */ 104 int 105 utf16_to_utf8(short_u *instr, int inlen, char_u *outstr) 106 { 107 int outlen = 0; 108 int todo = inlen; 109 short_u *p = instr; 110 int l; 111 int ch, ch2; 112 113 while (todo > 0) 114 { 115 ch = *p; 116 if (ch >= 0xD800 && ch <= 0xDBFF && todo > 1) 117 { 118 /* surrogate pairs handling */ 119 ch2 = p[1]; 120 if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) 121 { 122 ch = ((ch - 0xD800) << 10) + (ch2 & 0x3FF) + 0x10000; 123 ++p; 124 --todo; 125 } 126 } 127 if (outstr != NULL) 128 { 129 l = utf_char2bytes(ch, outstr); 130 outstr += l; 131 } 132 else 133 l = utf_char2len(ch); 134 ++p; 135 outlen += l; 136 --todo; 137 } 138 139 return outlen; 140 } 141 142 /* 143 * Call MultiByteToWideChar() and allocate memory for the result. 144 * Returns the result in "*out[*outlen]" with an extra zero appended. 145 * "outlen" is in words. 146 */ 147 void 148 MultiByteToWideChar_alloc(UINT cp, DWORD flags, 149 LPCSTR in, int inlen, 150 LPWSTR *out, int *outlen) 151 { 152 *outlen = MultiByteToWideChar(cp, flags, in, inlen, 0, 0); 153 /* Add one one word to avoid a zero-length alloc(). */ 154 *out = (LPWSTR)alloc(sizeof(WCHAR) * (*outlen + 1)); 155 if (*out != NULL) 156 { 157 MultiByteToWideChar(cp, flags, in, inlen, *out, *outlen); 158 (*out)[*outlen] = 0; 159 } 160 } 161 162 /* 163 * Call WideCharToMultiByte() and allocate memory for the result. 164 * Returns the result in "*out[*outlen]" with an extra NUL appended. 165 */ 166 void 167 WideCharToMultiByte_alloc(UINT cp, DWORD flags, 168 LPCWSTR in, int inlen, 169 LPSTR *out, int *outlen, 170 LPCSTR def, LPBOOL useddef) 171 { 172 *outlen = WideCharToMultiByte(cp, flags, in, inlen, NULL, 0, def, useddef); 173 /* Add one one byte to avoid a zero-length alloc(). */ 174 *out = (LPSTR)alloc((unsigned)*outlen + 1); 175 if (*out != NULL) 176 { 177 WideCharToMultiByte(cp, flags, in, inlen, *out, *outlen, def, useddef); 178 (*out)[*outlen] = 0; 179 } 180 } 181 182 #endif /* FEAT_MBYTE */ 183 184 #ifdef FEAT_CLIPBOARD 185 /* 186 * Clipboard stuff, for cutting and pasting text to other windows. 187 */ 188 189 void 190 win_clip_init(void) 191 { 192 clip_init(TRUE); 193 194 /* 195 * Vim's own clipboard format recognises whether the text is char, line, 196 * or rectangular block. Only useful for copying between two Vims. 197 * "VimClipboard" was used for previous versions, using the first 198 * character to specify MCHAR, MLINE or MBLOCK. 199 */ 200 clip_star.format = RegisterClipboardFormat("VimClipboard2"); 201 clip_star.format_raw = RegisterClipboardFormat("VimRawBytes"); 202 } 203 204 /* Type used for the clipboard type of Vim's data. */ 205 typedef struct 206 { 207 int type; /* MCHAR, MBLOCK or MLINE */ 208 int txtlen; /* length of CF_TEXT in bytes */ 209 int ucslen; /* length of CF_UNICODETEXT in words */ 210 int rawlen; /* length of clip_star.format_raw, including encoding, 211 excluding terminating NUL */ 212 } VimClipType_t; 213 214 /* 215 * Make vim the owner of the current selection. Return OK upon success. 216 */ 217 int 218 clip_mch_own_selection(VimClipboard *cbd UNUSED) 219 { 220 /* 221 * Never actually own the clipboard. If another application sets the 222 * clipboard, we don't want to think that we still own it. 223 */ 224 return FAIL; 225 } 226 227 /* 228 * Make vim NOT the owner of the current selection. 229 */ 230 void 231 clip_mch_lose_selection(VimClipboard *cbd UNUSED) 232 { 233 /* Nothing needs to be done here */ 234 } 235 236 /* 237 * Copy "str[*size]" into allocated memory, changing CR-NL to NL. 238 * Return the allocated result and the size in "*size". 239 * Returns NULL when out of memory. 240 */ 241 static char_u * 242 crnl_to_nl(const char_u *str, int *size) 243 { 244 int pos = 0; 245 int str_len = *size; 246 char_u *ret; 247 char_u *retp; 248 249 /* Avoid allocating zero bytes, it generates an error message. */ 250 ret = lalloc((long_u)(str_len == 0 ? 1 : str_len), TRUE); 251 if (ret != NULL) 252 { 253 retp = ret; 254 for (pos = 0; pos < str_len; ++pos) 255 { 256 if (str[pos] == '\r' && str[pos + 1] == '\n') 257 { 258 ++pos; 259 --(*size); 260 } 261 *retp++ = str[pos]; 262 } 263 } 264 265 return ret; 266 } 267 268 /* 269 * Wait for another process to Close the Clipboard. 270 * Returns TRUE for success. 271 */ 272 static int 273 vim_open_clipboard(void) 274 { 275 int delay = 10; 276 277 while (!OpenClipboard(NULL)) 278 { 279 if (delay > 500) 280 return FALSE; /* waited too long, give up */ 281 Sleep(delay); 282 delay *= 2; /* wait for 10, 20, 40, 80, etc. msec */ 283 } 284 return TRUE; 285 } 286 287 /* 288 * Get the current selection and put it in the clipboard register. 289 * 290 * NOTE: Must use GlobalLock/Unlock here to ensure Win32s compatibility. 291 * On NT/W95 the clipboard data is a fixed global memory object and 292 * so its handle = its pointer. 293 * On Win32s, however, co-operation with the Win16 system means that 294 * the clipboard data is moveable and its handle is not a pointer at all, 295 * so we can't just cast the return value of GetClipboardData to (char_u*). 296 * <VN> 297 */ 298 void 299 clip_mch_request_selection(VimClipboard *cbd) 300 { 301 VimClipType_t metadata = { -1, -1, -1, -1 }; 302 HGLOBAL hMem = NULL; 303 char_u *str = NULL; 304 #if defined(FEAT_MBYTE) && defined(WIN3264) 305 char_u *to_free = NULL; 306 #endif 307 #ifdef FEAT_MBYTE 308 HGLOBAL rawh = NULL; 309 #endif 310 int str_size = 0; 311 int maxlen; 312 size_t n; 313 314 /* 315 * Don't pass GetActiveWindow() as an argument to OpenClipboard() because 316 * then we can't paste back into the same window for some reason - webb. 317 */ 318 if (!vim_open_clipboard()) 319 return; 320 321 /* Check for vim's own clipboard format first. This only gets the type of 322 * the data, still need to use CF_UNICODETEXT or CF_TEXT for the text. */ 323 if (IsClipboardFormatAvailable(cbd->format)) 324 { 325 VimClipType_t *meta_p; 326 HGLOBAL meta_h; 327 328 /* We have metadata on the clipboard; try to get it. */ 329 if ((meta_h = GetClipboardData(cbd->format)) != NULL 330 && (meta_p = (VimClipType_t *)GlobalLock(meta_h)) != NULL) 331 { 332 /* The size of "VimClipType_t" changed, "rawlen" was added later. 333 * Only copy what is available for backwards compatibility. */ 334 n = sizeof(VimClipType_t); 335 if (GlobalSize(meta_h) < n) 336 n = GlobalSize(meta_h); 337 memcpy(&metadata, meta_p, n); 338 GlobalUnlock(meta_h); 339 } 340 } 341 342 #ifdef FEAT_MBYTE 343 /* Check for Vim's raw clipboard format first. This is used without 344 * conversion, but only if 'encoding' matches. */ 345 if (IsClipboardFormatAvailable(cbd->format_raw) 346 && metadata.rawlen > (int)STRLEN(p_enc)) 347 { 348 /* We have raw data on the clipboard; try to get it. */ 349 if ((rawh = GetClipboardData(cbd->format_raw)) != NULL) 350 { 351 char_u *rawp; 352 353 rawp = (char_u *)GlobalLock(rawh); 354 if (rawp != NULL && STRCMP(p_enc, rawp) == 0) 355 { 356 n = STRLEN(p_enc) + 1; 357 str = rawp + n; 358 str_size = (int)(metadata.rawlen - n); 359 } 360 else 361 { 362 GlobalUnlock(rawh); 363 rawh = NULL; 364 } 365 } 366 } 367 if (str == NULL) 368 { 369 #endif 370 371 #if defined(FEAT_MBYTE) && defined(WIN3264) 372 /* Try to get the clipboard in Unicode if it's not an empty string. */ 373 if (IsClipboardFormatAvailable(CF_UNICODETEXT) && metadata.ucslen != 0) 374 { 375 HGLOBAL hMemW; 376 377 if ((hMemW = GetClipboardData(CF_UNICODETEXT)) != NULL) 378 { 379 WCHAR *hMemWstr = (WCHAR *)GlobalLock(hMemW); 380 381 /* Use the length of our metadata if possible, but limit it to the 382 * GlobalSize() for safety. */ 383 maxlen = (int)(GlobalSize(hMemW) / sizeof(WCHAR)); 384 if (metadata.ucslen >= 0) 385 { 386 if (metadata.ucslen > maxlen) 387 str_size = maxlen; 388 else 389 str_size = metadata.ucslen; 390 } 391 else 392 { 393 for (str_size = 0; str_size < maxlen; ++str_size) 394 if (hMemWstr[str_size] == NUL) 395 break; 396 } 397 to_free = str = utf16_to_enc((short_u *)hMemWstr, &str_size); 398 GlobalUnlock(hMemW); 399 } 400 } 401 else 402 #endif 403 /* Get the clipboard in the Active codepage. */ 404 if (IsClipboardFormatAvailable(CF_TEXT)) 405 { 406 if ((hMem = GetClipboardData(CF_TEXT)) != NULL) 407 { 408 str = (char_u *)GlobalLock(hMem); 409 410 /* The length is either what our metadata says or the strlen(). 411 * But limit it to the GlobalSize() for safety. */ 412 maxlen = (int)GlobalSize(hMem); 413 if (metadata.txtlen >= 0) 414 { 415 if (metadata.txtlen > maxlen) 416 str_size = maxlen; 417 else 418 str_size = metadata.txtlen; 419 } 420 else 421 { 422 for (str_size = 0; str_size < maxlen; ++str_size) 423 if (str[str_size] == NUL) 424 break; 425 } 426 427 # if defined(FEAT_MBYTE) && defined(WIN3264) 428 /* The text is in the active codepage. Convert to 'encoding', 429 * going through UTF-16. */ 430 acp_to_enc(str, str_size, &to_free, &maxlen); 431 if (to_free != NULL) 432 { 433 str_size = maxlen; 434 str = to_free; 435 } 436 # endif 437 } 438 } 439 #ifdef FEAT_MBYTE 440 } 441 #endif 442 443 if (str != NULL && *str != NUL) 444 { 445 char_u *temp_clipboard; 446 447 /* If the type is not known detect it. */ 448 if (metadata.type == -1) 449 metadata.type = MAUTO; 450 451 /* Translate <CR><NL> into <NL>. */ 452 temp_clipboard = crnl_to_nl(str, &str_size); 453 if (temp_clipboard != NULL) 454 { 455 clip_yank_selection(metadata.type, temp_clipboard, str_size, cbd); 456 vim_free(temp_clipboard); 457 } 458 } 459 460 /* unlock the global object */ 461 if (hMem != NULL) 462 GlobalUnlock(hMem); 463 #ifdef FEAT_MBYTE 464 if (rawh != NULL) 465 GlobalUnlock(rawh); 466 #endif 467 CloseClipboard(); 468 #if defined(FEAT_MBYTE) && defined(WIN3264) 469 vim_free(to_free); 470 #endif 471 } 472 473 /* 474 * Send the current selection to the clipboard. 475 */ 476 void 477 clip_mch_set_selection(VimClipboard *cbd) 478 { 479 char_u *str = NULL; 480 VimClipType_t metadata; 481 long_u txtlen; 482 HGLOBAL hMemRaw = NULL; 483 HGLOBAL hMem = NULL; 484 HGLOBAL hMemVim = NULL; 485 # if defined(FEAT_MBYTE) && defined(WIN3264) 486 HGLOBAL hMemW = NULL; 487 # endif 488 489 /* If the '*' register isn't already filled in, fill it in now */ 490 cbd->owned = TRUE; 491 clip_get_selection(cbd); 492 cbd->owned = FALSE; 493 494 /* Get the text to be put on the clipboard, with CR-LF. */ 495 metadata.type = clip_convert_selection(&str, &txtlen, cbd); 496 if (metadata.type < 0) 497 return; 498 metadata.txtlen = (int)txtlen; 499 metadata.ucslen = 0; 500 metadata.rawlen = 0; 501 502 #ifdef FEAT_MBYTE 503 /* Always set the raw bytes: 'encoding', NUL and the text. This is used 504 * when copy/paste from/to Vim with the same 'encoding', so that illegal 505 * bytes can also be copied and no conversion is needed. */ 506 { 507 LPSTR lpszMemRaw; 508 509 metadata.rawlen = (int)(txtlen + STRLEN(p_enc) + 1); 510 hMemRaw = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 511 metadata.rawlen + 1); 512 lpszMemRaw = (LPSTR)GlobalLock(hMemRaw); 513 if (lpszMemRaw != NULL) 514 { 515 STRCPY(lpszMemRaw, p_enc); 516 memcpy(lpszMemRaw + STRLEN(p_enc) + 1, str, txtlen + 1); 517 GlobalUnlock(hMemRaw); 518 } 519 else 520 metadata.rawlen = 0; 521 } 522 #endif 523 524 # if defined(FEAT_MBYTE) && defined(WIN3264) 525 { 526 WCHAR *out; 527 int len = metadata.txtlen; 528 529 /* Convert the text to UTF-16. This is put on the clipboard as 530 * CF_UNICODETEXT. */ 531 out = (WCHAR *)enc_to_utf16(str, &len); 532 if (out != NULL) 533 { 534 WCHAR *lpszMemW; 535 536 /* Convert the text for CF_TEXT to Active codepage. Otherwise it's 537 * p_enc, which has no relation to the Active codepage. */ 538 metadata.txtlen = WideCharToMultiByte(GetACP(), 0, out, len, 539 NULL, 0, 0, 0); 540 vim_free(str); 541 str = (char_u *)alloc((unsigned)(metadata.txtlen == 0 ? 1 542 : metadata.txtlen)); 543 if (str == NULL) 544 { 545 vim_free(out); 546 return; /* out of memory */ 547 } 548 WideCharToMultiByte(GetACP(), 0, out, len, 549 (LPSTR)str, metadata.txtlen, 0, 0); 550 551 /* Allocate memory for the UTF-16 text, add one NUL word to 552 * terminate the string. */ 553 hMemW = (LPSTR)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 554 (len + 1) * sizeof(WCHAR)); 555 lpszMemW = (WCHAR *)GlobalLock(hMemW); 556 if (lpszMemW != NULL) 557 { 558 memcpy(lpszMemW, out, len * sizeof(WCHAR)); 559 lpszMemW[len] = NUL; 560 GlobalUnlock(hMemW); 561 } 562 vim_free(out); 563 metadata.ucslen = len; 564 } 565 } 566 # endif 567 568 /* Allocate memory for the text, add one NUL byte to terminate the string. 569 */ 570 hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, metadata.txtlen + 1); 571 { 572 LPSTR lpszMem = (LPSTR)GlobalLock(hMem); 573 574 if (lpszMem) 575 { 576 vim_strncpy((char_u *)lpszMem, str, metadata.txtlen); 577 GlobalUnlock(hMem); 578 } 579 } 580 581 /* Set up metadata: */ 582 { 583 VimClipType_t *lpszMemVim = NULL; 584 585 hMemVim = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, 586 sizeof(VimClipType_t)); 587 lpszMemVim = (VimClipType_t *)GlobalLock(hMemVim); 588 memcpy(lpszMemVim, &metadata, sizeof(metadata)); 589 GlobalUnlock(hMemVim); 590 } 591 592 /* 593 * Open the clipboard, clear it and put our text on it. 594 * Always set our Vim format. Put Unicode and plain text on it. 595 * 596 * Don't pass GetActiveWindow() as an argument to OpenClipboard() 597 * because then we can't paste back into the same window for some 598 * reason - webb. 599 */ 600 if (vim_open_clipboard()) 601 { 602 if (EmptyClipboard()) 603 { 604 SetClipboardData(cbd->format, hMemVim); 605 hMemVim = 0; 606 # if defined(FEAT_MBYTE) && defined(WIN3264) 607 if (hMemW != NULL) 608 { 609 if (SetClipboardData(CF_UNICODETEXT, hMemW) != NULL) 610 hMemW = NULL; 611 } 612 # endif 613 /* Always use CF_TEXT. On Win98 Notepad won't obtain the 614 * CF_UNICODETEXT text, only CF_TEXT. */ 615 SetClipboardData(CF_TEXT, hMem); 616 hMem = 0; 617 } 618 CloseClipboard(); 619 } 620 621 vim_free(str); 622 /* Free any allocations we didn't give to the clipboard: */ 623 if (hMemRaw) 624 GlobalFree(hMemRaw); 625 if (hMem) 626 GlobalFree(hMem); 627 # if defined(FEAT_MBYTE) && defined(WIN3264) 628 if (hMemW) 629 GlobalFree(hMemW); 630 # endif 631 if (hMemVim) 632 GlobalFree(hMemVim); 633 } 634 635 #endif /* FEAT_CLIPBOARD */ 636 637 #if defined(FEAT_MBYTE) || defined(PROTO) 638 /* 639 * Note: the following two functions are only guaranteed to work when using 640 * valid MS-Windows codepages or when iconv() is available. 641 */ 642 643 /* 644 * Convert "str" from 'encoding' to UTF-16. 645 * Input in "str" with length "*lenp". When "lenp" is NULL, use strlen(). 646 * Output is returned as an allocated string. "*lenp" is set to the length of 647 * the result. A trailing NUL is always added. 648 * Returns NULL when out of memory. 649 */ 650 short_u * 651 enc_to_utf16(char_u *str, int *lenp) 652 { 653 vimconv_T conv; 654 WCHAR *ret; 655 char_u *allocbuf = NULL; 656 int len_loc; 657 int length; 658 659 if (lenp == NULL) 660 { 661 len_loc = (int)STRLEN(str) + 1; 662 lenp = &len_loc; 663 } 664 665 if (enc_codepage > 0) 666 { 667 /* We can do any CP### -> UTF-16 in one pass, and we can do it 668 * without iconv() (convert_* may need iconv). */ 669 MultiByteToWideChar_alloc(enc_codepage, 0, (LPCSTR)str, *lenp, 670 &ret, &length); 671 } 672 else 673 { 674 /* Use "latin1" by default, we might be called before we have p_enc 675 * set up. Convert to utf-8 first, works better with iconv(). Does 676 * nothing if 'encoding' is "utf-8". */ 677 conv.vc_type = CONV_NONE; 678 if (convert_setup(&conv, p_enc ? p_enc : (char_u *)"latin1", 679 (char_u *)"utf-8") == FAIL) 680 return NULL; 681 if (conv.vc_type != CONV_NONE) 682 { 683 str = allocbuf = string_convert(&conv, str, lenp); 684 if (str == NULL) 685 return NULL; 686 } 687 convert_setup(&conv, NULL, NULL); 688 689 length = utf8_to_utf16(str, *lenp, NULL, NULL); 690 ret = (WCHAR *)alloc((unsigned)((length + 1) * sizeof(WCHAR))); 691 if (ret != NULL) 692 { 693 utf8_to_utf16(str, *lenp, (short_u *)ret, NULL); 694 ret[length] = 0; 695 } 696 697 vim_free(allocbuf); 698 } 699 700 *lenp = length; 701 return (short_u *)ret; 702 } 703 704 /* 705 * Convert an UTF-16 string to 'encoding'. 706 * Input in "str" with length (counted in wide characters) "*lenp". When 707 * "lenp" is NULL, use wcslen(). 708 * Output is returned as an allocated string. If "*lenp" is not NULL it is 709 * set to the length of the result. 710 * Returns NULL when out of memory. 711 */ 712 char_u * 713 utf16_to_enc(short_u *str, int *lenp) 714 { 715 vimconv_T conv; 716 char_u *utf8_str = NULL, *enc_str = NULL; 717 int len_loc; 718 719 if (lenp == NULL) 720 { 721 len_loc = (int)wcslen(str) + 1; 722 lenp = &len_loc; 723 } 724 725 if (enc_codepage > 0) 726 { 727 /* We can do any UTF-16 -> CP### in one pass. */ 728 int length; 729 730 WideCharToMultiByte_alloc(enc_codepage, 0, str, *lenp, 731 (LPSTR *)&enc_str, &length, 0, 0); 732 *lenp = length; 733 return enc_str; 734 } 735 736 /* Avoid allocating zero bytes, it generates an error message. */ 737 utf8_str = alloc(utf16_to_utf8(str, *lenp == 0 ? 1 : *lenp, NULL)); 738 if (utf8_str != NULL) 739 { 740 *lenp = utf16_to_utf8(str, *lenp, utf8_str); 741 742 /* We might be called before we have p_enc set up. */ 743 conv.vc_type = CONV_NONE; 744 convert_setup(&conv, (char_u *)"utf-8", 745 p_enc? p_enc: (char_u *)"latin1"); 746 if (conv.vc_type == CONV_NONE) 747 { 748 /* p_enc is utf-8, so we're done. */ 749 enc_str = utf8_str; 750 } 751 else 752 { 753 enc_str = string_convert(&conv, utf8_str, lenp); 754 vim_free(utf8_str); 755 } 756 757 convert_setup(&conv, NULL, NULL); 758 } 759 760 return enc_str; 761 } 762 #endif /* FEAT_MBYTE */ 763 764 #if (defined(FEAT_MBYTE) && defined(WIN3264)) || defined(PROTO) 765 /* 766 * Convert from the active codepage to 'encoding'. 767 * Input is "str[str_size]". 768 * The result is in allocated memory: "out[outlen]". With terminating NUL. 769 */ 770 void 771 acp_to_enc( 772 char_u *str, 773 int str_size, 774 char_u **out, 775 int *outlen) 776 777 { 778 LPWSTR widestr; 779 780 MultiByteToWideChar_alloc(GetACP(), 0, (LPCSTR)str, str_size, 781 &widestr, outlen); 782 if (widestr != NULL) 783 { 784 ++*outlen; /* Include the 0 after the string */ 785 *out = utf16_to_enc((short_u *)widestr, outlen); 786 vim_free(widestr); 787 } 788 } 789 790 /* 791 * Convert from 'encoding' to the active codepage. 792 * Input is "str[str_size]". 793 * The result is in allocated memory: "out[outlen]". With terminating NUL. 794 */ 795 void 796 enc_to_acp( 797 char_u *str, 798 int str_size, 799 char_u **out, 800 int *outlen) 801 802 { 803 LPWSTR widestr; 804 int len = str_size; 805 806 widestr = (WCHAR *)enc_to_utf16(str, &len); 807 if (widestr != NULL) 808 { 809 WideCharToMultiByte_alloc(GetACP(), 0, widestr, len, 810 (LPSTR *)out, outlen, 0, 0); 811 vim_free(widestr); 812 } 813 } 814 #endif 815