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