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