1 | /* 16-bit Windows Selection processing for emacs on MS-Windows |
---|
2 | Copyright (C) 1996, 1997 Free Software Foundation. |
---|
3 | |
---|
4 | This file is part of GNU Emacs. |
---|
5 | |
---|
6 | GNU Emacs is free software; you can redistribute it and/or modify |
---|
7 | it under the terms of the GNU General Public License as published by |
---|
8 | the Free Software Foundation; either version 2, or (at your option) |
---|
9 | any later version. |
---|
10 | |
---|
11 | GNU Emacs is distributed in the hope that it will be useful, |
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | GNU General Public License for more details. |
---|
15 | |
---|
16 | You should have received a copy of the GNU General Public License |
---|
17 | along with GNU Emacs; see the file COPYING. If not, write to |
---|
18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
19 | Boston, MA 02111-1307, USA. */ |
---|
20 | |
---|
21 | /* These functions work by using WinOldAp interface. WinOldAp |
---|
22 | (WINOLDAP.MOD) is a Microsoft Windows extension supporting |
---|
23 | "old" (character-mode) application access to Dynamic Data Exchange, |
---|
24 | menus, and the Windows clipboard. */ |
---|
25 | |
---|
26 | /* Written by Dale P. Smith <dpsm@en.com> */ |
---|
27 | /* Adapted to DJGPP v1 by Eli Zaretskii <eliz@is.elta.co.il> */ |
---|
28 | |
---|
29 | #ifdef MSDOS |
---|
30 | |
---|
31 | #include <config.h> |
---|
32 | #include <string.h> |
---|
33 | #include <dpmi.h> |
---|
34 | #include <go32.h> |
---|
35 | #include <sys/farptr.h> |
---|
36 | #include "lisp.h" |
---|
37 | #include "dispextern.h" /* frame.h seems to want this */ |
---|
38 | #include "frame.h" /* Need this to get the X window of selected_frame */ |
---|
39 | #include "blockinput.h" |
---|
40 | #include "buffer.h" |
---|
41 | #include "charset.h" |
---|
42 | #include "coding.h" |
---|
43 | |
---|
44 | /* If ever some function outside this file will need to call any |
---|
45 | clipboard-related function, the following prototypes and constants |
---|
46 | should be put on a header file. Right now, nobody else uses them. */ |
---|
47 | |
---|
48 | #define CF_TEXT 0x01 |
---|
49 | #define CF_BITMAP 0x02 |
---|
50 | #define CF_METAFILE 0x03 |
---|
51 | #define CF_SYLK 0x04 |
---|
52 | #define CF_DIF 0x05 |
---|
53 | #define CF_TIFF 0x06 |
---|
54 | #define CF_OEMTEXT 0x07 |
---|
55 | #define CF_DIBBITMAP 0x08 |
---|
56 | #define CF_WINWRITE 0x80 |
---|
57 | #define CF_DSPTEXT 0x81 |
---|
58 | #define CF_DSPBITMAP 0x82 |
---|
59 | |
---|
60 | unsigned identify_winoldap_version (void); |
---|
61 | unsigned open_clipboard (void); |
---|
62 | unsigned empty_clipboard (void); |
---|
63 | unsigned set_clipboard_data (unsigned, void *, unsigned, int); |
---|
64 | unsigned get_clipboard_data_size (unsigned); |
---|
65 | unsigned get_clipboard_data (unsigned, void *, unsigned, int); |
---|
66 | unsigned close_clipboard (void); |
---|
67 | unsigned clipboard_compact (unsigned); |
---|
68 | |
---|
69 | Lisp_Object QCLIPBOARD, QPRIMARY; |
---|
70 | |
---|
71 | /* Coding system for communicating with other Windows programs via the |
---|
72 | clipboard. */ |
---|
73 | static Lisp_Object Vselection_coding_system; |
---|
74 | |
---|
75 | /* Coding system for the next communicating with other Windows programs. */ |
---|
76 | static Lisp_Object Vnext_selection_coding_system; |
---|
77 | |
---|
78 | /* The segment address and the size of the buffer in low |
---|
79 | memory used to move data between us and WinOldAp module. */ |
---|
80 | static struct { |
---|
81 | unsigned long size; |
---|
82 | unsigned short rm_segment; |
---|
83 | } clipboard_xfer_buf_info; |
---|
84 | |
---|
85 | /* The last text we put into the clipboard. This is used to prevent |
---|
86 | passing back our own text from the clipboard, instead of using the |
---|
87 | kill ring. The former is undesirable because the clipboard data |
---|
88 | could be MULEtilated by inappropriately chosen |
---|
89 | (next-)selection-coding-system. For this reason, we must store the |
---|
90 | text *after* it was encoded/Unix-to-DOS-converted. */ |
---|
91 | static unsigned char *last_clipboard_text; |
---|
92 | |
---|
93 | /* The size of allocated storage for storing the clipboard data. */ |
---|
94 | static size_t clipboard_storage_size; |
---|
95 | |
---|
96 | /* Emulation of `__dpmi_int' and friends for DJGPP v1.x */ |
---|
97 | |
---|
98 | #if __DJGPP__ < 2 |
---|
99 | |
---|
100 | typedef _go32_dpmi_registers __dpmi_regs; |
---|
101 | #define __tb _go32_info_block.linear_address_of_transfer_buffer |
---|
102 | #define _dos_ds _go32_info_block.selector_for_linear_memory |
---|
103 | |
---|
104 | static int |
---|
105 | __dpmi_int (intno, regs) |
---|
106 | int intno; |
---|
107 | __dpmi_regs *regs; |
---|
108 | { |
---|
109 | regs->x.ss = regs->x.sp = regs->x.flags = 0; |
---|
110 | return _go32_dpmi_simulate_int (intno, regs); |
---|
111 | } |
---|
112 | |
---|
113 | #endif /* __DJGPP__ < 2 */ |
---|
114 | |
---|
115 | /* C functions to access the Windows 3.1x clipboard from DOS apps. |
---|
116 | |
---|
117 | The information was obtained from the Microsoft Knowledge Base, |
---|
118 | article Q67675 and can be found at: |
---|
119 | http://www.microsoft.com/kb/developr/win_dk/q67675.htm */ |
---|
120 | |
---|
121 | /* See also Ralf Brown's Interrupt List. |
---|
122 | |
---|
123 | I also seem to remember reading about this in Dr. Dobbs Journal a |
---|
124 | while ago, but if you knew my memory... :-) |
---|
125 | |
---|
126 | Dale P. Smith <dpsm@en.com> */ |
---|
127 | |
---|
128 | /* Return the WinOldAp support version, or 0x1700 if not supported. */ |
---|
129 | unsigned |
---|
130 | identify_winoldap_version () |
---|
131 | { |
---|
132 | __dpmi_regs regs; |
---|
133 | |
---|
134 | /* Calls Int 2Fh/AX=1700h |
---|
135 | Return Values AX == 1700H: Clipboard functions not available |
---|
136 | <> 1700H: AL = Major version number |
---|
137 | AH = Minor version number */ |
---|
138 | regs.x.ax = 0x1700; |
---|
139 | __dpmi_int(0x2f, ®s); |
---|
140 | return regs.x.ax; |
---|
141 | } |
---|
142 | |
---|
143 | /* Open the clipboard, return non-zero if successfull. */ |
---|
144 | unsigned |
---|
145 | open_clipboard () |
---|
146 | { |
---|
147 | __dpmi_regs regs; |
---|
148 | |
---|
149 | /* Is WINOLDAP supported? */ |
---|
150 | /* Kludge alert!! If WinOldAp is not supported, we return a 0, |
---|
151 | which is the same as ``Clipboard already open''. Currently, |
---|
152 | this is taken as an error by all the functions that use |
---|
153 | `open_clipboard', but if somebody someday will use that ``open'' |
---|
154 | clipboard, they will have interesting time debugging it... */ |
---|
155 | if (identify_winoldap_version () == 0x1700) |
---|
156 | return 0; |
---|
157 | |
---|
158 | /* Calls Int 2Fh/AX=1701h |
---|
159 | Return Values AX == 0: Clipboard already open |
---|
160 | <> 0: Clipboard opened */ |
---|
161 | regs.x.ax = 0x1701; |
---|
162 | __dpmi_int(0x2f, ®s); |
---|
163 | return regs.x.ax; |
---|
164 | } |
---|
165 | |
---|
166 | /* Empty clipboard, return non-zero if successfull. */ |
---|
167 | unsigned |
---|
168 | empty_clipboard () |
---|
169 | { |
---|
170 | __dpmi_regs regs; |
---|
171 | |
---|
172 | /* Calls Int 2Fh/AX=1702h |
---|
173 | Return Values AX == 0: Error occurred |
---|
174 | <> 0: OK, Clipboard emptied */ |
---|
175 | regs.x.ax = 0x1702; |
---|
176 | __dpmi_int(0x2f, ®s); |
---|
177 | return regs.x.ax; |
---|
178 | } |
---|
179 | |
---|
180 | /* Ensure we have a buffer in low memory with enough memory for data |
---|
181 | of size WANT_SIZE. Return the linear address of the buffer. */ |
---|
182 | static unsigned long |
---|
183 | alloc_xfer_buf (want_size) |
---|
184 | unsigned want_size; |
---|
185 | { |
---|
186 | __dpmi_regs regs; |
---|
187 | |
---|
188 | /* If the usual DJGPP transfer buffer is large enough, use that. */ |
---|
189 | if (want_size <= _go32_info_block.size_of_transfer_buffer) |
---|
190 | return __tb & 0xfffff; |
---|
191 | |
---|
192 | /* Don't even try to allocate more than 1MB of memory: DOS cannot |
---|
193 | possibly handle that (it will overflow the BX register below). */ |
---|
194 | if (want_size > 0xfffff) |
---|
195 | return 0; |
---|
196 | |
---|
197 | /* Need size rounded up to the nearest paragraph, and in |
---|
198 | paragraph units (1 paragraph = 16 bytes). */ |
---|
199 | clipboard_xfer_buf_info.size = (want_size + 15) >> 4; |
---|
200 | |
---|
201 | /* The NT DPMI host crashes us if we free DOS memory via the |
---|
202 | DPMI service. Work around by calling DOS allocate/free block. */ |
---|
203 | regs.h.ah = 0x48; |
---|
204 | regs.x.bx = clipboard_xfer_buf_info.size; |
---|
205 | __dpmi_int (0x21, ®s); |
---|
206 | if (regs.x.flags & 1) |
---|
207 | { |
---|
208 | clipboard_xfer_buf_info.size = 0; |
---|
209 | return 0; |
---|
210 | } |
---|
211 | |
---|
212 | clipboard_xfer_buf_info.rm_segment = regs.x.ax; |
---|
213 | return (((int)clipboard_xfer_buf_info.rm_segment) << 4) & 0xfffff; |
---|
214 | } |
---|
215 | |
---|
216 | /* Free our clipboard buffer. We always free it after use, because |
---|
217 | keeping it leaves less free conventional memory for subprocesses. |
---|
218 | The clipboard buffer tends to be large in size, because for small |
---|
219 | clipboard data sizes we use the DJGPP transfer buffer. */ |
---|
220 | static void |
---|
221 | free_xfer_buf () |
---|
222 | { |
---|
223 | /* If the size is 0, we used DJGPP transfer buffer, so don't free. */ |
---|
224 | if (clipboard_xfer_buf_info.size) |
---|
225 | { |
---|
226 | __dpmi_regs regs; |
---|
227 | |
---|
228 | /* The NT DPMI host crashes us if we free DOS memory via |
---|
229 | the DPMI service. Work around by calling DOS free block. */ |
---|
230 | regs.h.ah = 0x49; |
---|
231 | regs.x.es = clipboard_xfer_buf_info.rm_segment; |
---|
232 | __dpmi_int (0x21, ®s); |
---|
233 | clipboard_xfer_buf_info.size = 0; |
---|
234 | } |
---|
235 | } |
---|
236 | |
---|
237 | /* Copy data into the clipboard, return zero if successfull. */ |
---|
238 | unsigned |
---|
239 | set_clipboard_data (Format, Data, Size, Raw) |
---|
240 | unsigned Format; |
---|
241 | void *Data; |
---|
242 | unsigned Size; |
---|
243 | int Raw; |
---|
244 | { |
---|
245 | __dpmi_regs regs; |
---|
246 | unsigned truelen; |
---|
247 | unsigned long xbuf_addr, buf_offset; |
---|
248 | unsigned char *dp = Data, *dstart = dp; |
---|
249 | |
---|
250 | if (Format != CF_OEMTEXT) |
---|
251 | return 3; |
---|
252 | |
---|
253 | /* need to know final size after '\r' chars are inserted (the |
---|
254 | standard CF_OEMTEXT clipboard format uses CRLF line endings, |
---|
255 | while Emacs uses just LF internally). */ |
---|
256 | truelen = Size + 1; /* +1 for the terminating null */ |
---|
257 | |
---|
258 | if (!Raw) |
---|
259 | { |
---|
260 | /* avoid using strchr because it recomputes the length everytime */ |
---|
261 | while ((dp = memchr (dp, '\n', Size - (dp - dstart))) != 0) |
---|
262 | { |
---|
263 | truelen++; |
---|
264 | dp++; |
---|
265 | } |
---|
266 | } |
---|
267 | |
---|
268 | if (clipboard_compact (truelen) < truelen) |
---|
269 | return 1; |
---|
270 | |
---|
271 | if ((xbuf_addr = alloc_xfer_buf (truelen)) == 0) |
---|
272 | return 1; |
---|
273 | |
---|
274 | /* Move the buffer into the low memory, convert LF into CR-LF if needed. */ |
---|
275 | if (Raw) |
---|
276 | { |
---|
277 | dosmemput (Data, Size, xbuf_addr); |
---|
278 | |
---|
279 | /* Terminate with a null, otherwise Windows does strange things |
---|
280 | when the text size is an integral multiple of 32 bytes. */ |
---|
281 | _farpokeb (_dos_ds, xbuf_addr + Size, '\0'); |
---|
282 | } |
---|
283 | else |
---|
284 | { |
---|
285 | dp = Data; |
---|
286 | buf_offset = xbuf_addr; |
---|
287 | _farsetsel (_dos_ds); |
---|
288 | while (Size--) |
---|
289 | { |
---|
290 | /* Don't allow them to put binary data into the clipboard, since |
---|
291 | it will cause yanked data to be truncated at the first null. */ |
---|
292 | if (*dp == '\0') |
---|
293 | return 2; |
---|
294 | if (*dp == '\n') |
---|
295 | _farnspokeb (buf_offset++, '\r'); |
---|
296 | _farnspokeb (buf_offset++, *dp++); |
---|
297 | } |
---|
298 | |
---|
299 | /* Terminate with a null, otherwise Windows does strange things |
---|
300 | when the text size is an integral multiple of 32 bytes. */ |
---|
301 | _farnspokeb (buf_offset, '\0'); |
---|
302 | } |
---|
303 | |
---|
304 | /* Stash away the data we are about to put into the clipboard, so we |
---|
305 | could later check inside get_clipboard_data whether the clipboard |
---|
306 | still holds our data. */ |
---|
307 | if (clipboard_storage_size < truelen) |
---|
308 | { |
---|
309 | clipboard_storage_size = truelen + 100; |
---|
310 | last_clipboard_text = |
---|
311 | (char *) xrealloc (last_clipboard_text, clipboard_storage_size); |
---|
312 | } |
---|
313 | if (last_clipboard_text) |
---|
314 | dosmemget (xbuf_addr, truelen, last_clipboard_text); |
---|
315 | |
---|
316 | /* Calls Int 2Fh/AX=1703h with: |
---|
317 | DX = WinOldAp-Supported Clipboard format |
---|
318 | ES:BX = Pointer to data |
---|
319 | SI:CX = Size of data in bytes |
---|
320 | Return Values AX == 0: Error occurred |
---|
321 | <> 0: OK. Data copied into the Clipboard. */ |
---|
322 | regs.x.ax = 0x1703; |
---|
323 | regs.x.dx = Format; |
---|
324 | regs.x.si = truelen >> 16; |
---|
325 | regs.x.cx = truelen & 0xffff; |
---|
326 | regs.x.es = xbuf_addr >> 4; |
---|
327 | regs.x.bx = xbuf_addr & 15; |
---|
328 | __dpmi_int(0x2f, ®s); |
---|
329 | |
---|
330 | free_xfer_buf (); |
---|
331 | |
---|
332 | /* If the above failed, invalidate the local copy of the clipboard. */ |
---|
333 | if (regs.x.ax == 0) |
---|
334 | *last_clipboard_text = '\0'; |
---|
335 | |
---|
336 | /* Zero means success, otherwise (1, 2, or 3) it's an error. */ |
---|
337 | return regs.x.ax > 0 ? 0 : 3; |
---|
338 | } |
---|
339 | |
---|
340 | /* Return the size of the clipboard data of format FORMAT. */ |
---|
341 | unsigned |
---|
342 | get_clipboard_data_size (Format) |
---|
343 | unsigned Format; |
---|
344 | { |
---|
345 | __dpmi_regs regs; |
---|
346 | |
---|
347 | /* Calls Int 2Fh/AX=1704h with: |
---|
348 | DX = WinOldAp-Supported Clipboard format |
---|
349 | Return Values DX:AX == Size of the data in bytes, including any |
---|
350 | headers. |
---|
351 | == 0 If data in this format is not in |
---|
352 | the clipboard. */ |
---|
353 | regs.x.ax = 0x1704; |
---|
354 | regs.x.dx = Format; |
---|
355 | __dpmi_int(0x2f, ®s); |
---|
356 | return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax); |
---|
357 | } |
---|
358 | |
---|
359 | /* Get clipboard data, return its length. |
---|
360 | Warning: this doesn't check whether DATA has enough space to hold |
---|
361 | SIZE bytes. */ |
---|
362 | unsigned |
---|
363 | get_clipboard_data (Format, Data, Size, Raw) |
---|
364 | unsigned Format; |
---|
365 | void *Data; |
---|
366 | unsigned Size; |
---|
367 | int Raw; |
---|
368 | { |
---|
369 | __dpmi_regs regs; |
---|
370 | unsigned long xbuf_addr; |
---|
371 | unsigned char *dp = Data; |
---|
372 | |
---|
373 | if (Format != CF_OEMTEXT) |
---|
374 | return 0; |
---|
375 | |
---|
376 | if (Size == 0) |
---|
377 | return 0; |
---|
378 | |
---|
379 | if ((xbuf_addr = alloc_xfer_buf (Size)) == 0) |
---|
380 | return 0; |
---|
381 | |
---|
382 | /* Calls Int 2Fh/AX=1705h with: |
---|
383 | DX = WinOldAp-Supported Clipboard format |
---|
384 | ES:BX = Pointer to data buffer to hold data |
---|
385 | Return Values AX == 0: Error occurred (or data in this format is not |
---|
386 | in the clipboard) |
---|
387 | <> 0: OK */ |
---|
388 | regs.x.ax = 0x1705; |
---|
389 | regs.x.dx = Format; |
---|
390 | regs.x.es = xbuf_addr >> 4; |
---|
391 | regs.x.bx = xbuf_addr & 15; |
---|
392 | __dpmi_int(0x2f, ®s); |
---|
393 | if (regs.x.ax != 0) |
---|
394 | { |
---|
395 | unsigned char null_char = '\0'; |
---|
396 | unsigned long xbuf_beg = xbuf_addr; |
---|
397 | |
---|
398 | /* If last_clipboard_text is NULL, we don't want to slow down |
---|
399 | the next loop by an additional test. */ |
---|
400 | register unsigned char *lcdp = |
---|
401 | last_clipboard_text == NULL ? &null_char : last_clipboard_text; |
---|
402 | |
---|
403 | /* Copy data from low memory, remove CR |
---|
404 | characters before LF if needed. */ |
---|
405 | _farsetsel (_dos_ds); |
---|
406 | while (Size--) |
---|
407 | { |
---|
408 | register unsigned char c = _farnspeekb (xbuf_addr++); |
---|
409 | |
---|
410 | if (*lcdp == c) |
---|
411 | lcdp++; |
---|
412 | |
---|
413 | if ((*dp++ = c) == '\r' && !Raw && _farnspeekb (xbuf_addr) == '\n') |
---|
414 | { |
---|
415 | dp--; |
---|
416 | *dp++ = '\n'; |
---|
417 | xbuf_addr++; |
---|
418 | if (*lcdp == '\n') |
---|
419 | lcdp++; |
---|
420 | } |
---|
421 | /* Windows reportedly rounds up the size of clipboard data |
---|
422 | (passed in SIZE) to a multiple of 32, and removes trailing |
---|
423 | spaces from each line without updating SIZE. We therefore |
---|
424 | bail out when we see the first null character. */ |
---|
425 | else if (c == '\0') |
---|
426 | break; |
---|
427 | } |
---|
428 | |
---|
429 | /* If the text in clipboard is identical to what we put there |
---|
430 | last time set_clipboard_data was called, pretend there's no |
---|
431 | data in the clipboard. This is so we don't pass our own text |
---|
432 | from the clipboard (which might be troublesome if the killed |
---|
433 | text includes null characters). */ |
---|
434 | if (last_clipboard_text && |
---|
435 | xbuf_addr - xbuf_beg == (long)(lcdp - last_clipboard_text)) |
---|
436 | dp = (unsigned char *)Data + 1; |
---|
437 | } |
---|
438 | |
---|
439 | free_xfer_buf (); |
---|
440 | |
---|
441 | return (unsigned) (dp - (unsigned char *)Data - 1); |
---|
442 | } |
---|
443 | |
---|
444 | /* Close clipboard, return non-zero if successfull. */ |
---|
445 | unsigned |
---|
446 | close_clipboard () |
---|
447 | { |
---|
448 | __dpmi_regs regs; |
---|
449 | |
---|
450 | /* Calls Int 2Fh/AX=1708h |
---|
451 | Return Values AX == 0: Error occurred |
---|
452 | <> 0: OK */ |
---|
453 | regs.x.ax = 0x1708; |
---|
454 | __dpmi_int(0x2f, ®s); |
---|
455 | return regs.x.ax; |
---|
456 | } |
---|
457 | |
---|
458 | /* Compact clipboard data so that at least SIZE bytes is available. */ |
---|
459 | unsigned |
---|
460 | clipboard_compact (Size) |
---|
461 | unsigned Size; |
---|
462 | { |
---|
463 | __dpmi_regs regs; |
---|
464 | |
---|
465 | /* Calls Int 2Fh/AX=1709H with: |
---|
466 | SI:CX = Desired memory size in bytes. |
---|
467 | Return Values DX:AX == Number of bytes of largest block of free memory. |
---|
468 | == 0 if error or no memory */ |
---|
469 | regs.x.ax = 0x1709; |
---|
470 | regs.x.si = Size >> 16; |
---|
471 | regs.x.cx = Size & 0xffff; |
---|
472 | __dpmi_int(0x2f, ®s); |
---|
473 | return ((unsigned)regs.x.dx << 16) | regs.x.ax; |
---|
474 | } |
---|
475 | |
---|
476 | static char no_mem_msg[] = |
---|
477 | "(Not enough DOS memory to put saved text into clipboard.)"; |
---|
478 | static char binary_msg[] = |
---|
479 | "(Binary characters in saved text; clipboard data not set.)"; |
---|
480 | static char system_error_msg[] = |
---|
481 | "(Clipboard interface failure; clipboard data not set.)"; |
---|
482 | |
---|
483 | DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_data, 1, 2, 0, |
---|
484 | "This sets the clipboard data to the given text.") |
---|
485 | (string, frame) |
---|
486 | Lisp_Object string, frame; |
---|
487 | { |
---|
488 | unsigned ok = 1, put_status = 0; |
---|
489 | int nbytes; |
---|
490 | unsigned char *src, *dst = NULL; |
---|
491 | int charset_info; |
---|
492 | int no_crlf_conversion; |
---|
493 | |
---|
494 | CHECK_STRING (string, 0); |
---|
495 | |
---|
496 | if (NILP (frame)) |
---|
497 | frame = Fselected_frame (); |
---|
498 | |
---|
499 | CHECK_LIVE_FRAME (frame, 0); |
---|
500 | if ( !FRAME_MSDOS_P (XFRAME (frame))) |
---|
501 | goto done; |
---|
502 | |
---|
503 | BLOCK_INPUT; |
---|
504 | |
---|
505 | nbytes = STRING_BYTES (XSTRING (string)); |
---|
506 | src = XSTRING (string)->data; |
---|
507 | |
---|
508 | /* Since we are now handling multilingual text, we must consider |
---|
509 | encoding text for the clipboard. */ |
---|
510 | charset_info = find_charset_in_text (src, XSTRING (string)->size, nbytes, |
---|
511 | NULL, Qnil); |
---|
512 | |
---|
513 | if (charset_info == 0) |
---|
514 | { |
---|
515 | /* No multibyte character in OBJ. We need not encode it, but we |
---|
516 | will have to convert it to DOS CR-LF style. */ |
---|
517 | no_crlf_conversion = 0; |
---|
518 | } |
---|
519 | else |
---|
520 | { |
---|
521 | /* We must encode contents of STRING according to what |
---|
522 | clipboard-coding-system specifies. */ |
---|
523 | int bufsize; |
---|
524 | struct coding_system coding; |
---|
525 | unsigned char *htext2; |
---|
526 | |
---|
527 | if (NILP (Vnext_selection_coding_system)) |
---|
528 | Vnext_selection_coding_system = Vselection_coding_system; |
---|
529 | setup_coding_system |
---|
530 | (Fcheck_coding_system (Vnext_selection_coding_system), &coding); |
---|
531 | coding.src_multibyte = 1; |
---|
532 | coding.dst_multibyte = 0; |
---|
533 | Vnext_selection_coding_system = Qnil; |
---|
534 | coding.mode |= CODING_MODE_LAST_BLOCK; |
---|
535 | Vlast_coding_system_used = coding.symbol; |
---|
536 | bufsize = encoding_buffer_size (&coding, nbytes); |
---|
537 | dst = (unsigned char *) xmalloc (bufsize); |
---|
538 | encode_coding (&coding, src, dst, nbytes, bufsize); |
---|
539 | no_crlf_conversion = 1; |
---|
540 | nbytes = coding.produced; |
---|
541 | src = dst; |
---|
542 | } |
---|
543 | |
---|
544 | if (!open_clipboard ()) |
---|
545 | goto error; |
---|
546 | |
---|
547 | ok = empty_clipboard () |
---|
548 | && ((put_status |
---|
549 | = set_clipboard_data (CF_OEMTEXT, src, nbytes, no_crlf_conversion)) |
---|
550 | == 0); |
---|
551 | |
---|
552 | if (!no_crlf_conversion) |
---|
553 | Vlast_coding_system_used = Qraw_text; |
---|
554 | close_clipboard (); |
---|
555 | |
---|
556 | if (ok) goto unblock; |
---|
557 | |
---|
558 | error: |
---|
559 | |
---|
560 | ok = 0; |
---|
561 | |
---|
562 | unblock: |
---|
563 | if (dst) |
---|
564 | xfree (dst); |
---|
565 | UNBLOCK_INPUT; |
---|
566 | |
---|
567 | /* Notify user if the text is too large to fit into DOS memory. |
---|
568 | (This will happen somewhere after 600K bytes (470K in DJGPP v1.x), |
---|
569 | depending on user system configuration.) If we just silently |
---|
570 | fail the function, people might wonder why their text sometimes |
---|
571 | doesn't make it to the clipboard. */ |
---|
572 | if (put_status) |
---|
573 | { |
---|
574 | switch (put_status) |
---|
575 | { |
---|
576 | case 1: |
---|
577 | message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0); |
---|
578 | break; |
---|
579 | case 2: |
---|
580 | message2 (binary_msg, sizeof (binary_msg) - 1, 0); |
---|
581 | break; |
---|
582 | case 3: |
---|
583 | message2 (system_error_msg, sizeof (system_error_msg) - 1, 0); |
---|
584 | break; |
---|
585 | } |
---|
586 | sit_for (2, 0, 0, 1, 1); |
---|
587 | } |
---|
588 | |
---|
589 | done: |
---|
590 | |
---|
591 | return (ok && put_status == 0 ? string : Qnil); |
---|
592 | } |
---|
593 | |
---|
594 | DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_data, 0, 1, 0, |
---|
595 | "This gets the clipboard data in text format.") |
---|
596 | (frame) |
---|
597 | Lisp_Object frame; |
---|
598 | { |
---|
599 | unsigned data_size, truelen; |
---|
600 | unsigned char *htext; |
---|
601 | Lisp_Object ret = Qnil; |
---|
602 | int no_crlf_conversion; |
---|
603 | int require_encoding = 0; |
---|
604 | |
---|
605 | if (NILP (frame)) |
---|
606 | frame = Fselected_frame (); |
---|
607 | |
---|
608 | CHECK_LIVE_FRAME (frame, 0); |
---|
609 | if ( !FRAME_MSDOS_P (XFRAME (frame))) |
---|
610 | goto done; |
---|
611 | |
---|
612 | BLOCK_INPUT; |
---|
613 | |
---|
614 | if (!open_clipboard ()) |
---|
615 | goto unblock; |
---|
616 | |
---|
617 | if ((data_size = get_clipboard_data_size (CF_OEMTEXT)) == 0 || |
---|
618 | (htext = (unsigned char *)xmalloc (data_size)) == 0) |
---|
619 | goto closeclip; |
---|
620 | |
---|
621 | /* need to know final size after '\r' chars are removed because |
---|
622 | we can't change the string size manually, and doing an extra |
---|
623 | copy is silly */ |
---|
624 | if ((truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 0)) == 0) |
---|
625 | goto closeclip; |
---|
626 | |
---|
627 | /* Do we need to decode it? */ |
---|
628 | if ( |
---|
629 | #if 1 |
---|
630 | 1 |
---|
631 | #else |
---|
632 | ! NILP (buffer_defaults.enable_multibyte_characters) |
---|
633 | #endif |
---|
634 | ) |
---|
635 | { |
---|
636 | /* If the clipboard data contains any 8-bit Latin-1 code, we |
---|
637 | need to decode it. */ |
---|
638 | int i; |
---|
639 | |
---|
640 | for (i = 0; i < truelen; i++) |
---|
641 | { |
---|
642 | if (htext[i] >= 0x80) |
---|
643 | { |
---|
644 | require_encoding = 1; |
---|
645 | break; |
---|
646 | } |
---|
647 | } |
---|
648 | } |
---|
649 | if (require_encoding) |
---|
650 | { |
---|
651 | int bufsize; |
---|
652 | unsigned char *buf; |
---|
653 | struct coding_system coding; |
---|
654 | |
---|
655 | if (NILP (Vnext_selection_coding_system)) |
---|
656 | Vnext_selection_coding_system = Vselection_coding_system; |
---|
657 | setup_coding_system |
---|
658 | (Fcheck_coding_system (Vnext_selection_coding_system), &coding); |
---|
659 | coding.src_multibyte = 0; |
---|
660 | coding.dst_multibyte = 1; |
---|
661 | Vnext_selection_coding_system = Qnil; |
---|
662 | coding.mode |= CODING_MODE_LAST_BLOCK; |
---|
663 | truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 1); |
---|
664 | bufsize = decoding_buffer_size (&coding, truelen); |
---|
665 | buf = (unsigned char *) xmalloc (bufsize); |
---|
666 | decode_coding (&coding, htext, buf, truelen, bufsize); |
---|
667 | ret = make_string_from_bytes ((char *) buf, |
---|
668 | coding.produced_char, coding.produced); |
---|
669 | xfree (buf); |
---|
670 | Vlast_coding_system_used = coding.symbol; |
---|
671 | } |
---|
672 | else |
---|
673 | { |
---|
674 | ret = make_unibyte_string ((char *) htext, truelen); |
---|
675 | Vlast_coding_system_used = Qraw_text; |
---|
676 | } |
---|
677 | |
---|
678 | xfree (htext); |
---|
679 | |
---|
680 | closeclip: |
---|
681 | close_clipboard (); |
---|
682 | |
---|
683 | unblock: |
---|
684 | UNBLOCK_INPUT; |
---|
685 | |
---|
686 | done: |
---|
687 | |
---|
688 | return (ret); |
---|
689 | } |
---|
690 | |
---|
691 | /* Support checking for a clipboard selection. */ |
---|
692 | |
---|
693 | DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, |
---|
694 | 0, 1, 0, |
---|
695 | "Whether there is an owner for the given X Selection.\n\ |
---|
696 | The arg should be the name of the selection in question, typically one of\n\ |
---|
697 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ |
---|
698 | \(Those are literal upper-case symbol names, since that's what X expects.)\n\ |
---|
699 | For convenience, the symbol nil is the same as `PRIMARY',\n\ |
---|
700 | and t is the same as `SECONDARY'.") |
---|
701 | (selection) |
---|
702 | Lisp_Object selection; |
---|
703 | { |
---|
704 | CHECK_SYMBOL (selection, 0); |
---|
705 | |
---|
706 | /* Return nil for SECONDARY selection. For PRIMARY (or nil) |
---|
707 | selection, check if there is some text on the kill-ring; |
---|
708 | for CLIPBOARD, check if the clipboard currently has valid |
---|
709 | text format contents. |
---|
710 | |
---|
711 | The test for killed text on the kill-ring emulates the Emacs |
---|
712 | behavior on X, where killed text is also put into X selection |
---|
713 | by the X interface code. (On MSDOS, killed text is only put |
---|
714 | into the clipboard if we run under Windows, so we cannot check |
---|
715 | the clipboard alone.) */ |
---|
716 | if ((EQ (selection, Qnil) || EQ (selection, QPRIMARY)) |
---|
717 | && ! NILP (XSYMBOL (Fintern_soft (build_string ("kill-ring"), |
---|
718 | Qnil))->value)) |
---|
719 | return Qt; |
---|
720 | |
---|
721 | if (EQ (selection, QCLIPBOARD)) |
---|
722 | { |
---|
723 | Lisp_Object val = Qnil; |
---|
724 | |
---|
725 | if (open_clipboard ()) |
---|
726 | { |
---|
727 | if (get_clipboard_data_size (CF_OEMTEXT)) |
---|
728 | val = Qt; |
---|
729 | close_clipboard (); |
---|
730 | } |
---|
731 | return val; |
---|
732 | } |
---|
733 | return Qnil; |
---|
734 | } |
---|
735 | |
---|
736 | void |
---|
737 | syms_of_win16select () |
---|
738 | { |
---|
739 | defsubr (&Sw16_set_clipboard_data); |
---|
740 | defsubr (&Sw16_get_clipboard_data); |
---|
741 | defsubr (&Sx_selection_exists_p); |
---|
742 | |
---|
743 | DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, |
---|
744 | "Coding system for communicating with other X clients.\n\ |
---|
745 | When sending or receiving text via cut_buffer, selection, and clipboard,\n\ |
---|
746 | the text is encoded or decoded by this coding system.\n\ |
---|
747 | A default value is `iso-latin-1-dos'"); |
---|
748 | Vselection_coding_system=intern ("iso-latin-1-dos"); |
---|
749 | |
---|
750 | DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, |
---|
751 | "Coding system for the next communication with other X clients.\n\ |
---|
752 | Usually, `selection-coding-system' is used for communicating with\n\ |
---|
753 | other X clients. But, if this variable is set, it is used for the\n\ |
---|
754 | next communication only. After the communication, this variable is\n\ |
---|
755 | set to nil."); |
---|
756 | Vnext_selection_coding_system = Qnil; |
---|
757 | |
---|
758 | QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY); |
---|
759 | QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD); |
---|
760 | } |
---|
761 | |
---|
762 | #endif /* MSDOS */ |
---|