1 /* 16-bit Windows 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 /* Don't even try to allocate more than 1MB of memory: DOS cannot
173 possibly handle that (it will overflow the BX register below). */
174 if (want_size
> 0xfffff)
177 /* Need size rounded up to the nearest paragraph, and in
178 paragraph units (1 paragraph = 16 bytes). */
179 clipboard_xfer_buf_info
.size
= (want_size
+ 15) >> 4;
181 /* The NT DPMI host crashes us if we free DOS memory via the
182 DPMI service. Work around by calling DOS allocate/free block. */
184 regs
.x
.bx
= clipboard_xfer_buf_info
.size
;
185 __dpmi_int (0x21, ®s
);
186 if (regs
.x
.flags
& 1)
188 clipboard_xfer_buf_info
.size
= 0;
192 clipboard_xfer_buf_info
.rm_segment
= regs
.x
.ax
;
193 return (((int)clipboard_xfer_buf_info
.rm_segment
) << 4) & 0xfffff;
196 /* Free our clipboard buffer. We always free it after use, because
197 keeping it leaves less free conventional memory for subprocesses.
198 The clipboard buffer tends to be large in size, because for small
199 clipboard data sizes we use the DJGPP transfer buffer. */
203 /* If the size is 0, we used DJGPP transfer buffer, so don't free. */
204 if (clipboard_xfer_buf_info
.size
)
208 /* The NT DPMI host crashes us if we free DOS memory via
209 the DPMI service. Work around by calling DOS free block. */
211 regs
.x
.es
= clipboard_xfer_buf_info
.rm_segment
;
212 __dpmi_int (0x21, ®s
);
213 clipboard_xfer_buf_info
.size
= 0;
217 /* Copy data into the clipboard, return non-zero if successfull. */
219 set_clipboard_data (Format
, Data
, Size
)
226 unsigned long xbuf_addr
, buf_offset
;
227 unsigned char *dp
= Data
, *dstart
= dp
;
229 if (Format
!= CF_TEXT
)
232 /* need to know final size after '\r' chars are inserted (the
233 standard CF_TEXT clipboard format uses CRLF line endings,
234 while Emacs uses just LF internally). */
236 /* avoid using strchr because it recomputes the length everytime */
237 while ((dp
= memchr (dp
, '\n', Size
- (dp
- dstart
))) != 0)
243 if (clipboard_compact (truelen
) < truelen
)
246 if ((xbuf_addr
= alloc_xfer_buf (truelen
)) == 0)
249 /* Move the buffer into the low memory, convert LF into CR-LF pairs. */
251 buf_offset
= xbuf_addr
;
252 _farsetsel (_dos_ds
);
256 _farnspokeb (buf_offset
++, '\r');
257 _farnspokeb (buf_offset
++, *dp
++);
260 /* Calls Int 2Fh/AX=1703h with:
261 DX = WinOldAp-Supported Clipboard format
262 ES:BX = Pointer to data
263 SI:CX = Size of data in bytes
264 Return Values AX == 0: Error occurred
265 <> 0: OK. Data copied into the Clipboard. */
268 regs
.x
.si
= truelen
>> 16;
269 regs
.x
.cx
= truelen
& 0xffff;
270 regs
.x
.es
= xbuf_addr
>> 4;
271 regs
.x
.bx
= xbuf_addr
& 15;
272 __dpmi_int(0x2f, ®s
);
279 /* Return the size of the clipboard data of format FORMAT. */
281 get_clipboard_data_size (Format
)
286 /* Calls Int 2Fh/AX=1704h with:
287 DX = WinOldAp-Supported Clipboard format
288 Return Values DX:AX == Size of the data in bytes, including any
290 == 0 If data in this format is not in
294 __dpmi_int(0x2f, ®s
);
295 return ( (((unsigned)regs
.x
.dx
) << 16) | regs
.x
.ax
);
298 /* Get clipboard data, return its length.
299 Warning: this doesn't check whether DATA has enough space to hold
302 get_clipboard_data (Format
, Data
, Size
)
308 unsigned datalen
= 0;
309 unsigned long xbuf_addr
;
310 unsigned char *dp
= Data
;
312 if (Format
!= CF_TEXT
)
318 if ((xbuf_addr
= alloc_xfer_buf (Size
)) == 0)
321 /* Calls Int 2Fh/AX=1705h with:
322 DX = WinOldAp-Supported Clipboard format
323 ES:BX = Pointer to data buffer to hold data
324 Return Values AX == 0: Error occurred (or data in this format is not
329 regs
.x
.es
= xbuf_addr
>> 4;
330 regs
.x
.bx
= xbuf_addr
& 15;
331 __dpmi_int(0x2f, ®s
);
334 /* Copy data from low memory, remove CR characters if before LF. */
335 _farsetsel (_dos_ds
);
338 register unsigned char c
= _farnspeekb (xbuf_addr
++);
340 if ((*dp
++ = c
) == '\r' && _farnspeekb (xbuf_addr
) == '\n')
346 /* Windows reportedly rounds up the size of clipboard data
347 (passed in SIZE) to a multiple of 32. We therefore bail
348 out when we see the first null character. */
351 datalen
= dp
- (unsigned char *)Data
- 1;
362 /* Close clipboard, return non-zero if successfull. */
368 /* Calls Int 2Fh/AX=1708h
369 Return Values AX == 0: Error occurred
372 __dpmi_int(0x2f, ®s
);
376 /* Compact clipboard data so that at least SIZE bytes is available. */
378 clipboard_compact (Size
)
383 /* Calls Int 2Fh/AX=1709H with:
384 SI:CX = Desired memory size in bytes.
385 Return Values DX:AX == Number of bytes of largest block of free memory.
386 == 0 if error or no memory */
388 regs
.x
.si
= Size
>> 16;
389 regs
.x
.cx
= Size
& 0xffff;
390 __dpmi_int(0x2f, ®s
);
391 return ((unsigned)regs
.x
.dx
<< 16) | regs
.x
.ax
;
394 static char no_mem_msg
[] =
395 "(Not enough DOS memory to put saved text into clipboard.)";
397 DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data
, Sw16_set_clipboard_data
, 1, 2, 0,
398 "This sets the clipboard data to the given text.")
400 Lisp_Object string
, frame
;
406 CHECK_STRING (string
, 0);
409 frame
= Fselected_frame ();
411 CHECK_LIVE_FRAME (frame
, 0);
412 if ( !FRAME_MSDOS_P (XFRAME (frame
)))
417 nbytes
= XSTRING (string
)->size
+ 1;
418 src
= XSTRING (string
)->data
;
420 if (!open_clipboard ())
423 ok
= empty_clipboard () && (ok1
= set_clipboard_data (CF_TEXT
, src
, nbytes
));
427 if (ok
) goto unblock
;
436 /* Notify user if the text is too large to fit into DOS memory.
437 (This will happen somewhere after 600K bytes (470K in DJGPP v1.x),
438 depending on user system configuration.) If we just silently
439 fail the function, people might wonder why their text sometimes
440 doesn't make it to the clipboard. */
443 message2 (no_mem_msg
, sizeof (no_mem_msg
) - 1, 0);
444 sit_for (2, 0, 0, 1, 1);
449 return (ok
? string
: Qnil
);
452 DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data
, Sw16_get_clipboard_data
, 0, 1, 0,
453 "This gets the clipboard data in text format.")
457 unsigned data_size
, truelen
;
458 unsigned char *htext
;
459 Lisp_Object ret
= Qnil
;
462 CHECK_LIVE_FRAME (frame
, 0);
465 frame
= Fselected_frame ();
467 CHECK_LIVE_FRAME (frame
, 0);
468 if ( !FRAME_MSDOS_P (XFRAME (frame
)))
473 if (!open_clipboard ())
476 if ((data_size
= get_clipboard_data_size (CF_TEXT
)) == 0 ||
477 (htext
= (unsigned char *)xmalloc (data_size
)) == 0)
480 /* need to know final size after '\r' chars are removed because
481 we can't change the string size manually, and doing an extra
483 if ((truelen
= get_clipboard_data (CF_TEXT
, htext
, data_size
)) == 0)
486 ret
= make_string (htext
, truelen
);
500 /* Support checking for a clipboard selection. */
502 DEFUN ("x-selection-exists-p", Fx_selection_exists_p
, Sx_selection_exists_p
,
504 "Whether there is an owner for the given X Selection.\n\
505 The arg should be the name of the selection in question, typically one of\n\
506 the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
507 \(Those are literal upper-case symbol names, since that's what X expects.)\n\
508 For convenience, the symbol nil is the same as `PRIMARY',\n\
509 and t is the same as `SECONDARY'.")
511 Lisp_Object selection
;
513 CHECK_SYMBOL (selection
, 0);
515 /* Return nil for SECONDARY selection. For PRIMARY (or nil)
516 selection, check if there is some text on the kill-ring;
517 for CLIPBOARD, check if the clipboard currently has valid
518 text format contents.
520 The test for killed text on the kill-ring emulates the Emacs
521 behavior on X, where killed text is also put into X selection
522 by the X interface code. (On MSDOS, killed text is only put
523 into the clipboard if we run under Windows, so we cannot check
524 the clipboard alone.) */
525 if ((EQ (selection
, Qnil
) || EQ (selection
, QPRIMARY
))
526 && ! NILP (XSYMBOL (Fintern_soft (build_string ("kill-ring"),
530 if (EQ (selection
, QCLIPBOARD
))
532 Lisp_Object val
= Qnil
;
534 if (open_clipboard ())
536 if (get_clipboard_data_size (CF_TEXT
))
546 syms_of_win16select ()
548 defsubr (&Sw16_set_clipboard_data
);
549 defsubr (&Sw16_get_clipboard_data
);
550 defsubr (&Sx_selection_exists_p
);
552 QPRIMARY
= intern ("PRIMARY"); staticpro (&QPRIMARY
);
553 QCLIPBOARD
= intern ("CLIPBOARD"); staticpro (&QCLIPBOARD
);