XEmacs 21.2-b1
[chise/xemacs-chise.git.1] / src / glyphs-msw.c
1 /* mswindows-specific Lisp objects.
2    Copyright (C) 1998 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 <andyp@parallax.co.uk> plagerising buts 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 "buffer.h"
36 #include "frame.h"
37 #include "insdel.h"
38 #include "opaque.h"
39 #include "sysfile.h"
40 #include "faces.h"
41 #include "imgproc.h"
42
43 #ifdef FILE_CODING
44 #include "file-coding.h"
45 #endif
46 #include <stdio.h>
47 #include <ctype.h>
48
49
50 DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp);
51 Lisp_Object Qbmp;
52 Lisp_Object Vmswindows_bitmap_file_path;
53 static  COLORREF transparent_color = RGB (1,1,1);
54
55 DEFINE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource);
56 Lisp_Object Q_resource_type, Q_resource_id;
57 Lisp_Object Qmswindows_resource;
58
59 static void
60 mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii,
61                                             enum image_instance_type type);
62 static void
63 mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, 
64                                           struct frame* f);
65
66 COLORREF mswindows_string_to_color (CONST char *name);
67
68 #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3)))
69
70 /************************************************************************/
71 /* convert from a series of RGB triples to a BITMAPINFO formated for the*/
72 /* proper display                                                       */
73 /************************************************************************/
74 static BITMAPINFO* convert_EImage_to_DIBitmap (Lisp_Object device,
75                                                int width, int height,
76                                                unsigned char *pic,
77                                                int *bit_count,
78                                                unsigned char** bmp_data)
79 {
80   struct device *d = XDEVICE (device);
81   int i,j;
82   RGBQUAD* colortbl;
83   int           ncolors;
84   BITMAPINFO*   bmp_info;
85   unsigned char *ip, *dp;
86
87   if (DEVICE_MSWINDOWS_BITSPIXEL (d) > 0)
88     {
89       int bpline = BPLINE(width * 3);
90       /* FIXME: we can do this because 24bpp implies no colour table, once
91        * we start paletizing this is no longer true. The X versions of
92        * this function quantises to 256 colours or bit masks down to a
93        * long. Windows can actually handle rgb triples in the raw so I
94        * don't see much point trying to optimize down to the best
95        * structure - unless it has memory / color allocation implications
96        * .... */
97       bmp_info=xnew_and_zero (BITMAPINFO);
98       
99       if (!bmp_info)
100         {
101           return NULL;
102         }
103
104       bmp_info->bmiHeader.biBitCount=24; /* just RGB triples for now */
105       bmp_info->bmiHeader.biCompression=BI_RGB; /* just RGB triples for now */
106       bmp_info->bmiHeader.biSizeImage=width*height*3; 
107
108       /* bitmap data needs to be in blue, green, red triples - in that
109          order, eimage is in RGB format so we need to convert */
110       *bmp_data = xnew_array_and_zero (unsigned char, bpline * height);
111       *bit_count = bpline * height;
112
113       if (!bmp_data)
114         {
115           xfree (bmp_info);
116           return NULL;
117         }
118
119       ip = pic;
120       for (i = height-1; i >= 0; i--) {
121         dp = (*bmp_data) + (i * bpline);
122         for (j = 0; j < width; j++) {
123           dp[2] =*ip++;
124           dp[1] =*ip++;
125           *dp   =*ip++;
126           dp += 3;
127         }
128       }
129     }
130   else                          /* scale to 256 colors */
131     {
132       int rd,gr,bl;
133       quant_table *qtable;
134       int bpline = BPLINE (width * 3);
135       /* Quantize the image and get a histogram while we're at it.
136          Do this first to save memory */
137       qtable = build_EImage_quantable(pic, width, height, 256);
138       if (qtable == NULL) return NULL;
139
140       /* use our quantize table to allocate the colors */
141       ncolors = qtable->num_active_colors;
142       bmp_info=(BITMAPINFO*)xmalloc_and_zero (sizeof(BITMAPINFOHEADER) + 
143                                              sizeof(RGBQUAD) * ncolors);
144       if (!bmp_info)
145         {
146           xfree (qtable);
147           return NULL;
148         }
149
150       colortbl=(RGBQUAD*)(((unsigned char*)bmp_info)+sizeof(BITMAPINFOHEADER));
151
152       bmp_info->bmiHeader.biBitCount=8; 
153       bmp_info->bmiHeader.biCompression=BI_RGB; 
154       bmp_info->bmiHeader.biSizeImage=bpline*height;
155       bmp_info->bmiHeader.biClrUsed=ncolors; 
156       bmp_info->bmiHeader.biClrImportant=ncolors; 
157       
158       *bmp_data = (unsigned char *) xmalloc_and_zero (bpline * height);
159       *bit_count = bpline * height;
160
161       if (!*bmp_data)
162         {
163           xfree (qtable);
164           xfree (bmp_info);
165           return NULL;
166         }
167       
168       /* build up an RGBQUAD colortable */
169       for (i = 0; i < qtable->num_active_colors; i++) {
170         colortbl[i].rgbRed = (BYTE) qtable->rm[i];
171         colortbl[i].rgbGreen = (BYTE) qtable->gm[i];
172         colortbl[i].rgbBlue = (BYTE) qtable->bm[i];
173         colortbl[i].rgbReserved = 0;
174       }
175
176       /* now build up the data. picture has to be upside-down and
177          back-to-front for msw bitmaps */
178       ip = pic;
179       for (i = height-1; i >= 0; i--) {
180         dp = (*bmp_data) + (i * bpline);
181         for (j = 0; j < width; j++) {
182           rd = *ip++;
183           gr = *ip++;
184           bl = *ip++;
185           *dp++ = QUANT_GET_COLOR (qtable,rd,gr,bl);
186         }
187       }
188       xfree (qtable);
189     } 
190   /* fix up the standard stuff */
191   bmp_info->bmiHeader.biWidth=width;
192   bmp_info->bmiHeader.biHeight=height;
193   bmp_info->bmiHeader.biPlanes=1;
194   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
195   bmp_info->bmiHeader.biXPelsPerMeter=0; /* unless you know better */
196   bmp_info->bmiHeader.biYPelsPerMeter=0; 
197
198   return bmp_info;
199 }
200
201 /* Given a pixmap filename, look through all of the "standard" places
202    where the file might be located.  Return a full pathname if found;
203    otherwise, return Qnil. */
204
205 static Lisp_Object
206 mswindows_locate_pixmap_file (Lisp_Object name)
207 {
208   /* This function can GC if IN_REDISPLAY is false */
209   Lisp_Object found;
210
211   /* Check non-absolute pathnames with a directory component relative to
212      the search path; that's the way Xt does it. */
213   if (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 0)) ||
214       (XSTRING_BYTE (name, 0) == '.' &&
215        (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 1)) ||
216         (XSTRING_BYTE (name, 1) == '.' &&
217          (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 2)))))))
218     {
219       if (!NILP (Ffile_readable_p (name)))
220         return name;
221       else
222         return Qnil;
223     }
224
225   if (locate_file (Vmswindows_bitmap_file_path, name, "", &found, R_OK) < 0)
226     {
227       Lisp_Object temp = list1 (Vdata_directory);
228       struct gcpro gcpro1;
229
230       GCPRO1 (temp);
231       locate_file (temp, name, "", &found, R_OK);
232       UNGCPRO;
233     }
234     
235   return found;
236 }
237
238 \f
239 /* Initialize an image instance from a bitmap
240
241    DEST_MASK specifies the mask of allowed image types.
242
243    If this fails, signal an error.  INSTANTIATOR is only used
244    in the error message. */
245
246 static void
247 init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii,
248                                    BITMAPINFO *bmp_info,
249                                    int dest_mask,
250                                    void *bmp_data,
251                                    int bmp_bits,
252                                    Lisp_Object instantiator, 
253                                    int x_hot, int y_hot,
254                                    int create_mask)
255 {
256   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
257   struct device *d = XDEVICE (device);
258   struct frame *f;
259   void* bmp_buf=0;
260   int type;
261   HBITMAP bitmap;
262   HDC hdc;
263
264   if (!DEVICE_MSWINDOWS_P (d))
265     signal_simple_error ("Not an mswindows device", device);
266
267   if (NILP (DEVICE_SELECTED_FRAME (d)))
268     signal_simple_error ("No selected frame on mswindows device", device);
269
270   f = XFRAME (DEVICE_SELECTED_FRAME (d));
271   
272   if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
273     type = IMAGE_COLOR_PIXMAP;
274   else if (dest_mask & IMAGE_POINTER_MASK)
275     type = IMAGE_POINTER;
276   else 
277     incompatible_image_types (instantiator, dest_mask,
278                               IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
279   hdc = FRAME_MSWINDOWS_CDC (f);
280
281   bitmap=CreateDIBSection (hdc,  
282                           bmp_info,
283                           DIB_RGB_COLORS,
284                           &bmp_buf, 
285                           0,0);
286
287   if (!bitmap || !bmp_buf)
288     signal_simple_error ("Unable to create bitmap", instantiator);
289
290   /* copy in the actual bitmap */
291   memcpy (bmp_buf, bmp_data, bmp_bits);
292
293   mswindows_initialize_dibitmap_image_instance (ii, type);
294
295   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
296     find_keyword_in_vector (instantiator, Q_file);
297
298   IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap;
299   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
300   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth;
301   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight;
302   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = bmp_info->bmiHeader.biBitCount;
303   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), x_hot);
304   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), y_hot);
305
306   if (create_mask)
307     {
308       mswindows_initialize_image_instance_mask (ii, f);
309     }
310   
311   if (type == IMAGE_POINTER)
312     {
313       mswindows_initialize_image_instance_icon(ii, TRUE);
314     }
315 }
316
317 static void
318 mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
319                                            int width, int height,
320                                            unsigned char *eimage, 
321                                            int dest_mask,
322                                            Lisp_Object instantiator,
323                                            Lisp_Object domain)
324 {
325   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
326   BITMAPINFO*           bmp_info;
327   unsigned char*        bmp_data;
328   int                   bmp_bits;
329   COLORREF              bkcolor;
330   
331   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
332     signal_simple_error ("Not an mswindows device", device);
333
334   /* this is a hack but MaskBlt and TransparentBlt are not supported
335      on most windows variants */
336   bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR 
337     (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain)));
338
339   /* build a bitmap from the eimage */
340   if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage,
341                                              &bmp_bits, &bmp_data)))
342     {
343       signal_simple_error ("EImage to DIBitmap conversion failed",
344                            instantiator);
345     }
346
347   /* Now create the pixmap and set up the image instance */
348   init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
349                                      bmp_data, bmp_bits, instantiator,
350                                      0, 0, 0);
351
352   xfree (bmp_info);
353   xfree (bmp_data);
354 }
355
356 static void set_mono_pixel ( unsigned char* bits, 
357                              int bpline, int height, 
358                              int x, int y, int white ) 
359
360   int index;
361   unsigned char    bitnum;  
362   /* Find the byte on which this scanline begins */
363   index = (height - y - 1) * bpline; 
364   /* Find the byte containing this pixel */
365   index += (x >> 3); 
366   /* Which bit is it? */
367   bitnum = (unsigned char)( 7 - (x % 8) );  
368   if( white )         /* Turn it on */
369     bits[index] |= (1<<bitnum);
370   else         /* Turn it off */
371     bits[index] &= ~(1<<bitnum); 
372
373
374 static void
375 mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, 
376                                           struct frame* f)
377 {
378   HBITMAP mask;
379   HGDIOBJ old = NULL;
380   HDC hcdc = FRAME_MSWINDOWS_CDC (f);
381   unsigned char* dibits;
382   BITMAPINFO* bmp_info = 
383     xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
384   int i, j;
385   int height = IMAGE_INSTANCE_PIXMAP_HEIGHT (image);
386   
387   void* and_bits; 
388   int maskbpline = BPLINE (((IMAGE_INSTANCE_PIXMAP_WIDTH (image)+7)/8));
389   int bpline = BPLINE (IMAGE_INSTANCE_PIXMAP_WIDTH (image) * 3); 
390
391   if (!bmp_info)
392     return;
393
394   bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image);
395   bmp_info->bmiHeader.biHeight = height;
396   bmp_info->bmiHeader.biPlanes=1;
397   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
398   bmp_info->bmiHeader.biBitCount=1; 
399   bmp_info->bmiHeader.biCompression=BI_RGB; 
400   bmp_info->bmiHeader.biClrUsed = 2; 
401   bmp_info->bmiHeader.biClrImportant = 2; 
402   bmp_info->bmiHeader.biSizeImage = height * maskbpline; 
403   bmp_info->bmiColors[0].rgbRed = 0;
404   bmp_info->bmiColors[0].rgbGreen = 0;
405   bmp_info->bmiColors[0].rgbBlue = 0;
406   bmp_info->bmiColors[0].rgbReserved = 0;
407   bmp_info->bmiColors[1].rgbRed = 255;
408   bmp_info->bmiColors[1].rgbGreen = 255;
409   bmp_info->bmiColors[1].rgbBlue = 255;
410   bmp_info->bmiColors[0].rgbReserved = 0;
411     
412   if (!(mask = CreateDIBSection (hcdc,  
413                                  bmp_info,
414                                  DIB_RGB_COLORS,
415                                  &and_bits, 
416                                  0,0)))
417     {
418       xfree (bmp_info);
419       return;
420     }
421
422   old = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (image));
423   /* build up an in-memory set of bits to mess with */
424   xzero (*bmp_info);
425
426   bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_PIXMAP_WIDTH (image);
427   bmp_info->bmiHeader.biHeight = -height;
428   bmp_info->bmiHeader.biPlanes=1;
429   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
430   bmp_info->bmiHeader.biBitCount=24; 
431   bmp_info->bmiHeader.biCompression=BI_RGB; 
432   bmp_info->bmiHeader.biClrUsed = 0; 
433   bmp_info->bmiHeader.biClrImportant = 0; 
434   bmp_info->bmiHeader.biSizeImage = height * bpline;
435
436   dibits = xmalloc_and_zero (bpline * height);
437   if (GetDIBits (hcdc,
438                  IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
439                  0,
440                  height,
441                  dibits,
442                  bmp_info,
443                  DIB_RGB_COLORS) <= 0)
444     {
445       xfree (bmp_info);
446       return;
447     }
448
449   /* now set the colored bits in the mask and transparent ones to
450      black in the original */
451   for(i=0; i<IMAGE_INSTANCE_PIXMAP_WIDTH (image); i++)     
452     { 
453       for(j=0; j<height; j++)         
454         { 
455           unsigned char* idx = &dibits[j * bpline + i * 3];
456
457           if( RGB (idx[2], idx[1], idx[0]) == transparent_color )
458             { 
459               idx[0] = idx[1] = idx[2] = 0;
460               set_mono_pixel( and_bits, maskbpline, height, i, j, TRUE );
461             }
462           else             
463             { 
464               set_mono_pixel( and_bits, maskbpline, height, i, j, FALSE );
465             }
466         }
467     }
468
469   SetDIBits (hcdc,
470              IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
471              0,
472              height,
473              dibits,
474              bmp_info,
475              DIB_RGB_COLORS);
476
477   xfree (bmp_info);
478   xfree (dibits);
479   
480   SelectObject(hcdc, old);
481
482   IMAGE_INSTANCE_MSWINDOWS_MASK (image) = mask;
483 }
484
485 void
486 mswindows_initialize_image_instance_icon (struct Lisp_Image_Instance* image,
487                                           int cursor)
488 {
489   ICONINFO x_icon;
490
491   /* we rely on windows to do any resizing necessary */
492   x_icon.fIcon=cursor ? FALSE : TRUE;
493   x_icon.xHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image));
494   x_icon.yHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image));
495   x_icon.hbmMask=IMAGE_INSTANCE_MSWINDOWS_MASK (image);
496   x_icon.hbmColor=IMAGE_INSTANCE_MSWINDOWS_BITMAP (image);
497   
498   IMAGE_INSTANCE_MSWINDOWS_ICON (image)=
499     CreateIconIndirect (&x_icon);
500 }
501
502 HBITMAP
503 mswindows_create_resized_bitmap (struct Lisp_Image_Instance* ii,
504                                  struct frame* f,
505                                  int newx, int newy)
506 {
507   HBITMAP newbmp;
508   HGDIOBJ old1, old2;
509   HDC hcdc = FRAME_MSWINDOWS_CDC (f);
510   HDC hdcDst = CreateCompatibleDC (hcdc);  
511   
512   old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii)); 
513   
514   newbmp = CreateCompatibleBitmap (hcdc, newx, newy);
515
516   old2 = SelectObject (hdcDst, newbmp);
517   
518   if (!StretchBlt (hdcDst, 0, 0, newx, newy,
519                    hcdc, 0, 0, 
520                    IMAGE_INSTANCE_PIXMAP_WIDTH (ii), 
521                    IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), 
522                    SRCCOPY))
523     {
524       return 0;
525     }
526
527   SelectObject (hdcDst, old2);
528   SelectObject (hcdc, old1);
529   DeleteDC (hdcDst);
530
531   return newbmp;
532 }
533
534 HBITMAP
535 mswindows_create_resized_mask (struct Lisp_Image_Instance* ii,
536                                struct frame* f,
537                                int newx, int newy)
538 {
539   if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii))
540     {
541       HBITMAP newmask;
542       HGDIOBJ old1, old2;
543       HDC hcdc = FRAME_MSWINDOWS_CDC (f);
544       HDC hdcDst = CreateCompatibleDC (hcdc);  
545   
546       old1 = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_MASK (ii)); 
547       newmask = CreateCompatibleBitmap(hcdc, newx, newy);
548       old2 = SelectObject (hdcDst, newmask);
549
550       if (!StretchBlt(hdcDst, 0, 0, newx, newy,
551                       hcdc, 0, 0, 
552                       IMAGE_INSTANCE_PIXMAP_WIDTH (ii), 
553                       IMAGE_INSTANCE_PIXMAP_HEIGHT (ii), 
554                       SRCCOPY))
555         {
556           return NULL;
557         }
558       
559       SelectObject (hdcDst, old2);
560       SelectObject (hcdc, old1);
561
562       DeleteDC (hdcDst);
563
564       return newmask;
565     }
566
567   return NULL;
568 }
569
570 int
571 mswindows_resize_dibitmap_instance (struct Lisp_Image_Instance* ii,
572                                     struct frame* f,
573                                     int newx, int newy)
574 {
575   HBITMAP newbmp = mswindows_create_resized_bitmap (ii, f, newx, newy);
576   HBITMAP newmask = mswindows_create_resized_mask (ii, f, newx, newy);
577
578   if (!newbmp)
579     return FALSE;
580   
581   if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii))
582     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii));
583   if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii))
584     DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (ii));
585
586   IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = newbmp;
587   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = newmask;
588   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = newx;
589   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = newy;
590
591   return TRUE;
592 }
593
594 /**********************************************************************
595  *                               XPM                                  *
596  **********************************************************************/
597
598 #ifdef HAVE_XPM
599
600 struct color_symbol
601 {
602   char*         name;
603   COLORREF      color;
604 };
605
606 static struct color_symbol*
607 extract_xpm_color_names (Lisp_Object device,
608                          Lisp_Object domain,
609                          Lisp_Object color_symbol_alist,
610                          int* nsymbols)
611 {
612   /* This function can GC */
613   Lisp_Object rest;
614   Lisp_Object results = Qnil;
615   int i, j;
616   struct color_symbol *colortbl;
617   struct gcpro gcpro1, gcpro2;
618
619   GCPRO2 (results, device);
620
621   /* We built up results to be (("name" . #<color>) ...) so that if an
622      error happens we don't lose any malloc()ed data, or more importantly,
623      leave any pixels allocated in the server. */
624   i = 0;
625   LIST_LOOP (rest, color_symbol_alist)
626     {
627       Lisp_Object cons = XCAR (rest);
628       Lisp_Object name = XCAR (cons);
629       Lisp_Object value = XCDR (cons);
630       if (NILP (value))
631         continue;
632       if (STRINGP (value))
633         value =
634           Fmake_color_instance
635           (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
636       else
637         {
638           assert (COLOR_SPECIFIERP (value));
639           value = Fspecifier_instance (value, domain, Qnil, Qnil);
640         }
641       if (NILP (value))
642         continue;
643       results = noseeum_cons (noseeum_cons (name, value), results);
644       i++;
645     }
646   UNGCPRO;                      /* no more evaluation */
647
648   *nsymbols=i;
649   if (i == 0) return 0;
650
651   colortbl = xnew_array_and_zero (struct color_symbol, i);
652
653   for (j=0; j<i; j++)
654     {
655       Lisp_Object cons = XCAR (results);
656       colortbl[j].color = 
657         COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
658
659       colortbl[j].name = (char *) XSTRING_DATA (XCAR (cons));
660       free_cons (XCONS (cons));
661       cons = results;
662       results = XCDR (results);
663       free_cons (XCONS (cons));
664     }
665   return colortbl;
666 }
667
668 static int xpm_to_eimage (Lisp_Object image, CONST Extbyte *buffer,
669                           unsigned char** data,
670                           int* width, int* height,
671                           int* x_hot, int* y_hot,
672                           int* transp,
673                           struct color_symbol* color_symbols,
674                           int nsymbols)
675 {
676   XpmImage xpmimage;
677   XpmInfo xpminfo;
678   int result, i, j, transp_idx, maskbpline;
679   unsigned char* dptr;
680   unsigned int* sptr;
681   COLORREF color; /* the american spelling virus hits again .. */
682   COLORREF* colortbl; 
683
684   xzero (xpmimage);
685   xzero (xpminfo);
686   xpminfo.valuemask=XpmHotspot;
687   *transp=FALSE;
688
689   result = XpmCreateXpmImageFromBuffer ((char*)buffer,
690                                        &xpmimage,
691                                        &xpminfo);
692   switch (result)
693     {
694     case XpmSuccess:
695       break;
696     case XpmFileInvalid:
697       {
698         signal_simple_error ("invalid XPM data", image);
699       }
700     case XpmNoMemory:
701       {
702         signal_double_file_error ("Parsing pixmap data",
703                                   "out of memory", image);
704       }
705     default:
706       {
707         signal_double_file_error_2 ("Parsing pixmap data",
708                                     "unknown error code",
709                                     make_int (result), image);
710       }
711     }
712   
713   *width = xpmimage.width;
714   *height = xpmimage.height;
715   maskbpline = BPLINE (((~7UL & (unsigned long)(*width + 7)) / 8));
716   
717   *data = xnew_array_and_zero (unsigned char, *width * *height * 3);
718
719   if (!*data)
720     {
721       XpmFreeXpmImage (&xpmimage);
722       XpmFreeXpmInfo (&xpminfo);
723       return 0;
724     }
725
726   /* build a color table to speed things up */
727   colortbl = xnew_array_and_zero (COLORREF, xpmimage.ncolors);
728   if (!colortbl)
729     {
730       xfree (*data);
731       XpmFreeXpmImage (&xpmimage);
732       XpmFreeXpmInfo (&xpminfo);
733       return 0;
734     }
735
736   for (i=0; i<xpmimage.ncolors; i++)
737     {
738       /* goto alert!!!! */
739       /* pick up symbolic colors in preference */
740       if (xpmimage.colorTable[i].symbolic)
741         {
742           if (!strcasecmp (xpmimage.colorTable[i].symbolic,"BgColor")
743               ||
744               !strcasecmp (xpmimage.colorTable[i].symbolic,"None"))
745             {
746               *transp=TRUE;
747               colortbl[i]=transparent_color; 
748               transp_idx=i;
749               goto label_found_color;
750             }
751           else if (color_symbols)
752             {
753               for (j = 0; j<nsymbols; j++)
754                 {
755                   if (!strcmp (xpmimage.colorTable[i].symbolic,
756                                color_symbols[j].name ))
757                     {
758                       colortbl[i]=color_symbols[j].color;
759                       goto label_found_color;
760                     }
761                 }
762             }
763           else if (xpmimage.colorTable[i].c_color == 0)
764             {
765               goto label_no_color;
766             }
767         }
768       /* pick up transparencies */
769       if (!strcasecmp (xpmimage.colorTable[i].c_color,"None"))
770         {
771           *transp=TRUE;
772           colortbl[i]=transparent_color; 
773           transp_idx=i;
774           goto label_found_color;
775         }
776       /* finally pick up a normal color spec */
777       if (xpmimage.colorTable[i].c_color)
778         {
779           colortbl[i]=
780             mswindows_string_to_color (xpmimage.colorTable[i].c_color);
781           goto label_found_color;
782         }
783       
784     label_no_color:
785       xfree (*data);
786       xfree (colortbl);
787       XpmFreeXpmImage (&xpmimage);
788       XpmFreeXpmInfo (&xpminfo);
789       return 0;
790       
791     label_found_color:;
792     }
793
794   /* convert the image */
795   sptr=xpmimage.data;
796   dptr=*data;
797   for (i = 0; i< *width * *height; i++)
798     {
799       color = colortbl[*sptr++];
800
801       /* split out the 0x02bbggrr colorref into an rgb triple */
802       *dptr++=GetRValue (color); /* red */
803       *dptr++=GetGValue (color); /* green */
804       *dptr++=GetBValue (color); /* blue */
805     }
806
807   *x_hot=xpminfo.x_hotspot;
808   *y_hot=xpminfo.y_hotspot;
809
810   XpmFreeXpmImage (&xpmimage);
811   XpmFreeXpmInfo (&xpminfo);
812   xfree (colortbl);
813   return TRUE;
814 }
815
816 static void
817 mswindows_xpm_instantiate (Lisp_Object image_instance,
818                            Lisp_Object instantiator,
819                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
820                            int dest_mask, Lisp_Object domain)
821 {
822   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
823   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
824   CONST Extbyte         *bytes;
825   Extcount              len;
826   unsigned char         *eimage;
827   int                   width, height, x_hot, y_hot;
828   BITMAPINFO*           bmp_info;
829   unsigned char*        bmp_data;
830   int                   bmp_bits;
831   int                   nsymbols=0, transp;
832   struct color_symbol*  color_symbols=NULL;
833   
834   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
835   Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
836                                                            Q_color_symbols);
837
838   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
839     signal_simple_error ("Not an mswindows device", device);
840
841   assert (!NILP (data));
842
843   GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
844
845   /* in case we have color symbols */
846   color_symbols = extract_xpm_color_names (device, domain,
847                                            color_symbol_alist, &nsymbols);
848
849   /* convert to an eimage to make processing easier */
850   if (!xpm_to_eimage (image_instance, bytes, &eimage, &width, &height,
851                       &x_hot, &y_hot, &transp, color_symbols, nsymbols))
852     {
853       signal_simple_error ("XPM to EImage conversion failed", 
854                            image_instance);
855     }
856   
857   if (color_symbols)
858     xfree(color_symbols);
859   
860   /* build a bitmap from the eimage */
861   if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage,
862                                              &bmp_bits, &bmp_data)))
863     {
864       signal_simple_error ("XPM to EImage conversion failed",
865                            image_instance);
866     }
867   xfree (eimage);
868
869   /* Now create the pixmap and set up the image instance */
870   init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
871                                      bmp_data, bmp_bits, instantiator,
872                                      x_hot, y_hot, transp);
873
874   xfree (bmp_info);
875   xfree (bmp_data);
876 }
877 #endif /* HAVE_XPM */
878
879 /**********************************************************************
880  *                               BMP                                  *
881  **********************************************************************/
882
883 static void
884 bmp_validate (Lisp_Object instantiator)
885 {
886   file_or_data_must_be_present (instantiator);
887 }
888
889 static Lisp_Object
890 bmp_normalize (Lisp_Object inst, Lisp_Object console_type)
891 {
892   return simple_image_type_normalize (inst, console_type, Qbmp);
893 }
894
895 static int
896 bmp_possible_dest_types (void)
897 {
898   return IMAGE_COLOR_PIXMAP_MASK;
899 }
900
901 static void
902 bmp_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
903                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
904                  int dest_mask, Lisp_Object domain)
905 {
906   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
907   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
908   CONST Extbyte         *bytes;
909   Extcount              len;
910   BITMAPFILEHEADER*     bmp_file_header;
911   BITMAPINFO*           bmp_info;
912   void*                 bmp_data;
913   int                   bmp_bits;
914   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
915
916   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
917     signal_simple_error ("Not an mswindows device", device);
918
919   assert (!NILP (data));
920
921   GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
922   
923   /* Then slurp the image into memory, decoding along the way.
924      The result is the image in a simple one-byte-per-pixel
925      format. */
926   
927   bmp_file_header=(BITMAPFILEHEADER*)bytes;
928   bmp_info = (BITMAPINFO*)(bytes + sizeof(BITMAPFILEHEADER));
929   bmp_data = (Extbyte*)bytes + bmp_file_header->bfOffBits;
930   bmp_bits = bmp_file_header->bfSize - bmp_file_header->bfOffBits;
931
932   /* Now create the pixmap and set up the image instance */
933   init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
934                                      bmp_data, bmp_bits, instantiator,
935                                      0, 0, 0);
936 }
937
938 \f
939 /**********************************************************************
940  *                             RESOURCES                              *
941  **********************************************************************/
942
943 static void
944 mswindows_resource_validate (Lisp_Object instantiator)
945 {
946   if ((NILP (find_keyword_in_vector (instantiator, Q_file)) 
947        &&
948        NILP (find_keyword_in_vector (instantiator, Q_resource_id))) 
949       ||
950       NILP (find_keyword_in_vector (instantiator, Q_resource_type)))
951     signal_simple_error ("Must supply :file, :resource-id and :resource-type",
952                          instantiator);
953 }
954
955 static Lisp_Object
956 mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type)
957 {
958   /* This function can call lisp */
959   Lisp_Object file = Qnil;
960   struct gcpro gcpro1, gcpro2;
961   Lisp_Object alist = Qnil;
962
963   GCPRO2 (file, alist);
964
965   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data, 
966                                              console_type);
967
968   if (CONSP (file)) /* failure locating filename */
969     signal_double_file_error ("Opening pixmap file",
970                               "no such file or directory",
971                               Fcar (file));
972
973   if (NILP (file)) /* no conversion necessary */
974     RETURN_UNGCPRO (inst);
975
976   alist = tagged_vector_to_alist (inst);
977
978   {
979     alist = remassq_no_quit (Q_file, alist);
980     alist = Fcons (Fcons (Q_file, file), alist);
981   }
982
983   {
984     Lisp_Object result = alist_to_tagged_vector (Qmswindows_resource, alist);
985     free_alist (alist);
986     RETURN_UNGCPRO (result);
987   }
988 }
989
990 static int
991 mswindows_resource_possible_dest_types (void)
992 {
993   return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
994 }
995
996 typedef struct 
997 {
998   char *name;
999   int   resource_id;
1000 } resource_t;
1001
1002 #ifndef OCR_ICOCUR
1003 #define OCR_ICOCUR          32647
1004 #define OIC_SAMPLE          32512
1005 #define OIC_HAND            32513
1006 #define OIC_QUES            32514
1007 #define OIC_BANG            32515
1008 #define OIC_NOTE            32516
1009 #define OIC_WINLOGO         32517
1010 #define LR_SHARED           0x8000
1011 #endif
1012
1013 static CONST resource_t bitmap_table[] = 
1014 {
1015   /* bitmaps */
1016   { "close", OBM_CLOSE },
1017   { "uparrow", OBM_UPARROW },
1018   { "dnarrow", OBM_DNARROW },
1019   { "rgarrow", OBM_RGARROW },
1020   { "lfarrow", OBM_LFARROW },
1021   { "reduce", OBM_REDUCE },
1022   { "zoom", OBM_ZOOM },
1023   { "restore", OBM_RESTORE },
1024   { "reduced", OBM_REDUCED },
1025   { "zoomd", OBM_ZOOMD },
1026   { "restored", OBM_RESTORED },
1027   { "uparrowd", OBM_UPARROWD },
1028   { "dnarrowd", OBM_DNARROWD },
1029   { "rgarrowd", OBM_RGARROWD },
1030   { "lfarrowd", OBM_LFARROWD },
1031   { "mnarrow", OBM_MNARROW },
1032   { "combo", OBM_COMBO },
1033   { "uparrowi", OBM_UPARROWI },
1034   { "dnarrowi", OBM_DNARROWI },
1035   { "rgarrowi", OBM_RGARROWI },
1036   { "lfarrowi", OBM_LFARROWI },
1037   { "size", OBM_SIZE },
1038   { "btsize", OBM_BTSIZE },
1039   { "check", OBM_CHECK },
1040   { "cehckboxes", OBM_CHECKBOXES },
1041   { "btncorners" , OBM_BTNCORNERS },
1042   {0}
1043 };
1044
1045 static CONST resource_t cursor_table[] = 
1046 {
1047   /* cursors */
1048   { "normal", OCR_NORMAL },
1049   { "ibeam", OCR_IBEAM },
1050   { "wait", OCR_WAIT },
1051   { "cross", OCR_CROSS },
1052   { "up", OCR_UP },
1053   /* { "icon", OCR_ICON }, */
1054   { "sizenwse", OCR_SIZENWSE },
1055   { "sizenesw", OCR_SIZENESW },
1056   { "sizewe", OCR_SIZEWE },
1057   { "sizens", OCR_SIZENS },
1058   { "sizeall", OCR_SIZEALL },
1059   /* { "icour", OCR_ICOCUR }, */
1060   { "no", OCR_NO },
1061   { 0 }
1062 };
1063
1064 static CONST resource_t icon_table[] = 
1065 {
1066   /* icons */
1067   { "sample", OIC_SAMPLE },
1068   { "hand", OIC_HAND },
1069   { "ques", OIC_QUES },
1070   { "bang", OIC_BANG },
1071   { "note", OIC_NOTE },
1072   { "winlogo", OIC_WINLOGO },
1073   {0}
1074 };
1075
1076 static int resource_name_to_resource (Lisp_Object name, int type)
1077 {
1078   CONST resource_t* res = (type == IMAGE_CURSOR ? cursor_table 
1079                            : type == IMAGE_ICON ? icon_table 
1080                            : bitmap_table);
1081
1082   if (INTP (name))
1083     {
1084       return XINT (name);
1085     }
1086   else if (!STRINGP (name))
1087     {
1088       signal_simple_error ("invalid resource identifier", name);
1089     }
1090   
1091   do {
1092     if (!strcasecmp ((char*)res->name, XSTRING_DATA (name)))
1093       return res->resource_id;
1094   } while ((++res)->name);
1095   return 0;
1096 }
1097
1098 static int
1099 resource_symbol_to_type (Lisp_Object data)
1100 {
1101   if (EQ (data, Qcursor))
1102     return IMAGE_CURSOR;
1103   else if (EQ (data, Qicon))
1104     return IMAGE_ICON;
1105   else if (EQ (data, Qbitmap))
1106     return IMAGE_BITMAP;
1107   else
1108     return 0;
1109 }
1110
1111 static void
1112 mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1113                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1114                     int dest_mask, Lisp_Object domain)
1115 {
1116   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1117   unsigned int type = 0;
1118   HANDLE himage = NULL;
1119   LPCTSTR resid=0;
1120   HINSTANCE hinst = NULL;
1121   ICONINFO iconinfo;
1122   int iitype=0;
1123   char* fname=0;
1124   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1125
1126   Lisp_Object file = find_keyword_in_vector (instantiator, Q_file);
1127   Lisp_Object resource_type = find_keyword_in_vector (instantiator, 
1128                                                       Q_resource_type);
1129   Lisp_Object resource_id = find_keyword_in_vector (instantiator, 
1130                                                     Q_resource_id);
1131
1132   xzero (iconinfo);
1133
1134   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1135     signal_simple_error ("Not an mswindows device", device);
1136
1137   type = resource_symbol_to_type (resource_type);
1138
1139   if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR)
1140     iitype = IMAGE_POINTER;
1141   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1142     iitype = IMAGE_COLOR_PIXMAP;
1143   else 
1144     incompatible_image_types (instantiator, dest_mask,
1145                               IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
1146
1147   /* mess with the keyword info we were provided with */
1148   if (!NILP (file))
1149     {
1150 #ifdef __CYGWIN32__
1151       CYGWIN_WIN32_PATH (XSTRING_DATA (file), fname);
1152 #else
1153       /* #### FIXME someone who knows ... */
1154       fname = XSTRING_DATA (file);
1155 #endif
1156       
1157       if (NILP (resource_id))
1158         resid = (LPCTSTR)fname;
1159       else
1160         {
1161           hinst = LoadLibraryEx (fname, NULL,
1162                                  LOAD_LIBRARY_AS_DATAFILE);
1163           resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1164                                                            type));
1165           
1166           if (!resid)
1167             resid = XSTRING_DATA (resource_id);
1168         }
1169     }
1170   else if (!(resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1171                                                                type))))
1172     signal_simple_error ("invalid resource identifier", resource_id);
1173   
1174   /* load the image */
1175   if (!(himage = LoadImage (hinst, resid, type, 0, 0,
1176                             LR_CREATEDIBSECTION | LR_DEFAULTSIZE | 
1177                             LR_SHARED |      
1178                             (!NILP (file) ? LR_LOADFROMFILE : 0))))
1179     {
1180       signal_simple_error ("cannot load image", instantiator);
1181     }
1182
1183   if (hinst)
1184     FreeLibrary (hinst);
1185
1186   mswindows_initialize_dibitmap_image_instance (ii, iitype);
1187
1188   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file;
1189   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 
1190     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
1191   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 
1192     GetSystemMetrics (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON);
1193   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1194
1195   /* hey, we've got an icon type thing so we can reverse engineer the
1196      bitmap and mask */
1197   if (type != IMAGE_BITMAP)
1198     {
1199       GetIconInfo (himage, &iconinfo);
1200       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = iconinfo.hbmColor;
1201       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = iconinfo.hbmMask;
1202       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), iconinfo.xHotspot);
1203       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), iconinfo.yHotspot);
1204       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = himage;
1205     }
1206   else
1207     {
1208       IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = NULL;
1209       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = himage;
1210       IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
1211       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1212       XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1213     }
1214 }
1215
1216 static void
1217 check_valid_resource_symbol (Lisp_Object data)
1218 {
1219   CHECK_SYMBOL (data);
1220   if (!resource_symbol_to_type (data))
1221     signal_simple_error ("invalid resource type", data);
1222 }
1223
1224 static void
1225 check_valid_resource_id (Lisp_Object data)
1226 {
1227   if (!resource_name_to_resource (data, IMAGE_CURSOR)
1228       &&
1229       !resource_name_to_resource (data, IMAGE_ICON)
1230       &&
1231       !resource_name_to_resource (data, IMAGE_BITMAP))
1232     signal_simple_error ("invalid resource identifier", data);
1233 }
1234
1235 void
1236 check_valid_string_or_int (Lisp_Object data)
1237 {
1238   if (!INTP (data))
1239     CHECK_STRING (data);
1240   else
1241     CHECK_INT (data);
1242 }
1243
1244 /**********************************************************************
1245  *                             XBM                                    *
1246  **********************************************************************/
1247 #ifndef HAVE_X_WINDOWS
1248 /* $XConsortium: RdBitF.c,v 1.10 94/04/17 20:16:13 kaleb Exp $ */
1249
1250 /*
1251
1252 Copyright (c) 1988  X Consortium
1253
1254 Permission is hereby granted, free of charge, to any person obtaining a copy
1255 of this software and associated documentation files (the "Software"), to deal
1256 in the Software without restriction, including without limitation the rights
1257 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1258 copies of the Software, and to permit persons to whom the Software is
1259 furnished to do so, subject to the following conditions:
1260
1261 The above copyright notice and this permission notice shall be included in
1262 all copies or substantial portions of the Software.
1263
1264 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1265 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1266 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1267 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1268 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1269 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1270
1271 Except as contained in this notice, the name of the X Consortium shall not be
1272 used in advertising or otherwise to promote the sale, use or other dealings
1273 in this Software without prior written authorization from the X Consortium.
1274
1275 */
1276
1277 /*
1278  * This file contains miscellaneous utility routines and is not part of the
1279  * Xlib standard.
1280  *
1281  * Public entry points:
1282  *
1283  *     XmuReadBitmapData                read data from FILE descriptor
1284  *     XmuReadBitmapDataFromFile        read X10 or X11 format bitmap files
1285  *                                      and return data
1286  *
1287  * Note that this file and ../X/XRdBitF.c look very similar....  Keep them
1288  * that way (but don't use common source code so that people can have one 
1289  * without the other).
1290  */
1291
1292
1293 /*
1294  * Based on an optimized version provided by Jim Becker, Auguest 5, 1988.
1295  */
1296 #ifndef BitmapSuccess
1297 #define BitmapSuccess           0
1298 #define BitmapOpenFailed        1
1299 #define BitmapFileInvalid       2
1300 #define BitmapNoMemory          3
1301 #endif
1302 #define MAX_SIZE 255
1303
1304 /* shared data for the image read/parse logic */
1305 static short hexTable[256];             /* conversion value */
1306 static int initialized = FALSE; /* easier to fill in at run time */
1307
1308 /*
1309  *      Table index for the hex values. Initialized once, first time.
1310  *      Used for translation value or delimiter significance lookup.
1311  */
1312 static void initHexTable()
1313 {
1314     /*
1315      * We build the table at run time for several reasons:
1316      *
1317      *     1.  portable to non-ASCII machines.
1318      *     2.  still reentrant since we set the init flag after setting table.
1319      *     3.  easier to extend.
1320      *     4.  less prone to bugs.
1321      */
1322     hexTable['0'] = 0;  hexTable['1'] = 1;
1323     hexTable['2'] = 2;  hexTable['3'] = 3;
1324     hexTable['4'] = 4;  hexTable['5'] = 5;
1325     hexTable['6'] = 6;  hexTable['7'] = 7;
1326     hexTable['8'] = 8;  hexTable['9'] = 9;
1327     hexTable['A'] = 10; hexTable['B'] = 11;
1328     hexTable['C'] = 12; hexTable['D'] = 13;
1329     hexTable['E'] = 14; hexTable['F'] = 15;
1330     hexTable['a'] = 10; hexTable['b'] = 11;
1331     hexTable['c'] = 12; hexTable['d'] = 13;
1332     hexTable['e'] = 14; hexTable['f'] = 15;
1333
1334     /* delimiters of significance are flagged w/ negative value */
1335     hexTable[' '] = -1; hexTable[','] = -1;
1336     hexTable['}'] = -1; hexTable['\n'] = -1;
1337     hexTable['\t'] = -1;
1338         
1339     initialized = TRUE;
1340 }
1341
1342 /*
1343  *      read next hex value in the input stream, return -1 if EOF
1344  */
1345 static int NextInt ( FILE *fstream )
1346 {
1347     int ch;
1348     int value = 0;
1349     int gotone = 0;
1350     int done = 0;
1351     
1352     /* loop, accumulate hex value until find delimiter  */
1353     /* skip any initial delimiters found in read stream */
1354
1355     while (!done) {
1356         ch = getc(fstream);
1357         if (ch == EOF) {
1358             value       = -1;
1359             done++;
1360         } else {
1361             /* trim high bits, check type and accumulate */
1362             ch &= 0xff;
1363             if (isascii(ch) && isxdigit(ch)) {
1364                 value = (value << 4) + hexTable[ch];
1365                 gotone++;
1366             } else if ((hexTable[ch]) < 0 && gotone)
1367               done++;
1368         }
1369     }
1370     return value;
1371 }
1372
1373
1374 /*
1375  * The data returned by the following routine is always in left-most byte
1376  * first and left-most bit first.  If it doesn't return BitmapSuccess then
1377  * its arguments won't have been touched.  This routine should look as much
1378  * like the Xlib routine XReadBitmapfile as possible.
1379  */
1380 int read_bitmap_data (fstream, width, height, datap, x_hot, y_hot)
1381     FILE *fstream;                      /* handle on file  */
1382     unsigned int *width, *height;       /* RETURNED */
1383     unsigned char **datap;              /* RETURNED */
1384     int *x_hot, *y_hot;                 /* RETURNED */
1385 {
1386     unsigned char *data = NULL;         /* working variable */
1387     char line[MAX_SIZE];                /* input line from file */
1388     int size;                           /* number of bytes of data */
1389     char name_and_type[MAX_SIZE];       /* an input line */
1390     char *type;                         /* for parsing */
1391     int value;                          /* from an input line */
1392     int version10p;                     /* boolean, old format */
1393     int padding;                        /* to handle alignment */
1394     int bytes_per_line;                 /* per scanline of data */
1395     unsigned int ww = 0;                /* width */
1396     unsigned int hh = 0;                /* height */
1397     int hx = -1;                        /* x hotspot */
1398     int hy = -1;                        /* y hotspot */
1399
1400 #define Xmalloc(size) malloc(size)
1401
1402     /* first time initialization */
1403     if (initialized == FALSE) initHexTable();
1404
1405     /* error cleanup and return macro   */
1406 #define RETURN(code) { if (data) free (data); return code; }
1407
1408     while (fgets(line, MAX_SIZE, fstream)) {
1409         if (strlen(line) == MAX_SIZE-1) {
1410             RETURN (BitmapFileInvalid);
1411         }
1412         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
1413             if (!(type = strrchr(name_and_type, '_')))
1414               type = name_and_type;
1415             else
1416               type++;
1417
1418             if (!strcmp("width", type))
1419               ww = (unsigned int) value;
1420             if (!strcmp("height", type))
1421               hh = (unsigned int) value;
1422             if (!strcmp("hot", type)) {
1423                 if (type-- == name_and_type || type-- == name_and_type)
1424                   continue;
1425                 if (!strcmp("x_hot", type))
1426                   hx = value;
1427                 if (!strcmp("y_hot", type))
1428                   hy = value;
1429             }
1430             continue;
1431         }
1432     
1433         if (sscanf(line, "static short %s = {", name_and_type) == 1)
1434           version10p = 1;
1435         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
1436           version10p = 0;
1437         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
1438           version10p = 0;
1439         else
1440           continue;
1441
1442         if (!(type = strrchr(name_and_type, '_')))
1443           type = name_and_type;
1444         else
1445           type++;
1446
1447         if (strcmp("bits[]", type))
1448           continue;
1449     
1450         if (!ww || !hh)
1451           RETURN (BitmapFileInvalid);
1452
1453         if ((ww % 16) && ((ww % 16) < 9) && version10p)
1454           padding = 1;
1455         else
1456           padding = 0;
1457
1458         bytes_per_line = (ww+7)/8 + padding;
1459
1460         size = bytes_per_line * hh;
1461         data = (unsigned char *) Xmalloc ((unsigned int) size);
1462         if (!data) 
1463           RETURN (BitmapNoMemory);
1464
1465         if (version10p) {
1466             unsigned char *ptr;
1467             int bytes;
1468
1469             for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
1470                 if ((value = NextInt(fstream)) < 0)
1471                   RETURN (BitmapFileInvalid);
1472                 *(ptr++) = value;
1473                 if (!padding || ((bytes+2) % bytes_per_line))
1474                   *(ptr++) = value >> 8;
1475             }
1476         } else {
1477             unsigned char *ptr;
1478             int bytes;
1479
1480             for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
1481                 if ((value = NextInt(fstream)) < 0) 
1482                   RETURN (BitmapFileInvalid);
1483                 *ptr=value;
1484             }
1485         }
1486         break;
1487     }                                   /* end while */
1488
1489     if (data == NULL) {
1490         RETURN (BitmapFileInvalid);
1491     }
1492
1493     *datap = data;
1494     data = NULL;
1495     *width = ww;
1496     *height = hh;
1497     if (x_hot) *x_hot = hx;
1498     if (y_hot) *y_hot = hy;
1499
1500     RETURN (BitmapSuccess);
1501 }
1502
1503
1504 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width, 
1505                                 unsigned int *height, unsigned char **datap,
1506                                 int *x_hot, int *y_hot)
1507 {
1508     FILE *fstream;
1509     int status;
1510
1511     if ((fstream = fopen (filename, "r")) == NULL) {
1512         return BitmapOpenFailed;
1513     }
1514     status = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
1515     fclose (fstream);
1516     return status;
1517 }
1518 #endif /* HAVE_X_WINDOWS */
1519
1520 /* this table flips four bits around. */
1521 static int flip_table[] =
1522 {
1523   0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
1524 };
1525
1526 /* the bitmap data comes in the following format: Widths are padded to
1527    a multiple of 8.  Scan lines are stored in increasing byte order
1528    from left to right, little-endian within a byte.  0 = white, 1 =
1529    black.  It must be converted to the following format: Widths are
1530    padded to a multiple of 16.  Scan lines are stored in increasing
1531    byte order from left to right, big-endian within a byte.  0 =
1532    black, 1 = white.  */
1533 HBITMAP
1534 xbm_create_bitmap_from_data (HDC hdc, char *data,
1535                              unsigned int width, unsigned int height,
1536                              int mask, COLORREF fg, COLORREF bg)
1537 {
1538   int old_width = (width + 7)/8;
1539   int new_width = 2*((width + 15)/16);
1540   unsigned char *offset;
1541   void *bmp_buf = 0;
1542   unsigned char *new_data, *new_offset;
1543   int i, j;
1544   BITMAPINFO* bmp_info = 
1545     xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
1546   HBITMAP bitmap;
1547
1548   if (!bmp_info)
1549     return NULL;
1550   
1551   new_data = (unsigned char *) xmalloc (height * new_width);
1552       
1553   if (!new_data)
1554     {
1555       xfree (bmp_info);
1556       return NULL;
1557     }
1558   
1559   for (i=0; i<height; i++)
1560     {
1561       offset = data + i*old_width;
1562       new_offset = new_data + i*new_width;
1563
1564       new_offset[new_width - 1] = 0; /* there may be an extra byte
1565                                         that needs to be padded */
1566       for (j=0; j<old_width; j++)
1567         {
1568           int byte = offset[j];
1569           new_offset[j] = ~ (unsigned char)
1570             ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]);
1571         }
1572     }
1573
1574   /* if we want a mask invert the bits */
1575   if (!mask)
1576     {
1577       new_offset = &new_data[height * new_width];
1578       while (new_offset-- != new_data)
1579         {
1580           *new_offset ^= 0xff;
1581         }
1582     }
1583
1584   bmp_info->bmiHeader.biWidth=width;
1585   bmp_info->bmiHeader.biHeight=-height;
1586   bmp_info->bmiHeader.biPlanes=1;
1587   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
1588   bmp_info->bmiHeader.biBitCount=1; 
1589   bmp_info->bmiHeader.biCompression=BI_RGB;
1590   bmp_info->bmiHeader.biClrUsed = 2; 
1591   bmp_info->bmiHeader.biClrImportant = 2; 
1592   bmp_info->bmiHeader.biSizeImage = height * new_width; 
1593   bmp_info->bmiColors[0].rgbRed = GetRValue (fg);
1594   bmp_info->bmiColors[0].rgbGreen = GetGValue (fg);
1595   bmp_info->bmiColors[0].rgbBlue = GetBValue (fg);
1596   bmp_info->bmiColors[0].rgbReserved = 0;
1597   bmp_info->bmiColors[1].rgbRed = GetRValue (bg);
1598   bmp_info->bmiColors[1].rgbGreen = GetGValue (bg);
1599   bmp_info->bmiColors[1].rgbBlue = GetBValue (bg);
1600   bmp_info->bmiColors[1].rgbReserved = 0;
1601   
1602   bitmap = CreateDIBSection (hdc,  
1603                              bmp_info,
1604                              DIB_RGB_COLORS,
1605                              &bmp_buf, 
1606                              0,0);
1607
1608   xfree (bmp_info);
1609   
1610   if (!bitmap || !bmp_buf)
1611     {
1612       xfree (new_data);
1613       return NULL;
1614     }
1615   
1616   /* copy in the actual bitmap */
1617   memcpy (bmp_buf, new_data, height * new_width);
1618   xfree (new_data);
1619
1620   return bitmap;
1621 }
1622
1623 /* Given inline data for a mono pixmap, initialize the given
1624    image instance accordingly. */
1625
1626 static void
1627 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
1628                                      int width, int height,
1629                                      /* Note that data is in ext-format! */
1630                                      CONST char *bits,
1631                                      Lisp_Object instantiator,
1632                                      Lisp_Object pointer_fg,
1633                                      Lisp_Object pointer_bg,
1634                                      int dest_mask,
1635                                      HBITMAP mask,
1636                                      Lisp_Object mask_filename)
1637 {
1638   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1639   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (device)));
1640   Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1641   Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1642   enum image_instance_type type;
1643   COLORREF black = PALETTERGB (0,0,0);
1644   COLORREF white = PALETTERGB (255,255,255);
1645
1646   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1647
1648   if (!DEVICE_MSWINDOWS_P (XDEVICE (device)))
1649     signal_simple_error ("Not an MS-Windows device", device);
1650
1651   if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1652       (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1653     {
1654       if (!NILP (foreground) || !NILP (background))
1655         type = IMAGE_COLOR_PIXMAP;
1656       else
1657         type = IMAGE_MONO_PIXMAP;
1658     }
1659   else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1660     type = IMAGE_MONO_PIXMAP;
1661   else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1662     type = IMAGE_COLOR_PIXMAP;
1663   else if (dest_mask & IMAGE_POINTER_MASK)
1664     type = IMAGE_POINTER;
1665   else
1666     incompatible_image_types (instantiator, dest_mask,
1667                               IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1668                               | IMAGE_POINTER_MASK);
1669
1670   mswindows_initialize_dibitmap_image_instance (ii, type);
1671   
1672   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1673     find_keyword_in_vector (instantiator, Q_file);
1674   IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1675   IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1676   IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1677   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1678   XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1679   IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask :
1680     xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1681                                  TRUE, black, white);
1682
1683   switch (type)
1684     {
1685     case IMAGE_MONO_PIXMAP:
1686       IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1687         xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1688                                      FALSE, black, black);
1689       break;
1690
1691     case IMAGE_COLOR_PIXMAP:
1692       {
1693         COLORREF fg = black;
1694         COLORREF bg = white;
1695
1696         if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1697           foreground =
1698             Fmake_color_instance (foreground, device,
1699                                   encode_error_behavior_flag (ERROR_ME));
1700
1701         if (COLOR_INSTANCEP (foreground))
1702           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1703
1704         if (!NILP (background) && !COLOR_INSTANCEP (background))
1705           background =
1706             Fmake_color_instance (background, device,
1707                                   encode_error_behavior_flag (ERROR_ME));
1708
1709         if (COLOR_INSTANCEP (background))
1710           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1711
1712         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1713         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1714
1715         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1716           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1717                                        FALSE, fg, black);
1718       }
1719       break;
1720
1721     case IMAGE_POINTER:
1722       {
1723         COLORREF fg = black;
1724         COLORREF bg = white;
1725
1726         if (NILP (foreground))
1727           foreground = pointer_fg;
1728         if (NILP (background))
1729           background = pointer_bg;
1730
1731         XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 
1732                  find_keyword_in_vector (instantiator, Q_hotspot_x));
1733         XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 
1734                  find_keyword_in_vector (instantiator, Q_hotspot_y));
1735         IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1736         IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1737         if (COLOR_INSTANCEP (foreground))
1738           fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1739         if (COLOR_INSTANCEP (background))
1740           bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1741
1742         IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = 
1743           xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height, 
1744                                        TRUE, fg, black);
1745         mswindows_initialize_image_instance_icon (ii, TRUE);
1746       }
1747       break;
1748
1749     default:
1750       abort ();
1751     }
1752 }
1753
1754 static void
1755 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1756                    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1757                    int dest_mask, int width, int height,
1758                    /* Note that data is in ext-format! */
1759                    CONST char *bits)
1760 {
1761   Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1762   Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1763   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1764   struct frame* f = XFRAME (DEVICE_SELECTED_FRAME 
1765                             (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))));
1766   HDC hdc = FRAME_MSWINDOWS_CDC (f);
1767   HBITMAP mask = 0;
1768   CONST char *gcc_may_you_rot_in_hell;
1769
1770   if (!NILP (mask_data))
1771     {
1772       GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1773                                        gcc_may_you_rot_in_hell);
1774       mask =
1775         xbm_create_bitmap_from_data ( hdc,
1776                                       (unsigned char *)
1777                                       gcc_may_you_rot_in_hell,
1778                                       XINT (XCAR (mask_data)),
1779                                       XINT (XCAR (XCDR (mask_data))), FALSE,
1780                                       PALETTERGB (0,0,0),
1781                                       PALETTERGB (255,255,255));
1782     }
1783
1784   init_image_instance_from_xbm_inline (ii, width, height, bits,
1785                                        instantiator, pointer_fg, pointer_bg,
1786                                        dest_mask, mask, mask_file);
1787 }
1788
1789 /* Instantiate method for XBM's. */
1790
1791 static void
1792 mswindows_xbm_instantiate (Lisp_Object image_instance, 
1793                            Lisp_Object instantiator,
1794                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1795                            int dest_mask, Lisp_Object domain)
1796 {
1797   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1798   CONST char *gcc_go_home;
1799
1800   assert (!NILP (data));
1801
1802   GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1803                                    gcc_go_home);
1804
1805   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1806                      pointer_bg, dest_mask, XINT (XCAR (data)),
1807                      XINT (XCAR (XCDR (data))), gcc_go_home);
1808 }
1809
1810 \f
1811 /************************************************************************/
1812 /*                      image instance methods                          */
1813 /************************************************************************/
1814
1815 static void
1816 mswindows_print_image_instance (struct Lisp_Image_Instance *p,
1817                                 Lisp_Object printcharfun,
1818                                 int escapeflag)
1819 {
1820   char buf[100];
1821
1822   switch (IMAGE_INSTANCE_TYPE (p))
1823     {
1824     case IMAGE_MONO_PIXMAP:
1825     case IMAGE_COLOR_PIXMAP:
1826     case IMAGE_POINTER:
1827       sprintf (buf, " (0x%lx", 
1828                (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
1829       write_c_string (buf, printcharfun);
1830       if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
1831         {
1832           sprintf (buf, "/0x%lx", 
1833                    (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p));
1834           write_c_string (buf, printcharfun);
1835         }
1836       write_c_string (")", printcharfun);
1837       break;
1838     default:
1839       break;
1840     }
1841 }
1842
1843 static void
1844 mswindows_finalize_image_instance (struct Lisp_Image_Instance *p)
1845 {
1846   if (!p->data)
1847     return;
1848
1849   if (DEVICE_LIVE_P (XDEVICE (p->device)))
1850     {
1851       if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p))
1852         DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
1853       IMAGE_INSTANCE_MSWINDOWS_BITMAP (p) = 0;
1854       if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
1855         DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p));
1856       IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0;
1857       if (IMAGE_INSTANCE_MSWINDOWS_ICON (p))
1858         DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p));
1859       IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0;
1860     }
1861
1862   xfree (p->data);
1863   p->data = 0;
1864 }
1865
1866 static int
1867 mswindows_image_instance_equal (struct Lisp_Image_Instance *p1,
1868                                 struct Lisp_Image_Instance *p2, int depth)
1869 {
1870   switch (IMAGE_INSTANCE_TYPE (p1))
1871     {
1872     case IMAGE_MONO_PIXMAP:
1873     case IMAGE_COLOR_PIXMAP:
1874     case IMAGE_POINTER:
1875       if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1) 
1876           != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2))
1877         return 0;
1878       break;
1879     default:
1880       break;
1881     }
1882
1883   return 1;
1884 }
1885
1886 static unsigned long
1887 mswindows_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
1888 {
1889   switch (IMAGE_INSTANCE_TYPE (p))
1890     {
1891     case IMAGE_MONO_PIXMAP:
1892     case IMAGE_COLOR_PIXMAP:
1893     case IMAGE_POINTER:
1894       return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p);
1895     default:
1896       return 0;
1897     }
1898 }
1899
1900 /* Set all the slots in an image instance structure to reasonable
1901    default values.  This is used somewhere within an instantiate
1902    method.  It is assumed that the device slot within the image
1903    instance is already set -- this is the case when instantiate
1904    methods are called. */
1905
1906 static void
1907 mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii,
1908                                             enum image_instance_type type)
1909 {
1910   ii->data = xnew_and_zero (struct mswindows_image_instance_data);
1911   IMAGE_INSTANCE_TYPE (ii) = type;
1912   IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
1913   IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
1914   IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
1915   IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
1916   IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
1917   IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
1918 }
1919
1920 \f
1921 /************************************************************************/
1922 /*                            initialization                            */
1923 /************************************************************************/
1924
1925 void
1926 syms_of_glyphs_mswindows (void)
1927 {
1928   defkeyword (&Q_resource_id, ":resource-id");
1929   defkeyword (&Q_resource_type, ":resource-type");
1930 }
1931
1932 void
1933 console_type_create_glyphs_mswindows (void)
1934 {
1935   /* image methods */
1936
1937   CONSOLE_HAS_METHOD (mswindows, print_image_instance);
1938   CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
1939   CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
1940   CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
1941   CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
1942   CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
1943 #ifdef HAVE_XPM
1944   CONSOLE_HAS_METHOD (mswindows, xpm_instantiate);
1945 #endif
1946   CONSOLE_HAS_METHOD (mswindows, xbm_instantiate);
1947 }
1948
1949 void
1950 image_instantiator_format_create_glyphs_mswindows (void)
1951 {
1952   /* image-instantiator types */
1953
1954   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
1955
1956   IIFORMAT_HAS_METHOD (bmp, validate);
1957   IIFORMAT_HAS_METHOD (bmp, normalize);
1958   IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
1959   IIFORMAT_HAS_METHOD (bmp, instantiate);
1960
1961   IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
1962   IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
1963
1964   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
1965                                         "mswindows-resource");
1966
1967   IIFORMAT_HAS_METHOD (mswindows_resource, validate);
1968   IIFORMAT_HAS_METHOD (mswindows_resource, normalize);
1969   IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types);
1970   IIFORMAT_HAS_METHOD (mswindows_resource, instantiate);
1971
1972   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type, 
1973                           check_valid_resource_symbol);
1974   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
1975   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
1976 }
1977
1978 void
1979 vars_of_glyphs_mswindows (void)
1980 {
1981   Fprovide (Qbmp);
1982   Fprovide (Qmswindows_resource);
1983   DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
1984 A list of the directories in which mswindows bitmap files may be found.
1985 This is used by the `make-image-instance' function.
1986 */ );
1987   Vmswindows_bitmap_file_path = Qnil;
1988 }
1989
1990 void
1991 complex_vars_of_glyphs_mswindows (void)
1992 {
1993 }