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