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