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