1 /* Win16 Selection processing for emacs on MS-Windows
2 Copyright (C) 1996, 1997 Free Software Foundation.
4 This file is part of GNU Emacs.
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)
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.
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. */
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. */
26 /* Written by Dale P. Smith <dpsm@en.com> */
27 /* Adapted to DJGPP v1 by Eli Zaretskii <eliz@is.elta.co.il> */
35 #include <sys/farptr.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"
41 /* If ever some function outside this file will need to call any
42 clipboard-related function, the following prototypes and constants
43 should be put on a header file. Right now, nobody else uses them. */
46 #define CF_BITMAP 0x02
47 #define CF_METAFILE 0x03
51 #define CF_OEMTEXT 0x07
52 #define CF_DIBBITMAP 0x08
53 #define CF_WINWRITE 0x80
54 #define CF_DSPTEXT 0x81
55 #define CF_DSPBITMAP 0x82
57 unsigned identify_winoldap_version (void);
58 unsigned open_clipboard (void);
59 unsigned empty_clipboard (void);
60 unsigned set_clipboard_data (unsigned, void *, unsigned);
61 unsigned get_clipboard_data_size (unsigned);
62 unsigned get_clipboard_data (unsigned, void *, unsigned);
63 unsigned close_clipboard (void);
64 unsigned clipboard_compact (unsigned);
66 Lisp_Object QCLIPBOARD
, QPRIMARY
;
68 /* The segment address and the size of the buffer in low
69 memory used to move data between us and WinOldAp module. */
73 unsigned short rm_segment
;
74 } clipboard_xfer_buf_info
;
76 /* Emulation of `__dpmi_int' and friends for DJGPP v1.x */
80 typedef _go32_dpmi_registers __dpmi_regs
;
81 #define __tb _go32_info_block.linear_address_of_transfer_buffer
82 #define _dos_ds _go32_info_block.selector_for_linear_memory
85 __dpmi_int (intno
, regs
)
89 regs
->x
.ss
= regs
->x
.sp
= regs
->x
.flags
= 0;
90 return _go32_dpmi_simulate_int (intno
, regs
);
93 #endif /* __DJGPP__ < 2 */
95 /* C functions to access the Windows 3.1x clipboard from DOS apps.
97 The information was obtained from the Microsoft Knowledge Base,
98 article Q67675 and can be found at:
99 http://www.microsoft.com/kb/developr/win_dk/q67675.htm */
101 /* See also Ralf Brown's Interrupt List.
103 I also seem to remember reading about this in Dr. Dobbs Journal a
104 while ago, but if you knew my memory... :-)
106 Dale P. Smith <dpsm@en.com> */
108 /* Return the WinOldAp support version, or 0x1700 if not supported. */
110 identify_winoldap_version ()
114 /* Calls Int 2Fh/AX=1700h
115 Return Values AX == 1700H: Clipboard functions not available
116 <> 1700H: AL = Major version number
117 AH = Minor version number */
119 __dpmi_int(0x2f, ®s
);
123 /* Open the clipboard, return non-zero if successfull. */
129 /* Is WINOLDAP supported? */
130 /* Kludge alert!! If WinOldAp is not supported, we return a 0,
131 which is the same as ``Clipboard already open''. Currently,
132 this is taken as an error by all the functions that use
133 `open_clipboard', but if somebody someday will use that ``open''
134 clipboard, they will have interesting time debugging it... */
135 if (identify_winoldap_version () == 0x1700)
138 /* Calls Int 2Fh/AX=1701h
139 Return Values AX == 0: Clipboard already open
140 <> 0: Clipboard opened */
142 __dpmi_int(0x2f, ®s
);
146 /* Empty clipboard, return non-zero if successfull. */
152 /* Calls Int 2Fh/AX=1702h
153 Return Values AX == 0: Error occurred
154 <> 0: OK, Clipboard emptied */
156 __dpmi_int(0x2f, ®s
);
160 /* Ensure we have a buffer in low memory with enough memory for data
161 of size WANT_SIZE. Return the linear address of the buffer. */
163 alloc_xfer_buf (want_size
)
168 /* If the usual DJGPP transfer buffer is large enough, use that. */
169 if (want_size
<= _go32_info_block
.size_of_transfer_buffer
)
170 return __tb
& 0xfffff;
172 /* Need size rounded up to the nearest paragraph, and in
173 paragraph units (1 paragraph = 16 bytes). */
174 clipboard_xfer_buf_info
.size
= (want_size
+ 15) >> 4;
176 /* The NT DPMI host crashes us if we free DOS memory via the
177 DPMI service. Work around by calling DOS allocate/free block. */
179 regs
.x
.bx
= clipboard_xfer_buf_info
.size
;
180 __dpmi_int (0x21, ®s
);
181 if (regs
.x
.flags
& 1)
183 clipboard_xfer_buf_info
.size
= 0;
187 clipboard_xfer_buf_info
.rm_segment
= regs
.x
.ax
;
188 return (((int)clipboard_xfer_buf_info
.rm_segment
) << 4) & 0xfffff;
191 /* Free our clipboard buffer. We always free it after use, because
192 keeping it leaves less free conventional memory for subprocesses.
193 The clipboard buffer tends to be large in size, because for small
194 clipboard data sizes we use the DJGPP transfer buffer. */
198 /* If the size is 0, we used DJGPP transfer buffer, so don't free. */
199 if (clipboard_xfer_buf_info
.size
)
203 /* The NT DPMI host crashes us if we free DOS memory via
204 the DPMI service. Work around by calling DOS free block. */
206 regs
.x
.es
= clipboard_xfer_buf_info
.rm_segment
;
207 __dpmi_int (0x21, ®s
);
208 clipboard_xfer_buf_info
.size
= 0;
212 /* Copy data into the clipboard, return non-zero if successfull. */
214 set_clipboard_data (Format
, Data
, Size
)
221 unsigned long xbuf_addr
, buf_offset
;
222 unsigned char *dp
= Data
, *dstart
= dp
;
224 if (Format
!= CF_TEXT
)
227 /* need to know final size after '\r' chars are inserted (the
228 standard CF_TEXT clipboard format uses CRLF line endings,
229 while Emacs uses just LF internally). */
231 /* avoid using strchr because it recomputes the length everytime */
232 while ((dp
= memchr (dp
, '\n', Size
- (dp
- dstart
))) != 0)
238 if (clipboard_compact (truelen
) < truelen
)
241 if ((xbuf_addr
= alloc_xfer_buf (truelen
)) == 0)
244 /* Move the buffer into the low memory, convert LF into CR-LF pairs. */
246 buf_offset
= xbuf_addr
;
247 _farsetsel (_dos_ds
);
251 _farnspokeb (buf_offset
++, '\r');
252 _farnspokeb (buf_offset
++, *dp
++);
255 /* Calls Int 2Fh/AX=1703h with:
256 DX = WinOldAp-Supported Clipboard format
257 ES:BX = Pointer to data
258 SI:CX = Size of data in bytes
259 Return Values AX == 0: Error occurred
260 <> 0: OK. Data copied into the Clipboard. */
263 regs
.x
.si
= truelen
>> 16;
264 regs
.x
.cx
= truelen
& 0xffff;
265 regs
.x
.es
= xbuf_addr
>> 4;
266 regs
.x
.bx
= xbuf_addr
& 15;
267 __dpmi_int(0x2f, ®s
);
274 /* Return the size of the clipboard data of format FORMAT. */
276 get_clipboard_data_size (Format
)
281 /* Calls Int 2Fh/AX=1704h with:
282 DX = WinOldAp-Supported Clipboard format
283 Return Values DX:AX == Size of the data in bytes, including any
285 == 0 If data in this format is not in
289 __dpmi_int(0x2f, ®s
);
290 return ( (((unsigned)regs
.x
.dx
) << 16) | regs
.x
.ax
);
293 /* Get clipboard data, return its length.
294 Warning: this doesn't check whether DATA has enough space to hold
297 get_clipboard_data (Format
, Data
, Size
)
303 unsigned datalen
= 0;
304 unsigned long xbuf_addr
;
305 unsigned char *dp
= Data
;
307 if (Format
!= CF_TEXT
)
313 if ((xbuf_addr
= alloc_xfer_buf (Size
)) == 0)
316 /* Calls Int 2Fh/AX=1705h with:
317 DX = WinOldAp-Supported Clipboard format
318 ES:BX = Pointer to data buffer to hold data
319 Return Values AX == 0: Error occurred (or data in this format is not
324 regs
.x
.es
= xbuf_addr
>> 4;
325 regs
.x
.bx
= xbuf_addr
& 15;
326 __dpmi_int(0x2f, ®s
);
329 /* Copy data from low memory, remove CR characters if before LF. */
330 _farsetsel (_dos_ds
);
333 register unsigned char c
= _farnspeekb (xbuf_addr
++);
335 if ((*dp
++ = c
) == '\r' && _farnspeekb (xbuf_addr
) == '\n')
341 /* Windows reportedly rounds up the size of clipboard data
342 (passed in SIZE) to a multiple of 32. We therefore bail
343 out when we see the first null character. */
346 datalen
= dp
- (unsigned char *)Data
- 1;
357 /* Close clipboard, return non-zero if successfull. */
363 /* Calls Int 2Fh/AX=1708h
364 Return Values AX == 0: Error occurred
367 __dpmi_int(0x2f, ®s
);
371 /* Compact clipboard data so that at least SIZE bytes is available. */
373 clipboard_compact (Size
)
378 /* Calls Int 2Fh/AX=1709H with:
379 SI:CX = Desired memory size in bytes.
380 Return Values DX:AX == Number of bytes of largest block of free memory.
381 == 0 if error or no memory */
383 regs
.x
.si
= Size
>> 16;
384 regs
.x
.cx
= Size
& 0xffff;
385 __dpmi_int(0x2f, ®s
);
386 return ((unsigned)regs
.x
.dx
<< 16) | regs
.x
.ax
;
389 static char no_mem_msg
[] =
390 "(Not enough DOS memory to put saved text into clipboard.)";
392 DEFUN ("win16-set-clipboard-data", Fwin16_set_clipboard_data
, Swin16_set_clipboard_data
, 1, 2, 0,
393 "This sets the clipboard data to the given text.")
395 Lisp_Object string
, frame
;
401 CHECK_STRING (string
, 0);
404 frame
= Fselected_frame ();
406 CHECK_LIVE_FRAME (frame
, 0);
407 if ( !FRAME_MSDOS_P (XFRAME (frame
)))
412 nbytes
= XSTRING (string
)->size
+ 1;
413 src
= XSTRING (string
)->data
;
415 if (!open_clipboard ())
418 ok
= empty_clipboard () && (ok1
= set_clipboard_data (CF_TEXT
, src
, nbytes
));
428 /* Notify user if the text is too large to fit into DOS memory.
429 (This will happen somewhere after 600K bytes (470K in DJGPP v1.x),
430 depending on user system configuration.) If we just silently
431 fail the function, people might wonder why their text sometimes
432 doesn't make it to the clipboard. */
435 message2 (no_mem_msg
, sizeof (no_mem_msg
) - 1);
436 sit_for (2, 0, 0, 1);
442 return (ok
? string
: Qnil
);
445 DEFUN ("win16-get-clipboard-data", Fwin16_get_clipboard_data
, Swin16_get_clipboard_data
, 0, 1, 0,
446 "This gets the clipboard data in text format.")
450 unsigned data_size
, truelen
;
451 unsigned char *htext
;
452 Lisp_Object ret
= Qnil
;
455 CHECK_LIVE_FRAME (frame
, 0);
458 frame
= Fselected_frame ();
460 CHECK_LIVE_FRAME (frame
, 0);
461 if ( !FRAME_MSDOS_P (XFRAME (frame
)))
466 if (!open_clipboard ())
469 if ((data_size
= get_clipboard_data_size (CF_TEXT
)) == 0 ||
470 (htext
= (unsigned char *)xmalloc (data_size
)) == 0)
473 /* need to know final size after '\r' chars are removed because
474 we can't change the string size manually, and doing an extra
476 if ((truelen
= get_clipboard_data (CF_TEXT
, htext
, data_size
)) == 0)
479 ret
= make_string (htext
, truelen
);
491 /* Support checking for a clipboard selection. */
493 DEFUN ("x-selection-exists-p", Fx_selection_exists_p
, Sx_selection_exists_p
,
495 "Whether there is an owner for the given X Selection.\n\
496 The arg should be the name of the selection in question, typically one of\n\
497 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
498 \(Those are literal upper-case symbol names, since that's what X expects.)\n\
499 For convenience, the symbol nil is the same as `PRIMARY',\n\
500 and t is the same as `SECONDARY'.")
502 Lisp_Object selection
;
504 CHECK_SYMBOL (selection
, 0);
506 /* Return nil for SECONDARY selection. For PRIMARY (or nil)
507 selection, check if there is some text on the kill-ring;
508 for CLIPBOARD, check if the clipboard currently has valid
509 text format contents.
511 The test for killed text on the kill-ring emulates the Emacs
512 behavior on X, where killed text is also put into X selection
513 by the X interface code. (On MSDOS, killed text is only put
514 into the clipboard if we run under Windows, so we cannot check
515 the clipboard alone.) */
516 if ((EQ (selection
, Qnil
) || EQ (selection
, QPRIMARY
))
517 && ! NILP (XSYMBOL (Fintern_soft (build_string ("kill-ring"),
521 if (EQ (selection
, QCLIPBOARD
))
523 Lisp_Object val
= Qnil
;
525 if (open_clipboard ())
527 if (get_clipboard_data_size (CF_TEXT
))
537 syms_of_win16select ()
539 defsubr (&Swin16_set_clipboard_data
);
540 defsubr (&Swin16_get_clipboard_data
);
541 defsubr (&Sx_selection_exists_p
);
543 QPRIMARY
= intern ("PRIMARY"); staticpro (&QPRIMARY
);
544 QCLIPBOARD
= intern ("CLIPBOARD"); staticpro (&QCLIPBOARD
);