(main): Use Vbuffer_alist instead of Fbuffer_list.
[bpt/emacs.git] / src / w16select.c
CommitLineData
767079a8 1/* 16-bit Windows Selection processing for emacs on MS-Windows
21cfcccf
EZ
2 Copyright (C) 1996, 1997 Free Software Foundation.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, 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
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. */
44
45#define CF_TEXT 0x01
46#define CF_BITMAP 0x02
47#define CF_METAFILE 0x03
48#define CF_SYLK 0x04
49#define CF_DIF 0x05
50#define CF_TIFF 0x06
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
56
57unsigned identify_winoldap_version (void);
58unsigned open_clipboard (void);
59unsigned empty_clipboard (void);
60unsigned set_clipboard_data (unsigned, void *, unsigned);
61unsigned get_clipboard_data_size (unsigned);
62unsigned get_clipboard_data (unsigned, void *, unsigned);
63unsigned close_clipboard (void);
64unsigned clipboard_compact (unsigned);
65
66Lisp_Object QCLIPBOARD, QPRIMARY;
67
68/* The segment address and the size of the buffer in low
69 memory used to move data between us and WinOldAp module. */
70
71static struct {
72 unsigned long size;
73 unsigned short rm_segment;
74} clipboard_xfer_buf_info;
75\f
76/* Emulation of `__dpmi_int' and friends for DJGPP v1.x */
77
78#if __DJGPP__ < 2
79
80typedef _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
83
84static int
85__dpmi_int (intno, regs)
86 int intno;
87 __dpmi_regs *regs;
88{
89 regs->x.ss = regs->x.sp = regs->x.flags = 0;
90 return _go32_dpmi_simulate_int (intno, regs);
91}
92
93#endif /* __DJGPP__ < 2 */
94\f
95/* C functions to access the Windows 3.1x clipboard from DOS apps.
96
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 */
100
101/* See also Ralf Brown's Interrupt List.
102
103 I also seem to remember reading about this in Dr. Dobbs Journal a
104 while ago, but if you knew my memory... :-)
105
106 Dale P. Smith <dpsm@en.com> */
107
108/* Return the WinOldAp support version, or 0x1700 if not supported. */
109unsigned
110identify_winoldap_version ()
111{
112 __dpmi_regs regs;
113
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 */
118 regs.x.ax = 0x1700;
119 __dpmi_int(0x2f, &regs);
120 return regs.x.ax;
121}
122
123/* Open the clipboard, return non-zero if successfull. */
124unsigned
125open_clipboard ()
126{
127 __dpmi_regs regs;
128
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)
136 return 0;
137
138 /* Calls Int 2Fh/AX=1701h
139 Return Values AX == 0: Clipboard already open
140 <> 0: Clipboard opened */
141 regs.x.ax = 0x1701;
142 __dpmi_int(0x2f, &regs);
143 return regs.x.ax;
144}
145
146/* Empty clipboard, return non-zero if successfull. */
147unsigned
148empty_clipboard ()
149{
150 __dpmi_regs regs;
151
152 /* Calls Int 2Fh/AX=1702h
153 Return Values AX == 0: Error occurred
154 <> 0: OK, Clipboard emptied */
155 regs.x.ax = 0x1702;
156 __dpmi_int(0x2f, &regs);
157 return regs.x.ax;
158}
159
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. */
162static unsigned long
163alloc_xfer_buf (want_size)
164 unsigned want_size;
165{
166 __dpmi_regs regs;
167
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;
171
767079a8
EZ
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)
175 return 0;
176
21cfcccf
EZ
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;
180
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. */
183 regs.h.ah = 0x48;
184 regs.x.bx = clipboard_xfer_buf_info.size;
185 __dpmi_int (0x21, &regs);
186 if (regs.x.flags & 1)
187 {
188 clipboard_xfer_buf_info.size = 0;
189 return 0;
190 }
191
192 clipboard_xfer_buf_info.rm_segment = regs.x.ax;
193 return (((int)clipboard_xfer_buf_info.rm_segment) << 4) & 0xfffff;
194}
195
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. */
200static void
201free_xfer_buf ()
202{
203 /* If the size is 0, we used DJGPP transfer buffer, so don't free. */
204 if (clipboard_xfer_buf_info.size)
205 {
206 __dpmi_regs regs;
207
208 /* The NT DPMI host crashes us if we free DOS memory via
209 the DPMI service. Work around by calling DOS free block. */
210 regs.h.ah = 0x49;
211 regs.x.es = clipboard_xfer_buf_info.rm_segment;
212 __dpmi_int (0x21, &regs);
213 clipboard_xfer_buf_info.size = 0;
214 }
215}
216
217/* Copy data into the clipboard, return non-zero if successfull. */
218unsigned
219set_clipboard_data (Format, Data, Size)
220 unsigned Format;
221 void *Data;
222 unsigned Size;
223{
224 __dpmi_regs regs;
225 unsigned truelen;
226 unsigned long xbuf_addr, buf_offset;
227 unsigned char *dp = Data, *dstart = dp;
228
229 if (Format != CF_TEXT)
230 return 0;
231
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). */
235 truelen = Size;
236 /* avoid using strchr because it recomputes the length everytime */
237 while ((dp = memchr (dp, '\n', Size - (dp - dstart))) != 0)
238 {
239 truelen++;
240 dp++;
241 }
242
243 if (clipboard_compact (truelen) < truelen)
244 return 0;
245
246 if ((xbuf_addr = alloc_xfer_buf (truelen)) == 0)
247 return 0;
248
249 /* Move the buffer into the low memory, convert LF into CR-LF pairs. */
250 dp = Data;
251 buf_offset = xbuf_addr;
252 _farsetsel (_dos_ds);
253 while (Size--)
254 {
255 if (*dp == '\n')
256 _farnspokeb (buf_offset++, '\r');
257 _farnspokeb (buf_offset++, *dp++);
258 }
259
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. */
266 regs.x.ax = 0x1703;
267 regs.x.dx = Format;
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, &regs);
273
274 free_xfer_buf ();
275
276 return regs.x.ax;
277}
278
279/* Return the size of the clipboard data of format FORMAT. */
280unsigned
281get_clipboard_data_size (Format)
282 unsigned Format;
283{
284 __dpmi_regs regs;
285
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
289 headers.
290 == 0 If data in this format is not in
291 the clipboard. */
292 regs.x.ax = 0x1704;
293 regs.x.dx = Format;
294 __dpmi_int(0x2f, &regs);
295 return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax);
296}
297
298/* Get clipboard data, return its length.
299 Warning: this doesn't check whether DATA has enough space to hold
300 SIZE bytes. */
301unsigned
302get_clipboard_data (Format, Data, Size)
303 unsigned Format;
304 void *Data;
305 unsigned Size;
306{
307 __dpmi_regs regs;
308 unsigned datalen = 0;
309 unsigned long xbuf_addr;
310 unsigned char *dp = Data;
311
312 if (Format != CF_TEXT)
313 return 0;
314
315 if (Size == 0)
316 return 0;
317
318 if ((xbuf_addr = alloc_xfer_buf (Size)) == 0)
319 return 0;
320
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
325 in the clipboard)
326 <> 0: OK */
327 regs.x.ax = 0x1705;
328 regs.x.dx = Format;
329 regs.x.es = xbuf_addr >> 4;
330 regs.x.bx = xbuf_addr & 15;
331 __dpmi_int(0x2f, &regs);
332 if (regs.x.ax != 0)
333 {
334 /* Copy data from low memory, remove CR characters if before LF. */
335 _farsetsel (_dos_ds);
336 while (Size--)
337 {
338 register unsigned char c = _farnspeekb (xbuf_addr++);
339
340 if ((*dp++ = c) == '\r' && _farnspeekb (xbuf_addr) == '\n')
341 {
342 dp--;
343 *dp++ = '\n';
344 xbuf_addr++;
345 }
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. */
349 else if (c == '\0')
350 {
351 datalen = dp - (unsigned char *)Data - 1;
352 break;
353 }
354 }
355 }
356
357 free_xfer_buf ();
358
359 return datalen;
360}
361
362/* Close clipboard, return non-zero if successfull. */
363unsigned
364close_clipboard ()
365{
366 __dpmi_regs regs;
367
368 /* Calls Int 2Fh/AX=1708h
369 Return Values AX == 0: Error occurred
370 <> 0: OK */
371 regs.x.ax = 0x1708;
372 __dpmi_int(0x2f, &regs);
373 return regs.x.ax;
374}
375
376/* Compact clipboard data so that at least SIZE bytes is available. */
377unsigned
378clipboard_compact (Size)
379 unsigned Size;
380{
381 __dpmi_regs regs;
382
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 */
387 regs.x.ax = 0x1709;
388 regs.x.si = Size >> 16;
389 regs.x.cx = Size & 0xffff;
390 __dpmi_int(0x2f, &regs);
391 return ((unsigned)regs.x.dx << 16) | regs.x.ax;
392}
393\f
394static char no_mem_msg[] =
395 "(Not enough DOS memory to put saved text into clipboard.)";
396
767079a8 397DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_data, 1, 2, 0,
21cfcccf
EZ
398 "This sets the clipboard data to the given text.")
399 (string, frame)
400 Lisp_Object string, frame;
401{
402 int ok = 1, ok1 = 1;
403 int nbytes;
404 unsigned char *src;
405
406 CHECK_STRING (string, 0);
407
408 if (NILP (frame))
409 frame = Fselected_frame ();
410
411 CHECK_LIVE_FRAME (frame, 0);
412 if ( !FRAME_MSDOS_P (XFRAME (frame)))
413 goto done;
414
415 BLOCK_INPUT;
416
417 nbytes = XSTRING (string)->size + 1;
418 src = XSTRING (string)->data;
419
420 if (!open_clipboard ())
421 goto error;
422
423 ok = empty_clipboard () && (ok1 = set_clipboard_data (CF_TEXT, src, nbytes));
424
425 close_clipboard ();
426
31354c30 427 if (ok) goto unblock;
21cfcccf
EZ
428
429 error:
430
431 ok = 0;
432
31354c30
EZ
433 unblock:
434 UNBLOCK_INPUT;
435
21cfcccf
EZ
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. */
441 if (ok1 == 0)
442 {
a63f12f9 443 message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0);
ad66baa4 444 sit_for (2, 0, 0, 1, 1);
21cfcccf
EZ
445 }
446
447 done:
21cfcccf
EZ
448
449 return (ok ? string : Qnil);
450}
451
767079a8 452DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_data, 0, 1, 0,
21cfcccf
EZ
453 "This gets the clipboard data in text format.")
454 (frame)
455 Lisp_Object frame;
456{
457 unsigned data_size, truelen;
458 unsigned char *htext;
459 Lisp_Object ret = Qnil;
460
461 if (!NILP (frame))
462 CHECK_LIVE_FRAME (frame, 0);
463
464 if (NILP (frame))
465 frame = Fselected_frame ();
466
467 CHECK_LIVE_FRAME (frame, 0);
468 if ( !FRAME_MSDOS_P (XFRAME (frame)))
469 goto done;
470
471 BLOCK_INPUT;
472
473 if (!open_clipboard ())
31354c30 474 goto unblock;
21cfcccf
EZ
475
476 if ((data_size = get_clipboard_data_size (CF_TEXT)) == 0 ||
477 (htext = (unsigned char *)xmalloc (data_size)) == 0)
478 goto closeclip;
479
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
482 copy is silly */
483 if ((truelen = get_clipboard_data (CF_TEXT, htext, data_size)) == 0)
484 goto closeclip;
485
486 ret = make_string (htext, truelen);
487 xfree (htext);
488
489 closeclip:
490 close_clipboard ();
31354c30
EZ
491
492 unblock:
493 UNBLOCK_INPUT;
21cfcccf
EZ
494
495 done:
21cfcccf
EZ
496
497 return (ret);
498}
499
500/* Support checking for a clipboard selection. */
501
502DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
503 0, 1, 0,
504 "Whether there is an owner for the given X Selection.\n\
505The arg should be the name of the selection in question, typically one of\n\
506the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
507\(Those are literal upper-case symbol names, since that's what X expects.)\n\
508For convenience, the symbol nil is the same as `PRIMARY',\n\
509and t is the same as `SECONDARY'.")
510 (selection)
511 Lisp_Object selection;
512{
513 CHECK_SYMBOL (selection, 0);
514
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.
519
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"),
527 Qnil))->value))
528 return Qt;
529
530 if (EQ (selection, QCLIPBOARD))
531 {
532 Lisp_Object val = Qnil;
533
534 if (open_clipboard ())
535 {
536 if (get_clipboard_data_size (CF_TEXT))
537 val = Qt;
538 close_clipboard ();
539 }
540 return val;
541 }
542 return Qnil;
543}
544
545void
546syms_of_win16select ()
547{
767079a8
EZ
548 defsubr (&Sw16_set_clipboard_data);
549 defsubr (&Sw16_get_clipboard_data);
21cfcccf
EZ
550 defsubr (&Sx_selection_exists_p);
551
552 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
553 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
554}
555
556#endif /* MSDOS */