(tex-font-lock-keywords-2): Fontify \nocite like \cite.
[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"
583f5d53
EZ
40#include "buffer.h"
41#include "charset.h"
42#include "coding.h"
21cfcccf
EZ
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
60unsigned identify_winoldap_version (void);
61unsigned open_clipboard (void);
62unsigned empty_clipboard (void);
583f5d53 63unsigned set_clipboard_data (unsigned, void *, unsigned, int);
21cfcccf 64unsigned get_clipboard_data_size (unsigned);
583f5d53 65unsigned get_clipboard_data (unsigned, void *, unsigned, int);
21cfcccf
EZ
66unsigned close_clipboard (void);
67unsigned clipboard_compact (unsigned);
68
69Lisp_Object QCLIPBOARD, QPRIMARY;
70
583f5d53
EZ
71/* Coding system for communicating with other Windows programs via the
72 clipboard. */
199c7c44 73static Lisp_Object Vselection_coding_system;
583f5d53 74
21cfcccf
EZ
75/* The segment address and the size of the buffer in low
76 memory used to move data between us and WinOldAp module. */
77
78static struct {
79 unsigned long size;
80 unsigned short rm_segment;
81} clipboard_xfer_buf_info;
82\f
83/* Emulation of `__dpmi_int' and friends for DJGPP v1.x */
84
85#if __DJGPP__ < 2
86
87typedef _go32_dpmi_registers __dpmi_regs;
88#define __tb _go32_info_block.linear_address_of_transfer_buffer
89#define _dos_ds _go32_info_block.selector_for_linear_memory
90
91static int
92__dpmi_int (intno, regs)
93 int intno;
94 __dpmi_regs *regs;
95{
96 regs->x.ss = regs->x.sp = regs->x.flags = 0;
97 return _go32_dpmi_simulate_int (intno, regs);
98}
99
100#endif /* __DJGPP__ < 2 */
101\f
102/* C functions to access the Windows 3.1x clipboard from DOS apps.
103
104 The information was obtained from the Microsoft Knowledge Base,
105 article Q67675 and can be found at:
106 http://www.microsoft.com/kb/developr/win_dk/q67675.htm */
107
108/* See also Ralf Brown's Interrupt List.
109
110 I also seem to remember reading about this in Dr. Dobbs Journal a
111 while ago, but if you knew my memory... :-)
112
113 Dale P. Smith <dpsm@en.com> */
114
115/* Return the WinOldAp support version, or 0x1700 if not supported. */
116unsigned
117identify_winoldap_version ()
118{
119 __dpmi_regs regs;
120
121 /* Calls Int 2Fh/AX=1700h
122 Return Values AX == 1700H: Clipboard functions not available
123 <> 1700H: AL = Major version number
124 AH = Minor version number */
125 regs.x.ax = 0x1700;
126 __dpmi_int(0x2f, &regs);
127 return regs.x.ax;
128}
129
130/* Open the clipboard, return non-zero if successfull. */
131unsigned
132open_clipboard ()
133{
134 __dpmi_regs regs;
135
136 /* Is WINOLDAP supported? */
137 /* Kludge alert!! If WinOldAp is not supported, we return a 0,
138 which is the same as ``Clipboard already open''. Currently,
139 this is taken as an error by all the functions that use
140 `open_clipboard', but if somebody someday will use that ``open''
141 clipboard, they will have interesting time debugging it... */
142 if (identify_winoldap_version () == 0x1700)
143 return 0;
144
145 /* Calls Int 2Fh/AX=1701h
146 Return Values AX == 0: Clipboard already open
147 <> 0: Clipboard opened */
148 regs.x.ax = 0x1701;
149 __dpmi_int(0x2f, &regs);
150 return regs.x.ax;
151}
152
153/* Empty clipboard, return non-zero if successfull. */
154unsigned
155empty_clipboard ()
156{
157 __dpmi_regs regs;
158
159 /* Calls Int 2Fh/AX=1702h
160 Return Values AX == 0: Error occurred
161 <> 0: OK, Clipboard emptied */
162 regs.x.ax = 0x1702;
163 __dpmi_int(0x2f, &regs);
164 return regs.x.ax;
165}
166
167/* Ensure we have a buffer in low memory with enough memory for data
168 of size WANT_SIZE. Return the linear address of the buffer. */
169static unsigned long
170alloc_xfer_buf (want_size)
171 unsigned want_size;
172{
173 __dpmi_regs regs;
174
175 /* If the usual DJGPP transfer buffer is large enough, use that. */
176 if (want_size <= _go32_info_block.size_of_transfer_buffer)
177 return __tb & 0xfffff;
178
767079a8
EZ
179 /* Don't even try to allocate more than 1MB of memory: DOS cannot
180 possibly handle that (it will overflow the BX register below). */
181 if (want_size > 0xfffff)
182 return 0;
183
21cfcccf
EZ
184 /* Need size rounded up to the nearest paragraph, and in
185 paragraph units (1 paragraph = 16 bytes). */
186 clipboard_xfer_buf_info.size = (want_size + 15) >> 4;
187
188 /* The NT DPMI host crashes us if we free DOS memory via the
189 DPMI service. Work around by calling DOS allocate/free block. */
190 regs.h.ah = 0x48;
191 regs.x.bx = clipboard_xfer_buf_info.size;
192 __dpmi_int (0x21, &regs);
193 if (regs.x.flags & 1)
194 {
195 clipboard_xfer_buf_info.size = 0;
196 return 0;
197 }
198
199 clipboard_xfer_buf_info.rm_segment = regs.x.ax;
200 return (((int)clipboard_xfer_buf_info.rm_segment) << 4) & 0xfffff;
201}
202
203/* Free our clipboard buffer. We always free it after use, because
204 keeping it leaves less free conventional memory for subprocesses.
205 The clipboard buffer tends to be large in size, because for small
206 clipboard data sizes we use the DJGPP transfer buffer. */
207static void
208free_xfer_buf ()
209{
210 /* If the size is 0, we used DJGPP transfer buffer, so don't free. */
211 if (clipboard_xfer_buf_info.size)
212 {
213 __dpmi_regs regs;
214
215 /* The NT DPMI host crashes us if we free DOS memory via
216 the DPMI service. Work around by calling DOS free block. */
217 regs.h.ah = 0x49;
218 regs.x.es = clipboard_xfer_buf_info.rm_segment;
219 __dpmi_int (0x21, &regs);
220 clipboard_xfer_buf_info.size = 0;
221 }
222}
223
224/* Copy data into the clipboard, return non-zero if successfull. */
225unsigned
583f5d53 226set_clipboard_data (Format, Data, Size, Raw)
21cfcccf
EZ
227 unsigned Format;
228 void *Data;
229 unsigned Size;
583f5d53 230 int Raw;
21cfcccf
EZ
231{
232 __dpmi_regs regs;
233 unsigned truelen;
234 unsigned long xbuf_addr, buf_offset;
235 unsigned char *dp = Data, *dstart = dp;
236
538d05bb 237 if (Format != CF_OEMTEXT)
21cfcccf
EZ
238 return 0;
239
240 /* need to know final size after '\r' chars are inserted (the
538d05bb 241 standard CF_OEMTEXT clipboard format uses CRLF line endings,
21cfcccf
EZ
242 while Emacs uses just LF internally). */
243 truelen = Size;
583f5d53
EZ
244
245 if (!Raw)
21cfcccf 246 {
583f5d53
EZ
247 /* avoid using strchr because it recomputes the length everytime */
248 while ((dp = memchr (dp, '\n', Size - (dp - dstart))) != 0)
249 {
250 truelen++;
251 dp++;
252 }
21cfcccf
EZ
253 }
254
255 if (clipboard_compact (truelen) < truelen)
256 return 0;
257
258 if ((xbuf_addr = alloc_xfer_buf (truelen)) == 0)
259 return 0;
260
583f5d53
EZ
261 /* Move the buffer into the low memory, convert LF into CR-LF if needed. */
262 if (Raw)
263 dosmemput (Data, truelen, __tb);
264 else
21cfcccf 265 {
583f5d53
EZ
266 dp = Data;
267 buf_offset = xbuf_addr;
268 _farsetsel (_dos_ds);
269 while (Size--)
270 {
271 if (*dp == '\n')
272 _farnspokeb (buf_offset++, '\r');
273 _farnspokeb (buf_offset++, *dp++);
274 }
21cfcccf
EZ
275 }
276
277 /* Calls Int 2Fh/AX=1703h with:
278 DX = WinOldAp-Supported Clipboard format
279 ES:BX = Pointer to data
280 SI:CX = Size of data in bytes
281 Return Values AX == 0: Error occurred
282 <> 0: OK. Data copied into the Clipboard. */
283 regs.x.ax = 0x1703;
284 regs.x.dx = Format;
285 regs.x.si = truelen >> 16;
286 regs.x.cx = truelen & 0xffff;
287 regs.x.es = xbuf_addr >> 4;
288 regs.x.bx = xbuf_addr & 15;
289 __dpmi_int(0x2f, &regs);
290
291 free_xfer_buf ();
292
293 return regs.x.ax;
294}
295
296/* Return the size of the clipboard data of format FORMAT. */
297unsigned
298get_clipboard_data_size (Format)
299 unsigned Format;
300{
301 __dpmi_regs regs;
302
303 /* Calls Int 2Fh/AX=1704h with:
304 DX = WinOldAp-Supported Clipboard format
305 Return Values DX:AX == Size of the data in bytes, including any
306 headers.
307 == 0 If data in this format is not in
308 the clipboard. */
309 regs.x.ax = 0x1704;
310 regs.x.dx = Format;
311 __dpmi_int(0x2f, &regs);
312 return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax);
313}
314
315/* Get clipboard data, return its length.
316 Warning: this doesn't check whether DATA has enough space to hold
317 SIZE bytes. */
318unsigned
583f5d53 319get_clipboard_data (Format, Data, Size, Raw)
21cfcccf
EZ
320 unsigned Format;
321 void *Data;
322 unsigned Size;
583f5d53 323 int Raw;
21cfcccf
EZ
324{
325 __dpmi_regs regs;
326 unsigned datalen = 0;
327 unsigned long xbuf_addr;
328 unsigned char *dp = Data;
329
538d05bb 330 if (Format != CF_OEMTEXT)
21cfcccf
EZ
331 return 0;
332
333 if (Size == 0)
334 return 0;
335
336 if ((xbuf_addr = alloc_xfer_buf (Size)) == 0)
337 return 0;
338
339 /* Calls Int 2Fh/AX=1705h with:
340 DX = WinOldAp-Supported Clipboard format
341 ES:BX = Pointer to data buffer to hold data
342 Return Values AX == 0: Error occurred (or data in this format is not
343 in the clipboard)
344 <> 0: OK */
345 regs.x.ax = 0x1705;
346 regs.x.dx = Format;
347 regs.x.es = xbuf_addr >> 4;
348 regs.x.bx = xbuf_addr & 15;
349 __dpmi_int(0x2f, &regs);
350 if (regs.x.ax != 0)
351 {
583f5d53
EZ
352 /* Copy data from low memory, remove CR
353 characters before LF if needed. */
21cfcccf
EZ
354 _farsetsel (_dos_ds);
355 while (Size--)
356 {
357 register unsigned char c = _farnspeekb (xbuf_addr++);
358
583f5d53 359 if ((*dp++ = c) == '\r' && !Raw && _farnspeekb (xbuf_addr) == '\n')
21cfcccf
EZ
360 {
361 dp--;
362 *dp++ = '\n';
363 xbuf_addr++;
364 }
365 /* Windows reportedly rounds up the size of clipboard data
366 (passed in SIZE) to a multiple of 32. We therefore bail
367 out when we see the first null character. */
368 else if (c == '\0')
369 {
370 datalen = dp - (unsigned char *)Data - 1;
371 break;
372 }
373 }
374 }
375
376 free_xfer_buf ();
377
378 return datalen;
379}
380
381/* Close clipboard, return non-zero if successfull. */
382unsigned
383close_clipboard ()
384{
385 __dpmi_regs regs;
386
387 /* Calls Int 2Fh/AX=1708h
388 Return Values AX == 0: Error occurred
389 <> 0: OK */
390 regs.x.ax = 0x1708;
391 __dpmi_int(0x2f, &regs);
392 return regs.x.ax;
393}
394
395/* Compact clipboard data so that at least SIZE bytes is available. */
396unsigned
397clipboard_compact (Size)
398 unsigned Size;
399{
400 __dpmi_regs regs;
401
402 /* Calls Int 2Fh/AX=1709H with:
403 SI:CX = Desired memory size in bytes.
404 Return Values DX:AX == Number of bytes of largest block of free memory.
405 == 0 if error or no memory */
406 regs.x.ax = 0x1709;
407 regs.x.si = Size >> 16;
408 regs.x.cx = Size & 0xffff;
409 __dpmi_int(0x2f, &regs);
410 return ((unsigned)regs.x.dx << 16) | regs.x.ax;
411}
412\f
413static char no_mem_msg[] =
414 "(Not enough DOS memory to put saved text into clipboard.)";
415
767079a8 416DEFUN ("w16-set-clipboard-data", Fw16_set_clipboard_data, Sw16_set_clipboard_data, 1, 2, 0,
21cfcccf
EZ
417 "This sets the clipboard data to the given text.")
418 (string, frame)
419 Lisp_Object string, frame;
420{
421 int ok = 1, ok1 = 1;
422 int nbytes;
583f5d53
EZ
423 unsigned char *src, *dst = NULL;
424 int charsets[MAX_CHARSET + 1];
425 int num;
426 int no_crlf_conversion;
21cfcccf
EZ
427
428 CHECK_STRING (string, 0);
429
430 if (NILP (frame))
431 frame = Fselected_frame ();
432
433 CHECK_LIVE_FRAME (frame, 0);
434 if ( !FRAME_MSDOS_P (XFRAME (frame)))
435 goto done;
436
437 BLOCK_INPUT;
438
199c7c44 439 nbytes = STRING_BYTES (XSTRING (string));
21cfcccf 440 src = XSTRING (string)->data;
583f5d53
EZ
441
442 /* Since we are now handling multilingual text, we must consider
443 encoding text for the clipboard. */
444
445 bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
199c7c44 446 num = ((nbytes <= 1 /* Check the possibility of short cut. */
583f5d53
EZ
447 || NILP (buffer_defaults.enable_multibyte_characters))
448 ? 0
449 : find_charset_in_str (src, nbytes, charsets, Qnil, 1));
450
451 if (!num || (num == 1 && charsets[CHARSET_ASCII]))
452 {
453 /* No multibyte character in OBJ. We need not encode it, but we
454 will have to convert it to DOS CR-LF style. */
455 no_crlf_conversion = 0;
456 }
457 else
458 {
459 /* We must encode contents of STRING according to what
460 clipboard-coding-system specifies. */
461 int bufsize;
462 struct coding_system coding;
463 unsigned char *htext2;
464
465 setup_coding_system
199c7c44 466 (Fcheck_coding_system (Vselection_coding_system), &coding);
583f5d53
EZ
467 coding.mode |= CODING_MODE_LAST_BLOCK;
468 Vlast_coding_system_used = coding.symbol;
469 bufsize = encoding_buffer_size (&coding, nbytes);
470 dst = (unsigned char *) xmalloc (bufsize);
471 encode_coding (&coding, src, dst, nbytes, bufsize);
472 no_crlf_conversion = 1;
473 }
474
21cfcccf
EZ
475 if (!open_clipboard ())
476 goto error;
477
583f5d53 478 ok = empty_clipboard ()
538d05bb 479 && (ok1 = set_clipboard_data (CF_OEMTEXT, src, nbytes, no_crlf_conversion));
583f5d53
EZ
480
481 if (!no_crlf_conversion)
482 Vlast_coding_system_used = Qraw_text;
21cfcccf
EZ
483 close_clipboard ();
484
31354c30 485 if (ok) goto unblock;
21cfcccf
EZ
486
487 error:
488
489 ok = 0;
490
31354c30 491 unblock:
583f5d53
EZ
492 if (dst)
493 xfree (dst);
31354c30
EZ
494 UNBLOCK_INPUT;
495
21cfcccf
EZ
496 /* Notify user if the text is too large to fit into DOS memory.
497 (This will happen somewhere after 600K bytes (470K in DJGPP v1.x),
498 depending on user system configuration.) If we just silently
499 fail the function, people might wonder why their text sometimes
500 doesn't make it to the clipboard. */
501 if (ok1 == 0)
502 {
a63f12f9 503 message2 (no_mem_msg, sizeof (no_mem_msg) - 1, 0);
ad66baa4 504 sit_for (2, 0, 0, 1, 1);
21cfcccf
EZ
505 }
506
507 done:
21cfcccf
EZ
508
509 return (ok ? string : Qnil);
510}
511
767079a8 512DEFUN ("w16-get-clipboard-data", Fw16_get_clipboard_data, Sw16_get_clipboard_data, 0, 1, 0,
21cfcccf
EZ
513 "This gets the clipboard data in text format.")
514 (frame)
515 Lisp_Object frame;
516{
517 unsigned data_size, truelen;
518 unsigned char *htext;
519 Lisp_Object ret = Qnil;
583f5d53
EZ
520 int no_crlf_conversion;
521 int require_encoding = 0;
522
21cfcccf
EZ
523 if (NILP (frame))
524 frame = Fselected_frame ();
525
526 CHECK_LIVE_FRAME (frame, 0);
527 if ( !FRAME_MSDOS_P (XFRAME (frame)))
528 goto done;
529
530 BLOCK_INPUT;
531
532 if (!open_clipboard ())
31354c30 533 goto unblock;
21cfcccf 534
538d05bb 535 if ((data_size = get_clipboard_data_size (CF_OEMTEXT)) == 0 ||
21cfcccf
EZ
536 (htext = (unsigned char *)xmalloc (data_size)) == 0)
537 goto closeclip;
538
539 /* need to know final size after '\r' chars are removed because
540 we can't change the string size manually, and doing an extra
541 copy is silly */
538d05bb 542 if ((truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 0)) == 0)
21cfcccf
EZ
543 goto closeclip;
544
583f5d53
EZ
545 /* Do we need to decode it? */
546 if (! NILP (buffer_defaults.enable_multibyte_characters))
547 {
548 /* If the clipboard data contains any 8-bit Latin-1 code, we
549 need to decode it. */
550 int i;
551
552 for (i = 0; i < truelen; i++)
553 {
554 if (htext[i] >= 0x80)
555 {
556 require_encoding = 1;
557 break;
558 }
559 }
560 }
561 if (require_encoding)
562 {
563 int bufsize;
564 unsigned char *buf;
565 struct coding_system coding;
566
567 setup_coding_system
199c7c44 568 (Fcheck_coding_system (Vselection_coding_system), &coding);
583f5d53 569 coding.mode |= CODING_MODE_LAST_BLOCK;
538d05bb 570 truelen = get_clipboard_data (CF_OEMTEXT, htext, data_size, 1);
583f5d53
EZ
571 bufsize = decoding_buffer_size (&coding, truelen);
572 buf = (unsigned char *) xmalloc (bufsize);
573 decode_coding (&coding, htext, buf, truelen, bufsize);
574 truelen = (coding.fake_multibyte
575 ? multibyte_chars_in_text (buf, coding.produced)
576 : coding.produced_char);
577 ret = make_string_from_bytes ((char *) buf, truelen, coding.produced);
578 xfree (buf);
579 Vlast_coding_system_used = coding.symbol;
580 }
581 else
582 {
583 ret = make_unibyte_string ((char *) htext, truelen);
584 Vlast_coding_system_used = Qraw_text;
585 }
586
21cfcccf
EZ
587 xfree (htext);
588
589 closeclip:
590 close_clipboard ();
31354c30
EZ
591
592 unblock:
593 UNBLOCK_INPUT;
21cfcccf
EZ
594
595 done:
21cfcccf
EZ
596
597 return (ret);
598}
599
600/* Support checking for a clipboard selection. */
601
602DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
603 0, 1, 0,
604 "Whether there is an owner for the given X Selection.\n\
605The arg should be the name of the selection in question, typically one of\n\
606the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
607\(Those are literal upper-case symbol names, since that's what X expects.)\n\
608For convenience, the symbol nil is the same as `PRIMARY',\n\
609and t is the same as `SECONDARY'.")
610 (selection)
611 Lisp_Object selection;
612{
613 CHECK_SYMBOL (selection, 0);
614
615 /* Return nil for SECONDARY selection. For PRIMARY (or nil)
616 selection, check if there is some text on the kill-ring;
617 for CLIPBOARD, check if the clipboard currently has valid
618 text format contents.
619
620 The test for killed text on the kill-ring emulates the Emacs
621 behavior on X, where killed text is also put into X selection
622 by the X interface code. (On MSDOS, killed text is only put
623 into the clipboard if we run under Windows, so we cannot check
624 the clipboard alone.) */
625 if ((EQ (selection, Qnil) || EQ (selection, QPRIMARY))
626 && ! NILP (XSYMBOL (Fintern_soft (build_string ("kill-ring"),
627 Qnil))->value))
628 return Qt;
629
630 if (EQ (selection, QCLIPBOARD))
631 {
632 Lisp_Object val = Qnil;
633
634 if (open_clipboard ())
635 {
538d05bb 636 if (get_clipboard_data_size (CF_OEMTEXT))
21cfcccf
EZ
637 val = Qt;
638 close_clipboard ();
639 }
640 return val;
641 }
642 return Qnil;
643}
644
645void
646syms_of_win16select ()
647{
767079a8
EZ
648 defsubr (&Sw16_set_clipboard_data);
649 defsubr (&Sw16_get_clipboard_data);
21cfcccf
EZ
650 defsubr (&Sx_selection_exists_p);
651
199c7c44 652 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
583f5d53
EZ
653 "Coding system for communicating with other X clients.\n\
654When sending or receiving text via cut_buffer, selection, and clipboard,\n\
655the text is encoded or decoded by this coding system.\n\
656A default value is `iso-latin-1-dos'");
199c7c44
EZ
657 Vselection_coding_system=intern ("iso-latin-1-dos");
658 staticpro(&Vselection_coding_system);
583f5d53 659
21cfcccf
EZ
660 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
661 QCLIPBOARD = intern ("CLIPBOARD"); staticpro (&QCLIPBOARD);
662}
663
664#endif /* MSDOS */