From c3640fcc96ed80368209c73d7ac9a0f0d1833d93 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 1 Nov 2016 18:04:07 +0200 Subject: [PATCH] Support 'TARGETS' in clipboard selections on MS-Windows * src/w32select.c (Fw32_selection_targets): New function. * lisp/term/w32-win.el (w32--get-selection): Call 'w32-selection-targets' to obtain the list of data formats available in the clipboard. --- lisp/term/w32-win.el | 14 ++++-- src/w32select.c | 108 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index f705ec17a55..d8cf5efcfab 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el @@ -400,11 +400,15 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (put 'x-selections (or type 'PRIMARY) value))) (defun w32--get-selection (&optional type data-type) - (if (and (eq type 'CLIPBOARD) - (eq data-type 'STRING)) - (with-demoted-errors "w32-get-clipboard-data:%S" - (w32-get-clipboard-data)) - (get 'x-selections (or type 'PRIMARY)))) + (cond ((and (eq type 'CLIPBOARD) + (eq data-type 'STRING)) + (with-demoted-errors "w32-get-clipboard-data:%S" + (w32-get-clipboard-data))) + ((eq data-type 'TARGETS) + (if (eq type 'CLIPBOARD) + (w32-selection-targets type) + (if (get 'x-selections (or type 'PRIMARY)) '[STRING]))) + (t (get 'x-selections (or type 'PRIMARY))))) (defun w32--selection-owner-p (selection) (and (memq selection '(nil PRIMARY SECONDARY)) diff --git a/src/w32select.c b/src/w32select.c index a38a42ca050..1754534c3d3 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -1052,6 +1052,113 @@ frame's display, or the first available X display. */) return Qnil; } +/* Support enumerating available clipboard selection formats. */ + +DEFUN ("w32-selection-targets", Fw32_selection_targets, Sw32_selection_targets, + 0, 2, 0, + doc: /* Return a vector of data formats available in the specified SELECTION. +SELECTION should be the name of the selection in question, typically +one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. +The symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'. + +TERMINAL should be a terminal object or a frame specifying the X +server to query. If omitted or nil, that stands for the selected +frame's display, or the first available X display. + +This function currently ignores TERMINAL, and only returns non-nil +for `CLIPBOARD'. The return value is a vector of symbols, each symbol +representing a data format that is currently available in the clipboard. */) + (Lisp_Object selection, Lisp_Object terminal) +{ + /* Xlib-like names for standard Windows clipboard data formats. + They are in upper-case to mimic xselect.c. A couple of the names + were changed to be more like their X counterparts. */ + static const char *stdfmt_name[] = { + "UNDEFINED", + "STRING", + "BITMAP", + "METAFILE", + "SYMLINK", + "DIF", + "TIFF", + "OEM_STRING", + "DIB", + "PALETTE", + "PENDATA", + "RIFF", + "WAVE", + "UTF8_STRING", + "ENHMETAFILE", + "FILE_NAMES", /* DND */ + "LOCALE", /* not used */ + "DIBV5" + }; + CHECK_SYMBOL (selection); + + /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check + if the clipboard currently has valid text format contents. */ + + if (EQ (selection, QCLIPBOARD)) + { + Lisp_Object val = Qnil; + + setup_config (); + + if (OpenClipboard (NULL)) + { + UINT format = 0; + + /* Count how many formats are available. We ignore the + CF_LOCALE format, and don't put it into the vector we + return, because CF_LOCALE is automatically created by + Windows for any text in the clipboard, so its presence in + the value will simply confuse. */ + int fmtcount = 0; + while ((format = EnumClipboardFormats (format))) + if (format != CF_LOCALE) + fmtcount++; + + if (fmtcount > 0) + { + int i; + + /* We generate a vector because that's what xselect.c + does in this case. */ + val = Fmake_vector (make_number (fmtcount), Qnil); + /* Note: when stepping with GDB through this code, the + loop below terminates immediately because + EnumClipboardFormats for some reason returns with + "Thread does not have a clipboard open" error. */ + for (i = 0, format = 0; + (format = EnumClipboardFormats (format)) != 0; ) + { + const char *name; + + if (format == CF_LOCALE) + continue; + else if (format < CF_MAX) + name = stdfmt_name[format]; + else + { + char fmt_name[256]; + + if (!GetClipboardFormatName (format, fmt_name, + sizeof (fmt_name))) + continue; + name = fmt_name; + } + ASET (val, i, intern (name)); + i++; + } + } + CloseClipboard (); + } + return val; + } + /* For PRIMARY and SECONDARY we cons the values in w32--get-selection. */ + return Qnil; +} + /* One-time init. Called in the un-dumped Emacs, but not in the dumped version. */ @@ -1061,6 +1168,7 @@ syms_of_w32select (void) defsubr (&Sw32_set_clipboard_data); defsubr (&Sw32_get_clipboard_data); defsubr (&Sw32_selection_exists_p); + defsubr (&Sw32_selection_targets); DEFVAR_LISP ("selection-coding-system", Vselection_coding_system, doc: /* Coding system for communicating with other programs. -- 2.39.5