Mercurial > vim
annotate src/winclip.c @ 6973:7b35ee02b3c5 v7.4.804
patch 7.4.804
Problem: Xxd doesn't have a license notice.
Solution: Add license as indicated by Juergen.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Tue, 04 Aug 2015 17:29:07 +0200 |
parents | 22d7af9ff3e5 |
children | 33ba2adb6065 |
rev | line source |
---|---|
4168 | 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(). */ | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
183 *out = (LPSTR)alloc((unsigned)*outlen + 1); |
4168 | 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, | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
560 (LPSTR)str, metadata.txtlen, 0, 0); |
4168 | 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 { | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
587 vim_strncpy((char_u *)lpszMem, str, metadata.txtlen); |
4168 | 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). */ | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
680 MultiByteToWideChar_alloc(enc_codepage, 0, (LPCSTR)str, *lenp, |
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
681 &ret, &length); |
4168 | 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 | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
791 MultiByteToWideChar_alloc(GetACP(), 0, (LPCSTR)str, str_size, |
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
792 &widestr, outlen); |
4168 | 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 } | |
5714 | 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 } | |
4168 | 825 #endif |