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