1 /* mswindows selection processing for XEmacs
2 Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; 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 /* Synched up with: Not synched with FSF. */
25 Written by Kevin Gallo for FSF Emacs.
26 Rewritten for mswindows by Jonathan Harris, December 1997 for 21.0.
27 Hacked by Alastair Houghton, July 2000 for enhanced clipboard support.
35 #include "file-coding.h"
38 #include "console-msw.h"
40 /* A list of handles that we must release. Not accessible from Lisp. */
41 static Lisp_Object Vhandle_alist;
43 /* Test if this is an X symbol that we understand */
45 x_sym_p (Lisp_Object value)
47 if (NILP (value) || INTP (value))
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;
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... */
64 symbol_to_ms_cf (Lisp_Object value)
66 /* If it's NIL, we're in trouble. */
67 if (NILP (value)) return 0;
69 /* If it's an integer, assume it's a format ID */
70 if (INTP (value)) return (UINT) (XINT (value));
72 /* If it's a string, register the format(!) */
74 return RegisterClipboardFormat (XSTRING_DATA (value));
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;
86 if (EQ (value, QCF_DIBV5)) return CF_DIBV5;
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;
105 /* This converts an MS-Windows clipboard format to its corresponding
106 Lisp symbol, or a Lisp integer otherwise. */
108 ms_cf_to_symbol (UINT format)
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;
121 case CF_DIBV5: return QCF_DIBV5;
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);
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. */
144 cf_is_autofreed (UINT format)
148 /* This list comes from the SDK documentation */
149 case CF_DSPENHMETAFILE:
150 case CF_DSPMETAFILEPICT:
152 case CF_METAFILEPICT:
171 /* Do protocol to assert ourself as a selection owner.
175 * Only set the clipboard if (eq selection-name 'CLIPBOARD)
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.
180 * Otherwise assume the data is formatted appropriately for the data type
183 Then set the clipboard as necessary.
186 mswindows_own_selection (Lisp_Object selection_name,
187 Lisp_Object selection_value,
188 Lisp_Object how_to_add,
189 Lisp_Object selection_type,
190 int owned_p /* Not used */)
192 HGLOBAL hValue = NULL;
194 int is_X_type = FALSE;
195 Lisp_Object cfObject;
196 Lisp_Object data = Qnil;
199 struct frame *f = NULL;
201 /* Only continue if we're trying to set the clipboard - mswindows doesn't
202 use the same selection model as X */
203 if (!EQ (selection_name, QCLIPBOARD))
206 /* If this is one of the X-style atom name symbols, or NIL, convert it
208 if (NILP (selection_type) || x_sym_p (selection_type))
210 /* Should COMPOUND_TEXT map to CF_UNICODETEXT? */
217 cfType = symbol_to_ms_cf (selection_type);
219 /* Only continue if we can figure out a clipboard type */
223 cfObject = selection_type;
226 /* Convert things appropriately */
227 data = select_convert_out (selection_name,
236 if (!EQ (XCAR (data), cfObject))
237 cfType = symbol_to_ms_cf (XCAR (data));
245 /* We support opaque or string values, but we only mention string
251 /* Compute the data length */
253 size = XOPAQUE_SIZE (data);
255 size = XSTRING_LENGTH (data) + 1;
258 f = selected_frame ();
260 /* Open the clipboard */
261 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
264 /* Allocate memory */
265 hValue = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, size);
276 src = XOPAQUE_DATA (data);
278 src = XSTRING_DATA (data);
280 dst = GlobalLock (hValue);
290 memcpy (dst, src, size);
292 GlobalUnlock (hValue);
294 /* Empty the clipboard if we're replacing everything */
295 if (NILP (how_to_add) || EQ (how_to_add, Qreplace_all))
297 if (!EmptyClipboard ())
306 /* Append is currently handled in select.el; perhaps this should change,
307 but it only really makes sense for ordinary text in any case... */
309 SetClipboardData (cfType, hValue);
311 if (!cf_is_autofreed (cfType))
313 Lisp_Object alist_elt = Qnil, rest;
314 Lisp_Object cfType_int = make_int (cfType);
316 /* First check if there's an element in the alist for this type
318 alist_elt = assq_no_quit (cfType_int, Vhandle_alist);
320 /* Add an element to the alist */
321 Vhandle_alist = Fcons (Fcons (cfType_int, make_opaque_ptr (hValue)),
324 if (!NILP (alist_elt))
326 /* Free the original handle */
327 GlobalFree ((HGLOBAL) get_opaque_ptr (XCDR (alist_elt)));
329 /* Remove the original one (adding first makes life easier, because
330 we don't have to special case this being the first element) */
331 for (rest = Vhandle_alist; !NILP (rest); rest = Fcdr (rest))
332 if (EQ (cfType_int, Fcar (XCDR (rest))))
334 XCDR (rest) = Fcdr (XCDR (rest));
342 /* #### Should really return a time, though this is because of the
343 X model (by the looks of things) */
348 mswindows_available_selection_types (Lisp_Object selection_name)
350 Lisp_Object types = Qnil;
352 struct frame *f = NULL;
354 if (!EQ (selection_name, QCLIPBOARD))
358 f = selected_frame ();
360 /* Open the clipboard */
361 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
364 /* #### ajh - Should there be an unwind-protect handler around this?
365 It could (well it probably won't, but it's always better to
366 be safe) run out of memory and leave the clipboard open... */
368 while ((format = EnumClipboardFormats (format)))
369 types = Fcons (ms_cf_to_symbol (format), types);
378 mswindows_register_selection_data_type (Lisp_Object type_name)
380 /* Type already checked in select.c */
381 const char *name = XSTRING_DATA (type_name);
384 format = RegisterClipboardFormat (name);
387 return make_int ((int) format);
393 mswindows_selection_data_type_name (Lisp_Object type_id)
399 /* If it's an integer, convert to a symbol if appropriate */
401 type_id = ms_cf_to_symbol (XINT (type_id));
403 /* If this is a symbol, return it */
404 if (SYMBOLP (type_id))
407 /* Find the format code */
408 format = symbol_to_ms_cf (type_id);
413 /* Microsoft, stupid Microsoft */
414 numchars = GetClipboardFormatName (format, name_buf, 128);
420 /* Do this properly - though we could support UNICODE (UCS-2) if
421 MULE could hack it. */
422 name = make_ext_string (name_buf, numchars,
423 Fget_coding_system (Qraw_text));
432 mswindows_get_foreign_selection (Lisp_Object selection_symbol,
433 Lisp_Object target_type)
435 HGLOBAL hValue = NULL;
437 Lisp_Object cfObject = Qnil, ret = Qnil, value = Qnil;
438 int is_X_type = FALSE;
441 struct frame *f = NULL;
444 /* Only continue if we're trying to read the clipboard - mswindows doesn't
445 use the same selection model as X */
446 if (!EQ (selection_symbol, QCLIPBOARD))
449 /* If this is one of the X-style atom name symbols, or NIL, convert it
451 if (NILP (target_type) || x_sym_p (target_type))
453 /* Should COMPOUND_TEXT map to CF_UNICODETEXT? */
460 cfType = symbol_to_ms_cf (target_type);
462 /* Only continue if we can figure out a clipboard type */
466 cfObject = ms_cf_to_symbol (cfType);
470 f = selected_frame ();
472 /* Open the clipboard */
473 if (!OpenClipboard (FRAME_MSWINDOWS_HANDLE (f)))
476 /* Read the clipboard */
477 hValue = GetClipboardData (cfType);
487 size = GlobalSize (hValue);
488 data = GlobalLock (hValue);
497 /* Place it in a Lisp string */
498 TO_INTERNAL_FORMAT (DATA, (data, size),
507 /* Convert this to the appropriate type. If we can't find anything,
508 then we return a cons of the form (DATA-TYPE . STRING), where the
509 string contains the raw binary data. */
510 value = select_convert_in (selection_symbol,
517 return Fcons (cfObject, ret);
523 mswindows_disown_selection (Lisp_Object selection, Lisp_Object timeval)
525 if (EQ (selection, QCLIPBOARD))
527 BOOL success = OpenClipboard (NULL);
530 success = EmptyClipboard ();
531 /* Close it regardless of whether empty worked. */
532 if (!CloseClipboard ())
536 /* #### return success ? Qt : Qnil; */
541 mswindows_destroy_selection (Lisp_Object selection)
543 /* Do nothing if this isn't for the clipboard. */
544 if (!EQ (selection, QCLIPBOARD))
547 /* Right. We need to delete everything in Vhandle_alist. */
549 LIST_LOOP_2 (elt, Vhandle_alist)
550 GlobalFree ((HGLOBAL) get_opaque_ptr (XCDR (elt)));
553 Vhandle_alist = Qnil;
557 mswindows_selection_exists_p (Lisp_Object selection,
558 Lisp_Object selection_type)
560 /* We used to be picky about the format, but now we support anything. */
561 if (EQ (selection, QCLIPBOARD))
563 if (NILP (selection_type))
564 return CountClipboardFormats () ? Qt : Qnil;
566 return IsClipboardFormatAvailable (symbol_to_ms_cf (selection_type))
574 /************************************************************************/
576 /************************************************************************/
579 console_type_create_select_mswindows (void)
581 CONSOLE_HAS_METHOD (mswindows, own_selection);
582 CONSOLE_HAS_METHOD (mswindows, disown_selection);
583 CONSOLE_HAS_METHOD (mswindows, selection_exists_p);
584 CONSOLE_HAS_METHOD (mswindows, get_foreign_selection);
585 CONSOLE_HAS_METHOD (mswindows, available_selection_types);
586 CONSOLE_HAS_METHOD (mswindows, register_selection_data_type);
587 CONSOLE_HAS_METHOD (mswindows, selection_data_type_name);
591 syms_of_select_mswindows (void)
596 vars_of_select_mswindows (void)
598 /* Initialise Vhandle_alist */
599 Vhandle_alist = Qnil;
600 staticpro (&Vhandle_alist);