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