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