@section Yanking Media
@cindex yank media from window-system selections
- Data saved within window system selections is not restricted to
-plain text. It is possible for selection data to encompass images or
-other binary data of the like, as well as rich text content instanced
-by HTML, and also PostScript. Since the selection data types incident
-to this data are at variance with those for plain text, the insertion
-of such data is facilitated by a set of functions dubbed
-@dfn{yank-media handlers}, which are registered by each major mode
-undertaking its insertion and called where warranted upon the
+ Data saved within window system selections and the MS-Windows
+clipboard is not restricted to plain text. It is possible for selection
+data to encompass images or other binary data of the like, as well as
+rich text content instanced by HTML, and also PostScript. Since the
+selection data types incident to this data are at variance with those
+for plain text, the insertion of such data is facilitated by a set of
+functions dubbed @dfn{yank-media handlers}, which are registered by each
+major mode undertaking its insertion and called where warranted upon the
execution of the @code{yank-media} command.
@defun yank-media-handler types handler
To show color Emoji in Emacs, customize the default fontset to use a
color Emoji font installed on your system for the 'emoji' script.
++++
+** Emacs on MS-Windows now supports 'yank-media'.
+This command inserts clipboard data of different formats into the
+current buffer, if the major mode supports it.
+
+
\f
----------------------------------------------------------------------
This file is part of GNU Emacs.
(w32-set-clipboard-data (string-replace "\0" "\\0" value))
(put 'x-selections (or type 'PRIMARY) value)))
-(defun w32--get-selection (&optional type data-type)
+(defvar w32--selection-target-translations
+ '((PNG . image/png)
+ (DIBV5 . image/png)
+ (HTML\ Format . text/html)))
+
+(defun w32--translate-selection-target (target)
+ (let ((xlat (assoc target w32--selection-target-translations)))
+ (if xlat
+ (cdr xlat)
+ target)))
+
+(defun w32--translate-reverse-selection-target (target)
+ (append
+ (mapcar #'car
+ (seq-filter
+ (lambda (x)
+ (eq target
+ (w32--translate-selection-target (car x))))
+ w32--selection-target-translations))
+ (list target)))
+
+(defvar w32--textual-mime-types
+ '("application/xml"
+ "application/json"
+ "application/yaml"
+ "application/json-seq"
+ "\\`text/"
+ "+xml\\'"
+ "+json\\'"
+ "+yaml\\'"
+ "+json-seq\\'"))
+
+(defun w32--mime-type-textual-p (mime-type)
+ "Returns t if MIME-TYPE, a symbol, names a textual MIME type.
+
+This function is intended to classify clipboard data. All MIME subtypes
+of text/ are considered textual. Also those with suffixes +xml, +json,
++yaml, +json-seq. And application/xml, application/json,
+application/yaml, application/json-seq.
+
+This classification is not exhaustive. Some MIME types not listed may
+also be textual."
+ (string-match-p
+ (mapconcat #'identity w32--textual-mime-types "\\|")
+ (symbol-name mime-type)))
+
+(defun w32--get-selection (&optional type data-type)
(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)
+ (vconcat
+ (delete-dups
+ (seq-map #'w32--translate-selection-target
+ (w32-selection-targets type))))
(if (get 'x-selections (or type 'PRIMARY)) '[STRING])))
+ ((eq type 'CLIPBOARD)
+ (let ((tmp-file (make-temp-file "emacs-clipboard"))
+ (is-textual (w32--mime-type-textual-p data-type)))
+ (unwind-protect
+ (let* ((data-types (w32--translate-reverse-selection-target data-type))
+ (data (w32--get-clipboard-data-media data-types tmp-file is-textual)))
+ (cond
+ ;; data is in the file
+ ((eq data t)
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert-file-contents-literally tmp-file)
+ (buffer-string)))
+ ;; data is in data var
+ ((stringp data) data)
+ ;; No data
+ (t nil)))
+ (delete-file tmp-file))))
(t (get 'x-selections (or type 'PRIMARY)))))
(defun w32--selection-owner-p (selection)
(when (and (file-exists-p file)
(not (yes-or-no-p (format "%s exists; overwrite?" file))))
(user-error "%s exists" file))
- (with-temp-buffer
- (set-buffer-multibyte nil)
- (insert image)
- (write-region (point-min) (point-max) file))
+ (let ((coding-system-for-write 'emacs-internal))
+ (with-temp-file file
+ (insert image)))
(insert (format "<img src=%S>\n" (file-relative-name file)))
(insert-image
(create-image file (mailcap-mime-type-to-extension type) nil
--- /dev/null
+#ifdef WINDOWSNT
+typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc)
+ (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *);
+typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR);
+typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc)
+ (GpImage *, PROPID, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc)
+ (GpImage *, PROPID, UINT, PropertyItem *);
+typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc)
+ (GpImage *, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc)
+ (GpImage *, GUID *, UINT);
+typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc)
+ (GpImage *, GDIPCONST GUID *, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc)
+ (GpImage*, GDIPCONST GUID *, UINT);
+typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc)
+ (WCHAR *, GpBitmap **);
+typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc)
+ (IStream *, GpBitmap **);
+typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromScan0_Proc)
+ (INT, INT, INT, PixelFormat, BYTE*, GpBitmap**);
+typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT);
+typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc)
+ (GpBitmap *, HBITMAP *, ARGB);
+typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *);
+typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipGetImageEncodersSize_Proc) (UINT *, UINT *);
+typedef GpStatus (WINGDIPAPI *GdipGetImageEncoders_Proc)
+ (UINT, UINT, ImageCodecInfo *);
+typedef GpStatus (WINGDIPAPI *GdipLoadImageFromFile_Proc)
+ (GDIPCONST WCHAR *,GpImage **);
+typedef GpStatus (WINGDIPAPI *GdipGetImageThumbnail_Proc)
+ (GpImage *, UINT, UINT, GpImage**, GetThumbnailImageAbort, VOID *);
+typedef GpStatus (WINGDIPAPI *GdipSaveImageToFile_Proc)
+ (GpImage *, GDIPCONST WCHAR *, GDIPCONST CLSID *,
+ GDIPCONST EncoderParameters *);
+typedef GpStatus (WINGDIPAPI *GdipImageRotateFlip_Proc)
+ (GpImage *image, RotateFlipType rfType);
+
+extern GdiplusStartup_Proc fn_GdiplusStartup;
+extern GdiplusShutdown_Proc fn_GdiplusShutdown;
+extern GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
+extern GdipGetPropertyItem_Proc fn_GdipGetPropertyItem;
+extern GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount;
+extern GdipImageGetFrameDimensionsList_Proc fn_GdipImageGetFrameDimensionsList;
+extern GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount;
+extern GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame;
+extern GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile;
+extern GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
+extern GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
+extern SHCreateMemStream_Proc fn_SHCreateMemStream;
+extern GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
+extern GdipDisposeImage_Proc fn_GdipDisposeImage;
+extern GdipGetImageHeight_Proc fn_GdipGetImageHeight;
+extern GdipGetImageWidth_Proc fn_GdipGetImageWidth;
+extern GdipGetImageEncodersSize_Proc fn_GdipGetImageEncodersSize;
+extern GdipGetImageEncoders_Proc fn_GdipGetImageEncoders;
+extern GdipLoadImageFromFile_Proc fn_GdipLoadImageFromFile;
+extern GdipGetImageThumbnail_Proc fn_GdipGetImageThumbnail;
+extern GdipSaveImageToFile_Proc fn_GdipSaveImageToFile;
+extern GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
+
+# undef GdiplusStartup
+# undef GdiplusShutdown
+# undef GdipGetPropertyItemSize
+# undef GdipGetPropertyItem
+# undef GdipImageGetFrameDimensionsCount
+# undef GdipImageGetFrameDimensionsList
+# undef GdipImageGetFrameCount
+# undef GdipImageSelectActiveFrame
+# undef GdipCreateBitmapFromFile
+# undef GdipCreateBitmapFromStream
+# undef GdipCreateBitmapFromScan0
+# undef SHCreateMemStream
+# undef GdipCreateHBITMAPFromBitmap
+# undef GdipDisposeImage
+# undef GdipGetImageHeight
+# undef GdipGetImageWidth
+# undef GdipGetImageEncodersSize
+# undef GdipGetImageEncoders
+# undef GdipLoadImageFromFile
+# undef GdipGetImageThumbnail
+# undef GdipSaveImageToFile
+# undef GdipSaveImageRotateFlip
+
+# define GdiplusStartup fn_GdiplusStartup
+# define GdiplusShutdown fn_GdiplusShutdown
+# define GdipGetPropertyItemSize fn_GdipGetPropertyItemSize
+# define GdipGetPropertyItem fn_GdipGetPropertyItem
+# define GdipImageGetFrameDimensionsCount fn_GdipImageGetFrameDimensionsCount
+# define GdipImageGetFrameDimensionsList fn_GdipImageGetFrameDimensionsList
+# define GdipImageGetFrameCount fn_GdipImageGetFrameCount
+# define GdipImageSelectActiveFrame fn_GdipImageSelectActiveFrame
+# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile
+# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream
+# define GdipCreateBitmapFromScan0 fn_GdipCreateBitmapFromScan0
+# define SHCreateMemStream fn_SHCreateMemStream
+# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap
+# define GdipDisposeImage fn_GdipDisposeImage
+# define GdipGetImageHeight fn_GdipGetImageHeight
+# define GdipGetImageWidth fn_GdipGetImageWidth
+# define GdipGetImageEncodersSize fn_GdipGetImageEncodersSize
+# define GdipGetImageEncoders fn_GdipGetImageEncoders
+# define GdipLoadImageFromFile fn_GdipLoadImageFromFile
+# define GdipGetImageThumbnail fn_GdipGetImageThumbnail
+# define GdipSaveImageToFile fn_GdipSaveImageToFile
+# define GdipImageRotateFlip fn_GdipImageRotateFlip
+#endif
+
+int w32_gdip_get_encoder_clsid (const char *type, CLSID *clsid);
extern int w32_load_image (struct frame *f, struct image *img,
Lisp_Object spec_file, Lisp_Object spec_data);
extern bool w32_can_use_native_image_api (Lisp_Object);
+extern bool w32_gdiplus_startup (void);
extern void w32_gdiplus_shutdown (void);
+
extern size_t w32_image_size (Emacs_Pixmap);
#define FACE_DEFAULT (~0)
#include "frame.h"
#include "coding.h"
+#include "w32gdiplus.h"
#ifdef WINDOWSNT
-
-typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc)
- (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *);
-typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR);
-typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc)
- (GpImage *, PROPID, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc)
- (GpImage *, PROPID, UINT, PropertyItem *);
-typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc)
- (GpImage *, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc)
- (GpImage *, GUID *, UINT);
-typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc)
- (GpImage *, GDIPCONST GUID *, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc)
- (GpImage*, GDIPCONST GUID *, UINT);
-typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc)
- (WCHAR *, GpBitmap **);
-typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc)
- (IStream *, GpBitmap **);
-typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT);
-typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc)
- (GpBitmap *, HBITMAP *, ARGB);
-typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *);
-typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipGetImageEncodersSize_Proc) (UINT *, UINT *);
-typedef GpStatus (WINGDIPAPI *GdipGetImageEncoders_Proc)
- (UINT, UINT, ImageCodecInfo *);
-typedef GpStatus (WINGDIPAPI *GdipLoadImageFromFile_Proc)
- (GDIPCONST WCHAR *,GpImage **);
-typedef GpStatus (WINGDIPAPI *GdipGetImageThumbnail_Proc)
- (GpImage *, UINT, UINT, GpImage**, GetThumbnailImageAbort, VOID *);
-typedef GpStatus (WINGDIPAPI *GdipSaveImageToFile_Proc)
- (GpImage *, GDIPCONST WCHAR *, GDIPCONST CLSID *,
- GDIPCONST EncoderParameters *);
-
GdiplusStartup_Proc fn_GdiplusStartup;
GdiplusShutdown_Proc fn_GdiplusShutdown;
GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame;
GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile;
GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
+GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
SHCreateMemStream_Proc fn_SHCreateMemStream;
GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
GdipDisposeImage_Proc fn_GdipDisposeImage;
GdipLoadImageFromFile_Proc fn_GdipLoadImageFromFile;
GdipGetImageThumbnail_Proc fn_GdipGetImageThumbnail;
GdipSaveImageToFile_Proc fn_GdipSaveImageToFile;
+GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
static bool
gdiplus_init (void)
get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromStream");
if (!fn_GdipCreateBitmapFromStream)
return false;
+ fn_GdipCreateBitmapFromScan0 = (GdipCreateBitmapFromScan0_Proc)
+ get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromScan0");
+ if (!fn_GdipCreateBitmapFromScan0)
+ return false;
fn_GdipCreateHBITMAPFromBitmap = (GdipCreateHBITMAPFromBitmap_Proc)
get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap");
if (!fn_GdipCreateHBITMAPFromBitmap)
get_proc_addr (gdiplus_lib, "GdipSaveImageToFile");
if (!fn_GdipSaveImageToFile)
return false;
+ fn_GdipImageRotateFlip = (GdipImageRotateFlip_Proc)
+ get_proc_addr (gdiplus_lib, "GdipImageRotateFlip");
+ if (!fn_GdipImageRotateFlip)
+ return false;
return true;
}
-# undef GdiplusStartup
-# undef GdiplusShutdown
-# undef GdipGetPropertyItemSize
-# undef GdipGetPropertyItem
-# undef GdipImageGetFrameDimensionsCount
-# undef GdipImageGetFrameDimensionsList
-# undef GdipImageGetFrameCount
-# undef GdipImageSelectActiveFrame
-# undef GdipCreateBitmapFromFile
-# undef GdipCreateBitmapFromStream
-# undef SHCreateMemStream
-# undef GdipCreateHBITMAPFromBitmap
-# undef GdipDisposeImage
-# undef GdipGetImageHeight
-# undef GdipGetImageWidth
-# undef GdipGetImageEncodersSize
-# undef GdipGetImageEncoders
-# undef GdipLoadImageFromFile
-# undef GdipGetImageThumbnail
-# undef GdipSaveImageToFile
-
-# define GdiplusStartup fn_GdiplusStartup
-# define GdiplusShutdown fn_GdiplusShutdown
-# define GdipGetPropertyItemSize fn_GdipGetPropertyItemSize
-# define GdipGetPropertyItem fn_GdipGetPropertyItem
-# define GdipImageGetFrameDimensionsCount fn_GdipImageGetFrameDimensionsCount
-# define GdipImageGetFrameDimensionsList fn_GdipImageGetFrameDimensionsList
-# define GdipImageGetFrameCount fn_GdipImageGetFrameCount
-# define GdipImageSelectActiveFrame fn_GdipImageSelectActiveFrame
-# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile
-# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream
-# define SHCreateMemStream fn_SHCreateMemStream
-# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap
-# define GdipDisposeImage fn_GdipDisposeImage
-# define GdipGetImageHeight fn_GdipGetImageHeight
-# define GdipGetImageWidth fn_GdipGetImageWidth
-# define GdipGetImageEncodersSize fn_GdipGetImageEncodersSize
-# define GdipGetImageEncoders fn_GdipGetImageEncoders
-# define GdipLoadImageFromFile fn_GdipLoadImageFromFile
-# define GdipGetImageThumbnail fn_GdipGetImageThumbnail
-# define GdipSaveImageToFile fn_GdipSaveImageToFile
-
#endif /* WINDOWSNT */
static int gdip_initialized;
/* Initialize GDI+, return true if successful. */
-static bool
-gdiplus_startup (void)
+bool
+w32_gdiplus_startup (void)
{
GpStatus status;
But we don't yet support these in image.c. */
return false;
}
- return gdiplus_startup ();
+ return w32_gdiplus_startup ();
}
enum PropertyItem_type {
};
-static int
-get_encoder_clsid (const char *type, CLSID *clsid)
+int
+w32_gdip_get_encoder_clsid (const char *type, CLSID *clsid)
{
/* A simple cache based on the assumptions that many thumbnails will
be generated using the same TYPE. */
if (!gdiplus_started)
{
- if (!gdiplus_startup ())
+ if (!w32_gdiplus_startup ())
return Qnil;
}
CLSID thumb_clsid;
if (status == Ok
/* Get the GUID of the TYPE's encoder. */
- && get_encoder_clsid (SSDATA (type), &thumb_clsid) >= 0)
+ && w32_gdip_get_encoder_clsid (SSDATA (type), &thumb_clsid) >= 0)
{
/* Save the thumbnail image to a file of specified TYPE. */
wchar_t thumb_file_w[MAX_PATH];
*/
#include <config.h>
+#include <windows.h>
+#include <wingdi.h>
+#include <wtypes.h>
+#include <gdiplus.h>
+#ifndef CF_DIBV5
+# define CF_DIBV5 17
+# undef CF_MAX
+# define CF_MAX 18
+#endif
#include "lisp.h"
#include "w32common.h" /* os_subtype */
#include "w32term.h" /* for all of the w32 includes */
#include "w32select.h"
#include "blockinput.h"
#include "coding.h"
+#include "w32gdiplus.h"
#ifdef CYGWIN
#include <string.h>
return (ok ? string : Qnil);
}
+/* 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"
+};
+
+/* Must be called with block_input() active. */
+static bool
+convert_dibv5_to_png (char *data, int size, char *temp_file)
+{
+ CLSID clsid_png;
+
+ if (!w32_gdiplus_startup ()
+ || !w32_gdip_get_encoder_clsid ("png", &clsid_png))
+ return false;
+
+ BITMAPV5HEADER *bmi = (void *) data;
+ int stride = bmi->bV5SizeImage / bmi->bV5Height;
+ long offset = bmi->bV5Size + bmi->bV5ClrUsed * sizeof (RGBQUAD);
+ if (bmi->bV5Compression == BI_BITFIELDS)
+ offset += 12;
+ BYTE *scan0 = data + offset;
+
+ GpBitmap *bitmap = NULL;
+
+ GpStatus status
+ = GdipCreateBitmapFromScan0 (bmi->bV5Width, bmi->bV5Height, stride,
+ PixelFormat32bppARGB, scan0, &bitmap);
+
+ if (status != Ok)
+ return false;
+
+ /* The bitmap comes upside down. */
+ GdipImageRotateFlip (bitmap, RotateNoneFlipY);
+
+ WCHAR wide_filename[MAX_PATH];
+ filename_to_utf16 (temp_file, wide_filename);
+
+ status = GdipSaveImageToFile (bitmap, wide_filename, &clsid_png, NULL);
+ GdipDisposeImage (bitmap);
+ if (status != Ok)
+ return false;
+ return true;
+}
+
+static int
+get_clipboard_format_name (int format_index, char *name)
+{
+ *name = 0;
+ format_index = EnumClipboardFormats (format_index);
+ if (format_index == 0)
+ return 0;
+ if (format_index < CF_MAX)
+ strcpy (name, stdfmt_name[format_index]);
+ GetClipboardFormatName (format_index, name, 256);
+ return format_index;
+}
+
+DEFUN ("w32--get-clipboard-data-media", Fw32__get_clipboard_data_media,
+ Sw32__get_clipboard_data_media, 3, 3, 0,
+ doc: /* Gets media (not plain text) clipboard data in one of the given formats.
+
+FORMATS is a list of formats.
+TEMP-FILE-IN is the name of the file to store the data.
+
+Elements in FORMATS are symbols naming a format, such a image/png, or
+image/jpeg. For compatibility with X systems, some conventional
+format names are translated to equivalent MIME types, as configured with
+the variable 'w32--selection-target-translations'.
+
+The file named in TEMP-FILE-IN must be created by the caller, and also
+deleted if required.
+
+Returns nil it there is no such format, or something failed.
+If it returns t, then the caller should read the file to get the data.
+If it returns a string, then that is the data and the file is not used.
+
+When returning a string, it will be unibyte if IS-TEXTUAL is nil (the
+content is binary data). */)
+ (Lisp_Object formats, Lisp_Object temp_file_in, Lisp_Object is_textual)
+{
+ CHECK_LIST (formats);
+ CHECK_STRING (temp_file_in);
+
+ temp_file_in = Fexpand_file_name (temp_file_in, Qnil);
+ char *temp_file = SSDATA (ENCODE_FILE (temp_file_in));
+
+ Lisp_Object result = Qnil;
+
+ block_input();
+ if (!OpenClipboard (NULL))
+ {
+ unblock_input();
+ return Qnil;
+ }
+
+ for (int format_index = 0;;)
+ {
+ static char name[256];
+ format_index = get_clipboard_format_name (format_index, name);
+ if (format_index == 0)
+ break;
+
+ /* If name doesn't match any of the formats, try the next format. */
+ bool match = false;
+ for (Lisp_Object tail = formats; CONSP (tail); tail = XCDR (tail))
+ if (strcmp (name, SSDATA (SYMBOL_NAME (XCAR (tail)))) == 0)
+ match = true;
+ if (!match)
+ continue;
+
+ /* Of the standard formats, only DIBV5 is supported. */
+ if (format_index < CF_MAX && format_index != CF_DIBV5)
+ continue;
+
+ /* Found the format. */
+ HANDLE d = GetClipboardData (format_index);
+ if (!d)
+ break;
+ int size = GlobalSize (d);
+ char *data = GlobalLock (d);
+ if (!data)
+ break;
+ if (strcmp (name, "DIBV5") == 0)
+ {
+ if (convert_dibv5_to_png (data, size, temp_file))
+ result = Qt;
+ }
+ else
+ {
+ if (NILP (is_textual))
+ result = make_unibyte_string (data, size);
+ else
+ result = make_string (data, size);
+ }
+ GlobalUnlock (d);
+ break;
+ }
+ CloseClipboard ();
+ unblock_input ();
+ return result;
+}
DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
Sw32_get_clipboard_data, 0, 1, 0,
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
{
defsubr (&Sw32_set_clipboard_data);
defsubr (&Sw32_get_clipboard_data);
+ defsubr (&Sw32__get_clipboard_data_media);
defsubr (&Sw32_selection_exists_p);
defsubr (&Sw32_selection_targets);