Mercurial > vim
annotate src/winclip.c @ 15641:2c264fda0f59 v8.1.0828
patch 8.1.0828: still using FEAT_VIRTUALEDIT
commit https://github.com/vim/vim/commit/6aba96dd5778b4201c9f5cb065d7669d3398e724
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 26 17:43:21 2019 +0100
patch 8.1.0828: still using FEAT_VIRTUALEDIT
Problem: Still using FEAT_VIRTUALEDIT.
Solution: Remove last use of FEAT_VIRTUALEDIT.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 26 Jan 2019 17:45:13 +0100 |
parents | 62b3805506b3 |
children | 7fad90423bd2 |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
8140
diff
changeset
|
1 /* vi:set ts=8 sts=4 sw=4 noet: |
4168 | 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 * | |
10783
04eb70c77cf4
patch 8.0.0281: some files are still using ARGSUSED instead of UNUSED
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
13 * Routines for Win32 clipboard handling. |
4168 | 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(). */ | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
173 *out = (LPSTR)alloc((unsigned)*outlen + 1); |
4168 | 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 | |
10783
04eb70c77cf4
patch 8.0.0281: some files are still using ARGSUSED instead of UNUSED
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
216 clip_mch_own_selection(VimClipboard *cbd UNUSED) |
4168 | 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 | |
10783
04eb70c77cf4
patch 8.0.0281: some files are still using ARGSUSED instead of UNUSED
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
229 clip_mch_lose_selection(VimClipboard *cbd UNUSED) |
4168 | 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; | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
302 #if defined(WIN3264) |
4168 | 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 { | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
364 #if defined(WIN3264) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
365 /* Try to get the clipboard in Unicode if it's not an empty string. */ |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
366 if (IsClipboardFormatAvailable(CF_UNICODETEXT) && metadata.ucslen != 0) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
367 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
368 HGLOBAL hMemW; |
4168 | 369 |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
370 if ((hMemW = GetClipboardData(CF_UNICODETEXT)) != NULL) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
371 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
372 WCHAR *hMemWstr = (WCHAR *)GlobalLock(hMemW); |
4168 | 373 |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
374 /* Use the length of our metadata if possible, but limit it to |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
375 * the GlobalSize() for safety. */ |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
376 maxlen = (int)(GlobalSize(hMemW) / sizeof(WCHAR)); |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
377 if (metadata.ucslen >= 0) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
378 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
379 if (metadata.ucslen > maxlen) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
380 str_size = maxlen; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
381 else |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
382 str_size = metadata.ucslen; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
383 } |
4168 | 384 else |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
385 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
386 for (str_size = 0; str_size < maxlen; ++str_size) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
387 if (hMemWstr[str_size] == NUL) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
388 break; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
389 } |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
390 to_free = str = utf16_to_enc((short_u *)hMemWstr, &str_size); |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
391 GlobalUnlock(hMemW); |
4168 | 392 } |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
393 } |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
394 else |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
395 #endif |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
396 /* Get the clipboard in the Active codepage. */ |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
397 if (IsClipboardFormatAvailable(CF_TEXT)) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
398 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
399 if ((hMem = GetClipboardData(CF_TEXT)) != NULL) |
4168 | 400 { |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
401 str = (char_u *)GlobalLock(hMem); |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
402 |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
403 /* The length is either what our metadata says or the strlen(). |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
404 * But limit it to the GlobalSize() for safety. */ |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
405 maxlen = (int)GlobalSize(hMem); |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
406 if (metadata.txtlen >= 0) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
407 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
408 if (metadata.txtlen > maxlen) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
409 str_size = maxlen; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
410 else |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
411 str_size = metadata.txtlen; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
412 } |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
413 else |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
414 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
415 for (str_size = 0; str_size < maxlen; ++str_size) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
416 if (str[str_size] == NUL) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
417 break; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
418 } |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
419 |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
420 #if defined(WIN3264) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
421 /* The text is in the active codepage. Convert to |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
422 * 'encoding', going through UTF-16. */ |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
423 acp_to_enc(str, str_size, &to_free, &maxlen); |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
424 if (to_free != NULL) |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
425 { |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
426 str_size = maxlen; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
427 str = to_free; |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
428 } |
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
429 #endif |
4168 | 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(); | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
457 #if defined(WIN3264) |
4168 | 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; | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
474 # if defined(WIN3264) |
4168 | 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 | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
511 # if defined(WIN3264) |
4168 | 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, | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
536 (LPSTR)str, metadata.txtlen, 0, 0); |
4168 | 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 { | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
563 vim_strncpy((char_u *)lpszMem, str, metadata.txtlen); |
4168 | 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; | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
593 # if defined(WIN3264) |
4168 | 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); | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
614 # if defined(WIN3264) |
4168 | 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). */ | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
655 MultiByteToWideChar_alloc(enc_codepage, 0, (LPCSTR)str, *lenp, |
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
656 &ret, &length); |
4168 | 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 | |
15605
62b3805506b3
patch 8.1.0810: too many #ifdefs
Bram Moolenaar <Bram@vim.org>
parents:
10783
diff
changeset
|
749 #if defined(WIN3264) || defined(PROTO) |
4168 | 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 | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
756 acp_to_enc( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
757 char_u *str, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
758 int str_size, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
759 char_u **out, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
760 int *outlen) |
4168 | 761 |
762 { | |
763 LPWSTR widestr; | |
764 | |
5082
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
765 MultiByteToWideChar_alloc(GetACP(), 0, (LPCSTR)str, str_size, |
7b20dc804164
updated for version 7.3.1284
Bram Moolenaar <bram@vim.org>
parents:
4168
diff
changeset
|
766 &widestr, outlen); |
4168 | 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 } | |
5714 | 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 | |
7837
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
781 enc_to_acp( |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
782 char_u *str, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
783 int str_size, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
784 char_u **out, |
33ba2adb6065
commit https://github.com/vim/vim/commit/b638a7be952544ceb03052c25b84224577a6494b
Christian Brabandt <cb@256bit.org>
parents:
5714
diff
changeset
|
785 int *outlen) |
5714 | 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 } | |
4168 | 799 #endif |