XEmacs 21.2.30 "Hygeia".
[chise/xemacs-chise.git.1] / src / glyphs-msw.c
1 /* mswindows-specific glyph objects.
2    Copyright (C) 1998, 1999, 2000 Andy Piper.
3
4 This file is part of XEmacs.
5
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
9 later version.
10
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
14 for more details.
15
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.  */
20
21 /* Synched up with: Not in FSF. */
22
23 /* written by Andy Piper <andy@xemacs.org> plagerising bits from
24    glyphs-x.c */
25
26 #include <config.h>
27 #include "lisp.h"
28 #include "lstream.h"
29
30 #define OEMRESOURCE /* Define OCR_ and friend constants */
31 #include "console-msw.h"
32 #include "glyphs-msw.h"
33 #include "objects-msw.h"
34
35 #include "window.h"
36 #include "elhash.h"
37 #include "buffer.h"
38 #include "frame.h"
39 #include "insdel.h"
40 #include "opaque.h"
41 #include "sysfile.h"
42 #include "faces.h"
43 #include "imgproc.h"
44
45 #ifdef FILE_CODING
46 #include "file-coding.h"
47 #endif
48 #include <stdio.h>
49 #include <ctype.h>
50 #ifdef HAVE_XFACE
51 #include <setjmp.h>
52 #endif
53
54 #define WIDGET_GLYPH_SLOT 0
55
56 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
57 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
58 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
59 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
60 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
61 #ifdef HAVE_JPEG
62 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
63 #endif
64 #ifdef HAVE_TIFF
65 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
66 #endif
67 #ifdef HAVE_PNG
68 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
69 #endif
70 #ifdef HAVE_GIF
71 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
72 #endif
73 #ifdef HAVE_XPM
74 DEFINE_DEVICE_IIFORMAT (mswindows, xpm);
75 #endif
76 DEFINE_DEVICE_IIFORMAT (mswindows, xbm);
77 #ifdef HAVE_XFACE
78 DEFINE_DEVICE_IIFORMAT (mswindows, xface);
79 #endif
80 DEFINE_DEVICE_IIFORMAT (mswindows, button);
81 DEFINE_DEVICE_IIFORMAT (mswindows, edit_field);
82 DEFINE_DEVICE_IIFORMAT (mswindows, subwindow);
83 DEFINE_DEVICE_IIFORMAT (mswindows, widget);
84 DEFINE_DEVICE_IIFORMAT (mswindows, label);
85 DEFINE_DEVICE_IIFORMAT (mswindows, scrollbar);
86 DEFINE_DEVICE_IIFORMAT (mswindows, combo_box);
87 DEFINE_DEVICE_IIFORMAT (mswindows, progress_gauge);
88 DEFINE_DEVICE_IIFORMAT (mswindows, tree_view);
89 DEFINE_DEVICE_IIFORMAT (mswindows, tab_control);
90
91 DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp);
92 Lisp_Object Qbmp;
93 Lisp_Object Vmswindows_bitmap_file_path;
94 static  COLORREF transparent_color = RGB (1,1,1);
95
96 DEFINE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource);
97 Lisp_Object Q_resource_type, Q_resource_id;
98 Lisp_Object Qmswindows_resource;
99
100 static void
101 mswindows_initialize_dibitmap_image_instance (Lisp_Image_Instance *ii,
102                                              int slices,
103                                              enum image_instance_type type);
104 static void
105 mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image,
106                                           struct frame* f);
107
108 #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3)))
109
110 /************************************************************************/
111 /* convert from a series of RGB triples to a BITMAPINFO formated for the*/
112 /* proper display                                                       */
113 /************************************************************************/
114 static BITMAPINFO* convert_EImage_to_DIBitmap (Lisp_Object device,
115                                                int width, int height,
116                                                unsigned char *pic,
117                                                int *bit_count,
118                                                unsigned char** bmp_data)
119 {
120   struct device *d = XDEVICE (device);
121   int i,j;
122   RGBQUAD* colortbl;
123   int           ncolors;
124   BITMAPINFO*   bmp_info;
125   unsigned char *ip, *dp;
126
127   if (DEVICE_MSWINDOWS_BITSPIXEL (d) > 0)
128     {
129       int bpline = BPLINE(width * 3);
130       /* FIXME: we can do this because 24bpp implies no color table, once
131        * we start palettizing this is no longer true. The X versions of
132        * this function quantises to 256 colors or bit masks down to a
133        * long. Windows can actually handle rgb triples in the raw so I
134        * don't see much point trying to optimize down to the best
135        * structure - unless it has memory / color allocation implications
136        * .... */
137       bmp_info=xnew_and_zero (BITMAPINFO);
138
139       if (!bmp_info)
140         {
141           return NULL;
142         }
143
144       bmp_info->bmiHeader.biBitCount=24; /* just RGB triples for now */
145       bmp_info->bmiHeader.biCompression=BI_RGB; /* just RGB triples for now */
146       bmp_info->bmiHeader.biSizeImage=width*height*3;
147
148       /* bitmap data needs to be in blue, green, red triples - in that
149          order, eimage is in RGB format so we need to convert */
150       *bmp_data = xnew_array_and_zero (unsigned char, bpline * height);
151       *bit_count = bpline * height;
152
153       if (!bmp_data)
154         {
155           xfree (bmp_info);
156           return NULL;
157         }
158
159       ip = pic;
160       for (i = height-1; i >= 0; i--) {
161         dp = (*bmp_data) + (i * bpline);
162         for (j = 0; j < width; j++) {
163           dp[2] =*ip++;
164           dp[1] =*ip++;
165           *dp   =*ip++;
166           dp += 3;
167         }
168       }
169     }
170   else                          /* scale to 256 colors */
171     {
172       int rd,gr,bl;
173       quant_table *qtable;
174       int bpline = BPLINE (width * 3);
175       /* Quantize the image and get a histogram while we're at it.
176          Do this first to save memory */
177       qtable = build_EImage_quantable(pic, width, height, 256);
178       if (qtable == NULL) return NULL;
179
180       /* use our quantize table to allocate the colors */
181       ncolors = qtable->num_active_colors;
182       bmp_info=(BITMAPINFO*)xmalloc_and_zero (sizeof(BITMAPINFOHEADER) +
183                                              sizeof(RGBQUAD) * ncolors);
184       if (!bmp_info)
185         {
186           xfree (qtable);
187           return NULL;
188         }
189
190       colortbl=(RGBQUAD*)(((unsigned char*)bmp_info)+sizeof(BITMAPINFOHEADER));
191
192       bmp_info->bmiHeader.biBitCount=8;
193       bmp_info->bmiHeader.biCompression=BI_RGB;
194       bmp_info->bmiHeader.biSizeImage=bpline*height;
195       bmp_info->bmiHeader.biClrUsed=ncolors;
196       bmp_info->bmiHeader.biClrImportant=ncolors;
197
198       *bmp_data = (unsigned char *) xmalloc_and_zero (bpline * height);
199       *bit_count = bpline * height;
200
201       if (!*bmp_data)
202         {
203           xfree (qtable);
204           xfree (bmp_info);
205           return NULL;
206         }
207
208       /* build up an RGBQUAD colortable */
209       for (i = 0; i < qtable->num_active_colors; i++) {
210         colortbl[i].rgbRed = (BYTE) qtable->rm[i];
211         colortbl[i].rgbGreen = (BYTE) qtable->gm[i];
212         colortbl[i].rgbBlue = (BYTE) qtable->bm[i];
213         colortbl[i].rgbReserved = 0;
214       }
215
216       /* now build up the data. picture has to be upside-down and
217          back-to-front for msw bitmaps */
218       ip = pic;
219       for (i = height-1; i >= 0; i--) {
220         dp = (*bmp_data) + (i * bpline);
221         for (j = 0; j < width; j++) {
222           rd = *ip++;
223           gr = *ip++;
224           bl = *ip++;
225           *dp++ = QUANT_GET_COLOR (qtable,rd,gr,bl);
226         }
227       }
228       xfree (qtable);
229     }
230   /* fix up the standard stuff */
231   bmp_info->bmiHeader.biWidth=width;
232   bmp_info->bmiHeader.biHeight=height;
233   bmp_info->bmiHeader.biPlanes=1;
234   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
235   bmp_info->bmiHeader.biXPelsPerMeter=0; /* unless you know better */
236   bmp_info->bmiHeader.biYPelsPerMeter=0;
237
238   return bmp_info;
239 }
240
241 /* Given a pixmap filename, look through all of the "standard" places
242    where the file might be located.  Return a full pathname if found;
243    otherwise, return Qnil. */
244
245 static Lisp_Object
246 mswindows_locate_pixmap_file (Lisp_Object name)
247 {
248   /* This function can GC if IN_REDISPLAY is false */
249   Lisp_Object found;
250
251   /* Check non-absolute pathnames with a directory component relative to
252      the search path; that's the way Xt does it. */
253   if (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 0)) ||
254       (XSTRING_BYTE (name, 0) == '.' &&
255        (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 1)) ||
256         (XSTRING_BYTE (name, 1) == '.' &&
257          (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 2)))))))
258     {
259       if (!NILP (Ffile_readable_p (name)))
260         return Fexpand_file_name (name, Qnil);
261       else
262         return Qnil;
263     }
264
265   if (locate_file (Vmswindows_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
266     {
267       Lisp_Object temp = list1 (Vdata_directory);
268       struct gcpro gcpro1;
269
270       GCPRO1 (temp);
271       locate_file (temp, name, Qnil, &found, R_OK);
272       UNGCPRO;
273     }
274
275   return found;
276 }
277
278 \f
279 /* Initialize an image instance from a bitmap
280
281    DEST_MASK specifies the mask of allowed image types.
282
283    If this fails, signal an error.  INSTANTIATOR is only used
284    in the error message. */
285
286 static void
287 init_image_instance_from_dibitmap (Lisp_Image_Instance *ii,
288                                    BITMAPINFO *bmp_info,
289                                    int dest_mask,
290                                    void *bmp_data,
291                                    int bmp_bits,
292                                    int slices,
293                                    Lisp_Object instantiator,
294                                    int x_hot, int y_hot,
295                                    int create_mask)
296 {
297   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
298   struct device *d = XDEVICE (device);
299   struct frame *f;
300   void* bmp_buf=0;
301   enum image_instance_type type;
302   HBITMAP bitmap;
303   HDC hdc;
304
305   if (!DEVICE_MSWINDOWS_P (d))
306     signal_simple_error ("Not an mswindows device", device);
307
308   if (NILP (DEVICE_SELECTED_FRAME (d)))
309     signal_simple_error ("No selected frame on mswindows device", device);
310
311   f = XFRAME (DEVICE_SELECTED_FRAME (d));
312
313   if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
314     type = IMAGE_COLOR_PIXMAP;
315   else if (dest_mask & IMAGE_POINTER_MASK)
316     type = IMAGE_POINTER;
317   else
318     incompatible_image_types (instantiator, dest_mask,
319                               IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
320   hdc = FRAME_MSWINDOWS_CDC (f);
321
322   bitmap=CreateDIBSection (hdc,
323                           bmp_info,
324                           DIB_RGB_COLORS,
325                           &bmp_buf,
326                           0,0);
327
328   if (!bitmap || !bmp_buf)
329     signal_simple_error ("Unable to create bitmap", instantiator);
330
331   /* copy in the actual bitmap */
332   memcpy (bmp_buf, bmp_data, bmp_bits);
333
334   mswindows_initialize_dibitmap_image_instance (ii, slices, type);
335
336   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
337     find_keyword_in_vector (instantiator, Q_file);
338
339   /* Fixup a set of bitmaps. */
340   IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap;
341
342   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
343   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth;
344   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight;
345   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = bmp_info->bmiHeader.biBitCount;
346   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), x_hot);
347   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), y_hot);
348
349   if (create_mask)
350     {
351       mswindows_initialize_image_instance_mask (ii, f);
352     }
353
354   if (type == IMAGE_POINTER)
355     {
356       mswindows_initialize_image_instance_icon(ii, TRUE);
357     }
358 }
359
360 static void
361 image_instance_add_dibitmap (Lisp_Image_Instance *ii,
362                              BITMAPINFO *bmp_info,
363                              void *bmp_data,
364                              int bmp_bits,
365                              int slice,
366                              Lisp_Object instantiator)
367 {
368   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
369   struct device *d = XDEVICE (device);
370   struct frame *f = XFRAME (DEVICE_SELECTED_FRAME (d));
371   void* bmp_buf=0;
372   HDC hdc = FRAME_MSWINDOWS_CDC (f);
373   HBITMAP bitmap = CreateDIBSection (hdc,
374                                      bmp_info,
375                                      DIB_RGB_COLORS,
376                                      &bmp_buf,
377                                      0,0);
378
379   if (!bitmap || !bmp_buf)
380     signal_simple_error ("Unable to create bitmap", instantiator);
381
382   /* copy in the actual bitmap */
383   memcpy (bmp_buf, bmp_data, bmp_bits);
384   IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (ii, slice) = bitmap;
385 }
386
387 static void
388 mswindows_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
389                                            int width, int height,
390                                            int slices,
391                                            unsigned char *eimage,
392                                            int dest_mask,
393                                            Lisp_Object instantiator,
394                                            Lisp_Object domain)
395 {
396   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
397   BITMAPINFO*           bmp_info;
398   unsigned char*        bmp_data;
399   int                   bmp_bits;
400   COLORREF              bkcolor;
401   int slice;
402
403   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
404     signal_simple_error ("Not an mswindows device", device);
405
406   /* this is a hack but MaskBlt and TransparentBlt are not supported
407      on most windows variants */
408   bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR
409     (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain)));
410
411   for (slice = 0; slice < slices; slice++)
412     {
413       /* build a bitmap from the eimage */
414       if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height,
415                                                  eimage + (width * height * 3 * slice),
416                                                  &bmp_bits, &bmp_data)))
417         {
418           signal_simple_error ("EImage to DIBitmap conversion failed",
419                                instantiator);
420         }
421
422       /* Now create the pixmap and set up the image instance */
423       if (slice == 0)
424         init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
425                                            bmp_data, bmp_bits, slices, instantiator,
426                                            0, 0, 0);
427       else
428         image_instance_add_dibitmap (ii, bmp_info, bmp_data, bmp_bits, slice,
429                                      instantiator);
430
431       xfree (bmp_info);
432       xfree (bmp_data);
433     }
434 }
435
436 static void set_mono_pixel ( unsigned char* bits,
437                              int bpline, int height,
438                              int x, int y, int white )
439 {
440   int i;
441   unsigned char    bitnum;
442   /* Find the byte on which this scanline begins */
443   i = (height - y - 1) * bpline;
444   /* Find the byte containing this pixel */
445   i += (x >> 3);
446   /* Which bit is it? */
447   bitnum = (unsigned char)( 7 - (x % 8) );
448   if( white )         /* Turn it on */
449     bits[i] |= (1<<bitnum);
450   else         /* Turn it off */
451     bits[i] &= ~(1<<bitnum);
452 }
453
454 static void
455 mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image,
456                                           struct frame* f)
457 {
458   HBITMAP mask;
459   HGDIOBJ old = NULL;
460   HDC hcdc = FRAME_MSWINDOWS_CDC (f);
461   unsigned char *dibits, *and_bits;
462   BITMAPINFO *bmp_info =
463     (BITMAPINFO*) xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
464   int i, j;
465   int height = IMAGE_INSTANCE_PIXMAP_HEIGHT (image);
466
467   int maskbpline = BPLINE ((IMAGE_INSTANCE_PIXMAP_WIDTH (image)+7)/8);
468   int bpline = BPLINE (IMAGE_INSTANCE_PIXMAP_WIDTH (image) * 3);
469
470   if (!bmp_info)
471     return;
472
473   bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image);
474   bmp_info->bmiHeader.biHeight = height;
475   bmp_info->bmiHeader.biPlanes=1;
476   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
477   bmp_info->bmiHeader.biBitCount=1;
478   bmp_info->bmiHeader.biCompression=BI_RGB;
479   bmp_info->bmiHeader.biClrUsed = 2;
480   bmp_info->bmiHeader.biClrImportant = 2;
481   bmp_info->bmiHeader.biSizeImage = height * maskbpline;
482   bmp_info->bmiColors[0].rgbRed = 0;
483   bmp_info->bmiColors[0].rgbGreen = 0;
484   bmp_info->bmiColors[0].rgbBlue = 0;
485   bmp_info->bmiColors[0].rgbReserved = 0;
486   bmp_info->bmiColors[1].rgbRed = 255;
487   bmp_info->bmiColors[1].rgbGreen = 255;
488   bmp_info->bmiColors[1].rgbBlue = 255;
489   bmp_info->bmiColors[0].rgbReserved = 0;
490
491   if (!(mask = CreateDIBSection (hcdc,
492                                  bmp_info,
493                                  DIB_RGB_COLORS,
494                                  (void**)&and_bits,
495                                  0,0)))
496     {
497       xfree (bmp_info);
498       return;
499     }
500
501   old = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (image));
502   /* build up an in-memory set of bits to mess with */
503   xzero (*bmp_info);
504
505   bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image);
506   bmp_info->bmiHeader.biHeight = -height;
507   bmp_info->bmiHeader.biPlanes=1;
508   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
509   bmp_info->bmiHeader.biBitCount=24;
510   bmp_info->bmiHeader.biCompression=BI_RGB;
511   bmp_info->bmiHeader.biClrUsed = 0;
512   bmp_info->bmiHeader.biClrImportant = 0;
513   bmp_info->bmiHeader.biSizeImage = height * bpline;
514
515   dibits = (unsigned char*) xmalloc_and_zero (bpline * height);
516   if (GetDIBits (hcdc,
517                  IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
518                  0,
519                  height,
520                  dibits,
521                  bmp_info,
522                  DIB_RGB_COLORS) <= 0)
523     {
524       xfree (bmp_info);
525       return;
526     }
527
528   /* now set the colored bits in the mask and transparent ones to
529      black in the original */
530   for (i=0; i<IMAGE_INSTANCE_PIXMAP_WIDTH (image); i++)
531     {
532       for (j=0; j<height; j++)
533         {
534           unsigned char* idx = &dibits[j * bpline + i * 3];
535
536           if (RGB (idx[2], idx[1], idx[0]) == transparent_color)
537             {
538               idx[0] = idx[1] = idx[2] = 0;
539               set_mono_pixel (and_bits, maskbpline, height, i, j, TRUE);
540             }
541           else
542             {
543               set_mono_pixel (and_bits, maskbpline, height, i, j, FALSE);
544             }
545         }
546     }
547
548   SetDIBits (hcdc,
549              IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
550              0,
551              height,
552              dibits,
553              bmp_info,
554              DIB_RGB_COLORS);
555
556   xfree (bmp_info);
557   xfree (dibits);
558
559   SelectObject(hcdc, old);
560
561   IMAGE_INSTANCE_MSWINDOWS_MASK (image) = mask;
562 }
563
564 void
565 mswindows_initialize_image_instance_icon (Lisp_Image_Instance* image,
566                                           int cursor)
567 {
568   ICONINFO x_icon;
569
570   /* we rely on windows to do any resizing necessary */
571   x_icon.fIcon=cursor ? FALSE : TRUE;
572   x_icon.xHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image));
573   x_icon.yHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image));
574   x_icon.hbmMask=IMAGE_INSTANCE_MSWINDOWS_MASK (image);
575   x_icon.hbmColor=IMAGE_INSTANCE_MSWINDOWS_BITMAP (image);
576
577   IMAGE_INSTANCE_MSWINDOWS_ICON (image)=
578     CreateIconIndirect (&x_icon);
579 }
580
581 HBITMAP
582 mswindows_create_resized_bitmap (Lisp_Image_Instance* ii,
583                                  struct frame* f,
584                                  int newx, int newy)
585 {
586   HBITMAP newbmp;
587   HGDIOBJ old1, old2;
588   HDC hcdc = FRAME_MSWINDOWS_CDC (f);
589   HDC hdcDst = CreateCompatibleDC (hcdc);
590
591   old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii));
592
593   newbmp = CreateCompatibleBitmap (hcdc, newx, newy);
594
595   old2 = SelectObject (hdcDst, newbmp);
596
597   if (!StretchBlt (hdcDst, 0, 0, newx, newy,
598                    hcdc, 0, 0,
599                    IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
600                    IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
601                    SRCCOPY))
602     {
603       DeleteObject (newbmp);
604       DeleteDC (hdcDst);
605       return 0;
606     }
607
608   SelectObject (hdcDst, old2);
609   SelectObject (hcdc, old1);
610   DeleteDC (hdcDst);
611
612   return newbmp;
613 }
614
615 HBITMAP
616 mswindows_create_resized_mask (Lisp_Image_Instance* ii,
617                                struct frame* f,
618                                int newx, int newy)
619 {
620   if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii))
621     {
622       HBITMAP newmask;
623       HGDIOBJ old1, old2;
624       HDC hcdc = FRAME_MSWINDOWS_CDC (f);
625       HDC hdcDst = CreateCompatibleDC (hcdc);
626
627       old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_MASK (ii));
628       newmask = CreateCompatibleBitmap(hcdc, newx, newy);
629       old2 = SelectObject (hdcDst, newmask);
630
631       if (!StretchBlt(hdcDst, 0, 0, newx, newy,
632                       hcdc, 0, 0,
633                       IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
634                       IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
635                       SRCCOPY))
636         {
637           DeleteObject (newmask);
638           DeleteDC (hdcDst);
639           return NULL;
640         }
641
642       SelectObject (hdcDst, old2);
643       SelectObject (hcdc, old1);
644
645       DeleteDC (hdcDst);
646
647       return newmask;
648     }
649
650   return NULL;
651 }
652
653 int
654 mswindows_resize_dibitmap_instance (Lisp_Image_Instance* ii,
655                                     struct frame* f,
656                                     int newx, int newy)
657 {
658   HBITMAP newbmp = mswindows_create_resized_bitmap (ii, f, newx, newy);
659   HBITMAP newmask = mswindows_create_resized_mask (ii, f, newx, newy);
660
661   if (!newbmp)
662     return FALSE;
663
664   if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii))
665     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii));
666   if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii))
667     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (ii));
668
669   IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = newbmp;
670   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = newmask;
671   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = newx;
672   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = newy;
673
674   return TRUE;
675 }
676
677 /**********************************************************************
678  *                               XPM                                  *
679  **********************************************************************/
680
681 #ifdef HAVE_XPM
682
683 struct color_symbol
684 {
685   char*         name;
686   COLORREF      color;
687 };
688
689 static struct color_symbol*
690 extract_xpm_color_names (Lisp_Object device,
691                          Lisp_Object domain,
692                          Lisp_Object color_symbol_alist,
693                          int* nsymbols)
694 {
695   /* This function can GC */
696   Lisp_Object rest;
697   Lisp_Object results = Qnil;
698   int i, j;
699   struct color_symbol *colortbl;
700   struct gcpro gcpro1, gcpro2;
701
702   GCPRO2 (results, device);
703
704   /* We built up results to be (("name" . #<color>) ...) so that if an
705      error happens we don't lose any malloc()ed data, or more importantly,
706      leave any pixels allocated in the server. */
707   i = 0;
708   LIST_LOOP (rest, color_symbol_alist)
709     {
710       Lisp_Object cons = XCAR (rest);
711       Lisp_Object name = XCAR (cons);
712       Lisp_Object value = XCDR (cons);
713       if (NILP (value))
714         continue;
715       if (STRINGP (value))
716         value =
717           Fmake_color_instance
718           (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
719       else
720         {
721           assert (COLOR_SPECIFIERP (value));
722           value = Fspecifier_instance (value, domain, Qnil, Qnil);
723         }
724       if (NILP (value))
725         continue;
726       results = noseeum_cons (noseeum_cons (name, value), results);
727       i++;
728     }
729   UNGCPRO;                      /* no more evaluation */
730
731   *nsymbols=i;
732   if (i == 0) return 0;
733
734   colortbl = xnew_array_and_zero (struct color_symbol, i);
735
736   for (j=0; j<i; j++)
737     {
738       Lisp_Object cons = XCAR (results);
739       colortbl[j].color =
740         COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
741
742       TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (cons),
743                           C_STRING_ALLOCA, colortbl[j].name,
744                           Qnative);
745       colortbl[j].name = xstrdup (colortbl[j].name); /* mustn't lose this when we return */
746       free_cons (XCONS (cons));
747       cons = results;
748       results = XCDR (results);
749       free_cons (XCONS (cons));
750     }
751   return colortbl;
752 }
753
754 static int xpm_to_eimage (Lisp_Object image, const Extbyte *buffer,
755                           unsigned char** data,
756                           int* width, int* height,
757                           int* x_hot, int* y_hot,
758                           int* transp,
759                           struct color_symbol* color_symbols,
760                           int nsymbols)
761 {
762   XpmImage xpmimage;
763   XpmInfo xpminfo;
764   int result, i, j, transp_idx, maskbpline;
765   unsigned char* dptr;
766   unsigned int* sptr;
767   COLORREF color; /* the american spelling virus hits again .. */
768   COLORREF* colortbl;
769
770   xzero (xpmimage);
771   xzero (xpminfo);
772   xpminfo.valuemask=XpmHotspot;
773   *transp=FALSE;
774
775   result = XpmCreateXpmImageFromBuffer ((char*)buffer,
776                                        &xpmimage,
777                                        &xpminfo);
778   switch (result)
779     {
780     case XpmSuccess:
781       break;
782     case XpmFileInvalid:
783       {
784         signal_simple_error ("Invalid XPM data", image);
785       }
786     case XpmNoMemory:
787       {
788         signal_double_file_error ("Parsing pixmap data",
789                                   "out of memory", image);
790       }
791     default:
792       {
793         signal_double_file_error_2 ("Parsing pixmap data",
794                                     "unknown error code",
795                                     make_int (result), image);
796       }
797     }
798
799   *width = xpmimage.width;
800   *height = xpmimage.height;
801   maskbpline = BPLINE ((~7UL & (unsigned long)(*width + 7)) / 8);
802
803   *data = xnew_array_and_zero (unsigned char, *width * *height * 3);
804
805   if (!*data)
806     {
807       XpmFreeXpmImage (&xpmimage);
808       XpmFreeXpmInfo (&xpminfo);
809       return 0;
810     }
811
812   /* build a color table to speed things up */
813   colortbl = xnew_array_and_zero (COLORREF, xpmimage.ncolors);
814   if (!colortbl)
815     {
816       xfree (*data);
817       XpmFreeXpmImage (&xpmimage);
818       XpmFreeXpmInfo (&xpminfo);
819       return 0;
820     }
821
822   for (i=0; i<xpmimage.ncolors; i++)
823     {
824       /* goto alert!!!! */
825       /* pick up symbolic colors in preference */
826       if (xpmimage.colorTable[i].symbolic)
827         {
828           if (!strcasecmp (xpmimage.colorTable[i].symbolic,"BgColor")
829               ||
830               !strcasecmp (xpmimage.colorTable[i].symbolic,"None"))
831             {
832               *transp=TRUE;
833               colortbl[i]=transparent_color;
834               transp_idx=i;
835               goto label_found_color;
836             }
837           else if (color_symbols)
838             {
839               for (j = 0; j<nsymbols; j++)
840                 {
841                   if (!strcmp (xpmimage.colorTable[i].symbolic,
842                                color_symbols[j].name ))
843                     {
844                       colortbl[i]=color_symbols[j].color;
845                       goto label_found_color;
846                     }
847                 }
848             }
849           else if (xpmimage.colorTable[i].c_color == 0)
850             {
851               goto label_no_color;
852             }
853         }
854       /* pick up transparencies */
855       if (!strcasecmp (xpmimage.colorTable[i].c_color,"None"))
856         {
857           *transp=TRUE;
858           colortbl[i]=transparent_color;
859           transp_idx=i;
860           goto label_found_color;
861         }
862       /* finally pick up a normal color spec */
863       if (xpmimage.colorTable[i].c_color)
864         {
865           colortbl[i]=
866             mswindows_string_to_color (xpmimage.colorTable[i].c_color);
867           goto label_found_color;
868         }
869
870     label_no_color:
871       xfree (*data);
872       xfree (colortbl);
873       XpmFreeXpmImage (&xpmimage);
874       XpmFreeXpmInfo (&xpminfo);
875       return 0;
876
877     label_found_color:;
878     }
879
880   /* convert the image */
881   sptr=xpmimage.data;
882   dptr=*data;
883   for (i = 0; i< *width * *height; i++)
884     {
885       color = colortbl[*sptr++];
886
887       /* split out the 0x02bbggrr colorref into an rgb triple */
888       *dptr++=GetRValue (color); /* red */
889       *dptr++=GetGValue (color); /* green */
890       *dptr++=GetBValue (color); /* blue */
891     }
892
893   *x_hot=xpminfo.x_hotspot;
894   *y_hot=xpminfo.y_hotspot;
895
896   XpmFreeXpmImage (&xpmimage);
897   XpmFreeXpmInfo (&xpminfo);
898   xfree (colortbl);
899   return TRUE;
900 }
901
902 static void
903 mswindows_xpm_instantiate (Lisp_Object image_instance,
904                            Lisp_Object instantiator,
905                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
906                            int dest_mask, Lisp_Object domain)
907 {
908   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
909   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
910   const Extbyte         *bytes;
911   Extcount              len;
912   unsigned char         *eimage;
913   int                   width, height, x_hot, y_hot;
914   BITMAPINFO*           bmp_info;
915   unsigned char*        bmp_data;
916   int                   bmp_bits;
917   int                   nsymbols=0, transp;
918   struct color_symbol*  color_symbols=NULL;
919
920   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
921   Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
922                                                            Q_color_symbols);
923
924   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
925     signal_simple_error ("Not an mswindows device", device);
926
927   assert (!NILP (data));
928
929   TO_EXTERNAL_FORMAT (LISP_STRING, data,
930                       ALLOCA, (bytes, len),
931                       Qbinary);
932
933   /* in case we have color symbols */
934   color_symbols = extract_xpm_color_names (device, domain,
935                                            color_symbol_alist, &nsymbols);
936
937   /* convert to an eimage to make processing easier */
938   if (!xpm_to_eimage (image_instance, bytes, &eimage, &width, &height,
939                       &x_hot, &y_hot, &transp, color_symbols, nsymbols))
940     {
941       signal_simple_error ("XPM to EImage conversion failed",
942                            image_instance);
943     }
944
945   if (color_symbols)
946     {
947       while (nsymbols--)
948         {
949           xfree (color_symbols[nsymbols].name);
950         }
951       xfree(color_symbols);
952     }
953
954   /* build a bitmap from the eimage */
955   if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage,
956                                              &bmp_bits, &bmp_data)))
957     {
958       signal_simple_error ("XPM to EImage conversion failed",
959                            image_instance);
960     }
961   xfree (eimage);
962
963   /* Now create the pixmap and set up the image instance */
964   init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
965                                      bmp_data, bmp_bits, 1, instantiator,
966                                      x_hot, y_hot, transp);
967
968   xfree (bmp_info);
969   xfree (bmp_data);
970 }
971 #endif /* HAVE_XPM */
972
973 /**********************************************************************
974  *                               BMP                                  *
975  **********************************************************************/
976
977 static void
978 bmp_validate (Lisp_Object instantiator)
979 {
980   file_or_data_must_be_present (instantiator);
981 }
982
983 static Lisp_Object
984 bmp_normalize (Lisp_Object inst, Lisp_Object console_type)
985 {
986   return simple_image_type_normalize (inst, console_type, Qbmp);
987 }
988
989 static int
990 bmp_possible_dest_types (void)
991 {
992   return IMAGE_COLOR_PIXMAP_MASK;
993 }
994
995 static void
996 bmp_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
997                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
998                  int dest_mask, Lisp_Object domain)
999 {
1000   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1001   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1002   const Extbyte         *bytes;
1003   Extcount              len;
1004   BITMAPFILEHEADER*     bmp_file_header;
1005   BITMAPINFO*           bmp_info;
1006   void*                 bmp_data;
1007   int                   bmp_bits;
1008   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1009
1010   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1011     signal_simple_error ("Not an mswindows device", device);
1012
1013   assert (!NILP (data));
1014
1015   TO_EXTERNAL_FORMAT (LISP_STRING, data,
1016                       ALLOCA, (bytes, len),
1017                       Qbinary);
1018
1019   /* Then slurp the image into memory, decoding along the way.
1020      The result is the image in a simple one-byte-per-pixel
1021      format. */
1022
1023   bmp_file_header=(BITMAPFILEHEADER*)bytes;
1024   bmp_info = (BITMAPINFO*)(bytes + sizeof(BITMAPFILEHEADER));
1025   bmp_data = (Extbyte*)bytes + bmp_file_header->bfOffBits;
1026   bmp_bits = bmp_file_header->bfSize - bmp_file_header->bfOffBits;
1027
1028   /* Now create the pixmap and set up the image instance */
1029   init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
1030                                      bmp_data, bmp_bits, 1, instantiator,
1031                                      0, 0, 0);
1032 }
1033
1034 \f
1035 /**********************************************************************
1036  *                             RESOURCES                              *
1037  **********************************************************************/
1038
1039 static void
1040 mswindows_resource_validate (Lisp_Object instantiator)
1041 {
1042   if ((NILP (find_keyword_in_vector (instantiator, Q_file))
1043        &&
1044        NILP (find_keyword_in_vector (instantiator, Q_resource_id)))
1045       ||
1046       NILP (find_keyword_in_vector (instantiator, Q_resource_type)))
1047     signal_simple_error ("Must supply :file, :resource-id and :resource-type",
1048                          instantiator);
1049 }
1050
1051 static Lisp_Object
1052 mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type)
1053 {
1054   /* This function can call lisp */
1055   Lisp_Object file = Qnil;
1056   struct gcpro gcpro1, gcpro2;
1057   Lisp_Object alist = Qnil;
1058
1059   GCPRO2 (file, alist);
1060
1061   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1062                                              console_type);
1063
1064   if (CONSP (file)) /* failure locating filename */
1065     signal_double_file_error ("Opening pixmap file",
1066                               "no such file or directory",
1067                               Fcar (file));
1068
1069   if (NILP (file)) /* no conversion necessary */
1070     RETURN_UNGCPRO (inst);
1071
1072   alist = tagged_vector_to_alist (inst);
1073
1074   {
1075     alist = remassq_no_quit (Q_file, alist);
1076     alist = Fcons (Fcons (Q_file, file), alist);
1077   }
1078
1079   {
1080     Lisp_Object result = alist_to_tagged_vector (Qmswindows_resource, alist);
1081     free_alist (alist);
1082     RETURN_UNGCPRO (result);
1083   }
1084 }
1085
1086 static int
1087 mswindows_resource_possible_dest_types (void)
1088 {
1089   return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
1090 }
1091
1092 typedef struct
1093 {
1094   char *name;
1095   int   resource_id;
1096 } resource_t;
1097
1098 #ifndef OCR_ICOCUR
1099 #define OCR_ICOCUR          32647
1100 #define OIC_SAMPLE          32512
1101 #define OIC_HAND            32513
1102 #define OIC_QUES            32514
1103 #define OIC_BANG            32515
1104 #define OIC_NOTE            32516
1105 #define OIC_WINLOGO         32517
1106 #if defined (__CYGWIN32__) && CYGWIN_VERSION_DLL_MAJOR < 21
1107 #define LR_SHARED           0x8000
1108 #endif
1109 #endif
1110
1111 static const resource_t bitmap_table[] =
1112 {
1113   /* bitmaps */
1114   { "close", OBM_CLOSE },
1115   { "uparrow", OBM_UPARROW },
1116   { "dnarrow", OBM_DNARROW },
1117   { "rgarrow", OBM_RGARROW },
1118   { "lfarrow", OBM_LFARROW },
1119   { "reduce", OBM_REDUCE },
1120   { "zoom", OBM_ZOOM },
1121   { "restore", OBM_RESTORE },
1122   { "reduced", OBM_REDUCED },
1123   { "zoomd", OBM_ZOOMD },
1124   { "restored", OBM_RESTORED },
1125   { "uparrowd", OBM_UPARROWD },
1126   { "dnarrowd", OBM_DNARROWD },
1127   { "rgarrowd", OBM_RGARROWD },
1128   { "lfarrowd", OBM_LFARROWD },
1129   { "mnarrow", OBM_MNARROW },
1130   { "combo", OBM_COMBO },
1131   { "uparrowi", OBM_UPARROWI },
1132   { "dnarrowi", OBM_DNARROWI },
1133   { "rgarrowi", OBM_RGARROWI },
1134   { "lfarrowi", OBM_LFARROWI },
1135   { "size", OBM_SIZE },
1136   { "btsize", OBM_BTSIZE },
1137   { "check", OBM_CHECK },
1138   { "checkboxes", OBM_CHECKBOXES },
1139   { "btncorners" , OBM_BTNCORNERS },
1140   {0}
1141 };
1142
1143 static const resource_t cursor_table[] =
1144 {
1145   /* cursors */
1146   { "normal", OCR_NORMAL },
1147   { "ibeam", OCR_IBEAM },
1148   { "wait", OCR_WAIT },
1149   { "cross", OCR_CROSS },
1150   { "up", OCR_UP },
1151   /* { "icon", OCR_ICON }, */
1152   { "sizenwse", OCR_SIZENWSE },
1153   { "sizenesw", OCR_SIZENESW },
1154   { "sizewe", OCR_SIZEWE },
1155   { "sizens", OCR_SIZENS },
1156   { "sizeall", OCR_SIZEALL },
1157   /* { "icour", OCR_ICOCUR }, */
1158   { "no", OCR_NO },
1159   { 0 }
1160 };
1161
1162 static const resource_t icon_table[] =
1163 {
1164   /* icons */
1165   { "sample", OIC_SAMPLE },
1166   { "hand", OIC_HAND },
1167   { "ques", OIC_QUES },
1168   { "bang", OIC_BANG },
1169   { "note", OIC_NOTE },
1170   { "winlogo", OIC_WINLOGO },
1171   {0}
1172 };
1173
1174 static int resource_name_to_resource (Lisp_Object name, int type)
1175 {
1176   const resource_t* res = (type == IMAGE_CURSOR ? cursor_table
1177                            : type == IMAGE_ICON ? icon_table
1178                            : bitmap_table);
1179
1180   if (INTP (name))
1181     {
1182       return XINT (name);
1183     }
1184   else if (!STRINGP (name))
1185     {
1186       signal_simple_error ("invalid resource identifier", name);
1187     }
1188
1189   do {
1190     Extbyte* nm=0;
1191     TO_EXTERNAL_FORMAT (LISP_STRING, name,
1192                         C_STRING_ALLOCA, nm,
1193                         Qnative);
1194       if (!strcasecmp ((char*)res->name, nm))
1195       return res->resource_id;
1196   } while ((++res)->name);
1197   return 0;
1198 }
1199
1200 static int
1201 resource_symbol_to_type (Lisp_Object data)
1202 {
1203   if (EQ (data, Qcursor))
1204     return IMAGE_CURSOR;
1205   else if (EQ (data, Qicon))
1206     return IMAGE_ICON;
1207   else if (EQ (data, Qbitmap))
1208     return IMAGE_BITMAP;
1209   else
1210     return 0;
1211 }
1212
1213 static void
1214 mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1215                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1216                     int dest_mask, Lisp_Object domain)
1217 {
1218   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1219   unsigned int type = 0;
1220   HANDLE himage = NULL;
1221   LPCTSTR resid=0;
1222   HINSTANCE hinst = NULL;
1223   ICONINFO iconinfo;
1224   enum image_instance_type iitype;
1225   char* fname=0;
1226   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1227
1228   Lisp_Object file = find_keyword_in_vector (instantiator, Q_file);
1229   Lisp_Object resource_type = find_keyword_in_vector (instantiator,
1230                                                       Q_resource_type);
1231   Lisp_Object resource_id = find_keyword_in_vector (instantiator,
1232                                                     Q_resource_id);
1233
1234   xzero (iconinfo);
1235
1236   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1237     signal_simple_error ("Not an mswindows device", device);
1238
1239   type = resource_symbol_to_type (resource_type);
1240
1241   if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR)
1242     iitype = IMAGE_POINTER;
1243   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1244     iitype = IMAGE_COLOR_PIXMAP;
1245   else
1246     incompatible_image_types (instantiator, dest_mask,
1247                               IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
1248
1249   /* mess with the keyword info we were provided with */
1250   if (!NILP (file))
1251     {
1252       Extbyte* f=0;
1253       TO_EXTERNAL_FORMAT (LISP_STRING, file,
1254                           C_STRING_ALLOCA, f,
1255                           Qfile_name);
1256 #ifdef __CYGWIN32__
1257       CYGWIN_WIN32_PATH (f, fname);
1258 #else
1259       fname = f;
1260 #endif
1261
1262       if (NILP (resource_id))
1263         resid = (LPCTSTR)fname;
1264       else
1265         {
1266           hinst = LoadLibraryEx (fname, NULL,
1267                                  LOAD_LIBRARY_AS_DATAFILE);
1268           resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1269                                                            type));
1270
1271           if (!resid)
1272             TO_EXTERNAL_FORMAT (LISP_STRING, resource_id,
1273                                 C_STRING_ALLOCA, resid,
1274                                 Qnative);
1275         }
1276     }
1277   else if (!(resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1278                                                                type))))
1279     signal_simple_error ("Invalid resource identifier", resource_id);
1280
1281   /* load the image */
1282   if (!(himage = LoadImage (hinst, resid, type, 0, 0,
1283                             LR_CREATEDIBSECTION | LR_DEFAULTSIZE |
1284                             LR_SHARED |
1285                             (!NILP (file) ? LR_LOADFROMFILE : 0))))
1286     {
1287       signal_simple_error ("Cannot load image", instantiator);
1288     }
1289
1290   if (hinst)
1291     FreeLibrary (hinst);
1292
1293   mswindows_initialize_dibitmap_image_instance (ii, 1, iitype);
1294
1295   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file;
1296   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) =
1297     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
1298   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) =
1299     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON);
1300   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1301
1302   /* hey, we've got an icon type thing so we can reverse engineer the
1303      bitmap and mask */
1304   if (type != IMAGE_BITMAP)
1305     {
1306       GetIconInfo ((HICON)himage, &iconinfo);
1307       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = iconinfo.hbmColor;
1308       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = iconinfo.hbmMask;
1309       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), iconinfo.xHotspot);
1310       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), iconinfo.yHotspot);
1311       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = (HICON) himage;
1312     }
1313   else
1314     {
1315       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = NULL;
1316       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = (HBITMAP) himage;
1317       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
1318       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1319       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1320     }
1321 }
1322
1323 static void
1324 check_valid_resource_symbol (Lisp_Object data)
1325 {
1326   CHECK_SYMBOL (data);
1327   if (!resource_symbol_to_type (data))
1328     signal_simple_error ("invalid resource type", data);
1329 }
1330
1331 static void
1332 check_valid_resource_id (Lisp_Object data)
1333 {
1334   if (!resource_name_to_resource (data, IMAGE_CURSOR)
1335       &&
1336       !resource_name_to_resource (data, IMAGE_ICON)
1337       &&
1338       !resource_name_to_resource (data, IMAGE_BITMAP))
1339     signal_simple_error ("invalid resource identifier", data);
1340 }
1341
1342 /**********************************************************************
1343  *                             XBM                                    *
1344  **********************************************************************/
1345 #ifndef HAVE_X_WINDOWS
1346 /* $XConsortium: RdBitF.c,v 1.10 94/04/17 20:16:13 kaleb Exp $ */
1347
1348 /*
1349
1350 Copyright (c) 1988  X Consortium
1351
1352 Permission is hereby granted, free of charge, to any person obtaining a copy
1353 of this software and associated documentation files (the "Software"), to deal
1354 in the Software without restriction, including without limitation the rights
1355 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1356 copies of the Software, and to permit persons to whom the Software is
1357 furnished to do so, subject to the following conditions:
1358
1359 The above copyright notice and this permission notice shall be included in
1360 all copies or substantial portions of the Software.
1361
1362 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1363 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1364 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1365 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1366 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1367 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1368
1369 Except as contained in this notice, the name of the X Consortium shall not be
1370 used in advertising or otherwise to promote the sale, use or other dealings
1371 in this Software without prior written authorization from the X Consortium.
1372
1373 */
1374
1375 /*
1376  * This file contains miscellaneous utility routines and is not part of the
1377  * Xlib standard.
1378  *
1379  * Public entry points:
1380  *
1381  *     XmuReadBitmapData                read data from FILE descriptor
1382  *     XmuReadBitmapDataFromFile        read X10 or X11 format bitmap files
1383  *                                      and return data
1384  *
1385  * Note that this file and ../X/XRdBitF.c look very similar....  Keep them
1386  * that way (but don't use common source code so that people can have one
1387  * without the other).
1388  */
1389
1390
1391 /*
1392  * Based on an optimized version provided by Jim Becker, August 5, 1988.
1393  */
1394 #ifndef BitmapSuccess
1395 #define BitmapSuccess           0
1396 #define BitmapOpenFailed        1
1397 #define BitmapFileInvalid       2
1398 #define BitmapNoMemory          3
1399 #endif
1400 #define MAX_SIZE 255
1401
1402 /* shared data for the image read/parse logic */
1403 static short hexTable[256];             /* conversion value */
1404 static int initialized = FALSE; /* easier to fill in at run time */
1405
1406 /*
1407  *      Table index for the hex values. Initialized once, first time.
1408  *      Used for translation value or delimiter significance lookup.
1409  */
1410 static void initHexTable()
1411 {
1412     /*
1413      * We build the table at run time for several reasons:
1414      *
1415      *     1.  portable to non-ASCII machines.
1416      *     2.  still reentrant since we set the init flag after setting table.
1417      *     3.  easier to extend.
1418      *     4.  less prone to bugs.
1419      */
1420     hexTable['0'] = 0;  hexTable['1'] = 1;
1421     hexTable['2'] = 2;  hexTable['3'] = 3;
1422     hexTable['4'] = 4;  hexTable['5'] = 5;
1423     hexTable['6'] = 6;  hexTable['7'] = 7;
1424     hexTable['8'] = 8;  hexTable['9'] = 9;
1425     hexTable['A'] = 10; hexTable['B'] = 11;
1426     hexTable['C'] = 12; hexTable['D'] = 13;
1427     hexTable['E'] = 14; hexTable['F'] = 15;
1428     hexTable['a'] = 10; hexTable['b'] = 11;
1429     hexTable['c'] = 12; hexTable['d'] = 13;
1430     hexTable['e'] = 14; hexTable['f'] = 15;
1431
1432     /* delimiters of significance are flagged w/ negative value */
1433     hexTable[' '] = -1; hexTable[','] = -1;
1434     hexTable['}'] = -1; hexTable['\n'] = -1;
1435     hexTable['\t'] = -1;
1436
1437     initialized = TRUE;
1438 }
1439
1440 /*
1441  *      read next hex value in the input stream, return -1 if EOF
1442  */
1443 static int NextInt ( FILE *fstream )
1444 {
1445     int ch;
1446     int value = 0;
1447     int gotone = 0;
1448     int done = 0;
1449
1450     /* loop, accumulate hex value until find delimiter  */
1451     /* skip any initial delimiters found in read stream */
1452
1453     while (!done) {
1454         ch = getc(fstream);
1455         if (ch == EOF) {
1456             value       = -1;
1457             done++;
1458         } else {
1459             /* trim high bits, check type and accumulate */
1460             ch &= 0xff;
1461             if (isascii(ch) && isxdigit(ch)) {
1462                 value = (value << 4) + hexTable[ch];
1463                 gotone++;
1464             } else if ((hexTable[ch]) < 0 && gotone)
1465               done++;
1466         }
1467     }
1468     return value;
1469 }
1470
1471
1472 /*
1473  * The data returned by the following routine is always in left-most byte
1474  * first and left-most bit first.  If it doesn't return BitmapSuccess then
1475  * its arguments won't have been touched.  This routine should look as much
1476  * like the Xlib routine XReadBitmapfile as possible.
1477  */
1478 int read_bitmap_data (FILE* fstream, unsigned int *width,
1479                       unsigned int *height, unsigned char **datap,
1480                       int *x_hot, int *y_hot)
1481 {
1482     unsigned char *data = NULL;         /* working variable */
1483     char line[MAX_SIZE];                /* input line from file */
1484     int size;                           /* number of bytes of data */
1485     char name_and_type[MAX_SIZE];       /* an input line */
1486     char *type;                         /* for parsing */
1487     int value;                          /* from an input line */
1488     int version10p;                     /* boolean, old format */
1489     int padding;                        /* to handle alignment */
1490     int bytes_per_line;                 /* per scanline of data */
1491     unsigned int ww = 0;                /* width */
1492     unsigned int hh = 0;                /* height */
1493     int hx = -1;                        /* x hotspot */
1494     int hy = -1;                        /* y hotspot */
1495
1496 #define Xmalloc(size) malloc(size)
1497
1498     /* first time initialization */
1499     if (initialized == FALSE) initHexTable();
1500
1501     /* error cleanup and return macro   */
1502 #define RETURN(code) { if (data) free (data); return code; }
1503
1504     while (fgets(line, MAX_SIZE, fstream)) {
1505         if (strlen(line) == MAX_SIZE-1) {
1506             RETURN (BitmapFileInvalid);
1507         }
1508         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
1509             if (!(type = strrchr(name_and_type, '_')))
1510               type = name_and_type;
1511             else
1512               type++;
1513
1514             if (!strcmp("width", type))
1515               ww = (unsigned int) value;
1516             if (!strcmp("height", type))
1517               hh = (unsigned int) value;
1518             if (!strcmp("hot", type)) {
1519                 if (type-- == name_and_type || type-- == name_and_type)
1520                   continue;
1521                 if (!strcmp("x_hot", type))
1522                   hx = value;
1523                 if (!strcmp("y_hot", type))
1524                   hy = value;
1525             }
1526             continue;
1527         }
1528
1529         if (sscanf(line, "static short %s = {", name_and_type) == 1)
1530           version10p = 1;
1531         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
1532           version10p = 0;
1533         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
1534           version10p = 0;
1535         else
1536           continue;
1537
1538         if (!(type = strrchr(name_and_type, '_')))
1539           type = name_and_type;
1540         else
1541           type++;
1542
1543         if (strcmp("bits[]", type))
1544           continue;
1545
1546         if (!ww || !hh)
1547           RETURN (BitmapFileInvalid);
1548
1549         if ((ww % 16) && ((ww % 16) < 9) && version10p)
1550           padding = 1;
1551         else
1552           padding = 0;
1553
1554         bytes_per_line = (ww+7)/8 + padding;
1555
1556         size = bytes_per_line * hh;
1557         data = (unsigned char *) Xmalloc ((unsigned int) size);
1558         if (!data)
1559           RETURN (BitmapNoMemory);
1560
1561         if (version10p) {
1562             unsigned char *ptr;
1563             int bytes;
1564
1565             for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
1566                 if ((value = NextInt(fstream)) < 0)
1567                   RETURN (BitmapFileInvalid);
1568                 *(ptr++) = value;
1569                 if (!padding || ((bytes+2) % bytes_per_line))
1570                   *(ptr++) = value >> 8;
1571             }
1572         } else {
1573             unsigned char *ptr;
1574             int bytes;
1575
1576             for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
1577                 if ((value = NextInt(fstream)) < 0)
1578                   RETURN (BitmapFileInvalid);
1579                 *ptr=value;
1580             }
1581         }
1582         break;
1583     }                                   /* end while */
1584
1585     if (data == NULL) {
1586         RETURN (BitmapFileInvalid);
1587     }
1588
1589     *datap = data;
1590     data = NULL;
1591     *width = ww;
1592     *height = hh;
1593     if (x_hot) *x_hot = hx;
1594     if (y_hot) *y_hot = hy;
1595
1596     RETURN (BitmapSuccess);
1597 }
1598
1599
1600 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
1601                                 unsigned int *height, unsigned char **datap,
1602                                 int *x_hot, int *y_hot)
1603 {
1604     FILE *fstream;
1605     int status;
1606
1607     if ((fstream = fopen (filename, "r")) == NULL) {
1608         return BitmapOpenFailed;
1609     }
1610     status = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
1611     fclose (fstream);
1612     return status;
1613 }
1614 #endif /* HAVE_X_WINDOWS */
1615
1616 /* this table flips four bits around. */
1617 static int flip_table[] =
1618 {
1619   0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
1620 };
1621
1622 /* the bitmap data comes in the following format: Widths are padded to
1623    a multiple of 8.  Scan lines are stored in increasing byte order
1624    from left to right, little-endian within a byte.  0 = white, 1 =
1625    black.  It must be converted to the following format: Widths are
1626    padded to a multiple of 16.  Scan lines are stored in increasing
1627    byte order from left to right, big-endian within a byte.  0 =
1628    black, 1 = white.  */
1629 static HBITMAP
1630 xbm_create_bitmap_from_data (HDC hdc, char *data,
1631                              unsigned int width, unsigned int height,
1632                              int mask, COLORREF fg, COLORREF bg)
1633 {
1634   int old_width = (width + 7)/8;
1635   int new_width = BPLINE (2*((width + 15)/16));
1636   unsigned char *offset;
1637   void *bmp_buf = 0;
1638   unsigned char *new_data, *new_offset;
1639   int i, j;
1640   BITMAPINFO *bmp_info =
1641     (BITMAPINFO*) xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
1642   HBITMAP bitmap;
1643
1644   if (!bmp_info)
1645     return NULL;
1646
1647   new_data = (unsigned char *) xmalloc_and_zero (height * new_width);
1648
1649   if (!new_data)
1650     {
1651       xfree (bmp_info);
1652       return NULL;
1653     }
1654
1655   for (i=0; i<height; i++)
1656     {
1657       offset = data + i*old_width;
1658       new_offset = new_data + i*new_width;
1659
1660       for (j=0; j<old_width; j++)
1661         {
1662           int byte = offset[j];
1663           new_offset[j] = ~ (unsigned char)
1664             ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]);
1665         }
1666     }
1667
1668   /* if we want a mask invert the bits */
1669   if (!mask)
1670     {
1671       new_offset = &new_data[height * new_width];
1672       while (new_offset-- != new_data)
1673         {
1674           *new_offset ^= 0xff;
1675         }
1676     }
1677
1678   bmp_info->bmiHeader.biWidth=width;
1679   bmp_info->bmiHeader.biHeight=-(LONG)height;
1680   bmp_info->bmiHeader.biPlanes=1;
1681   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
1682   bmp_info->bmiHeader.biBitCount=1;
1683   bmp_info->bmiHeader.biCompression=BI_RGB;
1684   bmp_info->bmiHeader.biClrUsed = 2;
1685   bmp_info->bmiHeader.biClrImportant = 2;
1686   bmp_info->bmiHeader.biSizeImage = height * new_width;
1687   bmp_info->bmiColors[0].rgbRed = GetRValue (fg);
1688   bmp_info->bmiColors[0].rgbGreen = GetGValue (fg);
1689   bmp_info->bmiColors[0].rgbBlue = GetBValue (fg);
1690   bmp_info->bmiColors[0].rgbReserved = 0;
1691   bmp_info->bmiColors[1].rgbRed = GetRValue (bg);
1692   bmp_info->bmiColors[1].rgbGreen = GetGValue (bg);
1693   bmp_info->bmiColors[1].rgbBlue = GetBValue (bg);
1694   bmp_info->bmiColors[1].rgbReserved = 0;
1695
1696   bitmap = CreateDIBSection (hdc,
1697                              bmp_info,
1698                              DIB_RGB_COLORS,
1699                              &bmp_buf,
1700                              0,0);
1701
1702   xfree (bmp_info);
1703
1704   if (!bitmap || !bmp_buf)
1705     {
1706       xfree (new_data);
1707       return NULL;
1708     }
1709
1710   /* copy in the actual bitmap */
1711   memcpy (bmp_buf, new_data, height * new_width);
1712   xfree (new_data);
1713
1714   return bitmap;
1715 }
1716
1717 /* Given inline data for a mono pixmap, initialize the given
1718    image instance accordingly. */
1719
1720 static void
1721 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1722                                      int width, int height,
1723                                      /* Note that data is in ext-format! */
1724                                      const char *bits,
1725                                      Lisp_Object instantiator,
1726                                      Lisp_Object pointer_fg,
1727                                      Lisp_Object pointer_bg,
1728                                      int dest_mask,
1729                                      HBITMAP mask,
1730                                      Lisp_Object mask_filename)
1731 {
1732   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1733   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (device)));
1734   Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1735   Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1736   enum image_instance_type type;
1737   COLORREF black = PALETTERGB (0,0,0);
1738   COLORREF white = PALETTERGB (255,255,255);
1739
1740   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1741
1742   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1743     signal_simple_error ("Not an MS-Windows device", device);
1744
1745   if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1746       (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1747     {
1748       if (!NILP (foreground) || !NILP (background))
1749         type = IMAGE_COLOR_PIXMAP;
1750       else
1751         type = IMAGE_MONO_PIXMAP;
1752     }
1753   else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1754     type = IMAGE_MONO_PIXMAP;
1755   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1756     type = IMAGE_COLOR_PIXMAP;
1757   else if (dest_mask & IMAGE_POINTER_MASK)
1758     type = IMAGE_POINTER;
1759   else
1760     incompatible_image_types (instantiator, dest_mask,
1761                               IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1762                               | IMAGE_POINTER_MASK);
1763
1764   mswindows_initialize_dibitmap_image_instance (ii, 1, type);
1765
1766   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1767     find_keyword_in_vector (instantiator, Q_file);
1768   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1769   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1770   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1771   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1772   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1773   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask :
1774     xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1775                                  TRUE, black, white);
1776
1777   switch (type)
1778     {
1779     case IMAGE_MONO_PIXMAP:
1780       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1781         xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1782                                      FALSE, black, black);
1783       break;
1784
1785     case IMAGE_COLOR_PIXMAP:
1786       {
1787         COLORREF fg = black;
1788         COLORREF bg = white;
1789
1790         if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1791           foreground =
1792             Fmake_color_instance (foreground, device,
1793                                   encode_error_behavior_flag (ERROR_ME));
1794
1795         if (COLOR_INSTANCEP (foreground))
1796           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1797
1798         if (!NILP (background) && !COLOR_INSTANCEP (background))
1799           background =
1800             Fmake_color_instance (background, device,
1801                                   encode_error_behavior_flag (ERROR_ME));
1802
1803         if (COLOR_INSTANCEP (background))
1804           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1805
1806         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1807         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1808
1809         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1810           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1811                                        FALSE, fg, black);
1812       }
1813       break;
1814
1815     case IMAGE_POINTER:
1816       {
1817         COLORREF fg = black;
1818         COLORREF bg = white;
1819
1820         if (NILP (foreground))
1821           foreground = pointer_fg;
1822         if (NILP (background))
1823           background = pointer_bg;
1824
1825         IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1826           find_keyword_in_vector (instantiator, Q_hotspot_x);
1827         IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1828           find_keyword_in_vector (instantiator, Q_hotspot_y);
1829         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1830         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1831         if (COLOR_INSTANCEP (foreground))
1832           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1833         if (COLOR_INSTANCEP (background))
1834           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1835
1836         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1837           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1838                                        TRUE, fg, black);
1839         mswindows_initialize_image_instance_icon (ii, TRUE);
1840       }
1841       break;
1842
1843     default:
1844       abort ();
1845     }
1846 }
1847
1848 static void
1849 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1850                    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1851                    int dest_mask, int width, int height,
1852                    /* Note that data is in ext-format! */
1853                    const char *bits)
1854 {
1855   Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1856   Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1857   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1858   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME
1859                             (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))));
1860   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1861   HBITMAP mask = 0;
1862
1863   if (!NILP (mask_data))
1864     {
1865       const char *ext_data;
1866
1867       TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
1868                           C_STRING_ALLOCA, ext_data,
1869                           Qbinary);
1870       mask = xbm_create_bitmap_from_data (hdc,
1871                                           (unsigned char *) ext_data,
1872                                           XINT (XCAR (mask_data)),
1873                                           XINT (XCAR (XCDR (mask_data))),
1874                                           FALSE,
1875                                           PALETTERGB (0,0,0),
1876                                           PALETTERGB (255,255,255));
1877     }
1878
1879   init_image_instance_from_xbm_inline (ii, width, height, bits,
1880                                        instantiator, pointer_fg, pointer_bg,
1881                                        dest_mask, mask, mask_file);
1882 }
1883
1884 /* Instantiate method for XBM's. */
1885
1886 static void
1887 mswindows_xbm_instantiate (Lisp_Object image_instance,
1888                            Lisp_Object instantiator,
1889                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1890                            int dest_mask, Lisp_Object domain)
1891 {
1892   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1893   const char *ext_data;
1894
1895   assert (!NILP (data));
1896
1897   TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
1898                       C_STRING_ALLOCA, ext_data,
1899                       Qbinary);
1900
1901   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1902                      pointer_bg, dest_mask, XINT (XCAR (data)),
1903                      XINT (XCAR (XCDR (data))), ext_data);
1904 }
1905
1906 #ifdef HAVE_XFACE
1907 /**********************************************************************
1908  *                             X-Face                                 *
1909  **********************************************************************/
1910 #if defined(EXTERN)
1911 /* This is about to get redefined! */
1912 #undef EXTERN
1913 #endif
1914 /* We have to define SYSV32 so that compface.h includes string.h
1915    instead of strings.h. */
1916 #define SYSV32
1917 #ifdef __cplusplus
1918 extern "C" {
1919 #endif
1920 #include <compface.h>
1921 #ifdef __cplusplus
1922 }
1923 #endif
1924 /* JMP_BUF cannot be used here because if it doesn't get defined
1925    to jmp_buf we end up with a conflicting type error with the
1926    definition in compface.h */
1927 extern jmp_buf comp_env;
1928 #undef SYSV32
1929
1930 static void
1931 mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1932                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1933                              int dest_mask, Lisp_Object domain)
1934 {
1935   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1936   int i, stattis;
1937   char *p, *bits, *bp;
1938   const char * volatile emsg = 0;
1939   const char * volatile dstring;
1940
1941   assert (!NILP (data));
1942
1943   TO_EXTERNAL_FORMAT (LISP_STRING, data,
1944                       C_STRING_ALLOCA, dstring,
1945                       Qbinary);
1946
1947   if ((p = strchr (dstring, ':')))
1948     {
1949       dstring = p + 1;
1950     }
1951
1952   /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1953   if (!(stattis = setjmp (comp_env)))
1954     {
1955       UnCompAll ((char *) dstring);
1956       UnGenFace ();
1957     }
1958
1959   switch (stattis)
1960     {
1961     case -2:
1962       emsg = "uncompface: internal error";
1963       break;
1964     case -1:
1965       emsg = "uncompface: insufficient or invalid data";
1966       break;
1967     case 1:
1968       emsg = "uncompface: excess data ignored";
1969       break;
1970     }
1971
1972   if (emsg)
1973     signal_simple_error_2 (emsg, data, Qimage);
1974
1975   bp = bits = (char *) alloca (PIXELS / 8);
1976
1977   /* the compface library exports char F[], which uses a single byte per
1978      pixel to represent a 48x48 bitmap.  Yuck. */
1979   for (i = 0, p = F; i < (PIXELS / 8); ++i)
1980     {
1981       int n, b;
1982       /* reverse the bit order of each byte... */
1983       for (b = n = 0; b < 8; ++b)
1984         {
1985           n |= ((*p++) << b);
1986         }
1987       *bp++ = (char) n;
1988     }
1989
1990   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1991                      pointer_bg, dest_mask, 48, 48, bits);
1992 }
1993 #endif /* HAVE_XFACE */
1994
1995 \f
1996 /************************************************************************/
1997 /*                      image instance methods                          */
1998 /************************************************************************/
1999
2000 static void
2001 mswindows_print_image_instance (Lisp_Image_Instance *p,
2002                                 Lisp_Object printcharfun,
2003                                 int escapeflag)
2004 {
2005   char buf[100];
2006
2007   switch (IMAGE_INSTANCE_TYPE (p))
2008     {
2009     case IMAGE_MONO_PIXMAP:
2010     case IMAGE_COLOR_PIXMAP:
2011     case IMAGE_POINTER:
2012       sprintf (buf, " (0x%lx",
2013                (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
2014       write_c_string (buf, printcharfun);
2015       if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2016         {
2017           sprintf (buf, "/0x%lx",
2018                    (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2019           write_c_string (buf, printcharfun);
2020         }
2021       write_c_string (")", printcharfun);
2022       break;
2023
2024     default:
2025       break;
2026     }
2027 }
2028
2029 #ifdef DEBUG_WIDGETS
2030 extern int debug_widget_instances;
2031 #endif
2032
2033 static void
2034 mswindows_finalize_image_instance (Lisp_Image_Instance *p)
2035 {
2036   if (DEVICE_LIVE_P (XDEVICE (p->device)))
2037     {
2038       if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET
2039           ||
2040           IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2041         {
2042 #ifdef DEBUG_WIDGETS
2043           debug_widget_instances--;
2044           stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
2045 #endif
2046           if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2047             {
2048               DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
2049               DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p));
2050               IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
2051             }
2052         }
2053       else if (p->data)
2054         {
2055           int i;
2056           if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
2057             disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
2058
2059           if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p))
2060             {
2061               for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
2062                 {
2063                   if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i))
2064                     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i));
2065                   IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0;
2066                 }
2067               xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p));
2068               IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0;
2069             }
2070           if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2071             DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2072           IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0;
2073           if (IMAGE_INSTANCE_MSWINDOWS_ICON (p))
2074             DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p));
2075           IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0;
2076         }
2077     }
2078
2079   if (p->data)
2080     {
2081       xfree (p->data);
2082       p->data = 0;
2083     }
2084 }
2085
2086 /************************************************************************/
2087 /*                      subwindow and widget support                      */
2088 /************************************************************************/
2089
2090 static HFONT
2091 mswindows_widget_hfont (Lisp_Image_Instance *p,
2092                         Lisp_Object domain)
2093 {
2094   Lisp_Object face = IMAGE_INSTANCE_WIDGET_FACE (p);
2095   int under = FACE_UNDERLINE_P (face, domain);
2096   int strike = FACE_STRIKETHRU_P (face, domain);
2097   Lisp_Object font = query_string_font (IMAGE_INSTANCE_WIDGET_TEXT (p),
2098                                         face, domain);
2099
2100   return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike);
2101 }
2102
2103 /* unmap the image if it is a widget. This is used by redisplay via
2104    redisplay_unmap_subwindows */
2105 static void
2106 mswindows_unmap_subwindow (Lisp_Image_Instance *p)
2107 {
2108   if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2109     {
2110       SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2111                     NULL,
2112                     0, 0, 0, 0,
2113                     SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE
2114                     | SWP_NOSENDCHANGING);
2115       if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))
2116         SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
2117     }
2118 }
2119
2120 /* map the subwindow. This is used by redisplay via
2121    redisplay_output_subwindow */
2122 static void
2123 mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2124                          struct display_glyph_area* dga)
2125 {
2126   /* move the window before mapping it ... */
2127   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2128                 NULL,
2129                 x, y, dga->width, dga->height,
2130                 SWP_NOZORDER
2131                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2132   /* ... adjust the child ... */
2133   SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2134                 NULL,
2135                 -dga->xoffset, -dga->yoffset, 0, 0,
2136                 SWP_NOZORDER | SWP_NOSIZE
2137                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2138   /* ... now map it - we are not allowed to move it at the same time. */
2139   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2140                 NULL,
2141                 0, 0, 0, 0,
2142                 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2143                 | SWP_SHOWWINDOW | SWP_NOCOPYBITS
2144                 | SWP_NOSENDCHANGING);
2145 }
2146
2147 /* resize the subwindow instance */
2148 static void
2149 mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h)
2150 {
2151   /* Set the size of the control .... */
2152   SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2153                 NULL,
2154                 0, 0, w, h,
2155                 SWP_NOZORDER | SWP_NOMOVE
2156                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2157 }
2158
2159 /* Simply resize the window here. */
2160 static void
2161 mswindows_update_subwindow (Lisp_Image_Instance *p)
2162 {
2163   mswindows_resize_subwindow (p,
2164                               IMAGE_INSTANCE_WIDTH (p),
2165                               IMAGE_INSTANCE_HEIGHT (p));
2166 }
2167
2168 /* when you click on a widget you may activate another widget this
2169    needs to be checked and all appropriate widgets updated */
2170 static void
2171 mswindows_update_widget (Lisp_Image_Instance *p)
2172 {
2173   /* Possibly update the face font and colors. */
2174   if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p))
2175     {
2176       /* set the widget font from the widget face */
2177       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2178                    WM_SETFONT,
2179                    (WPARAM) mswindows_widget_hfont
2180                    (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)),
2181                    MAKELPARAM (TRUE, 0));
2182     }
2183   /* Possibly update the dimensions. */
2184   if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2185     {
2186       mswindows_resize_subwindow (p, 
2187                                   IMAGE_INSTANCE_WIDTH (p),
2188                                   IMAGE_INSTANCE_HEIGHT (p));
2189     }
2190   /* Possibly update the text in the widget. */
2191   if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2192     {
2193       Extbyte* lparam=0;
2194       TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p),
2195                           C_STRING_ALLOCA, lparam,
2196                           Qnative);
2197       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2198                    WM_SETTEXT, 0, (LPARAM)lparam);
2199     }
2200 }
2201
2202 /* register widgets into our hastable so that we can cope with the
2203    callbacks. The hashtable is weak so deregistration is handled
2204    automatically */
2205 static int
2206 mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain)
2207 {
2208   Lisp_Object frame = FW_FRAME (domain);
2209   struct frame* f = XFRAME (frame);
2210   int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
2211                              gui,
2212                              WIDGET_GLYPH_SLOT);
2213   Fputhash (make_int (id),
2214             XGUI_ITEM (gui)->callback,
2215             FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
2216   return id;
2217 }
2218
2219 static int
2220 mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
2221 {
2222   return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_ITEM (instance),
2223                                       domain);
2224 }
2225
2226 static void
2227 mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2228                                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2229                                  int dest_mask, Lisp_Object domain)
2230 {
2231   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2232   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2233   struct device* d = XDEVICE (device);
2234   Lisp_Object frame = FW_FRAME (domain);
2235   HWND wnd;
2236
2237   if (!DEVICE_MSWINDOWS_P (d))
2238     signal_simple_error ("Not an mswindows device", device);
2239
2240   /* have to set the type this late in case there is no device
2241      instantiation for a widget */
2242   IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2243   /* Allocate space for the clip window */
2244   ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2245
2246   if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2247        = CreateWindowEx(
2248                         0,              /* EX flags */
2249                         XEMACS_CONTROL_CLASS,
2250                         0,              /* text */
2251                         WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2252                         0,         /* starting x position */
2253                         0,         /* starting y position */
2254                         IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2255                         IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2256                         /* parent window */
2257                         FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2258                         NULL,       /* No menu */
2259                         NULL, /* must be null for this class */
2260                         NULL)) == NULL)
2261     signal_simple_error ("window creation failed with code",
2262                          make_int (GetLastError()));
2263
2264   wnd = CreateWindow( "STATIC",
2265                       "",
2266                       WS_CHILD,
2267                       0,         /* starting x position */
2268                       0,         /* starting y position */
2269                       IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2270                       IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2271                       IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2272                       0,
2273                       (HINSTANCE)
2274                       GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2275                                      GWL_HINSTANCE),
2276                       NULL);
2277
2278   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2279   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2280 }
2281
2282 static int
2283 mswindows_image_instance_equal (Lisp_Image_Instance *p1,
2284                                 Lisp_Image_Instance *p2, int depth)
2285 {
2286   switch (IMAGE_INSTANCE_TYPE (p1))
2287     {
2288     case IMAGE_MONO_PIXMAP:
2289     case IMAGE_COLOR_PIXMAP:
2290     case IMAGE_POINTER:
2291       if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1)
2292           != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2))
2293         return 0;
2294       break;
2295
2296     default:
2297       break;
2298     }
2299
2300   return 1;
2301 }
2302
2303 static unsigned long
2304 mswindows_image_instance_hash (Lisp_Image_Instance *p, int depth)
2305 {
2306   switch (IMAGE_INSTANCE_TYPE (p))
2307     {
2308     case IMAGE_MONO_PIXMAP:
2309     case IMAGE_COLOR_PIXMAP:
2310     case IMAGE_POINTER:
2311       return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p);
2312
2313     default:
2314       return 0;
2315     }
2316 }
2317
2318 /* Set all the slots in an image instance structure to reasonable
2319    default values.  This is used somewhere within an instantiate
2320    method.  It is assumed that the device slot within the image
2321    instance is already set -- this is the case when instantiate
2322    methods are called. */
2323
2324 static void
2325 mswindows_initialize_dibitmap_image_instance (Lisp_Image_Instance *ii,
2326                                               int slices,
2327                                               enum image_instance_type type)
2328 {
2329   ii->data = xnew_and_zero (struct mswindows_image_instance_data);
2330   IMAGE_INSTANCE_TYPE (ii) = type;
2331   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
2332   IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
2333   IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
2334   IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
2335   IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
2336   IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
2337   IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
2338   IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) =
2339     xnew_array_and_zero (HBITMAP, slices);
2340 }
2341
2342 \f
2343 #ifdef HAVE_WIDGETS
2344
2345 /************************************************************************/
2346 /*                            widgets                            */
2347 /************************************************************************/
2348 static void
2349 mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2350                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2351                               int dest_mask, Lisp_Object domain,
2352                               const char* class, int flags, int exflags)
2353 {
2354   /* this function can call lisp */
2355   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2356   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
2357   struct device* d = XDEVICE (device);
2358   Lisp_Object frame = FW_FRAME (domain);
2359   Extbyte* nm=0;
2360   HWND wnd;
2361   int id = 0xffff;
2362   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2363   Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2364
2365   if (!DEVICE_MSWINDOWS_P (d))
2366     signal_simple_error ("Not an mswindows device", device);
2367
2368   if (!gui_item_active_p (gui))
2369     flags |= WS_DISABLED;
2370
2371   style = pgui->style;
2372
2373   if (!NILP (pgui->callback))
2374     {
2375       id = mswindows_register_widget_instance (image_instance, domain);
2376     }
2377
2378   if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2379     TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
2380                         C_STRING_ALLOCA, nm,
2381                         Qnative);
2382
2383   /* allocate space for the clip window and then allocate the clip window */
2384   ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2385
2386   if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2387        = CreateWindowEx(
2388                         WS_EX_CONTROLPARENT,    /* EX flags */
2389                         XEMACS_CONTROL_CLASS,
2390                         0,              /* text */
2391                         WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2392                         0,         /* starting x position */
2393                         0,         /* starting y position */
2394                         IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2395                         IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2396                         /* parent window */
2397                         FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2398                         (HMENU)id,       /* No menu */
2399                         NULL, /* must be null for this class */
2400                         NULL)) == NULL)
2401     signal_simple_error ("window creation failed with code",
2402                          make_int (GetLastError()));
2403
2404   if ((wnd = CreateWindowEx(
2405                             exflags /* | WS_EX_NOPARENTNOTIFY*/,
2406                             class,
2407                             nm,
2408                             flags | WS_CHILD | WS_VISIBLE,
2409                             0,         /* starting x position */
2410                             0,         /* starting y position */
2411                             IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2412                             IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2413                             /* parent window */
2414                             IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2415                             (HMENU)id,       /* No menu */
2416                             (HINSTANCE)
2417                             GetWindowLong
2418                             (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2419                              GWL_HINSTANCE),
2420                             NULL)) == NULL)
2421     signal_simple_error ("window creation failed with code",
2422                          make_int (GetLastError()));
2423
2424   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2425   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2426   /* set the widget font from the widget face */
2427   SendMessage (wnd, WM_SETFONT,
2428                (WPARAM) mswindows_widget_hfont (ii, domain),
2429                MAKELPARAM (TRUE, 0));
2430 }
2431
2432 /* Instantiate a button widget. Unfortunately instantiated widgets are
2433    particular to a frame since they need to have a parent. It's not
2434    like images where you just select the image into the context you
2435    want to display it in and BitBlt it. So image instances can have a
2436    many-to-one relationship with things you see, whereas widgets can
2437    only be one-to-one (i.e. per frame) */
2438 static void
2439 mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2440                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2441                               int dest_mask, Lisp_Object domain)
2442 {
2443   /* this function can call lisp */
2444   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2445   HWND wnd;
2446   int flags = WS_TABSTOP;/* BS_NOTIFY #### is needed to get exotic feedback
2447                             only. Since we seem to want nothing beyond BN_CLICK,
2448                             the style is perhaps not necessary -- kkm */
2449   Lisp_Object style;
2450   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2451   Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2452   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2453
2454   if (!NILP (glyph))
2455     {
2456       if (!IMAGE_INSTANCEP (glyph))
2457         glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2458
2459       if (IMAGE_INSTANCEP (glyph))
2460         flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2461           BS_BITMAP : BS_ICON;
2462     }
2463
2464   style = pgui->style;
2465
2466   /* #### consider using the default face for radio and toggle
2467      buttons. */
2468   if (EQ (style, Qradio))
2469     {
2470       flags |= BS_RADIOBUTTON;
2471     }
2472   else if (EQ (style, Qtoggle))
2473     {
2474       flags |= BS_AUTOCHECKBOX;
2475     }
2476   else
2477     {
2478       flags |= BS_DEFPUSHBUTTON;
2479     }
2480
2481   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2482                                 pointer_bg, dest_mask, domain, "BUTTON",
2483                                 flags, 0);
2484
2485   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2486   /* set the checked state */
2487   if (gui_item_selected_p (gui))
2488     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2489   else
2490     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2491   /* add the image if one was given */
2492   if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2493       &&
2494       IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2495     {
2496       SendMessage (wnd, BM_SETIMAGE,
2497                    (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2498                              IMAGE_BITMAP : IMAGE_ICON),
2499                    (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2500                     (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
2501                     (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
2502     }
2503 }
2504
2505 /* Update the state of a button. */
2506 static void
2507 mswindows_button_update (Lisp_Object image_instance)
2508 {
2509   /* This function can GC if IN_REDISPLAY is false. */
2510   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2511
2512   /* buttons checked or otherwise */
2513   if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
2514     SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2515                  BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2516   else
2517     SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2518                  BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2519 }
2520
2521 /* instantiate an edit control */
2522 static void
2523 mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2524                             Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2525                             int dest_mask, Lisp_Object domain)
2526 {
2527   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2528                                 pointer_bg, dest_mask, domain, "EDIT",
2529                                 ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP
2530                                 | WS_BORDER, WS_EX_CLIENTEDGE);
2531 }
2532
2533 /* instantiate a progress gauge */
2534 static void
2535 mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2536                                 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2537                                 int dest_mask, Lisp_Object domain)
2538 {
2539   HWND wnd;
2540   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2541   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2542                                 pointer_bg, dest_mask, domain, PROGRESS_CLASS,
2543                                 WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE);
2544   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2545   /* set the colors */
2546 #ifdef PBS_SETBKCOLOR
2547   SendMessage (wnd, PBS_SETBKCOLOR, 0,
2548                (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2549                          (XCOLOR_INSTANCE
2550                           (FACE_BACKGROUND
2551                            (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2552                             XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
2553 #endif
2554 #ifdef PBS_SETBARCOLOR
2555   SendMessage (wnd, PBS_SETBARCOLOR, 0,
2556                (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2557                           (XCOLOR_INSTANCE
2558                            (FACE_FOREGROUND
2559                             (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2560                              XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
2561 #endif
2562 }
2563
2564 /* instantiate a tree view widget */
2565 static HTREEITEM add_tree_item (Lisp_Object image_instance,
2566                                 HWND wnd, HTREEITEM parent, Lisp_Object item,
2567                                 int children, Lisp_Object domain)
2568 {
2569   TV_INSERTSTRUCT tvitem;
2570   HTREEITEM ret;
2571
2572   tvitem.hParent = parent;
2573   tvitem.hInsertAfter = TVI_LAST;
2574   tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
2575   tvitem.item.cChildren = children;
2576
2577   if (GUI_ITEMP (item))
2578     {
2579       tvitem.item.lParam = mswindows_register_gui_item (item, domain);
2580       tvitem.item.mask |= TVIF_PARAM;
2581       TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2582                           C_STRING_ALLOCA, tvitem.item.pszText,
2583                           Qnative);
2584     }
2585   else
2586     TO_EXTERNAL_FORMAT (LISP_STRING, item,
2587                         C_STRING_ALLOCA, tvitem.item.pszText,
2588                         Qnative);
2589
2590   tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
2591
2592   if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM,
2593                                      0, (LPARAM)&tvitem)) == 0)
2594     signal_simple_error ("error adding tree view entry", item);
2595
2596   return ret;
2597 }
2598
2599 static void add_tree_item_list (Lisp_Object image_instance,
2600                                 HWND wnd, HTREEITEM parent, Lisp_Object list,
2601                                 Lisp_Object domain)
2602 {
2603   Lisp_Object rest;
2604
2605   /* get the first item */
2606   parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
2607   /* recursively add items to the tree view */
2608   LIST_LOOP (rest, XCDR (list))
2609     {
2610       if (LISTP (XCAR (rest)))
2611         add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2612       else
2613         add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2614     }
2615 }
2616
2617 static void
2618 mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2619                             Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2620                             int dest_mask, Lisp_Object domain)
2621 {
2622   Lisp_Object rest;
2623   HWND wnd;
2624   HTREEITEM parent;
2625   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2626   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2627                                 pointer_bg, dest_mask, domain, WC_TREEVIEW,
2628                                 WS_TABSTOP | WS_BORDER | PBS_SMOOTH
2629                                 | TVS_HASLINES | TVS_HASBUTTONS,
2630                                 WS_EX_CLIENTEDGE);
2631
2632   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2633
2634   /* define a root */
2635   parent = add_tree_item (image_instance, wnd, NULL,
2636                           XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
2637                           TRUE, domain);
2638
2639   /* recursively add items to the tree view */
2640   /* add items to the tab */
2641   LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2642     {
2643       if (LISTP (XCAR (rest)))
2644         add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2645       else
2646         add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2647     }
2648 }
2649
2650 /* instantiate a tab control */
2651 static TC_ITEM* add_tab_item (Lisp_Object image_instance,
2652                              HWND wnd, Lisp_Object item,
2653                              Lisp_Object domain, int i)
2654 {
2655   TC_ITEM tvitem, *ret;
2656
2657   tvitem.mask = TCIF_TEXT;
2658
2659   if (GUI_ITEMP (item))
2660     {
2661       tvitem.lParam = mswindows_register_gui_item (item, domain);
2662       tvitem.mask |= TCIF_PARAM;
2663       TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2664                           C_STRING_ALLOCA, tvitem.pszText,
2665                           Qnative);
2666     }
2667   else
2668     {
2669       CHECK_STRING (item);
2670       TO_EXTERNAL_FORMAT (LISP_STRING, item,
2671                           C_STRING_ALLOCA, tvitem.pszText,
2672                           Qnative);
2673     }
2674
2675   tvitem.cchTextMax = strlen (tvitem.pszText);
2676
2677   if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM,
2678                                     i, (LPARAM)&tvitem)) < 0)
2679     signal_simple_error ("error adding tab entry", item);
2680
2681   return ret;
2682 }
2683
2684 static void
2685 mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2686                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2687                            int dest_mask, Lisp_Object domain)
2688 {
2689   Lisp_Object rest;
2690   HWND wnd;
2691   int i = 0;
2692   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2693   Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
2694   unsigned int flags = WS_TABSTOP;
2695
2696   if (EQ (orient, Qleft) || EQ (orient, Qright))
2697     {
2698       flags |= TCS_VERTICAL | TCS_MULTILINE;
2699     }
2700   if (EQ (orient, Qright) || EQ (orient, Qbottom))
2701     {
2702       flags |= TCS_BOTTOM;
2703     }
2704
2705   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2706                                 pointer_bg, dest_mask, domain, WC_TABCONTROL,
2707                                 /* borders don't suit tabs so well */
2708                                 flags, 0);
2709
2710   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2711   /* add items to the tab */
2712   LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2713     {
2714       add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
2715       i++;
2716     }
2717 }
2718
2719 /* set the properties of a tab control */
2720 static void
2721 mswindows_tab_control_update (Lisp_Object image_instance)
2722 {
2723   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2724
2725   if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2726     {
2727       HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2728       int i = 0;
2729       Lisp_Object rest;
2730
2731       /* delete the pre-existing items */
2732       SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
2733
2734       /* add items to the tab */
2735       LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2736         {
2737           add_tab_item (image_instance, wnd, XCAR (rest),
2738                         IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), i);
2739           i++;
2740         }
2741     }
2742 }
2743
2744 /* instantiate a static control possible for putting other things in */
2745 static void
2746 mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2747                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2748                              int dest_mask, Lisp_Object domain)
2749 {
2750   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2751                                 pointer_bg, dest_mask, domain, "STATIC",
2752                                 0, WS_EX_STATICEDGE);
2753 }
2754
2755 /* instantiate a scrollbar control */
2756 static void
2757 mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2758                                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2759                                  int dest_mask, Lisp_Object domain)
2760 {
2761   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2762                                 pointer_bg, dest_mask, domain, "SCROLLBAR",
2763                                 WS_TABSTOP, WS_EX_CLIENTEDGE);
2764 }
2765
2766 /* instantiate a combo control */
2767 static void
2768 mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2769                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2770                              int dest_mask, Lisp_Object domain)
2771 {
2772   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2773   HWND wnd;
2774   Lisp_Object rest;
2775   Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
2776                                  Q_items, Qnil);
2777   int len, height;
2778
2779   /* Maybe ought to generalise this more but it may be very windows
2780      specific. In windows the window height of a combo box is the
2781      height when the combo box is open. Thus we need to set the height
2782      before creating the window and then reset it to a single line
2783      after the window is created so that redisplay does the right
2784      thing. */
2785   widget_instantiate (image_instance, instantiator, pointer_fg,
2786                       pointer_bg, dest_mask, domain);
2787
2788   /* We now have everything right apart from the height. */
2789   default_face_font_info (domain, 0, 0, &height, 0, 0);
2790   GET_LIST_LENGTH (data, len);
2791
2792   height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len;
2793   IMAGE_INSTANCE_HEIGHT (ii) = height;
2794
2795   /* Now create the widget. */
2796   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2797                                 pointer_bg, dest_mask, domain, "COMBOBOX",
2798                                 WS_BORDER | WS_TABSTOP | CBS_DROPDOWN
2799                                 | CBS_AUTOHSCROLL
2800                                 | CBS_HASSTRINGS | WS_VSCROLL,
2801                                 WS_EX_CLIENTEDGE);
2802   /* Reset the height. layout will probably do this safely, but better make sure. */
2803   image_instance_layout (image_instance,
2804                          IMAGE_UNSPECIFIED_GEOMETRY,
2805                          IMAGE_UNSPECIFIED_GEOMETRY,
2806                          domain);
2807
2808   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2809   /* add items to the combo box */
2810   SendMessage (wnd, CB_RESETCONTENT, 0, 0);
2811   LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
2812     {
2813       Extbyte* lparam;
2814       TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest),
2815                           C_STRING_ALLOCA, lparam,
2816                           Qnative);
2817       if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR)
2818         signal_simple_error ("error adding combo entries", instantiator);
2819     }
2820 }
2821
2822 /* get properties of a control */
2823 static Lisp_Object
2824 mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2825 {
2826   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2827   HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2828   /* get the text from a control */
2829   if (EQ (prop, Q_text))
2830     {
2831       Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
2832       Extbyte *buf = (Extbyte*) alloca (len+1);
2833
2834       SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf);
2835       return build_ext_string (buf, Qnative);
2836     }
2837   return Qunbound;
2838 }
2839
2840 /* get properties of a button */
2841 static Lisp_Object
2842 mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
2843 {
2844   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2845   HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2846   /* check the state of a button */
2847   if (EQ (prop, Q_selected))
2848     {
2849       if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
2850         return Qt;
2851       else
2852         return Qnil;
2853     }
2854   return Qunbound;
2855 }
2856
2857 /* get properties of a combo box */
2858 static Lisp_Object
2859 mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
2860 {
2861   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2862   HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2863   /* get the text from a control */
2864   if (EQ (prop, Q_text))
2865     {
2866       long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
2867       Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
2868       Extbyte* buf = (Extbyte*) alloca (len+1);
2869       SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf);
2870       return build_ext_string (buf, Qnative);
2871     }
2872   return Qunbound;
2873 }
2874
2875 /* set the properties of a progres guage */
2876 static void
2877 mswindows_progress_gauge_update (Lisp_Object image_instance)
2878 {
2879   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2880   
2881   if (IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii))
2882     {
2883       /* #### I'm not convinced we should store this in the plist. */
2884       Lisp_Object val = Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii),
2885                                     Q_percent, Qnil);
2886       CHECK_INT (val);
2887       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2888                    PBM_SETPOS, (WPARAM)XINT (val), 0);
2889     }
2890 }
2891
2892 LRESULT WINAPI
2893 mswindows_control_wnd_proc (HWND hwnd, UINT msg,
2894                             WPARAM wParam, LPARAM lParam)
2895 {
2896   switch (msg)
2897     {
2898     case WM_NOTIFY:
2899     case WM_COMMAND:
2900     case WM_CTLCOLORBTN:
2901     case WM_CTLCOLORLISTBOX:
2902     case WM_CTLCOLOREDIT:
2903     case WM_CTLCOLORSTATIC:
2904     case WM_CTLCOLORSCROLLBAR:
2905
2906       return mswindows_wnd_proc (GetParent (hwnd), msg, wParam, lParam);
2907     default:
2908       return DefWindowProc (hwnd, msg, wParam, lParam);
2909     }
2910 }
2911
2912 #endif /* HAVE_WIDGETS */
2913
2914 \f
2915 /************************************************************************/
2916 /*                            initialization                            */
2917 /************************************************************************/
2918
2919 void
2920 syms_of_glyphs_mswindows (void)
2921 {
2922   defkeyword (&Q_resource_id, ":resource-id");
2923   defkeyword (&Q_resource_type, ":resource-type");
2924 }
2925
2926 void
2927 console_type_create_glyphs_mswindows (void)
2928 {
2929   /* image methods */
2930
2931   CONSOLE_HAS_METHOD (mswindows, print_image_instance);
2932   CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
2933   CONSOLE_HAS_METHOD (mswindows, unmap_subwindow);
2934   CONSOLE_HAS_METHOD (mswindows, map_subwindow);
2935   CONSOLE_HAS_METHOD (mswindows, update_subwindow);
2936   CONSOLE_HAS_METHOD (mswindows, update_widget);
2937   CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
2938   CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
2939   CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
2940   CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
2941   CONSOLE_HAS_METHOD (mswindows, resize_subwindow);
2942 }
2943
2944 void
2945 image_instantiator_format_create_glyphs_mswindows (void)
2946 {
2947   IIFORMAT_VALID_CONSOLE (mswindows, nothing);
2948   IIFORMAT_VALID_CONSOLE (mswindows, string);
2949   IIFORMAT_VALID_CONSOLE (mswindows, layout);
2950   IIFORMAT_VALID_CONSOLE (mswindows, formatted_string);
2951   IIFORMAT_VALID_CONSOLE (mswindows, inherit);
2952   /* image-instantiator types */
2953 #ifdef HAVE_XPM
2954   INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm);
2955   IIFORMAT_HAS_DEVMETHOD (mswindows, xpm, instantiate);
2956 #endif
2957   INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm);
2958   IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate);
2959 #ifdef HAVE_XFACE
2960   INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
2961   IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
2962 #endif
2963 #ifdef HAVE_JPEG
2964   IIFORMAT_VALID_CONSOLE (mswindows, jpeg);
2965 #endif
2966 #ifdef HAVE_TIFF
2967   IIFORMAT_VALID_CONSOLE (mswindows, tiff);
2968 #endif
2969 #ifdef HAVE_PNG
2970   IIFORMAT_VALID_CONSOLE (mswindows, png);
2971 #endif
2972 #ifdef HAVE_GIF
2973   IIFORMAT_VALID_CONSOLE (mswindows, gif);
2974 #endif
2975 #ifdef HAVE_WIDGETS
2976   /* button widget */
2977   INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
2978   IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
2979   IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
2980   IIFORMAT_HAS_DEVMETHOD (mswindows, button, update);
2981
2982   INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
2983   IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
2984
2985   INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
2986   IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
2987
2988   INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
2989   IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
2990
2991   /* label */
2992   INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
2993   IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
2994
2995   /* combo box */
2996   INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
2997   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
2998   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
2999
3000   /* scrollbar */
3001   INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
3002   IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
3003
3004   /* progress gauge */
3005   INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
3006   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, update);
3007   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
3008
3009   /* tree view widget */
3010   INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
3011   /*  IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/
3012   IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
3013
3014   /* tab control widget */
3015   INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
3016   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
3017   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, update);
3018 #endif
3019   /* windows bitmap format */
3020   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
3021   IIFORMAT_HAS_METHOD (bmp, validate);
3022   IIFORMAT_HAS_METHOD (bmp, normalize);
3023   IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
3024   IIFORMAT_HAS_METHOD (bmp, instantiate);
3025
3026   IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
3027   IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
3028   IIFORMAT_VALID_CONSOLE (mswindows, bmp);
3029
3030   /* mswindows resources */
3031   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
3032                                         "mswindows-resource");
3033
3034   IIFORMAT_HAS_METHOD (mswindows_resource, validate);
3035   IIFORMAT_HAS_METHOD (mswindows_resource, normalize);
3036   IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types);
3037   IIFORMAT_HAS_METHOD (mswindows_resource, instantiate);
3038
3039   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type,
3040                           check_valid_resource_symbol);
3041   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
3042   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
3043   IIFORMAT_VALID_CONSOLE (mswindows, mswindows_resource);
3044 }
3045
3046 void
3047 vars_of_glyphs_mswindows (void)
3048 {
3049   DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
3050 A list of the directories in which mswindows bitmap files may be found.
3051 This is used by the `make-image-instance' function.
3052 */ );
3053   Vmswindows_bitmap_file_path = Qnil;
3054 }
3055
3056 void
3057 complex_vars_of_glyphs_mswindows (void)
3058 {
3059 }