aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCecilio Pardo2024-10-28 22:18:13 +0100
committerEli Zaretskii2024-11-03 15:12:20 +0200
commit8e7f5f97db647ce6e9606364dc15d8bbd7ef6016 (patch)
treeaa033dc97c284c7842dc291c6a9f7fbcd044fce8 /src
parent5ee56b86938b7759dd92f507d03907280f48ffca (diff)
downloademacs-8e7f5f97db647ce6e9606364dc15d8bbd7ef6016.tar.gz
emacs-8e7f5f97db647ce6e9606364dc15d8bbd7ef6016.zip
Add support for 'yank-media' on MS-Windows
Adds the capacity to handle types different from strings to the clipboard management functions on MS-Windows, and some logic required to convert media types names and content to be what yank-media and the modes that use it expect (bug#71909). * lisp/term/w32-win.el (w32--selection-target-translations): New variable that holds the name translations for media types. (w32--translate-selection-target): New function, translate the name of a media type. (w32--translate-reverse-selection-target): New function, reverse translation. (w32--get-selection): Modified to translate target names when asked for targets, and retrieve media types when asked for them. (w32--mime-type-textual-p): New function, checks if a MIME type is textual. * lisp/textmodes/sgml-mode.el (html-mode--image-yank-handler): Fixed the image save mechanism, that added line feed characters on MS-Windows, breaking binary formats. * src/w32image.c (gdiplus_init): Modified to fetch more functions fromm gdiplus. (get_encoder_clsid): Renamed to 'w32_gdip_get_encoder_clsid' and made nonstatic. (gdiplus_startup): Renamed to 'w32_gdiplus_startup' and made nonstatic. * src/w32select.c (stdfmt_name): Made global, was static function. (convert_dibv5_to_png): New function to convert DIBV5 clipboard format to PNG. (get_clipboard_format_name): New function get the name of a format given its index. (Fw32__get_clipboard_data_media): New function, retrieves and converts media content. (syms_of_w32select): Export new lisp functions. * src/w32gdiplus.h: New file, for definitions in w32image.c * doc/lispref/frames.texi: Updated with MS-Windows support. * etc/NEWS: Added entry about new feature.
Diffstat (limited to 'src')
-rw-r--r--src/w32gdiplus.h112
-rw-r--r--src/w32gui.h2
-rw-r--r--src/w32image.c104
-rw-r--r--src/w32select.c194
4 files changed, 303 insertions, 109 deletions
diff --git a/src/w32gdiplus.h b/src/w32gdiplus.h
new file mode 100644
index 00000000000..9d05ae6c190
--- /dev/null
+++ b/src/w32gdiplus.h
@@ -0,0 +1,112 @@
1#ifdef WINDOWSNT
2typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc)
3 (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *);
4typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR);
5typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc)
6 (GpImage *, PROPID, UINT *);
7typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc)
8 (GpImage *, PROPID, UINT, PropertyItem *);
9typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc)
10 (GpImage *, UINT *);
11typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc)
12 (GpImage *, GUID *, UINT);
13typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc)
14 (GpImage *, GDIPCONST GUID *, UINT *);
15typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc)
16 (GpImage*, GDIPCONST GUID *, UINT);
17typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc)
18 (WCHAR *, GpBitmap **);
19typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc)
20 (IStream *, GpBitmap **);
21typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromScan0_Proc)
22 (INT, INT, INT, PixelFormat, BYTE*, GpBitmap**);
23typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT);
24typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc)
25 (GpBitmap *, HBITMAP *, ARGB);
26typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *);
27typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *);
28typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *);
29typedef GpStatus (WINGDIPAPI *GdipGetImageEncodersSize_Proc) (UINT *, UINT *);
30typedef GpStatus (WINGDIPAPI *GdipGetImageEncoders_Proc)
31 (UINT, UINT, ImageCodecInfo *);
32typedef GpStatus (WINGDIPAPI *GdipLoadImageFromFile_Proc)
33 (GDIPCONST WCHAR *,GpImage **);
34typedef GpStatus (WINGDIPAPI *GdipGetImageThumbnail_Proc)
35 (GpImage *, UINT, UINT, GpImage**, GetThumbnailImageAbort, VOID *);
36typedef GpStatus (WINGDIPAPI *GdipSaveImageToFile_Proc)
37 (GpImage *, GDIPCONST WCHAR *, GDIPCONST CLSID *,
38 GDIPCONST EncoderParameters *);
39typedef GpStatus (WINGDIPAPI *GdipImageRotateFlip_Proc)
40 (GpImage *image, RotateFlipType rfType);
41
42extern GdiplusStartup_Proc fn_GdiplusStartup;
43extern GdiplusShutdown_Proc fn_GdiplusShutdown;
44extern GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
45extern GdipGetPropertyItem_Proc fn_GdipGetPropertyItem;
46extern GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount;
47extern GdipImageGetFrameDimensionsList_Proc fn_GdipImageGetFrameDimensionsList;
48extern GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount;
49extern GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame;
50extern GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile;
51extern GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
52extern GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
53extern SHCreateMemStream_Proc fn_SHCreateMemStream;
54extern GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
55extern GdipDisposeImage_Proc fn_GdipDisposeImage;
56extern GdipGetImageHeight_Proc fn_GdipGetImageHeight;
57extern GdipGetImageWidth_Proc fn_GdipGetImageWidth;
58extern GdipGetImageEncodersSize_Proc fn_GdipGetImageEncodersSize;
59extern GdipGetImageEncoders_Proc fn_GdipGetImageEncoders;
60extern GdipLoadImageFromFile_Proc fn_GdipLoadImageFromFile;
61extern GdipGetImageThumbnail_Proc fn_GdipGetImageThumbnail;
62extern GdipSaveImageToFile_Proc fn_GdipSaveImageToFile;
63extern GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
64
65# undef GdiplusStartup
66# undef GdiplusShutdown
67# undef GdipGetPropertyItemSize
68# undef GdipGetPropertyItem
69# undef GdipImageGetFrameDimensionsCount
70# undef GdipImageGetFrameDimensionsList
71# undef GdipImageGetFrameCount
72# undef GdipImageSelectActiveFrame
73# undef GdipCreateBitmapFromFile
74# undef GdipCreateBitmapFromStream
75# undef GdipCreateBitmapFromScan0
76# undef SHCreateMemStream
77# undef GdipCreateHBITMAPFromBitmap
78# undef GdipDisposeImage
79# undef GdipGetImageHeight
80# undef GdipGetImageWidth
81# undef GdipGetImageEncodersSize
82# undef GdipGetImageEncoders
83# undef GdipLoadImageFromFile
84# undef GdipGetImageThumbnail
85# undef GdipSaveImageToFile
86# undef GdipSaveImageRotateFlip
87
88# define GdiplusStartup fn_GdiplusStartup
89# define GdiplusShutdown fn_GdiplusShutdown
90# define GdipGetPropertyItemSize fn_GdipGetPropertyItemSize
91# define GdipGetPropertyItem fn_GdipGetPropertyItem
92# define GdipImageGetFrameDimensionsCount fn_GdipImageGetFrameDimensionsCount
93# define GdipImageGetFrameDimensionsList fn_GdipImageGetFrameDimensionsList
94# define GdipImageGetFrameCount fn_GdipImageGetFrameCount
95# define GdipImageSelectActiveFrame fn_GdipImageSelectActiveFrame
96# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile
97# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream
98# define GdipCreateBitmapFromScan0 fn_GdipCreateBitmapFromScan0
99# define SHCreateMemStream fn_SHCreateMemStream
100# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap
101# define GdipDisposeImage fn_GdipDisposeImage
102# define GdipGetImageHeight fn_GdipGetImageHeight
103# define GdipGetImageWidth fn_GdipGetImageWidth
104# define GdipGetImageEncodersSize fn_GdipGetImageEncodersSize
105# define GdipGetImageEncoders fn_GdipGetImageEncoders
106# define GdipLoadImageFromFile fn_GdipLoadImageFromFile
107# define GdipGetImageThumbnail fn_GdipGetImageThumbnail
108# define GdipSaveImageToFile fn_GdipSaveImageToFile
109# define GdipImageRotateFlip fn_GdipImageRotateFlip
110#endif
111
112int w32_gdip_get_encoder_clsid (const char *type, CLSID *clsid);
diff --git a/src/w32gui.h b/src/w32gui.h
index 739a790911e..26565dcae6b 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -45,7 +45,9 @@ struct image;
45extern int w32_load_image (struct frame *f, struct image *img, 45extern int w32_load_image (struct frame *f, struct image *img,
46 Lisp_Object spec_file, Lisp_Object spec_data); 46 Lisp_Object spec_file, Lisp_Object spec_data);
47extern bool w32_can_use_native_image_api (Lisp_Object); 47extern bool w32_can_use_native_image_api (Lisp_Object);
48extern bool w32_gdiplus_startup (void);
48extern void w32_gdiplus_shutdown (void); 49extern void w32_gdiplus_shutdown (void);
50
49extern size_t w32_image_size (Emacs_Pixmap); 51extern size_t w32_image_size (Emacs_Pixmap);
50 52
51#define FACE_DEFAULT (~0) 53#define FACE_DEFAULT (~0)
diff --git a/src/w32image.c b/src/w32image.c
index 359a4fa3a72..44eed087528 100644
--- a/src/w32image.c
+++ b/src/w32image.c
@@ -38,44 +38,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
38#include "frame.h" 38#include "frame.h"
39#include "coding.h" 39#include "coding.h"
40 40
41#include "w32gdiplus.h"
41#ifdef WINDOWSNT 42#ifdef WINDOWSNT
42
43typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc)
44 (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *);
45typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR);
46typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc)
47 (GpImage *, PROPID, UINT *);
48typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc)
49 (GpImage *, PROPID, UINT, PropertyItem *);
50typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc)
51 (GpImage *, UINT *);
52typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc)
53 (GpImage *, GUID *, UINT);
54typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc)
55 (GpImage *, GDIPCONST GUID *, UINT *);
56typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc)
57 (GpImage*, GDIPCONST GUID *, UINT);
58typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc)
59 (WCHAR *, GpBitmap **);
60typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc)
61 (IStream *, GpBitmap **);
62typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT);
63typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc)
64 (GpBitmap *, HBITMAP *, ARGB);
65typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *);
66typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *);
67typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *);
68typedef GpStatus (WINGDIPAPI *GdipGetImageEncodersSize_Proc) (UINT *, UINT *);
69typedef GpStatus (WINGDIPAPI *GdipGetImageEncoders_Proc)
70 (UINT, UINT, ImageCodecInfo *);
71typedef GpStatus (WINGDIPAPI *GdipLoadImageFromFile_Proc)
72 (GDIPCONST WCHAR *,GpImage **);
73typedef GpStatus (WINGDIPAPI *GdipGetImageThumbnail_Proc)
74 (GpImage *, UINT, UINT, GpImage**, GetThumbnailImageAbort, VOID *);
75typedef GpStatus (WINGDIPAPI *GdipSaveImageToFile_Proc)
76 (GpImage *, GDIPCONST WCHAR *, GDIPCONST CLSID *,
77 GDIPCONST EncoderParameters *);
78
79GdiplusStartup_Proc fn_GdiplusStartup; 43GdiplusStartup_Proc fn_GdiplusStartup;
80GdiplusShutdown_Proc fn_GdiplusShutdown; 44GdiplusShutdown_Proc fn_GdiplusShutdown;
81GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize; 45GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize;
@@ -86,6 +50,7 @@ GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount;
86GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame; 50GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame;
87GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile; 51GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile;
88GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream; 52GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream;
53GdipCreateBitmapFromScan0_Proc fn_GdipCreateBitmapFromScan0;
89SHCreateMemStream_Proc fn_SHCreateMemStream; 54SHCreateMemStream_Proc fn_SHCreateMemStream;
90GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap; 55GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap;
91GdipDisposeImage_Proc fn_GdipDisposeImage; 56GdipDisposeImage_Proc fn_GdipDisposeImage;
@@ -96,6 +61,7 @@ GdipGetImageEncoders_Proc fn_GdipGetImageEncoders;
96GdipLoadImageFromFile_Proc fn_GdipLoadImageFromFile; 61GdipLoadImageFromFile_Proc fn_GdipLoadImageFromFile;
97GdipGetImageThumbnail_Proc fn_GdipGetImageThumbnail; 62GdipGetImageThumbnail_Proc fn_GdipGetImageThumbnail;
98GdipSaveImageToFile_Proc fn_GdipSaveImageToFile; 63GdipSaveImageToFile_Proc fn_GdipSaveImageToFile;
64GdipImageRotateFlip_Proc fn_GdipImageRotateFlip;
99 65
100static bool 66static bool
101gdiplus_init (void) 67gdiplus_init (void)
@@ -146,6 +112,10 @@ gdiplus_init (void)
146 get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromStream"); 112 get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromStream");
147 if (!fn_GdipCreateBitmapFromStream) 113 if (!fn_GdipCreateBitmapFromStream)
148 return false; 114 return false;
115 fn_GdipCreateBitmapFromScan0 = (GdipCreateBitmapFromScan0_Proc)
116 get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromScan0");
117 if (!fn_GdipCreateBitmapFromScan0)
118 return false;
149 fn_GdipCreateHBITMAPFromBitmap = (GdipCreateHBITMAPFromBitmap_Proc) 119 fn_GdipCreateHBITMAPFromBitmap = (GdipCreateHBITMAPFromBitmap_Proc)
150 get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap"); 120 get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap");
151 if (!fn_GdipCreateHBITMAPFromBitmap) 121 if (!fn_GdipCreateHBITMAPFromBitmap)
@@ -196,52 +166,14 @@ gdiplus_init (void)
196 get_proc_addr (gdiplus_lib, "GdipSaveImageToFile"); 166 get_proc_addr (gdiplus_lib, "GdipSaveImageToFile");
197 if (!fn_GdipSaveImageToFile) 167 if (!fn_GdipSaveImageToFile)
198 return false; 168 return false;
169 fn_GdipImageRotateFlip = (GdipImageRotateFlip_Proc)
170 get_proc_addr (gdiplus_lib, "GdipImageRotateFlip");
171 if (!fn_GdipImageRotateFlip)
172 return false;
199 173
200 return true; 174 return true;
201} 175}
202 176
203# undef GdiplusStartup
204# undef GdiplusShutdown
205# undef GdipGetPropertyItemSize
206# undef GdipGetPropertyItem
207# undef GdipImageGetFrameDimensionsCount
208# undef GdipImageGetFrameDimensionsList
209# undef GdipImageGetFrameCount
210# undef GdipImageSelectActiveFrame
211# undef GdipCreateBitmapFromFile
212# undef GdipCreateBitmapFromStream
213# undef SHCreateMemStream
214# undef GdipCreateHBITMAPFromBitmap
215# undef GdipDisposeImage
216# undef GdipGetImageHeight
217# undef GdipGetImageWidth
218# undef GdipGetImageEncodersSize
219# undef GdipGetImageEncoders
220# undef GdipLoadImageFromFile
221# undef GdipGetImageThumbnail
222# undef GdipSaveImageToFile
223
224# define GdiplusStartup fn_GdiplusStartup
225# define GdiplusShutdown fn_GdiplusShutdown
226# define GdipGetPropertyItemSize fn_GdipGetPropertyItemSize
227# define GdipGetPropertyItem fn_GdipGetPropertyItem
228# define GdipImageGetFrameDimensionsCount fn_GdipImageGetFrameDimensionsCount
229# define GdipImageGetFrameDimensionsList fn_GdipImageGetFrameDimensionsList
230# define GdipImageGetFrameCount fn_GdipImageGetFrameCount
231# define GdipImageSelectActiveFrame fn_GdipImageSelectActiveFrame
232# define GdipCreateBitmapFromFile fn_GdipCreateBitmapFromFile
233# define GdipCreateBitmapFromStream fn_GdipCreateBitmapFromStream
234# define SHCreateMemStream fn_SHCreateMemStream
235# define GdipCreateHBITMAPFromBitmap fn_GdipCreateHBITMAPFromBitmap
236# define GdipDisposeImage fn_GdipDisposeImage
237# define GdipGetImageHeight fn_GdipGetImageHeight
238# define GdipGetImageWidth fn_GdipGetImageWidth
239# define GdipGetImageEncodersSize fn_GdipGetImageEncodersSize
240# define GdipGetImageEncoders fn_GdipGetImageEncoders
241# define GdipLoadImageFromFile fn_GdipLoadImageFromFile
242# define GdipGetImageThumbnail fn_GdipGetImageThumbnail
243# define GdipSaveImageToFile fn_GdipSaveImageToFile
244
245#endif /* WINDOWSNT */ 177#endif /* WINDOWSNT */
246 178
247static int gdip_initialized; 179static int gdip_initialized;
@@ -252,8 +184,8 @@ static GdiplusStartupOutput output;
252 184
253 185
254/* Initialize GDI+, return true if successful. */ 186/* Initialize GDI+, return true if successful. */
255static bool 187bool
256gdiplus_startup (void) 188w32_gdiplus_startup (void)
257{ 189{
258 GpStatus status; 190 GpStatus status;
259 191
@@ -305,7 +237,7 @@ w32_can_use_native_image_api (Lisp_Object type)
305 But we don't yet support these in image.c. */ 237 But we don't yet support these in image.c. */
306 return false; 238 return false;
307 } 239 }
308 return gdiplus_startup (); 240 return w32_gdiplus_startup ();
309} 241}
310 242
311enum PropertyItem_type { 243enum PropertyItem_type {
@@ -549,8 +481,8 @@ static struct thumb_type_data thumb_types [] =
549 }; 481 };
550 482
551 483
552static int 484int
553get_encoder_clsid (const char *type, CLSID *clsid) 485w32_gdip_get_encoder_clsid (const char *type, CLSID *clsid)
554{ 486{
555 /* A simple cache based on the assumptions that many thumbnails will 487 /* A simple cache based on the assumptions that many thumbnails will
556 be generated using the same TYPE. */ 488 be generated using the same TYPE. */
@@ -625,7 +557,7 @@ Return non-nil if thumbnail creation succeeds, nil otherwise. */)
625 557
626 if (!gdiplus_started) 558 if (!gdiplus_started)
627 { 559 {
628 if (!gdiplus_startup ()) 560 if (!w32_gdiplus_startup ())
629 return Qnil; 561 return Qnil;
630 } 562 }
631 563
@@ -649,7 +581,7 @@ Return non-nil if thumbnail creation succeeds, nil otherwise. */)
649 CLSID thumb_clsid; 581 CLSID thumb_clsid;
650 if (status == Ok 582 if (status == Ok
651 /* Get the GUID of the TYPE's encoder. */ 583 /* Get the GUID of the TYPE's encoder. */
652 && get_encoder_clsid (SSDATA (type), &thumb_clsid) >= 0) 584 && w32_gdip_get_encoder_clsid (SSDATA (type), &thumb_clsid) >= 0)
653 { 585 {
654 /* Save the thumbnail image to a file of specified TYPE. */ 586 /* Save the thumbnail image to a file of specified TYPE. */
655 wchar_t thumb_file_w[MAX_PATH]; 587 wchar_t thumb_file_w[MAX_PATH];
diff --git a/src/w32select.c b/src/w32select.c
index 006bf408b47..7e8dc3f0702 100644
--- a/src/w32select.c
+++ b/src/w32select.c
@@ -73,12 +73,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
73 */ 73 */
74 74
75#include <config.h> 75#include <config.h>
76#include <windows.h>
77#include <wingdi.h>
78#include <wtypes.h>
79#include <gdiplus.h>
80#ifndef CF_DIBV5
81# define CF_DIBV5 17
82# undef CF_MAX
83# define CF_MAX 18
84#endif
76#include "lisp.h" 85#include "lisp.h"
77#include "w32common.h" /* os_subtype */ 86#include "w32common.h" /* os_subtype */
78#include "w32term.h" /* for all of the w32 includes */ 87#include "w32term.h" /* for all of the w32 includes */
79#include "w32select.h" 88#include "w32select.h"
80#include "blockinput.h" 89#include "blockinput.h"
81#include "coding.h" 90#include "coding.h"
91#include "w32gdiplus.h"
82 92
83#ifdef CYGWIN 93#ifdef CYGWIN
84#include <string.h> 94#include <string.h>
@@ -787,6 +797,166 @@ DEFUN ("w32-set-clipboard-data", Fw32_set_clipboard_data,
787 return (ok ? string : Qnil); 797 return (ok ? string : Qnil);
788} 798}
789 799
800/* Xlib-like names for standard Windows clipboard data formats.
801 They are in upper-case to mimic xselect.c. A couple of the names
802 were changed to be more like their X counterparts. */
803static const char *stdfmt_name[] = {
804 "UNDEFINED",
805 "STRING",
806 "BITMAP",
807 "METAFILE",
808 "SYMLINK",
809 "DIF",
810 "TIFF",
811 "OEM_STRING",
812 "DIB",
813 "PALETTE",
814 "PENDATA",
815 "RIFF",
816 "WAVE",
817 "UTF8_STRING",
818 "ENHMETAFILE",
819 "FILE_NAMES", /* DND */
820 "LOCALE", /* not used */
821 "DIBV5"
822};
823
824/* Must be called with block_input() active. */
825static bool
826convert_dibv5_to_png (char *data, int size, char *temp_file)
827{
828 CLSID clsid_png;
829
830 if (!w32_gdiplus_startup ()
831 || !w32_gdip_get_encoder_clsid ("png", &clsid_png))
832 return false;
833
834 BITMAPV5HEADER *bmi = (void *) data;
835 int stride = bmi->bV5SizeImage / bmi->bV5Height;
836 long offset = bmi->bV5Size + bmi->bV5ClrUsed * sizeof (RGBQUAD);
837 if (bmi->bV5Compression == BI_BITFIELDS)
838 offset += 12;
839 BYTE *scan0 = data + offset;
840
841 GpBitmap *bitmap = NULL;
842
843 GpStatus status
844 = GdipCreateBitmapFromScan0 (bmi->bV5Width, bmi->bV5Height, stride,
845 PixelFormat32bppARGB, scan0, &bitmap);
846
847 if (status != Ok)
848 return false;
849
850 /* The bitmap comes upside down. */
851 GdipImageRotateFlip (bitmap, RotateNoneFlipY);
852
853 WCHAR wide_filename[MAX_PATH];
854 filename_to_utf16 (temp_file, wide_filename);
855
856 status = GdipSaveImageToFile (bitmap, wide_filename, &clsid_png, NULL);
857 GdipDisposeImage (bitmap);
858 if (status != Ok)
859 return false;
860 return true;
861}
862
863static int
864get_clipboard_format_name (int format_index, char *name)
865{
866 *name = 0;
867 format_index = EnumClipboardFormats (format_index);
868 if (format_index == 0)
869 return 0;
870 if (format_index < CF_MAX)
871 strcpy (name, stdfmt_name[format_index]);
872 GetClipboardFormatName (format_index, name, 256);
873 return format_index;
874}
875
876DEFUN ("w32--get-clipboard-data-media", Fw32__get_clipboard_data_media,
877 Sw32__get_clipboard_data_media, 3, 3, 0,
878 doc: /* Gets media (not plain text) clipboard data in one of the given formats.
879
880FORMATS is a list of formats.
881TEMP-FILE-IN is the name of the file to store the data.
882
883Elements in FORMATS are symbols naming a format, such a image/png, or
884image/jpeg. For compatibility with X systems, some conventional
885format names are translated to equivalent MIME types, as configured with
886the variable 'w32--selection-target-translations'.
887
888The file named in TEMP-FILE-IN must be created by the caller, and also
889deleted if required.
890
891Returns nil it there is no such format, or something failed.
892If it returns t, then the caller should read the file to get the data.
893If it returns a string, then that is the data and the file is not used.
894
895When returning a string, it will be unibyte if IS-TEXTUAL is nil (the
896content is binary data). */)
897 (Lisp_Object formats, Lisp_Object temp_file_in, Lisp_Object is_textual)
898{
899 CHECK_LIST (formats);
900 CHECK_STRING (temp_file_in);
901
902 temp_file_in = Fexpand_file_name (temp_file_in, Qnil);
903 char *temp_file = SSDATA (ENCODE_FILE (temp_file_in));
904
905 Lisp_Object result = Qnil;
906
907 block_input();
908 if (!OpenClipboard (NULL))
909 {
910 unblock_input();
911 return Qnil;
912 }
913
914 for (int format_index = 0;;)
915 {
916 static char name[256];
917 format_index = get_clipboard_format_name (format_index, name);
918 if (format_index == 0)
919 break;
920
921 /* If name doesn't match any of the formats, try the next format. */
922 bool match = false;
923 for (Lisp_Object tail = formats; CONSP (tail); tail = XCDR (tail))
924 if (strcmp (name, SSDATA (SYMBOL_NAME (XCAR (tail)))) == 0)
925 match = true;
926 if (!match)
927 continue;
928
929 /* Of the standard formats, only DIBV5 is supported. */
930 if (format_index < CF_MAX && format_index != CF_DIBV5)
931 continue;
932
933 /* Found the format. */
934 HANDLE d = GetClipboardData (format_index);
935 if (!d)
936 break;
937 int size = GlobalSize (d);
938 char *data = GlobalLock (d);
939 if (!data)
940 break;
941 if (strcmp (name, "DIBV5") == 0)
942 {
943 if (convert_dibv5_to_png (data, size, temp_file))
944 result = Qt;
945 }
946 else
947 {
948 if (NILP (is_textual))
949 result = make_unibyte_string (data, size);
950 else
951 result = make_string (data, size);
952 }
953 GlobalUnlock (d);
954 break;
955 }
956 CloseClipboard ();
957 unblock_input ();
958 return result;
959}
790 960
791DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data, 961DEFUN ("w32-get-clipboard-data", Fw32_get_clipboard_data,
792 Sw32_get_clipboard_data, 0, 1, 0, 962 Sw32_get_clipboard_data, 0, 1, 0,
@@ -1069,29 +1239,6 @@ for `CLIPBOARD'. The return value is a vector of symbols, each symbol
1069representing a data format that is currently available in the clipboard. */) 1239representing a data format that is currently available in the clipboard. */)
1070 (Lisp_Object selection, Lisp_Object terminal) 1240 (Lisp_Object selection, Lisp_Object terminal)
1071{ 1241{
1072 /* Xlib-like names for standard Windows clipboard data formats.
1073 They are in upper-case to mimic xselect.c. A couple of the names
1074 were changed to be more like their X counterparts. */
1075 static const char *stdfmt_name[] = {
1076 "UNDEFINED",
1077 "STRING",
1078 "BITMAP",
1079 "METAFILE",
1080 "SYMLINK",
1081 "DIF",
1082 "TIFF",
1083 "OEM_STRING",
1084 "DIB",
1085 "PALETTE",
1086 "PENDATA",
1087 "RIFF",
1088 "WAVE",
1089 "UTF8_STRING",
1090 "ENHMETAFILE",
1091 "FILE_NAMES", /* DND */
1092 "LOCALE", /* not used */
1093 "DIBV5"
1094 };
1095 CHECK_SYMBOL (selection); 1242 CHECK_SYMBOL (selection);
1096 1243
1097 /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check 1244 /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
@@ -1166,6 +1313,7 @@ syms_of_w32select (void)
1166{ 1313{
1167 defsubr (&Sw32_set_clipboard_data); 1314 defsubr (&Sw32_set_clipboard_data);
1168 defsubr (&Sw32_get_clipboard_data); 1315 defsubr (&Sw32_get_clipboard_data);
1316 defsubr (&Sw32__get_clipboard_data_media);
1169 defsubr (&Sw32_selection_exists_p); 1317 defsubr (&Sw32_selection_exists_p);
1170 defsubr (&Sw32_selection_targets); 1318 defsubr (&Sw32_selection_targets);
1171 1319