XEmacs 21.2.20 "Yoko".
[chise/xemacs-chise.git.1] / src / glyphs-msw.c
1 /* mswindows-specific glyph objects.
2    Copyright (C) 1998, 1999 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 index;
443   unsigned char    bitnum;  
444   /* Find the byte on which this scanline begins */
445   index = (height - y - 1) * bpline; 
446   /* Find the byte containing this pixel */
447   index += (x >> 3); 
448   /* Which bit is it? */
449   bitnum = (unsigned char)( 7 - (x % 8) );  
450   if( white )         /* Turn it on */
451     bits[index] |= (1<<bitnum);
452   else         /* Turn it off */
453     bits[index] &= ~(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 #define LR_SHARED           0x8000
1104 #endif
1105
1106 static CONST resource_t bitmap_table[] = 
1107 {
1108   /* bitmaps */
1109   { "close", OBM_CLOSE },
1110   { "uparrow", OBM_UPARROW },
1111   { "dnarrow", OBM_DNARROW },
1112   { "rgarrow", OBM_RGARROW },
1113   { "lfarrow", OBM_LFARROW },
1114   { "reduce", OBM_REDUCE },
1115   { "zoom", OBM_ZOOM },
1116   { "restore", OBM_RESTORE },
1117   { "reduced", OBM_REDUCED },
1118   { "zoomd", OBM_ZOOMD },
1119   { "restored", OBM_RESTORED },
1120   { "uparrowd", OBM_UPARROWD },
1121   { "dnarrowd", OBM_DNARROWD },
1122   { "rgarrowd", OBM_RGARROWD },
1123   { "lfarrowd", OBM_LFARROWD },
1124   { "mnarrow", OBM_MNARROW },
1125   { "combo", OBM_COMBO },
1126   { "uparrowi", OBM_UPARROWI },
1127   { "dnarrowi", OBM_DNARROWI },
1128   { "rgarrowi", OBM_RGARROWI },
1129   { "lfarrowi", OBM_LFARROWI },
1130   { "size", OBM_SIZE },
1131   { "btsize", OBM_BTSIZE },
1132   { "check", OBM_CHECK },
1133   { "checkboxes", OBM_CHECKBOXES },
1134   { "btncorners" , OBM_BTNCORNERS },
1135   {0}
1136 };
1137
1138 static CONST resource_t cursor_table[] = 
1139 {
1140   /* cursors */
1141   { "normal", OCR_NORMAL },
1142   { "ibeam", OCR_IBEAM },
1143   { "wait", OCR_WAIT },
1144   { "cross", OCR_CROSS },
1145   { "up", OCR_UP },
1146   /* { "icon", OCR_ICON }, */
1147   { "sizenwse", OCR_SIZENWSE },
1148   { "sizenesw", OCR_SIZENESW },
1149   { "sizewe", OCR_SIZEWE },
1150   { "sizens", OCR_SIZENS },
1151   { "sizeall", OCR_SIZEALL },
1152   /* { "icour", OCR_ICOCUR }, */
1153   { "no", OCR_NO },
1154   { 0 }
1155 };
1156
1157 static CONST resource_t icon_table[] = 
1158 {
1159   /* icons */
1160   { "sample", OIC_SAMPLE },
1161   { "hand", OIC_HAND },
1162   { "ques", OIC_QUES },
1163   { "bang", OIC_BANG },
1164   { "note", OIC_NOTE },
1165   { "winlogo", OIC_WINLOGO },
1166   {0}
1167 };
1168
1169 static int resource_name_to_resource (Lisp_Object name, int type)
1170 {
1171   CONST resource_t* res = (type == IMAGE_CURSOR ? cursor_table 
1172                            : type == IMAGE_ICON ? icon_table 
1173                            : bitmap_table);
1174
1175   if (INTP (name))
1176     {
1177       return XINT (name);
1178     }
1179   else if (!STRINGP (name))
1180     {
1181       signal_simple_error ("invalid resource identifier", name);
1182     }
1183   
1184   do {
1185     Extbyte* nm=0;
1186     GET_C_STRING_OS_DATA_ALLOCA (name, nm);
1187       if (!strcasecmp ((char*)res->name, nm))
1188       return res->resource_id;
1189   } while ((++res)->name);
1190   return 0;
1191 }
1192
1193 static int
1194 resource_symbol_to_type (Lisp_Object data)
1195 {
1196   if (EQ (data, Qcursor))
1197     return IMAGE_CURSOR;
1198   else if (EQ (data, Qicon))
1199     return IMAGE_ICON;
1200   else if (EQ (data, Qbitmap))
1201     return IMAGE_BITMAP;
1202   else
1203     return 0;
1204 }
1205
1206 static void
1207 mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1208                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1209                     int dest_mask, Lisp_Object domain)
1210 {
1211   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1212   unsigned int type = 0;
1213   HANDLE himage = NULL;
1214   LPCTSTR resid=0;
1215   HINSTANCE hinst = NULL;
1216   ICONINFO iconinfo;
1217   int iitype=0;
1218   char* fname=0;
1219   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1220
1221   Lisp_Object file = find_keyword_in_vector (instantiator, Q_file);
1222   Lisp_Object resource_type = find_keyword_in_vector (instantiator, 
1223                                                       Q_resource_type);
1224   Lisp_Object resource_id = find_keyword_in_vector (instantiator, 
1225                                                     Q_resource_id);
1226
1227   xzero (iconinfo);
1228
1229   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1230     signal_simple_error ("Not an mswindows device", device);
1231
1232   type = resource_symbol_to_type (resource_type);
1233
1234   if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR)
1235     iitype = IMAGE_POINTER;
1236   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1237     iitype = IMAGE_COLOR_PIXMAP;
1238   else 
1239     incompatible_image_types (instantiator, dest_mask,
1240                               IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
1241
1242   /* mess with the keyword info we were provided with */
1243   if (!NILP (file))
1244     {
1245       Extbyte* f=0;
1246       GET_C_STRING_FILENAME_DATA_ALLOCA (file, f);
1247 #ifdef __CYGWIN32__
1248       CYGWIN_WIN32_PATH (f, fname);
1249 #else
1250       fname = f;
1251 #endif
1252       
1253       if (NILP (resource_id))
1254         resid = (LPCTSTR)fname;
1255       else
1256         {
1257           hinst = LoadLibraryEx (fname, NULL,
1258                                  LOAD_LIBRARY_AS_DATAFILE);
1259           resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1260                                                            type));
1261           
1262           if (!resid)
1263             GET_C_STRING_OS_DATA_ALLOCA (resource_id, resid);
1264         }
1265     }
1266   else if (!(resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1267                                                                type))))
1268     signal_simple_error ("Invalid resource identifier", resource_id);
1269   
1270   /* load the image */
1271   if (!(himage = LoadImage (hinst, resid, type, 0, 0,
1272                             LR_CREATEDIBSECTION | LR_DEFAULTSIZE | 
1273                             LR_SHARED |      
1274                             (!NILP (file) ? LR_LOADFROMFILE : 0))))
1275     {
1276       signal_simple_error ("Cannot load image", instantiator);
1277     }
1278
1279   if (hinst)
1280     FreeLibrary (hinst);
1281
1282   mswindows_initialize_dibitmap_image_instance (ii, 1, iitype);
1283
1284   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file;
1285   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 
1286     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
1287   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 
1288     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON);
1289   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1290
1291   /* hey, we've got an icon type thing so we can reverse engineer the
1292      bitmap and mask */
1293   if (type != IMAGE_BITMAP)
1294     {
1295       GetIconInfo (himage, &iconinfo);
1296       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = iconinfo.hbmColor;
1297       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = iconinfo.hbmMask;
1298       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), iconinfo.xHotspot);
1299       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), iconinfo.yHotspot);
1300       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = himage;
1301     }
1302   else
1303     {
1304       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = NULL;
1305       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = himage;
1306       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
1307       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1308       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1309     }
1310 }
1311
1312 static void
1313 check_valid_resource_symbol (Lisp_Object data)
1314 {
1315   CHECK_SYMBOL (data);
1316   if (!resource_symbol_to_type (data))
1317     signal_simple_error ("invalid resource type", data);
1318 }
1319
1320 static void
1321 check_valid_resource_id (Lisp_Object data)
1322 {
1323   if (!resource_name_to_resource (data, IMAGE_CURSOR)
1324       &&
1325       !resource_name_to_resource (data, IMAGE_ICON)
1326       &&
1327       !resource_name_to_resource (data, IMAGE_BITMAP))
1328     signal_simple_error ("invalid resource identifier", data);
1329 }
1330
1331 void
1332 check_valid_string_or_int (Lisp_Object data)
1333 {
1334   if (!INTP (data))
1335     CHECK_STRING (data);
1336   else
1337     CHECK_INT (data);
1338 }
1339
1340 /**********************************************************************
1341  *                             XBM                                    *
1342  **********************************************************************/
1343 #ifndef HAVE_X_WINDOWS
1344 /* $XConsortium: RdBitF.c,v 1.10 94/04/17 20:16:13 kaleb Exp $ */
1345
1346 /*
1347
1348 Copyright (c) 1988  X Consortium
1349
1350 Permission is hereby granted, free of charge, to any person obtaining a copy
1351 of this software and associated documentation files (the "Software"), to deal
1352 in the Software without restriction, including without limitation the rights
1353 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1354 copies of the Software, and to permit persons to whom the Software is
1355 furnished to do so, subject to the following conditions:
1356
1357 The above copyright notice and this permission notice shall be included in
1358 all copies or substantial portions of the Software.
1359
1360 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1361 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1362 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1363 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1364 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1365 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1366
1367 Except as contained in this notice, the name of the X Consortium shall not be
1368 used in advertising or otherwise to promote the sale, use or other dealings
1369 in this Software without prior written authorization from the X Consortium.
1370
1371 */
1372
1373 /*
1374  * This file contains miscellaneous utility routines and is not part of the
1375  * Xlib standard.
1376  *
1377  * Public entry points:
1378  *
1379  *     XmuReadBitmapData                read data from FILE descriptor
1380  *     XmuReadBitmapDataFromFile        read X10 or X11 format bitmap files
1381  *                                      and return data
1382  *
1383  * Note that this file and ../X/XRdBitF.c look very similar....  Keep them
1384  * that way (but don't use common source code so that people can have one 
1385  * without the other).
1386  */
1387
1388
1389 /*
1390  * Based on an optimized version provided by Jim Becker, August 5, 1988.
1391  */
1392 #ifndef BitmapSuccess
1393 #define BitmapSuccess           0
1394 #define BitmapOpenFailed        1
1395 #define BitmapFileInvalid       2
1396 #define BitmapNoMemory          3
1397 #endif
1398 #define MAX_SIZE 255
1399
1400 /* shared data for the image read/parse logic */
1401 static short hexTable[256];             /* conversion value */
1402 static int initialized = FALSE; /* easier to fill in at run time */
1403
1404 /*
1405  *      Table index for the hex values. Initialized once, first time.
1406  *      Used for translation value or delimiter significance lookup.
1407  */
1408 static void initHexTable()
1409 {
1410     /*
1411      * We build the table at run time for several reasons:
1412      *
1413      *     1.  portable to non-ASCII machines.
1414      *     2.  still reentrant since we set the init flag after setting table.
1415      *     3.  easier to extend.
1416      *     4.  less prone to bugs.
1417      */
1418     hexTable['0'] = 0;  hexTable['1'] = 1;
1419     hexTable['2'] = 2;  hexTable['3'] = 3;
1420     hexTable['4'] = 4;  hexTable['5'] = 5;
1421     hexTable['6'] = 6;  hexTable['7'] = 7;
1422     hexTable['8'] = 8;  hexTable['9'] = 9;
1423     hexTable['A'] = 10; hexTable['B'] = 11;
1424     hexTable['C'] = 12; hexTable['D'] = 13;
1425     hexTable['E'] = 14; hexTable['F'] = 15;
1426     hexTable['a'] = 10; hexTable['b'] = 11;
1427     hexTable['c'] = 12; hexTable['d'] = 13;
1428     hexTable['e'] = 14; hexTable['f'] = 15;
1429
1430     /* delimiters of significance are flagged w/ negative value */
1431     hexTable[' '] = -1; hexTable[','] = -1;
1432     hexTable['}'] = -1; hexTable['\n'] = -1;
1433     hexTable['\t'] = -1;
1434         
1435     initialized = TRUE;
1436 }
1437
1438 /*
1439  *      read next hex value in the input stream, return -1 if EOF
1440  */
1441 static int NextInt ( FILE *fstream )
1442 {
1443     int ch;
1444     int value = 0;
1445     int gotone = 0;
1446     int done = 0;
1447     
1448     /* loop, accumulate hex value until find delimiter  */
1449     /* skip any initial delimiters found in read stream */
1450
1451     while (!done) {
1452         ch = getc(fstream);
1453         if (ch == EOF) {
1454             value       = -1;
1455             done++;
1456         } else {
1457             /* trim high bits, check type and accumulate */
1458             ch &= 0xff;
1459             if (isascii(ch) && isxdigit(ch)) {
1460                 value = (value << 4) + hexTable[ch];
1461                 gotone++;
1462             } else if ((hexTable[ch]) < 0 && gotone)
1463               done++;
1464         }
1465     }
1466     return value;
1467 }
1468
1469
1470 /*
1471  * The data returned by the following routine is always in left-most byte
1472  * first and left-most bit first.  If it doesn't return BitmapSuccess then
1473  * its arguments won't have been touched.  This routine should look as much
1474  * like the Xlib routine XReadBitmapfile as possible.
1475  */
1476 int read_bitmap_data (fstream, width, height, datap, x_hot, y_hot)
1477     FILE *fstream;                      /* handle on file  */
1478     unsigned int *width, *height;       /* RETURNED */
1479     unsigned char **datap;              /* RETURNED */
1480     int *x_hot, *y_hot;                 /* RETURNED */
1481 {
1482     unsigned char *data = NULL;         /* working variable */
1483     char line[MAX_SIZE];                /* input line from file */
1484     int size;                           /* number of bytes of data */
1485     char name_and_type[MAX_SIZE];       /* an input line */
1486     char *type;                         /* for parsing */
1487     int value;                          /* from an input line */
1488     int version10p;                     /* boolean, old format */
1489     int padding;                        /* to handle alignment */
1490     int bytes_per_line;                 /* per scanline of data */
1491     unsigned int ww = 0;                /* width */
1492     unsigned int hh = 0;                /* height */
1493     int hx = -1;                        /* x hotspot */
1494     int hy = -1;                        /* y hotspot */
1495
1496 #define Xmalloc(size) malloc(size)
1497
1498     /* first time initialization */
1499     if (initialized == FALSE) initHexTable();
1500
1501     /* error cleanup and return macro   */
1502 #define RETURN(code) { if (data) free (data); return code; }
1503
1504     while (fgets(line, MAX_SIZE, fstream)) {
1505         if (strlen(line) == MAX_SIZE-1) {
1506             RETURN (BitmapFileInvalid);
1507         }
1508         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
1509             if (!(type = strrchr(name_and_type, '_')))
1510               type = name_and_type;
1511             else
1512               type++;
1513
1514             if (!strcmp("width", type))
1515               ww = (unsigned int) value;
1516             if (!strcmp("height", type))
1517               hh = (unsigned int) value;
1518             if (!strcmp("hot", type)) {
1519                 if (type-- == name_and_type || type-- == name_and_type)
1520                   continue;
1521                 if (!strcmp("x_hot", type))
1522                   hx = value;
1523                 if (!strcmp("y_hot", type))
1524                   hy = value;
1525             }
1526             continue;
1527         }
1528     
1529         if (sscanf(line, "static short %s = {", name_and_type) == 1)
1530           version10p = 1;
1531         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
1532           version10p = 0;
1533         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
1534           version10p = 0;
1535         else
1536           continue;
1537
1538         if (!(type = strrchr(name_and_type, '_')))
1539           type = name_and_type;
1540         else
1541           type++;
1542
1543         if (strcmp("bits[]", type))
1544           continue;
1545     
1546         if (!ww || !hh)
1547           RETURN (BitmapFileInvalid);
1548
1549         if ((ww % 16) && ((ww % 16) < 9) && version10p)
1550           padding = 1;
1551         else
1552           padding = 0;
1553
1554         bytes_per_line = (ww+7)/8 + padding;
1555
1556         size = bytes_per_line * hh;
1557         data = (unsigned char *) Xmalloc ((unsigned int) size);
1558         if (!data) 
1559           RETURN (BitmapNoMemory);
1560
1561         if (version10p) {
1562             unsigned char *ptr;
1563             int bytes;
1564
1565             for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
1566                 if ((value = NextInt(fstream)) < 0)
1567                   RETURN (BitmapFileInvalid);
1568                 *(ptr++) = value;
1569                 if (!padding || ((bytes+2) % bytes_per_line))
1570                   *(ptr++) = value >> 8;
1571             }
1572         } else {
1573             unsigned char *ptr;
1574             int bytes;
1575
1576             for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
1577                 if ((value = NextInt(fstream)) < 0) 
1578                   RETURN (BitmapFileInvalid);
1579                 *ptr=value;
1580             }
1581         }
1582         break;
1583     }                                   /* end while */
1584
1585     if (data == NULL) {
1586         RETURN (BitmapFileInvalid);
1587     }
1588
1589     *datap = data;
1590     data = NULL;
1591     *width = ww;
1592     *height = hh;
1593     if (x_hot) *x_hot = hx;
1594     if (y_hot) *y_hot = hy;
1595
1596     RETURN (BitmapSuccess);
1597 }
1598
1599
1600 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width, 
1601                                 unsigned int *height, unsigned char **datap,
1602                                 int *x_hot, int *y_hot)
1603 {
1604     FILE *fstream;
1605     int status;
1606
1607     if ((fstream = fopen (filename, "r")) == NULL) {
1608         return BitmapOpenFailed;
1609     }
1610     status = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
1611     fclose (fstream);
1612     return status;
1613 }
1614 #endif /* HAVE_X_WINDOWS */
1615
1616 /* this table flips four bits around. */
1617 static int flip_table[] =
1618 {
1619   0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
1620 };
1621
1622 /* the bitmap data comes in the following format: Widths are padded to
1623    a multiple of 8.  Scan lines are stored in increasing byte order
1624    from left to right, little-endian within a byte.  0 = white, 1 =
1625    black.  It must be converted to the following format: Widths are
1626    padded to a multiple of 16.  Scan lines are stored in increasing
1627    byte order from left to right, big-endian within a byte.  0 =
1628    black, 1 = white.  */
1629 HBITMAP
1630 xbm_create_bitmap_from_data (HDC hdc, char *data,
1631                              unsigned int width, unsigned int height,
1632                              int mask, COLORREF fg, COLORREF bg)
1633 {
1634   int old_width = (width + 7)/8;
1635   int new_width = BPLINE (2*((width + 15)/16));
1636   unsigned char *offset;
1637   void *bmp_buf = 0;
1638   unsigned char *new_data, *new_offset;
1639   int i, j;
1640   BITMAPINFO* bmp_info = 
1641     xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
1642   HBITMAP bitmap;
1643
1644   if (!bmp_info)
1645     return NULL;
1646   
1647   new_data = (unsigned char *) xmalloc_and_zero (height * new_width);
1648       
1649   if (!new_data)
1650     {
1651       xfree (bmp_info);
1652       return NULL;
1653     }
1654   
1655   for (i=0; i<height; i++)
1656     {
1657       offset = data + i*old_width;
1658       new_offset = new_data + i*new_width;
1659
1660       for (j=0; j<old_width; j++)
1661         {
1662           int byte = offset[j];
1663           new_offset[j] = ~ (unsigned char)
1664             ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]);
1665         }
1666     }
1667
1668   /* if we want a mask invert the bits */
1669   if (!mask)
1670     {
1671       new_offset = &new_data[height * new_width];
1672       while (new_offset-- != new_data)
1673         {
1674           *new_offset ^= 0xff;
1675         }
1676     }
1677
1678   bmp_info->bmiHeader.biWidth=width;
1679   bmp_info->bmiHeader.biHeight=-(LONG)height;
1680   bmp_info->bmiHeader.biPlanes=1;
1681   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
1682   bmp_info->bmiHeader.biBitCount=1; 
1683   bmp_info->bmiHeader.biCompression=BI_RGB;
1684   bmp_info->bmiHeader.biClrUsed = 2; 
1685   bmp_info->bmiHeader.biClrImportant = 2; 
1686   bmp_info->bmiHeader.biSizeImage = height * new_width; 
1687   bmp_info->bmiColors[0].rgbRed = GetRValue (fg);
1688   bmp_info->bmiColors[0].rgbGreen = GetGValue (fg);
1689   bmp_info->bmiColors[0].rgbBlue = GetBValue (fg);
1690   bmp_info->bmiColors[0].rgbReserved = 0;
1691   bmp_info->bmiColors[1].rgbRed = GetRValue (bg);
1692   bmp_info->bmiColors[1].rgbGreen = GetGValue (bg);
1693   bmp_info->bmiColors[1].rgbBlue = GetBValue (bg);
1694   bmp_info->bmiColors[1].rgbReserved = 0;
1695   
1696   bitmap = CreateDIBSection (hdc,  
1697                              bmp_info,
1698                              DIB_RGB_COLORS,
1699                              &bmp_buf, 
1700                              0,0);
1701
1702   xfree (bmp_info);
1703   
1704   if (!bitmap || !bmp_buf)
1705     {
1706       xfree (new_data);
1707       return NULL;
1708     }
1709   
1710   /* copy in the actual bitmap */
1711   memcpy (bmp_buf, new_data, height * new_width);
1712   xfree (new_data);
1713
1714   return bitmap;
1715 }
1716
1717 /* Given inline data for a mono pixmap, initialize the given
1718    image instance accordingly. */
1719
1720 static void
1721 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
1722                                      int width, int height,
1723                                      /* Note that data is in ext-format! */
1724                                      CONST char *bits,
1725                                      Lisp_Object instantiator,
1726                                      Lisp_Object pointer_fg,
1727                                      Lisp_Object pointer_bg,
1728                                      int dest_mask,
1729                                      HBITMAP mask,
1730                                      Lisp_Object mask_filename)
1731 {
1732   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1733   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (device)));
1734   Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1735   Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1736   enum image_instance_type type;
1737   COLORREF black = PALETTERGB (0,0,0);
1738   COLORREF white = PALETTERGB (255,255,255);
1739
1740   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1741
1742   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1743     signal_simple_error ("Not an MS-Windows device", device);
1744
1745   if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1746       (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1747     {
1748       if (!NILP (foreground) || !NILP (background))
1749         type = IMAGE_COLOR_PIXMAP;
1750       else
1751         type = IMAGE_MONO_PIXMAP;
1752     }
1753   else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1754     type = IMAGE_MONO_PIXMAP;
1755   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1756     type = IMAGE_COLOR_PIXMAP;
1757   else if (dest_mask & IMAGE_POINTER_MASK)
1758     type = IMAGE_POINTER;
1759   else
1760     incompatible_image_types (instantiator, dest_mask,
1761                               IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1762                               | IMAGE_POINTER_MASK);
1763
1764   mswindows_initialize_dibitmap_image_instance (ii, 1, type);
1765   
1766   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1767     find_keyword_in_vector (instantiator, Q_file);
1768   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1769   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1770   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1771   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1772   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1773   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask :
1774     xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1775                                  TRUE, black, white);
1776
1777   switch (type)
1778     {
1779     case IMAGE_MONO_PIXMAP:
1780       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1781         xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1782                                      FALSE, black, black);
1783       break;
1784
1785     case IMAGE_COLOR_PIXMAP:
1786       {
1787         COLORREF fg = black;
1788         COLORREF bg = white;
1789
1790         if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1791           foreground =
1792             Fmake_color_instance (foreground, device,
1793                                   encode_error_behavior_flag (ERROR_ME));
1794
1795         if (COLOR_INSTANCEP (foreground))
1796           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1797
1798         if (!NILP (background) && !COLOR_INSTANCEP (background))
1799           background =
1800             Fmake_color_instance (background, device,
1801                                   encode_error_behavior_flag (ERROR_ME));
1802
1803         if (COLOR_INSTANCEP (background))
1804           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1805
1806         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1807         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1808
1809         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1810           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1811                                        FALSE, fg, black);
1812       }
1813       break;
1814
1815     case IMAGE_POINTER:
1816       {
1817         COLORREF fg = black;
1818         COLORREF bg = white;
1819
1820         if (NILP (foreground))
1821           foreground = pointer_fg;
1822         if (NILP (background))
1823           background = pointer_bg;
1824
1825         IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = 
1826           find_keyword_in_vector (instantiator, Q_hotspot_x);
1827         IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = 
1828           find_keyword_in_vector (instantiator, Q_hotspot_y);
1829         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1830         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1831         if (COLOR_INSTANCEP (foreground))
1832           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1833         if (COLOR_INSTANCEP (background))
1834           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1835
1836         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1837           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1838                                        TRUE, fg, black);
1839         mswindows_initialize_image_instance_icon (ii, TRUE);
1840       }
1841       break;
1842
1843     default:
1844       abort ();
1845     }
1846 }
1847
1848 static void
1849 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1850                    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1851                    int dest_mask, int width, int height,
1852                    /* Note that data is in ext-format! */
1853                    CONST char *bits)
1854 {
1855   Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1856   Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1857   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1858   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME 
1859                             (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))));
1860   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1861   HBITMAP mask = 0;
1862   CONST char *gcc_may_you_rot_in_hell;
1863
1864   if (!NILP (mask_data))
1865     {
1866       GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1867                                        gcc_may_you_rot_in_hell);
1868       mask =
1869         xbm_create_bitmap_from_data ( hdc,
1870                                       (unsigned char *)
1871                                       gcc_may_you_rot_in_hell,
1872                                       XINT (XCAR (mask_data)),
1873                                       XINT (XCAR (XCDR (mask_data))), FALSE,
1874                                       PALETTERGB (0,0,0),
1875                                       PALETTERGB (255,255,255));
1876     }
1877
1878   init_image_instance_from_xbm_inline (ii, width, height, bits,
1879                                        instantiator, pointer_fg, pointer_bg,
1880                                        dest_mask, mask, mask_file);
1881 }
1882
1883 /* Instantiate method for XBM's. */
1884
1885 static void
1886 mswindows_xbm_instantiate (Lisp_Object image_instance, 
1887                            Lisp_Object instantiator,
1888                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1889                            int dest_mask, Lisp_Object domain)
1890 {
1891   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1892   CONST char *gcc_go_home;
1893
1894   assert (!NILP (data));
1895
1896   GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1897                                    gcc_go_home);
1898
1899   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1900                      pointer_bg, dest_mask, XINT (XCAR (data)),
1901                      XINT (XCAR (XCDR (data))), gcc_go_home);
1902 }
1903
1904 #ifdef HAVE_XFACE
1905 /**********************************************************************
1906  *                             X-Face                                 *
1907  **********************************************************************/
1908 #if defined(EXTERN)
1909 /* This is about to get redefined! */
1910 #undef EXTERN
1911 #endif
1912 /* We have to define SYSV32 so that compface.h includes string.h
1913    instead of strings.h. */
1914 #define SYSV32
1915 #ifdef __cplusplus
1916 extern "C" {
1917 #endif
1918 #include <compface.h>
1919 #ifdef __cplusplus
1920 }
1921 #endif
1922 /* JMP_BUF cannot be used here because if it doesn't get defined
1923    to jmp_buf we end up with a conflicting type error with the
1924    definition in compface.h */
1925 extern jmp_buf comp_env;
1926 #undef SYSV32
1927
1928 static void
1929 mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1930                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1931                              int dest_mask, Lisp_Object domain)
1932 {
1933   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1934   int i, stattis;
1935   char *p, *bits, *bp;
1936   CONST char * volatile emsg = 0;
1937   CONST char * volatile dstring;
1938
1939   assert (!NILP (data));
1940
1941   GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
1942
1943   if ((p = strchr (dstring, ':')))
1944     {
1945       dstring = p + 1;
1946     }
1947
1948   /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1949   if (!(stattis = setjmp (comp_env)))
1950     {
1951       UnCompAll ((char *) dstring);
1952       UnGenFace ();
1953     }
1954
1955   switch (stattis)
1956     {
1957     case -2:
1958       emsg = "uncompface: internal error";
1959       break;
1960     case -1:
1961       emsg = "uncompface: insufficient or invalid data";
1962       break;
1963     case 1:
1964       emsg = "uncompface: excess data ignored";
1965       break;
1966     }
1967
1968   if (emsg)
1969     signal_simple_error_2 (emsg, data, Qimage);
1970
1971   bp = bits = (char *) alloca (PIXELS / 8);
1972
1973   /* the compface library exports char F[], which uses a single byte per
1974      pixel to represent a 48x48 bitmap.  Yuck. */
1975   for (i = 0, p = F; i < (PIXELS / 8); ++i)
1976     {
1977       int n, b;
1978       /* reverse the bit order of each byte... */
1979       for (b = n = 0; b < 8; ++b)
1980         {
1981           n |= ((*p++) << b);
1982         }
1983       *bp++ = (char) n;
1984     }
1985
1986   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1987                      pointer_bg, dest_mask, 48, 48, bits);
1988 }
1989 #endif /* HAVE_XFACE */
1990
1991 \f
1992 /************************************************************************/
1993 /*                      image instance methods                          */
1994 /************************************************************************/
1995
1996 static void
1997 mswindows_print_image_instance (struct Lisp_Image_Instance *p,
1998                                 Lisp_Object printcharfun,
1999                                 int escapeflag)
2000 {
2001   char buf[100];
2002
2003   switch (IMAGE_INSTANCE_TYPE (p))
2004     {
2005     case IMAGE_MONO_PIXMAP:
2006     case IMAGE_COLOR_PIXMAP:
2007     case IMAGE_POINTER:
2008       sprintf (buf, " (0x%lx", 
2009                (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
2010       write_c_string (buf, printcharfun);
2011       if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2012         {
2013           sprintf (buf, "/0x%lx", 
2014                    (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2015           write_c_string (buf, printcharfun);
2016         }
2017       write_c_string (")", printcharfun);
2018       break;
2019
2020     default:
2021       break;
2022     }
2023 }
2024
2025 #ifdef DEBUG_WIDGETS
2026 extern int debug_widget_instances;
2027 #endif
2028
2029 static void
2030 mswindows_finalize_image_instance (struct Lisp_Image_Instance *p)
2031 {
2032   if (DEVICE_LIVE_P (XDEVICE (p->device)))
2033     {
2034       if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET
2035           || 
2036           IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2037         {
2038 #ifdef DEBUG_WIDGETS
2039           debug_widget_instances--;
2040           stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
2041 #endif
2042           if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2043             {
2044               DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
2045               DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p));
2046               IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
2047             }
2048         }
2049       else if (p->data)
2050         {
2051           int i;
2052           if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
2053             disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
2054
2055           if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p))
2056             {
2057               for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
2058                 {
2059                   if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i))
2060                     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i));
2061                   IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0;
2062                 }
2063               xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p));
2064               IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0;
2065             }
2066           if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2067             DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2068           IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0;
2069           if (IMAGE_INSTANCE_MSWINDOWS_ICON (p))
2070             DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p));
2071           IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0;
2072         }
2073     }
2074
2075   if (p->data)
2076     {
2077       xfree (p->data);
2078       p->data = 0;
2079     }
2080 }
2081
2082 /************************************************************************/
2083 /*                      subwindow and widget support                      */
2084 /************************************************************************/
2085
2086 /* unmap the image if it is a widget. This is used by redisplay via
2087    redisplay_unmap_subwindows */
2088 static void
2089 mswindows_unmap_subwindow (struct Lisp_Image_Instance *p)
2090 {
2091   if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2092     {
2093       SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), 
2094                     NULL, 
2095                     0, 0, 0, 0,
2096                     SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE
2097                     | SWP_NOSENDCHANGING);
2098     }
2099 }
2100
2101 /* map the subwindow. This is used by redisplay via
2102    redisplay_output_subwindow */
2103 static void
2104 mswindows_map_subwindow (struct Lisp_Image_Instance *p, int x, int y,
2105                          struct display_glyph_area* dga)
2106 {
2107   /* move the window before mapping it ... */
2108   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2109                 NULL, 
2110                 x, y, dga->width, dga->height,
2111                 SWP_NOZORDER 
2112                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2113   /* ... adjust the child ... */
2114   SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2115                 NULL, 
2116                 -dga->xoffset, -dga->yoffset, 0, 0,
2117                 SWP_NOZORDER | SWP_NOSIZE
2118                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2119   /* ... now map it - we are not allowed to move it at the same time. */
2120   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), 
2121                 NULL, 
2122                 0, 0, 0, 0,
2123                 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2124                 | SWP_SHOWWINDOW | SWP_NOCOPYBITS 
2125                 | SWP_NOSENDCHANGING);
2126 }
2127
2128 /* resize the subwindow instance */
2129 static void 
2130 mswindows_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h)
2131 {
2132   /* Set the size of the control .... */
2133   SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), 
2134                 NULL, 
2135                 0, 0, w, h,
2136                 SWP_NOZORDER | SWP_NOMOVE
2137                 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2138 }
2139
2140 /* when you click on a widget you may activate another widget this
2141    needs to be checked and all appropriate widgets updated */
2142 static void
2143 mswindows_update_subwindow (struct Lisp_Image_Instance *p)
2144 {
2145   if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
2146     {
2147       /* buttons checked or otherwise */
2148       if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton))
2149         {
2150           if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (p)))
2151             SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), 
2152                          BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 
2153           else
2154             SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2155                          BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2156         }
2157
2158       /* set the widget font from the widget face */
2159       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2160                    WM_SETFONT, 
2161                    (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT 
2162                    (XFONT_INSTANCE (widget_face_font_info
2163                                     (IMAGE_INSTANCE_SUBWINDOW_FRAME (p), 
2164                                      IMAGE_INSTANCE_WIDGET_FACE (p),
2165                                      0, 0))), 
2166                    MAKELPARAM (TRUE, 0));
2167     }
2168 }
2169
2170 /* register widgets into our hastable so that we can cope with the
2171    callbacks. The hashtable is weak so deregistration is handled
2172    automatically */
2173 static int
2174 mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain)
2175 {
2176   Lisp_Object frame = FW_FRAME (domain);
2177   struct frame* f = XFRAME (frame);
2178   int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
2179                              gui,
2180                              WIDGET_GLYPH_SLOT);
2181   Fputhash (make_int (id),
2182             XGUI_ITEM (gui)->callback,
2183             FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
2184   return id;
2185 }
2186
2187 static int
2188 mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
2189 {
2190   return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_ITEM (instance),
2191                                       domain);
2192 }
2193
2194 static void
2195 mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2196                                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2197                                  int dest_mask, Lisp_Object domain)
2198 {
2199   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2200   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2201   struct device* d = XDEVICE (device);
2202   Lisp_Object frame = FW_FRAME (domain);
2203   HWND wnd;
2204
2205   if (!DEVICE_MSWINDOWS_P (d))
2206     signal_simple_error ("Not an mswindows device", device);
2207
2208   /* have to set the type this late in case there is no device
2209      instantiation for a widget */
2210   IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2211   /* Allocate space for the clip window */
2212   ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2213
2214   if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2215        = CreateWindowEx(
2216                         0,              /* EX flags */
2217                         XEMACS_CONTROL_CLASS,
2218                         0,              /* text */
2219                         WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2220                         0,         /* starting x position */
2221                         0,         /* starting y position */
2222                         IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2223                         IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2224                         /* parent window */
2225                         FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2226                         NULL,       /* No menu */
2227                         NULL, /* must be null for this class */
2228                         NULL)) == NULL)
2229     signal_simple_error ("window creation failed with code", 
2230                          make_int (GetLastError()));
2231
2232   wnd = CreateWindow( "STATIC",  
2233                       "",
2234                       WS_CHILD,  
2235                       0,         /* starting x position */
2236                       0,         /* starting y position */
2237                       IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2238                       IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2239                       IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2240                       0,
2241                       (HINSTANCE) 
2242                       GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2243                                      GWL_HINSTANCE), 
2244                       NULL);
2245
2246   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2247   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2248 }
2249
2250 static int
2251 mswindows_image_instance_equal (struct Lisp_Image_Instance *p1,
2252                                 struct Lisp_Image_Instance *p2, int depth)
2253 {
2254   switch (IMAGE_INSTANCE_TYPE (p1))
2255     {
2256     case IMAGE_MONO_PIXMAP:
2257     case IMAGE_COLOR_PIXMAP:
2258     case IMAGE_POINTER:
2259       if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1) 
2260           != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2))
2261         return 0;
2262       break;
2263     
2264     default:
2265       break;
2266     }
2267
2268   return 1;
2269 }
2270
2271 static unsigned long
2272 mswindows_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
2273 {
2274   switch (IMAGE_INSTANCE_TYPE (p))
2275     {
2276     case IMAGE_MONO_PIXMAP:
2277     case IMAGE_COLOR_PIXMAP:
2278     case IMAGE_POINTER:
2279       return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p);
2280     
2281     default:
2282       return 0;
2283     }
2284 }
2285
2286 /* Set all the slots in an image instance structure to reasonable
2287    default values.  This is used somewhere within an instantiate
2288    method.  It is assumed that the device slot within the image
2289    instance is already set -- this is the case when instantiate
2290    methods are called. */
2291
2292 static void
2293 mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii,
2294                                               int slices,
2295                                               enum image_instance_type type)
2296 {
2297   ii->data = xnew_and_zero (struct mswindows_image_instance_data);
2298   IMAGE_INSTANCE_TYPE (ii) = type;
2299   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
2300   IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
2301   IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
2302   IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
2303   IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
2304   IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
2305   IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
2306   IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) = 
2307     xnew_array_and_zero (HBITMAP, slices);
2308 }
2309
2310 \f
2311 #ifdef HAVE_WIDGETS
2312
2313 /************************************************************************/
2314 /*                            widgets                            */
2315 /************************************************************************/
2316 static void
2317 mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2318                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2319                               int dest_mask, Lisp_Object domain,
2320                               CONST char* class, int flags, int exflags)
2321 {
2322   /* this function can call lisp */
2323   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2324   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
2325   struct device* d = XDEVICE (device);
2326   Lisp_Object frame = FW_FRAME (domain);
2327   Extbyte* nm=0;
2328   HWND wnd;
2329   int id = 0xffff;
2330   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2331   struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2332
2333   if (!DEVICE_MSWINDOWS_P (d))
2334     signal_simple_error ("Not an mswindows device", device);
2335
2336   if (!gui_item_active_p (gui))
2337     flags |= WS_DISABLED;
2338
2339   style = pgui->style;
2340
2341   if (!NILP (pgui->callback))
2342     {
2343       id = mswindows_register_widget_instance (image_instance, domain);
2344     }
2345   /* have to set the type this late in case there is no device
2346      instantiation for a widget */
2347   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2348   if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2349     GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm);
2350
2351   /* allocate space for the clip window and then allocate the clip window */
2352   ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2353
2354   if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2355        = CreateWindowEx(
2356                         0,              /* EX flags */
2357                         XEMACS_CONTROL_CLASS,
2358                         0,              /* text */
2359                         WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2360                         0,         /* starting x position */
2361                         0,         /* starting y position */
2362                         IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2363                         IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2364                         /* parent window */
2365                         FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2366                         (HMENU)id,       /* No menu */
2367                         NULL, /* must be null for this class */
2368                         NULL)) == NULL)
2369     signal_simple_error ("window creation failed with code", 
2370                          make_int (GetLastError()));
2371
2372   if ((wnd = CreateWindowEx( 
2373                             exflags /* | WS_EX_NOPARENTNOTIFY*/,
2374                             class,  
2375                             nm,
2376                             flags | WS_CHILD | WS_VISIBLE,
2377                             0,         /* starting x position */
2378                             0,         /* starting y position */
2379                             IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2380                             IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2381                             /* parent window */
2382                             IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2383                             (HMENU)id,       /* No menu */
2384                             (HINSTANCE) 
2385                             GetWindowLong 
2386                             (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2387                              GWL_HINSTANCE), 
2388                             NULL)) == NULL)
2389     signal_simple_error ("window creation failed with code", 
2390                          make_int (GetLastError()));
2391
2392   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2393   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2394   /* set the widget font from the widget face */
2395   SendMessage (wnd, WM_SETFONT, 
2396                (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT 
2397                (XFONT_INSTANCE (widget_face_font_info 
2398                                 (domain, 
2399                                  IMAGE_INSTANCE_WIDGET_FACE (ii),
2400                                  0, 0))), 
2401                MAKELPARAM (TRUE, 0));
2402 }
2403
2404 /* Instantiate a button widget. Unfortunately instantiated widgets are
2405    particular to a frame since they need to have a parent. It's not
2406    like images where you just select the image into the context you
2407    want to display it in and BitBlt it. So images instances can have a
2408    many-to-one relationship with things you see, whereas widgets can
2409    only be one-to-one (i.e. per frame) */
2410 static void
2411 mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2412                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2413                               int dest_mask, Lisp_Object domain)
2414 {
2415   /* this function can call lisp */
2416   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2417   HWND wnd;
2418   int flags = BS_NOTIFY;
2419   Lisp_Object style;
2420   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2421   struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2422   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2423
2424   if (!gui_item_active_p (gui))
2425     flags |= WS_DISABLED;
2426
2427   if (!NILP (glyph))
2428     {
2429       if (!IMAGE_INSTANCEP (glyph))
2430         glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2431
2432       if (IMAGE_INSTANCEP (glyph))
2433         flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? 
2434           BS_BITMAP : BS_ICON;
2435     }
2436
2437   style = pgui->style;
2438
2439   if (EQ (style, Qradio))
2440     {
2441       flags |= BS_RADIOBUTTON;
2442     }
2443   else if (EQ (style, Qtoggle))
2444     {
2445       flags |= BS_AUTOCHECKBOX;
2446     }
2447   else
2448     flags |= BS_DEFPUSHBUTTON;
2449
2450   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2451                                 pointer_bg, dest_mask, domain, "BUTTON", flags, 
2452                                 WS_EX_CONTROLPARENT);
2453
2454   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2455   /* set the checked state */
2456   if (gui_item_selected_p (gui))
2457     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 
2458   else
2459     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2460   /* add the image if one was given */
2461   if (!NILP (glyph) && IMAGE_INSTANCEP (glyph))
2462     {
2463       SendMessage (wnd, BM_SETIMAGE, 
2464                    (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? 
2465                              IMAGE_BITMAP : IMAGE_ICON),
2466                    (LPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2467                              XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
2468                              XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
2469     }
2470 }
2471
2472 /* instantiate an edit control */
2473 static void
2474 mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2475                             Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2476                             int dest_mask, Lisp_Object domain)
2477 {
2478   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2479                                 pointer_bg, dest_mask, domain, "EDIT", 
2480                                 ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP
2481                                 | WS_BORDER,
2482                                 WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
2483 }
2484
2485 /* instantiate a progress gauge */
2486 static void
2487 mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2488                                 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2489                                 int dest_mask, Lisp_Object domain)
2490 {
2491   HWND wnd;
2492   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2493   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2494                                 pointer_bg, dest_mask, domain, PROGRESS_CLASS, 
2495                                 WS_TABSTOP | WS_BORDER | PBS_SMOOTH,
2496                                 WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
2497   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2498   /* set the colors */
2499 #ifdef PBS_SETBKCOLOR
2500   SendMessage (wnd, PBS_SETBKCOLOR, 0, 
2501                (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR 
2502                          (XCOLOR_INSTANCE 
2503                           (FACE_BACKGROUND 
2504                            (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2505                             XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
2506 #endif
2507 #ifdef PBS_SETBARCOLOR
2508   SendMessage (wnd, PBS_SETBARCOLOR, 0, 
2509                (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR 
2510                           (XCOLOR_INSTANCE 
2511                            (FACE_FOREGROUND 
2512                             (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2513                              XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
2514 #endif
2515 }
2516
2517 /* instantiate a tree view widget */
2518 static HTREEITEM add_tree_item (Lisp_Object image_instance,
2519                                 HWND wnd, HTREEITEM parent, Lisp_Object item,
2520                                 int children, Lisp_Object domain)
2521 {
2522   TV_INSERTSTRUCT tvitem;
2523   HTREEITEM ret;
2524
2525   tvitem.hParent = parent;
2526   tvitem.hInsertAfter = TVI_LAST;
2527   tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
2528   tvitem.item.cChildren = children;
2529       
2530   if (GUI_ITEMP (item))
2531     {
2532       tvitem.item.lParam = mswindows_register_gui_item (item, domain);
2533       tvitem.item.mask |= TVIF_PARAM;
2534       GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, 
2535                                    tvitem.item.pszText);
2536     }
2537   else
2538     GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.item.pszText);
2539
2540   tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
2541
2542   if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM, 
2543                                      0, (LPARAM)&tvitem)) == 0)
2544     signal_simple_error ("error adding tree view entry", item);
2545
2546   return ret;
2547 }
2548
2549 static void add_tree_item_list (Lisp_Object image_instance,
2550                                 HWND wnd, HTREEITEM parent, Lisp_Object list,
2551                                 Lisp_Object domain)
2552 {
2553   Lisp_Object rest;
2554
2555   /* get the first item */
2556   parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
2557   /* recursively add items to the tree view */
2558   LIST_LOOP (rest, XCDR (list))
2559     {
2560       if (LISTP (XCAR (rest)))
2561         add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2562       else
2563         add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2564     }
2565 }
2566
2567 static void
2568 mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2569                             Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2570                             int dest_mask, Lisp_Object domain)
2571 {
2572   Lisp_Object rest;
2573   HWND wnd;
2574   HTREEITEM parent;
2575   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2576   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2577                                 pointer_bg, dest_mask, domain, WC_TREEVIEW, 
2578                                 WS_TABSTOP | WS_BORDER | PBS_SMOOTH
2579                                 | TVS_HASLINES | TVS_HASBUTTONS,
2580                                 WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
2581
2582   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2583  
2584   /* define a root */
2585   parent = add_tree_item (image_instance, wnd, NULL, 
2586                           XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), 
2587                           TRUE, domain);
2588  
2589   /* recursively add items to the tree view */
2590   /* add items to the tab */
2591   LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2592     {
2593       if (LISTP (XCAR (rest)))
2594         add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2595       else
2596         add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2597     }
2598 }
2599
2600 /* instantiate a tab control */
2601 static TC_ITEM* add_tab_item (Lisp_Object image_instance,
2602                              HWND wnd, Lisp_Object item,
2603                              Lisp_Object domain, int index)
2604 {
2605   TC_ITEM tvitem, *ret;
2606
2607   tvitem.mask = TCIF_TEXT;
2608       
2609   if (GUI_ITEMP (item))
2610     {
2611       tvitem.lParam = mswindows_register_gui_item (item, domain);
2612       tvitem.mask |= TCIF_PARAM;
2613       GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, 
2614                                    tvitem.pszText);
2615     }
2616   else
2617     {
2618       CHECK_STRING (item);
2619       GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.pszText);
2620     }
2621
2622   tvitem.cchTextMax = strlen (tvitem.pszText);
2623
2624   if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM, 
2625                                     index, (LPARAM)&tvitem)) < 0)
2626     signal_simple_error ("error adding tab entry", item);
2627
2628   return ret;
2629 }
2630
2631 static void
2632 mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2633                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2634                            int dest_mask, Lisp_Object domain)
2635 {
2636   Lisp_Object rest;
2637   HWND wnd;
2638   int index = 0;
2639   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2640   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2641                                 pointer_bg, dest_mask, domain, WC_TABCONTROL, 
2642                                 /* borders don't suit tabs so well */
2643                                 WS_TABSTOP,
2644                                 WS_EX_CONTROLPARENT);
2645
2646   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2647   /* add items to the tab */
2648   LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2649     {
2650       add_tab_item (image_instance, wnd, XCAR (rest), domain, index);
2651       index++;
2652     }
2653 }
2654
2655 /* set the properties of a tab control */
2656 static Lisp_Object
2657 mswindows_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop,
2658                                     Lisp_Object val)
2659 {
2660   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2661
2662   if (EQ (prop, Q_items))
2663     {
2664       HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2665       int index = 0;
2666       Lisp_Object rest;
2667       check_valid_item_list_1 (val);
2668
2669       /* delete the pre-existing items */
2670       SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
2671   
2672       IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
2673         Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), 
2674                parse_gui_item_tree_children (val));
2675
2676       /* add items to the tab */
2677       LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2678         {
2679           add_tab_item (image_instance, wnd, XCAR (rest), 
2680                         IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), index);
2681           index++;
2682         }
2683
2684       return Qt;
2685     }
2686   return Qunbound;
2687 }
2688
2689 /* instantiate a static control possible for putting other things in */
2690 static void
2691 mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2692                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2693                              int dest_mask, Lisp_Object domain)
2694 {
2695   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2696                                 pointer_bg, dest_mask, domain, "STATIC", 
2697                                 0, WS_EX_STATICEDGE);
2698 }
2699
2700 /* instantiate a scrollbar control */
2701 static void
2702 mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2703                                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2704                                  int dest_mask, Lisp_Object domain)
2705 {
2706   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2707                                 pointer_bg, dest_mask, domain, "SCROLLBAR", 
2708                                 0,
2709                                 WS_EX_CLIENTEDGE );
2710 }
2711
2712 /* instantiate a combo control */
2713 static void
2714 mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2715                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2716                              int dest_mask, Lisp_Object domain)
2717 {
2718   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2719   HANDLE wnd;
2720   Lisp_Object rest;
2721   Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
2722                                  Q_items, Qnil);
2723   int len;
2724   GET_LIST_LENGTH (data, len);
2725
2726   /* Maybe ought to generalise this more but it may be very windows
2727      specific. In windows the window height of a combo box is the
2728      height when the combo box is open. Thus we need to set the height
2729      before creating the window and then reset it to a single line
2730      after the window is created so that redisplay does the right
2731      thing. */
2732   widget_instantiate_1 (image_instance, instantiator, pointer_fg,
2733                         pointer_bg, dest_mask, domain, len + 1, 0, 0);
2734
2735   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2736                                 pointer_bg, dest_mask, domain, "COMBOBOX", 
2737                                 WS_BORDER | WS_TABSTOP | CBS_DROPDOWN
2738                                 | CBS_AUTOHSCROLL  
2739                                 | CBS_HASSTRINGS | WS_VSCROLL,
2740                                 WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
2741   /* reset the height */
2742   widget_text_to_pixel_conversion (domain, 
2743                                    IMAGE_INSTANCE_WIDGET_FACE (ii), 1, 0, 
2744                                    &IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii), 0);
2745   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2746   /* add items to the combo box */
2747   SendMessage (wnd, CB_RESETCONTENT, 0, 0);
2748   LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
2749     {
2750       Extbyte* lparam;
2751       GET_C_STRING_OS_DATA_ALLOCA (XCAR (rest), lparam);
2752       if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR)
2753         signal_simple_error ("error adding combo entries", instantiator);
2754     }
2755 }
2756
2757 /* get properties of a control */
2758 static Lisp_Object
2759 mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2760 {
2761   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2762   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2763   /* get the text from a control */
2764   if (EQ (prop, Q_text))
2765     {
2766       Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
2767       Extbyte* buf =alloca (len+1);
2768       
2769       SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf);
2770       return build_ext_string (buf, FORMAT_OS);
2771     }
2772   return Qunbound;
2773 }
2774
2775 /* get properties of a button */
2776 static Lisp_Object
2777 mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
2778 {
2779   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2780   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2781   /* check the state of a button */
2782   if (EQ (prop, Q_selected))
2783     {
2784       if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
2785         return Qt;
2786       else
2787         return Qnil;
2788     }
2789   return Qunbound;
2790 }
2791
2792 /* get properties of a combo box */
2793 static Lisp_Object
2794 mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
2795 {
2796   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2797   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2798   /* get the text from a control */
2799   if (EQ (prop, Q_text))
2800     {
2801       long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
2802       Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
2803       Extbyte* buf = alloca (len+1);
2804       SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf);
2805       return build_ext_string (buf, FORMAT_OS);
2806     }
2807   return Qunbound;
2808 }
2809
2810 /* set the properties of a control */
2811 static Lisp_Object
2812 mswindows_widget_set_property (Lisp_Object image_instance, Lisp_Object prop,
2813                                Lisp_Object val)
2814 {
2815   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2816
2817   if (EQ (prop, Q_text))
2818     {
2819       Extbyte* lparam=0;
2820       CHECK_STRING (val);
2821       GET_C_STRING_OS_DATA_ALLOCA (val, lparam);
2822       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2823                    WM_SETTEXT, 0, (LPARAM)lparam);
2824       return Qt;
2825     }
2826   return Qunbound;
2827 }
2828
2829 /* set the properties of a progres guage */
2830 static Lisp_Object
2831 mswindows_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop,
2832                                  Lisp_Object val)
2833 {
2834   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2835
2836   if (EQ (prop, Q_percent))
2837     {
2838       CHECK_INT (val);
2839       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2840                    PBM_SETPOS, (WPARAM)XINT (val), 0);
2841       return Qt;
2842     }
2843   return Qunbound;
2844 }
2845
2846 LRESULT WINAPI
2847 mswindows_control_wnd_proc (HWND hwnd, UINT message,
2848                             WPARAM wParam, LPARAM lParam)
2849 {
2850   switch (message)
2851     {
2852     case WM_NOTIFY:
2853     case WM_COMMAND:
2854     case WM_CTLCOLORBTN:
2855     case WM_CTLCOLORLISTBOX:
2856     case WM_CTLCOLOREDIT:
2857     case WM_CTLCOLORSTATIC:
2858     case WM_CTLCOLORSCROLLBAR:
2859
2860       return mswindows_wnd_proc (GetParent (hwnd), message, wParam, lParam);
2861     default:
2862       return DefWindowProc (hwnd, message, wParam, lParam);
2863     }
2864 }
2865
2866 #endif /* HAVE_WIDGETS */
2867
2868 \f
2869 /************************************************************************/
2870 /*                            initialization                            */
2871 /************************************************************************/
2872
2873 void
2874 syms_of_glyphs_mswindows (void)
2875 {
2876   defkeyword (&Q_resource_id, ":resource-id");
2877   defkeyword (&Q_resource_type, ":resource-type");
2878 }
2879
2880 void
2881 console_type_create_glyphs_mswindows (void)
2882 {
2883   /* image methods */
2884
2885   CONSOLE_HAS_METHOD (mswindows, print_image_instance);
2886   CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
2887   CONSOLE_HAS_METHOD (mswindows, unmap_subwindow);
2888   CONSOLE_HAS_METHOD (mswindows, map_subwindow);
2889   CONSOLE_HAS_METHOD (mswindows, update_subwindow);
2890   CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
2891   CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
2892   CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
2893   CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
2894   CONSOLE_HAS_METHOD (mswindows, resize_subwindow);
2895 }
2896
2897 void
2898 image_instantiator_format_create_glyphs_mswindows (void)
2899 {
2900   IIFORMAT_VALID_CONSOLE (mswindows, nothing);
2901   IIFORMAT_VALID_CONSOLE (mswindows, string);
2902   IIFORMAT_VALID_CONSOLE (mswindows, layout);
2903   IIFORMAT_VALID_CONSOLE (mswindows, formatted_string);
2904   IIFORMAT_VALID_CONSOLE (mswindows, inherit);
2905   /* image-instantiator types */
2906 #ifdef HAVE_XPM
2907   INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm);
2908   IIFORMAT_HAS_DEVMETHOD (mswindows, xpm, instantiate);
2909 #endif
2910   INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm);
2911   IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate);
2912 #ifdef HAVE_XFACE
2913   INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
2914   IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
2915 #endif
2916 #ifdef HAVE_JPEG
2917   IIFORMAT_VALID_CONSOLE (mswindows, jpeg);
2918 #endif
2919 #ifdef HAVE_TIFF
2920   IIFORMAT_VALID_CONSOLE (mswindows, tiff);
2921 #endif  
2922 #ifdef HAVE_PNG
2923   IIFORMAT_VALID_CONSOLE (mswindows, png);
2924 #endif  
2925 #ifdef HAVE_GIF
2926   IIFORMAT_VALID_CONSOLE (mswindows, gif);
2927 #endif  
2928 #ifdef HAVE_WIDGETS
2929   /* button widget */
2930   INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
2931   IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
2932   IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
2933
2934   INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
2935   IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
2936   
2937   INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
2938   IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
2939
2940   INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
2941   IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
2942   IIFORMAT_HAS_DEVMETHOD (mswindows, widget, set_property);
2943
2944   /* label */
2945   INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
2946   IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
2947
2948   /* combo box */
2949   INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
2950   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
2951   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
2952
2953   /* scrollbar */
2954   INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
2955   IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
2956
2957   /* progress gauge */
2958   INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
2959   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, set_property);
2960   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
2961
2962   /* tree view widget */
2963   INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
2964   /*  IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/
2965   IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
2966
2967   /* tab control widget */
2968   INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
2969   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
2970   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, set_property);
2971 #endif
2972   /* windows bitmap format */
2973   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
2974   IIFORMAT_HAS_METHOD (bmp, validate);
2975   IIFORMAT_HAS_METHOD (bmp, normalize);
2976   IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
2977   IIFORMAT_HAS_METHOD (bmp, instantiate);
2978
2979   IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
2980   IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
2981   IIFORMAT_VALID_CONSOLE (mswindows, bmp);
2982
2983   /* mswindows resources */
2984   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
2985                                         "mswindows-resource");
2986
2987   IIFORMAT_HAS_METHOD (mswindows_resource, validate);
2988   IIFORMAT_HAS_METHOD (mswindows_resource, normalize);
2989   IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types);
2990   IIFORMAT_HAS_METHOD (mswindows_resource, instantiate);
2991
2992   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type, 
2993                           check_valid_resource_symbol);
2994   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
2995   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
2996   IIFORMAT_VALID_CONSOLE (mswindows, mswindows_resource);
2997 }
2998
2999 void
3000 vars_of_glyphs_mswindows (void)
3001 {
3002   DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
3003 A list of the directories in which mswindows bitmap files may be found.
3004 This is used by the `make-image-instance' function.
3005 */ );
3006   Vmswindows_bitmap_file_path = Qnil;
3007 }
3008
3009 void
3010 complex_vars_of_glyphs_mswindows (void)
3011 {
3012 }