comparison src/select-msw.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents a5df635868b2
children e7ef97881643
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
22 22
23 /* Authorship: 23 /* Authorship:
24 24
25 Written by Kevin Gallo for FSF Emacs. 25 Written by Kevin Gallo for FSF Emacs.
26 Rewritten for mswindows by Jonathan Harris, December 1997 for 21.0. 26 Rewritten for mswindows by Jonathan Harris, December 1997 for 21.0.
27 */ 27 Hacked by Alastair Houghton, July 2000 for enhanced clipboard support.
28 28 */
29 29
30 #include <config.h> 30 #include <config.h>
31 #include "lisp.h" 31 #include "lisp.h"
32 #include "frame.h" 32 #include "frame.h"
33 #include "select.h" 33 #include "select.h"
34 #include "opaque.h"
35 #include "file-coding.h"
36 #include "buffer.h"
34 37
35 #include "console-msw.h" 38 #include "console-msw.h"
36 39
37 DEFUN ("mswindows-set-clipboard", Fmswindows_set_clipboard, 1, 1, 0, /* 40 /* A list of handles that we must release. Not accessible from Lisp. */
38 Copy STRING to the mswindows clipboard. 41 static Lisp_Object Vhandle_alist;
42
43 /* Test if this is an X symbol that we understand */
44 static int
45 x_sym_p (Lisp_Object value)
46 {
47 if (NILP (value) || INTP (value))
48 return 0;
49
50 /* Check for some of the X symbols */
51 if (EQ (value, QSTRING)) return 1;
52 if (EQ (value, QTEXT)) return 1;
53 if (EQ (value, QCOMPOUND_TEXT)) return 1;
54
55 return 0;
56 }
57
58 /* This converts a Lisp symbol to an MS-Windows clipboard format.
59 We have symbols for all predefined clipboard formats, but that
60 doesn't mean we support them all ;-)
61 The name of this function is actually a lie - it also knows about
62 integers and strings... */
63 static UINT
64 symbol_to_ms_cf (Lisp_Object value)
65 {
66 /* If it's NIL, we're in trouble. */
67 if (NILP (value)) return 0;
68
69 /* If it's an integer, assume it's a format ID */
70 if (INTP (value)) return (UINT) (XINT (value));
71
72 /* If it's a string, register the format(!) */
73 if (STRINGP (value))
74 return RegisterClipboardFormat (XSTRING_DATA (value));
75
76 /* Check for Windows clipboard format symbols */
77 if (EQ (value, QCF_TEXT)) return CF_TEXT;
78 if (EQ (value, QCF_BITMAP)) return CF_BITMAP;
79 if (EQ (value, QCF_METAFILEPICT)) return CF_METAFILEPICT;
80 if (EQ (value, QCF_SYLK)) return CF_SYLK;
81 if (EQ (value, QCF_DIF)) return CF_DIF;
82 if (EQ (value, QCF_TIFF)) return CF_TIFF;
83 if (EQ (value, QCF_OEMTEXT)) return CF_OEMTEXT;
84 if (EQ (value, QCF_DIB)) return CF_DIB;
85 #ifdef CF_DIBV5
86 if (EQ (value, QCF_DIBV5)) return CF_DIBV5;
87 #endif
88 if (EQ (value, QCF_PALETTE)) return CF_PALETTE;
89 if (EQ (value, QCF_PENDATA)) return CF_PENDATA;
90 if (EQ (value, QCF_RIFF)) return CF_RIFF;
91 if (EQ (value, QCF_WAVE)) return CF_WAVE;
92 if (EQ (value, QCF_UNICODETEXT)) return CF_UNICODETEXT;
93 if (EQ (value, QCF_ENHMETAFILE)) return CF_ENHMETAFILE;
94 if (EQ (value, QCF_HDROP)) return CF_HDROP;
95 if (EQ (value, QCF_LOCALE)) return CF_LOCALE;
96 if (EQ (value, QCF_OWNERDISPLAY)) return CF_OWNERDISPLAY;
97 if (EQ (value, QCF_DSPTEXT)) return CF_DSPTEXT;
98 if (EQ (value, QCF_DSPBITMAP)) return CF_DSPBITMAP;
99 if (EQ (value, QCF_DSPMETAFILEPICT)) return CF_DSPMETAFILEPICT;
100 if (EQ (value, QCF_DSPENHMETAFILE)) return CF_DSPENHMETAFILE;
101
102 return 0;
103 }
104
105 /* This converts an MS-Windows clipboard format to its corresponding
106 Lisp symbol, or a Lisp integer otherwise. */
107 static Lisp_Object
108 ms_cf_to_symbol (UINT format)
109 {
110 switch (format)
111 {
112 case CF_TEXT: return QCF_TEXT;
113 case CF_BITMAP: return QCF_BITMAP;
114 case CF_METAFILEPICT: return QCF_METAFILEPICT;
115 case CF_SYLK: return QCF_SYLK;
116 case CF_DIF: return QCF_DIF;
117 case CF_TIFF: return QCF_TIFF;
118 case CF_OEMTEXT: return QCF_OEMTEXT;
119 case CF_DIB: return QCF_DIB;
120 #ifdef CF_DIBV5
121 case CF_DIBV5: return QCF_DIBV5;
122 #endif
123 case CF_PALETTE: return QCF_PALETTE;
124 case CF_PENDATA: return QCF_PENDATA;
125 case CF_RIFF: return QCF_RIFF;
126 case CF_WAVE: return QCF_WAVE;
127 case CF_UNICODETEXT: return QCF_UNICODETEXT;
128 case CF_ENHMETAFILE: return QCF_ENHMETAFILE;
129 case CF_HDROP: return QCF_HDROP;
130 case CF_LOCALE: return QCF_LOCALE;
131 case CF_OWNERDISPLAY: return QCF_OWNERDISPLAY;
132 case CF_DSPTEXT: return QCF_DSPTEXT;
133 case CF_DSPBITMAP: return QCF_DSPBITMAP;
134 case CF_DSPMETAFILEPICT: return QCF_DSPMETAFILEPICT;
135 case CF_DSPENHMETAFILE: return QCF_DSPENHMETAFILE;
136 default: return make_int ((int) format);
137 }
138 }
139
140 /* Test if the specified clipboard format is auto-released by the OS. If
141 not, we must remember the handle on Vhandle_alist, and free it if
142 the clipboard is emptied or if we set data with the same format. */
143 static int
144 cf_is_autofreed (UINT format)
145 {
146 switch (format)
147 {
148 /* This list comes from the SDK documentation */
149 case CF_DSPENHMETAFILE:
150 case CF_DSPMETAFILEPICT:
151 case CF_ENHMETAFILE:
152 case CF_METAFILEPICT:
153 case CF_BITMAP:
154 case CF_DSPBITMAP:
155 case CF_PALETTE:
156 case CF_DIB:
157 #ifdef CF_DIBV5
158 case CF_DIBV5:
159 #endif
160 case CF_DSPTEXT:
161 case CF_OEMTEXT:
162 case CF_TEXT:
163 case CF_UNICODETEXT:
164 return TRUE;
165
166 default:
167 return FALSE;
168 }
169 }
170
171 /* Do protocol to assert ourself as a selection owner.
172
173 Under mswindows, we:
174
175 * Only set the clipboard if (eq selection-name 'CLIPBOARD)
176
177 * Check if an X atom name has been passed. If so, convert to CF_TEXT
178 (or CF_UNICODETEXT) remembering to perform LF -> CR-LF conversion.
179
180 * Otherwise assume the data is formatted appropriately for the data type
181 that was passed.
182
183 Then set the clipboard as necessary.
39 */ 184 */
40 (string)) 185 static Lisp_Object
41 { 186 mswindows_own_selection (Lisp_Object selection_name,
42 int rawsize, size, i; 187 Lisp_Object selection_value,
43 unsigned char *src, *dst, *next; 188 Lisp_Object how_to_add,
44 HGLOBAL h = NULL; 189 Lisp_Object selection_type)
45 struct frame *f = NULL; 190 {
46 191 HGLOBAL hValue = NULL;
47 CHECK_STRING (string); 192 UINT cfType;
48 193 int is_X_type = FALSE;
49 /* Calculate size with LFs converted to CRLFs because 194 Lisp_Object cfObject;
50 * CF_TEXT format uses CRLF delimited ASCIIZ */ 195 Lisp_Object data = Qnil;
51 src = XSTRING_DATA (string); 196 int size;
52 size = rawsize = XSTRING_LENGTH (string) + 1; 197 void *src, *dst;
53 for (i=0; i<rawsize; i++) 198 struct frame *f = NULL;
54 if (src[i] == '\n') 199
55 size++; 200 /* Only continue if we're trying to set the clipboard - mswindows doesn't
56 201 use the same selection model as X */
202 if (!EQ (selection_name, QCLIPBOARD))
203 return Qnil;
204
205 /* If this is one of the X-style atom name symbols, or NIL, convert it
206 as appropriate */
207 if (NILP (selection_type) || x_sym_p (selection_type))
208 {
209 /* Should COMPOUND_TEXT map to CF_UNICODETEXT? */
210 cfType = CF_TEXT;
211 cfObject = QCF_TEXT;
212 is_X_type = TRUE;
213 }
214 else
215 {
216 cfType = symbol_to_ms_cf (selection_type);
217
218 /* Only continue if we can figure out a clipboard type */
219 if (!cfType)
220 return Qnil;
221
222 cfObject = selection_type;
223 }
224
225 /* Convert things appropriately */
226 data = select_convert_out (selection_name,
227 cfObject,
228 selection_value);
229
230 if (NILP (data))
231 return Qnil;
232
233 if (CONSP (data))
234 {
235 if (!EQ (XCAR (data), cfObject))
236 cfType = symbol_to_ms_cf (XCAR (data));
237
238 if (!cfType)
239 return Qnil;
240
241 data = XCDR (data);
242 }
243
244 /* We support opaque or string values, but we only mention string
245 values for now... */
246 if (!OPAQUEP (data)
247 && !STRINGP (data))
248 return Qnil;
249
250 /* Compute the data length */
251 if (OPAQUEP (data))
252 size = XOPAQUE_SIZE (data);
253 else
254 size = XSTRING_LENGTH (data) + 1;
255
256 /* Find the frame */
57 f = selected_frame (); 257 f = selected_frame ();
258
259 /* Open the clipboard */
58 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f))) 260 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
59 return Qnil; 261 return Qnil;
60 262
61 if (!EmptyClipboard () || 263 /* Allocate memory */
62 (h = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, size)) == NULL || 264 hValue = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, size);
63 (dst = (unsigned char *) GlobalLock (h)) == NULL) 265
64 { 266 if (!hValue)
65 if (h != NULL) GlobalFree (h); 267 {
66 CloseClipboard (); 268 CloseClipboard ();
269
67 return Qnil; 270 return Qnil;
68 } 271 }
69 272
70 /* Convert LFs to CRLFs */ 273 /* Copy the data */
71 do 274 if (OPAQUEP (data))
72 { 275 src = XOPAQUE_DATA (data);
73 /* copy next line or remaining bytes including '\0' */ 276 else
74 next = memccpy (dst, src, '\n', rawsize); 277 src = XSTRING_DATA (data);
75 if (next) 278
279 dst = GlobalLock (hValue);
280
281 if (!dst)
282 {
283 GlobalFree (hValue);
284 CloseClipboard ();
285
286 return Qnil;
287 }
288
289 memcpy (dst, src, size);
290
291 GlobalUnlock (hValue);
292
293 /* Empty the clipboard if we're replacing everything */
294 if (NILP (how_to_add) || EQ (how_to_add, Qreplace_all))
295 {
296 if (!EmptyClipboard ())
76 { 297 {
77 /* copied one line ending with '\n' */ 298 CloseClipboard ();
78 int copied = next - dst; 299 GlobalFree (hValue);
79 rawsize -= copied; 300
80 src += copied; 301 return Qnil;
81 /* insert '\r' before '\n' */ 302 }
82 next[-1] = '\r'; 303 }
83 next[0] = '\n'; 304
84 dst = next+1; 305 /* Append is currently handled in select.el; perhaps this should change,
85 } 306 but it only really makes sense for ordinary text in any case... */
86 } 307
87 while (next); 308 SetClipboardData (cfType, hValue);
88 309
89 GlobalUnlock (h); 310 if (!cf_is_autofreed (cfType))
90 311 {
91 i = (SetClipboardData (CF_TEXT, h) != NULL); 312 Lisp_Object alist_elt = Qnil, rest;
92 313 Lisp_Object cfType_int = make_int (cfType);
314
315 /* First check if there's an element in the alist for this type
316 already. */
317 alist_elt = assq_no_quit (cfType_int, Vhandle_alist);
318
319 /* Add an element to the alist */
320 Vhandle_alist = Fcons (Fcons (cfType_int, make_opaque_ptr (hValue)),
321 Vhandle_alist);
322
323 if (!NILP (alist_elt))
324 {
325 /* Free the original handle */
326 GlobalFree ((HGLOBAL) get_opaque_ptr (XCDR (alist_elt)));
327
328 /* Remove the original one (adding first makes life easier, because
329 we don't have to special case this being the first element) */
330 for (rest = Vhandle_alist; !NILP (rest); rest = Fcdr (rest))
331 if (EQ (cfType_int, Fcar (XCDR (rest))))
332 {
333 XCDR (rest) = Fcdr (XCDR (rest));
334 break;
335 }
336 }
337 }
338
93 CloseClipboard (); 339 CloseClipboard ();
94 340
95 return i ? Qt : Qnil; 341 /* #### Should really return a time, though this is because of the
96 } 342 X model (by the looks of things) */
97 343 return Qnil;
98 /* Do protocol to assert ourself as a selection owner. Under mswindows 344 }
99 this is easy, we just set the clipboard. */ 345
100 static Lisp_Object 346 static Lisp_Object
101 mswindows_own_selection (Lisp_Object selection_name, Lisp_Object selection_value) 347 mswindows_available_selection_types (Lisp_Object selection_name)
102 { 348 {
103 Lisp_Object converted_value = get_local_selection (selection_name, QSTRING); 349 Lisp_Object types = Qnil;
104 if (!NILP (converted_value) && 350 UINT format = 0;
105 CONSP (converted_value) && 351 struct frame *f = NULL;
106 EQ (XCAR (converted_value), QSTRING) && 352
107 /* pure mswindows behaviour only says we can own the selection 353 if (!EQ (selection_name, QCLIPBOARD))
108 if it is the clipboard */ 354 return Qnil;
109 EQ (selection_name, QCLIPBOARD)) 355
110 Fmswindows_set_clipboard (XCDR (converted_value)); 356 /* Find the frame */
357 f = selected_frame ();
358
359 /* Open the clipboard */
360 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
361 return Qnil;
362
363 /* #### ajh - Should there be an unwind-protect handler around this?
364 It could (well it probably won't, but it's always better to
365 be safe) run out of memory and leave the clipboard open... */
366
367 while ((format = EnumClipboardFormats (format)))
368 types = Fcons (ms_cf_to_symbol (format), types);
369
370 /* Close it */
371 CloseClipboard ();
372
373 return types;
374 }
375
376 static Lisp_Object
377 mswindows_register_selection_data_type (Lisp_Object type_name)
378 {
379 /* Type already checked in select.c */
380 const char *name = XSTRING_DATA (type_name);
381 UINT format;
382
383 format = RegisterClipboardFormat (name);
384
385 if (format)
386 return make_int ((int) format);
387 else
388 return Qnil;
389 }
390
391 static Lisp_Object
392 mswindows_selection_data_type_name (Lisp_Object type_id)
393 {
394 UINT format;
395 int numchars;
396 char name_buf[128];
397
398 /* If it's an integer, convert to a symbol if appropriate */
399 if (INTP (type_id))
400 type_id = ms_cf_to_symbol (XINT (type_id));
401
402 /* If this is a symbol, return it */
403 if (SYMBOLP (type_id))
404 return type_id;
405
406 /* Find the format code */
407 format = symbol_to_ms_cf (type_id);
408
409 if (!format)
410 return Qnil;
411
412 /* Microsoft, stupid Microsoft */
413 numchars = GetClipboardFormatName (format, name_buf, 128);
414
415 if (numchars)
416 {
417 Lisp_Object name;
418
419 /* Do this properly - though we could support UNICODE (UCS-2) if
420 MULE could hack it. */
421 name = make_ext_string (name_buf, numchars,
422 Fget_coding_system (Qraw_text));
423
424 return name;
425 }
111 426
112 return Qnil; 427 return Qnil;
113 } 428 }
114 429
115 DEFUN ("mswindows-get-clipboard", Fmswindows_get_clipboard, 0, 0, 0, /* 430 static Lisp_Object
116 Return the contents of the mswindows clipboard. 431 mswindows_get_foreign_selection (Lisp_Object selection_symbol,
117 */ 432 Lisp_Object target_type)
118 ()) 433 {
119 { 434 HGLOBAL hValue = NULL;
120 HANDLE h; 435 UINT cfType;
121 unsigned char *src, *dst, *next; 436 Lisp_Object cfObject = Qnil, ret = Qnil, value = Qnil;
122 Lisp_Object ret = Qnil; 437 int is_X_type = FALSE;
123 438 int size;
124 if (!OpenClipboard (NULL)) 439 void *data;
125 return Qnil; 440 struct frame *f = NULL;
126 441 struct gcpro gcpro1;
127 if ((h = GetClipboardData (CF_TEXT)) != NULL && 442
128 (src = (unsigned char *) GlobalLock (h)) != NULL) 443 /* Only continue if we're trying to read the clipboard - mswindows doesn't
129 { 444 use the same selection model as X */
130 int i; 445 if (!EQ (selection_symbol, QCLIPBOARD))
131 int size, rawsize; 446 return Qnil;
132 size = rawsize = strlen (src); 447
133 448 /* If this is one of the X-style atom name symbols, or NIL, convert it
134 for (i=0; i<rawsize; i++) 449 as appropriate */
135 if (src[i] == '\r' && src[i+1] == '\n') 450 if (NILP (target_type) || x_sym_p (target_type))
136 size--; 451 {
137 452 /* Should COMPOUND_TEXT map to CF_UNICODETEXT? */
138 /* Convert CRLFs to LFs */ 453 cfType = CF_TEXT;
139 ret = make_uninit_string (size); 454 cfObject = QCF_TEXT;
140 dst = XSTRING_DATA (ret); 455 is_X_type = TRUE;
141 do 456 }
142 { 457 else
143 /* copy next line or remaining bytes excluding '\0' */ 458 {
144 next = memccpy (dst, src, '\r', rawsize); 459 cfType = symbol_to_ms_cf (target_type);
145 if (next) 460
146 { 461 /* Only continue if we can figure out a clipboard type */
147 /* copied one line ending with '\r' */ 462 if (!cfType)
148 int copied = next - dst; 463 return Qnil;
149 rawsize -= copied; 464
150 src += copied; 465 cfObject = ms_cf_to_symbol (cfType);
151 if (*src == '\n') 466 }
152 dst += copied - 1; /* overwrite '\r' */ 467
153 else 468 /* Find the frame */
154 dst += copied; 469 f = selected_frame ();
155 } 470
156 } 471 /* Open the clipboard */
157 while (next); 472 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
158 473 return Qnil;
159 GlobalUnlock (h); 474
160 } 475 /* Read the clipboard */
161 476 hValue = GetClipboardData (cfType);
477
478 if (!hValue)
479 {
480 CloseClipboard ();
481
482 return Qnil;
483 }
484
485 /* Find the data */
486 size = GlobalSize (hValue);
487 data = GlobalLock (hValue);
488
489 if (!data)
490 {
491 CloseClipboard ();
492
493 return Qnil;
494 }
495
496 /* Place it in a Lisp string */
497 TO_INTERNAL_FORMAT (DATA, (data, size),
498 LISP_STRING, ret,
499 Qbinary);
500
501 GlobalUnlock (data);
162 CloseClipboard (); 502 CloseClipboard ();
163 503
164 return ret; 504 GCPRO1 (ret);
165 } 505
166 506 /* Convert this to the appropriate type. If we can't find anything,
167 static Lisp_Object 507 then we return a cons of the form (DATA-TYPE . STRING), where the
168 mswindows_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type) 508 string contains the raw binary data. */
169 { 509 value = select_convert_in (selection_symbol,
170 if (EQ (selection_symbol, QCLIPBOARD)) 510 cfObject,
171 return Fmswindows_get_clipboard (); 511 ret);
512
513 UNGCPRO;
514
515 if (NILP (value))
516 return Fcons (cfObject, ret);
172 else 517 else
173 return Qnil; 518 return value;
174 }
175
176 DEFUN ("mswindows-selection-exists-p", Fmswindows_selection_exists_p, 0, 0, 0, /*
177 Whether there is an MS-Windows selection.
178 */
179 ())
180 {
181 return IsClipboardFormatAvailable (CF_TEXT) ? Qt : Qnil;
182 }
183
184 DEFUN ("mswindows-delete-selection", Fmswindows_delete_selection, 0, 0, 0, /*
185 Remove the current MS-Windows selection from the clipboard.
186 */
187 ())
188 {
189 BOOL success = OpenClipboard (NULL);
190 if (success)
191 {
192 success = EmptyClipboard ();
193 /* Close it regardless of whether empty worked. */
194 if (!CloseClipboard ())
195 success = FALSE;
196 }
197
198 return success ? Qt : Qnil;
199 } 519 }
200 520
201 static void 521 static void
202 mswindows_disown_selection (Lisp_Object selection, Lisp_Object timeval) 522 mswindows_disown_selection (Lisp_Object selection, Lisp_Object timeval)
203 { 523 {
204 if (EQ (selection, QCLIPBOARD)) 524 if (EQ (selection, QCLIPBOARD))
205 Fmswindows_delete_selection (); 525 {
526 BOOL success = OpenClipboard (NULL);
527 if (success)
528 {
529 success = EmptyClipboard ();
530 /* Close it regardless of whether empty worked. */
531 if (!CloseClipboard ())
532 success = FALSE;
533 }
534
535 /* #### return success ? Qt : Qnil; */
536 }
537 }
538
539 void
540 mswindows_destroy_selection (Lisp_Object selection)
541 {
542 /* Do nothing if this isn't for the clipboard. */
543 if (!EQ (selection, QCLIPBOARD))
544 return;
545
546 /* Right. We need to delete everything in Vhandle_alist. */
547 {
548 LIST_LOOP_2 (elt, Vhandle_alist)
549 GlobalFree ((HGLOBAL) get_opaque_ptr (XCDR (elt)));
550 }
551
552 Vhandle_alist = Qnil;
553 }
554
555 static Lisp_Object
556 mswindows_selection_exists_p (Lisp_Object selection,
557 Lisp_Object selection_type)
558 {
559 /* We used to be picky about the format, but now we support anything. */
560 if (EQ (selection, QCLIPBOARD))
561 {
562 if (NILP (selection_type))
563 return CountClipboardFormats () ? Qt : Qnil;
564 else
565 return IsClipboardFormatAvailable (symbol_to_ms_cf (selection_type))
566 ? Qt : Qnil;
567 }
568 else
569 return Qnil;
206 } 570 }
207 571
208 572
209 /************************************************************************/ 573 /************************************************************************/
210 /* initialization */ 574 /* initialization */
213 void 577 void
214 console_type_create_select_mswindows (void) 578 console_type_create_select_mswindows (void)
215 { 579 {
216 CONSOLE_HAS_METHOD (mswindows, own_selection); 580 CONSOLE_HAS_METHOD (mswindows, own_selection);
217 CONSOLE_HAS_METHOD (mswindows, disown_selection); 581 CONSOLE_HAS_METHOD (mswindows, disown_selection);
582 CONSOLE_HAS_METHOD (mswindows, selection_exists_p);
218 CONSOLE_HAS_METHOD (mswindows, get_foreign_selection); 583 CONSOLE_HAS_METHOD (mswindows, get_foreign_selection);
584 CONSOLE_HAS_METHOD (mswindows, available_selection_types);
585 CONSOLE_HAS_METHOD (mswindows, register_selection_data_type);
586 CONSOLE_HAS_METHOD (mswindows, selection_data_type_name);
219 } 587 }
220 588
221 void 589 void
222 syms_of_select_mswindows (void) 590 syms_of_select_mswindows (void)
223 { 591 {
224 DEFSUBR (Fmswindows_set_clipboard);
225 DEFSUBR (Fmswindows_get_clipboard);
226 DEFSUBR (Fmswindows_selection_exists_p);
227 DEFSUBR (Fmswindows_delete_selection);
228 } 592 }
229 593
230 void 594 void
231 vars_of_select_mswindows (void) 595 vars_of_select_mswindows (void)
232 { 596 {
233 } 597 /* Initialise Vhandle_alist */
598 Vhandle_alist = Qnil;
599 staticpro (&Vhandle_alist);
600 }