1 /* mswindows-specific glyph objects.
2 Copyright (C) 1998, 1999, 2000 Andy Piper.
4 This file is part of XEmacs.
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
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
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. */
21 /* Synched up with: Not in FSF. */
23 /* written by Andy Piper <andy@xemacs.org> plagiarising bits from
30 #define OEMRESOURCE /* Define OCR_ and friend constants */
31 #include "console-msw.h"
32 #include "glyphs-msw.h"
33 #include "objects-msw.h"
46 #include "file-coding.h"
54 #define WIDGET_GLYPH_SLOT 0
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);
61 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
64 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
67 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
70 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
73 DEFINE_DEVICE_IIFORMAT (mswindows, xpm);
74 DEFINE_DEVICE_IIFORMAT (msprinter, xpm);
76 DEFINE_DEVICE_IIFORMAT (mswindows, xbm);
77 DEFINE_DEVICE_IIFORMAT (msprinter, xbm);
79 DEFINE_DEVICE_IIFORMAT (mswindows, xface);
80 DEFINE_DEVICE_IIFORMAT (msprinter, xface);
82 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
83 DEFINE_DEVICE_IIFORMAT (mswindows, native_layout);
84 DEFINE_DEVICE_IIFORMAT (mswindows, button);
85 DEFINE_DEVICE_IIFORMAT (mswindows, edit_field);
86 DEFINE_DEVICE_IIFORMAT (mswindows, subwindow);
87 DEFINE_DEVICE_IIFORMAT (mswindows, widget);
88 DEFINE_DEVICE_IIFORMAT (mswindows, label);
89 DEFINE_DEVICE_IIFORMAT (mswindows, scrollbar);
90 DEFINE_DEVICE_IIFORMAT (mswindows, combo_box);
91 DEFINE_DEVICE_IIFORMAT (mswindows, progress_gauge);
92 DEFINE_DEVICE_IIFORMAT (mswindows, tree_view);
93 DEFINE_DEVICE_IIFORMAT (mswindows, tab_control);
95 DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp);
97 Lisp_Object Vmswindows_bitmap_file_path;
98 static COLORREF transparent_color = RGB (1,1,1);
100 DEFINE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource);
101 Lisp_Object Q_resource_type, Q_resource_id;
102 Lisp_Object Qmswindows_resource;
105 mswindows_initialize_dibitmap_image_instance (Lisp_Image_Instance *ii,
107 enum image_instance_type type);
109 mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image,
113 * Given device D, retrieve compatible device context. D can be either
114 * mswindows or an msprinter device.
117 get_device_compdc (struct device *d)
119 if (DEVICE_MSWINDOWS_P (d))
120 return DEVICE_MSWINDOWS_HCDC (d);
122 return DEVICE_MSPRINTER_HCDC (d);
126 * Initialize image instance pixel sizes in II. For a display bitmap,
127 * these will be same as real bitmap sizes. For a printer bitmap,
128 * these will be scaled up so that the bitmap is proportionally enlarged
129 * when output to printer. Redisplay code takes care of scaling, to
130 * conserve memory we do not really scale bitmaps. Set the watermark
132 * #### Add support for unscalable bitmaps.
134 static void init_image_instance_geometry (Lisp_Image_Instance *ii)
136 struct device *d = DOMAIN_XDEVICE (ii->domain);
138 if (/* #### Scaleable && */ DEVICE_MSPRINTER_P (d))
140 HDC printer_dc = DEVICE_MSPRINTER_HCDC (d);
141 HDC display_dc = CreateCompatibleDC (NULL);
142 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) =
143 MulDiv (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii),
144 GetDeviceCaps (printer_dc, LOGPIXELSX),
145 GetDeviceCaps (display_dc, LOGPIXELSX));
146 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) =
147 MulDiv (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii),
148 GetDeviceCaps (printer_dc, LOGPIXELSY),
149 GetDeviceCaps (display_dc, LOGPIXELSY));
153 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) =
154 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii);
155 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) =
156 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii);
160 #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3)))
162 /************************************************************************/
163 /* convert from a series of RGB triples to a BITMAPINFO formated for the*/
165 /************************************************************************/
166 static BITMAPINFO* convert_EImage_to_DIBitmap (Lisp_Object device,
167 int width, int height,
170 unsigned char** bmp_data)
172 struct device *d = XDEVICE (device);
176 BITMAPINFO* bmp_info;
177 unsigned char *ip, *dp;
179 if (GetDeviceCaps (get_device_compdc (d), BITSPIXEL) > 0)
181 int bpline = BPLINE(width * 3);
182 /* FIXME: we can do this because 24bpp implies no color table, once
183 * we start palettizing this is no longer true. The X versions of
184 * this function quantises to 256 colors or bit masks down to a
185 * long. Windows can actually handle rgb triples in the raw so I
186 * don't see much point trying to optimize down to the best
187 * structure - unless it has memory / color allocation implications
189 bmp_info=xnew_and_zero (BITMAPINFO);
196 bmp_info->bmiHeader.biBitCount=24; /* just RGB triples for now */
197 bmp_info->bmiHeader.biCompression=BI_RGB; /* just RGB triples for now */
198 bmp_info->bmiHeader.biSizeImage=width*height*3;
200 /* bitmap data needs to be in blue, green, red triples - in that
201 order, eimage is in RGB format so we need to convert */
202 *bmp_data = xnew_array_and_zero (unsigned char, bpline * height);
203 *bit_count = bpline * height;
212 for (i = height-1; i >= 0; i--) {
213 dp = (*bmp_data) + (i * bpline);
214 for (j = 0; j < width; j++) {
222 else /* scale to 256 colors */
226 int bpline = BPLINE (width * 3);
227 /* Quantize the image and get a histogram while we're at it.
228 Do this first to save memory */
229 qtable = build_EImage_quantable(pic, width, height, 256);
230 if (qtable == NULL) return NULL;
232 /* use our quantize table to allocate the colors */
233 ncolors = qtable->num_active_colors;
234 bmp_info=(BITMAPINFO*)xmalloc_and_zero (sizeof(BITMAPINFOHEADER) +
235 sizeof(RGBQUAD) * ncolors);
242 colortbl=(RGBQUAD*)(((unsigned char*)bmp_info)+sizeof(BITMAPINFOHEADER));
244 bmp_info->bmiHeader.biBitCount=8;
245 bmp_info->bmiHeader.biCompression=BI_RGB;
246 bmp_info->bmiHeader.biSizeImage=bpline*height;
247 bmp_info->bmiHeader.biClrUsed=ncolors;
248 bmp_info->bmiHeader.biClrImportant=ncolors;
250 *bmp_data = (unsigned char *) xmalloc_and_zero (bpline * height);
251 *bit_count = bpline * height;
260 /* build up an RGBQUAD colortable */
261 for (i = 0; i < qtable->num_active_colors; i++)
263 colortbl[i].rgbRed = (BYTE) qtable->rm[i];
264 colortbl[i].rgbGreen = (BYTE) qtable->gm[i];
265 colortbl[i].rgbBlue = (BYTE) qtable->bm[i];
266 colortbl[i].rgbReserved = 0;
269 /* now build up the data. picture has to be upside-down and
270 back-to-front for msw bitmaps */
272 for (i = height-1; i >= 0; i--)
274 dp = (*bmp_data) + (i * bpline);
275 for (j = 0; j < width; j++)
280 *dp++ = QUANT_GET_COLOR (qtable,rd,gr,bl);
285 /* fix up the standard stuff */
286 bmp_info->bmiHeader.biWidth=width;
287 bmp_info->bmiHeader.biHeight=height;
288 bmp_info->bmiHeader.biPlanes=1;
289 bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
290 bmp_info->bmiHeader.biXPelsPerMeter=0; /* unless you know better */
291 bmp_info->bmiHeader.biYPelsPerMeter=0;
296 /* Given a pixmap filename, look through all of the "standard" places
297 where the file might be located. Return a full pathname if found;
298 otherwise, return Qnil. */
301 mswindows_locate_pixmap_file (Lisp_Object name)
303 /* This function can GC if IN_REDISPLAY is false */
306 /* Check non-absolute pathnames with a directory component relative to
307 the search path; that's the way Xt does it. */
308 if (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 0)) ||
309 (XSTRING_BYTE (name, 0) == '.' &&
310 (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 1)) ||
311 (XSTRING_BYTE (name, 1) == '.' &&
312 (IS_DIRECTORY_SEP(XSTRING_BYTE (name, 2)))))))
314 if (!NILP (Ffile_readable_p (name)))
315 return Fexpand_file_name (name, Qnil);
320 if (locate_file (Vmswindows_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
322 Lisp_Object temp = list1 (Vdata_directory);
326 locate_file (temp, name, Qnil, &found, R_OK);
334 /* Initialize an image instance from a bitmap
336 DEST_MASK specifies the mask of allowed image types.
338 If this fails, signal an error. INSTANTIATOR is only used
339 in the error message. */
342 init_image_instance_from_dibitmap (Lisp_Image_Instance *ii,
343 BITMAPINFO *bmp_info,
348 Lisp_Object instantiator,
349 int x_hot, int y_hot,
352 struct device *d = XDEVICE (IMAGE_INSTANCE_DEVICE (ii));
354 enum image_instance_type type;
358 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
359 type = IMAGE_COLOR_PIXMAP;
360 else if (dest_mask & IMAGE_POINTER_MASK)
361 type = IMAGE_POINTER;
363 incompatible_image_types (instantiator, dest_mask,
364 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
366 hdc = get_device_compdc (d);
367 bitmap = CreateDIBSection (hdc,
373 if (!bitmap || !bmp_buf)
374 signal_simple_error ("Unable to create bitmap", instantiator);
376 /* copy in the actual bitmap */
377 memcpy (bmp_buf, bmp_data, bmp_bits);
379 mswindows_initialize_dibitmap_image_instance (ii, slices, type);
381 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
382 find_keyword_in_vector (instantiator, Q_file);
384 /* Fixup a set of bitmaps. */
385 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap;
387 IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
388 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii) =
389 bmp_info->bmiHeader.biWidth;
390 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii) =
391 bmp_info->bmiHeader.biHeight;
392 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = bmp_info->bmiHeader.biBitCount;
393 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), x_hot);
394 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), y_hot);
395 init_image_instance_geometry (ii);
399 mswindows_initialize_image_instance_mask (ii, hdc);
402 if (type == IMAGE_POINTER)
404 mswindows_initialize_image_instance_icon(ii, TRUE);
409 image_instance_add_dibitmap (Lisp_Image_Instance *ii,
410 BITMAPINFO *bmp_info,
414 Lisp_Object instantiator)
416 struct device *d = XDEVICE (IMAGE_INSTANCE_DEVICE (ii));
419 HBITMAP bitmap = CreateDIBSection (get_device_compdc (d),
425 if (!bitmap || !bmp_buf)
426 signal_simple_error ("Unable to create bitmap", instantiator);
428 /* copy in the actual bitmap */
429 memcpy (bmp_buf, bmp_data, bmp_bits);
430 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (ii, slice) = bitmap;
434 mswindows_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
435 int width, int height,
437 unsigned char *eimage,
439 Lisp_Object instantiator,
442 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
443 BITMAPINFO* bmp_info;
444 unsigned char* bmp_data;
449 CHECK_MSGDI_DEVICE (device);
451 /* this is a hack but MaskBlt and TransparentBlt are not supported
452 on most windows variants */
453 bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR
454 (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain)));
456 for (slice = 0; slice < slices; slice++)
458 /* build a bitmap from the eimage */
459 if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height,
460 eimage + (width * height * 3 * slice),
461 &bmp_bits, &bmp_data)))
463 signal_simple_error ("EImage to DIBitmap conversion failed",
467 /* Now create the pixmap and set up the image instance */
469 init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
470 bmp_data, bmp_bits, slices, instantiator,
473 image_instance_add_dibitmap (ii, bmp_info, bmp_data, bmp_bits, slice,
482 set_mono_pixel (unsigned char* bits,
483 int bpline, int height,
484 int x, int y, int white)
487 unsigned char bitnum;
488 /* Find the byte on which this scanline begins */
489 i = (height - y - 1) * bpline;
490 /* Find the byte containing this pixel */
492 /* Which bit is it? */
493 bitnum = (unsigned char) (7 - (x & 7));
494 if (white) /* Turn it on */
495 bits[i] |= (1 << bitnum);
496 else /* Turn it off */
497 bits[i] &= ~(1 << bitnum);
501 mswindows_initialize_image_instance_mask (Lisp_Image_Instance* image,
506 unsigned char *dibits, *and_bits;
507 BITMAPINFO *bmp_info =
508 (BITMAPINFO*) xmalloc_and_zero (sizeof (BITMAPINFO) + sizeof (RGBQUAD));
510 int height = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (image);
512 int maskbpline = BPLINE ((IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image) + 7) / 8);
513 int bpline = BPLINE (IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image) * 3);
518 bmp_info->bmiHeader.biWidth=IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image);
519 bmp_info->bmiHeader.biHeight = height;
520 bmp_info->bmiHeader.biPlanes = 1;
521 bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
522 bmp_info->bmiHeader.biBitCount = 1;
523 bmp_info->bmiHeader.biCompression = BI_RGB;
524 bmp_info->bmiHeader.biClrUsed = 2;
525 bmp_info->bmiHeader.biClrImportant = 2;
526 bmp_info->bmiHeader.biSizeImage = height * maskbpline;
527 bmp_info->bmiColors[0].rgbRed = 0;
528 bmp_info->bmiColors[0].rgbGreen = 0;
529 bmp_info->bmiColors[0].rgbBlue = 0;
530 bmp_info->bmiColors[0].rgbReserved = 0;
531 bmp_info->bmiColors[1].rgbRed = 255;
532 bmp_info->bmiColors[1].rgbGreen = 255;
533 bmp_info->bmiColors[1].rgbBlue = 255;
534 bmp_info->bmiColors[0].rgbReserved = 0;
536 if (!(mask = CreateDIBSection (hcdc,
546 old = SelectObject (hcdc, IMAGE_INSTANCE_MSWINDOWS_BITMAP (image));
547 /* build up an in-memory set of bits to mess with */
550 bmp_info->bmiHeader.biWidth = IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image);
551 bmp_info->bmiHeader.biHeight = -height;
552 bmp_info->bmiHeader.biPlanes = 1;
553 bmp_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
554 bmp_info->bmiHeader.biBitCount = 24;
555 bmp_info->bmiHeader.biCompression = BI_RGB;
556 bmp_info->bmiHeader.biClrUsed = 0;
557 bmp_info->bmiHeader.biClrImportant = 0;
558 bmp_info->bmiHeader.biSizeImage = height * bpline;
560 dibits = (unsigned char*) xmalloc_and_zero (bpline * height);
562 IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
567 DIB_RGB_COLORS) <= 0)
573 /* now set the colored bits in the mask and transparent ones to
574 black in the original */
575 for (i = 0; i < IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (image); i++)
577 for (j=0; j<height; j++)
579 unsigned char* idx = &dibits[j * bpline + i * 3];
581 if (RGB (idx[2], idx[1], idx[0]) == transparent_color)
583 idx[0] = idx[1] = idx[2] = 0;
584 set_mono_pixel (and_bits, maskbpline, height, i, j, TRUE);
588 set_mono_pixel (and_bits, maskbpline, height, i, j, FALSE);
594 IMAGE_INSTANCE_MSWINDOWS_BITMAP (image),
604 SelectObject(hcdc, old);
606 IMAGE_INSTANCE_MSWINDOWS_MASK (image) = mask;
610 mswindows_initialize_image_instance_icon (Lisp_Image_Instance* image,
615 /* we rely on windows to do any resizing necessary */
616 x_icon.fIcon=cursor ? FALSE : TRUE;
617 x_icon.xHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image));
618 x_icon.yHotspot=XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image));
619 x_icon.hbmMask=IMAGE_INSTANCE_MSWINDOWS_MASK (image);
620 x_icon.hbmColor=IMAGE_INSTANCE_MSWINDOWS_BITMAP (image);
622 IMAGE_INSTANCE_MSWINDOWS_ICON (image)=
623 CreateIconIndirect (&x_icon);
627 create_resized_bitmap (HBITMAP curbmp, struct frame *f,
634 HDC hcdc = get_device_compdc (XDEVICE (FRAME_DEVICE (f)));
635 HDC hdcDst = CreateCompatibleDC (hcdc);
637 old1 = SelectObject (hcdc, curbmp);
639 newbmp = CreateCompatibleBitmap (hcdc, newx, newy);
641 old2 = SelectObject (hdcDst, newbmp);
643 if (!StretchBlt (hdcDst, 0, 0, newx, newy,
649 DeleteObject (newbmp);
654 SelectObject (hdcDst, old2);
655 SelectObject (hcdc, old1);
662 mswindows_create_resized_bitmap (Lisp_Image_Instance* ii,
666 return create_resized_bitmap (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii),
668 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii),
669 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii),
674 mswindows_create_resized_mask (Lisp_Image_Instance* ii,
678 if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii) == NULL)
681 return create_resized_bitmap (IMAGE_INSTANCE_MSWINDOWS_MASK (ii),
683 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii),
684 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii),
688 #if 0 /* Currently unused */
689 /* #### Warning: This function is not correct anymore with
690 resizable printer bitmaps. If you uncomment it, clean it. --kkm */
692 mswindows_resize_dibitmap_instance (Lisp_Image_Instance* ii,
696 HBITMAP newbmp = mswindows_create_resized_bitmap (ii, f, newx, newy);
697 HBITMAP newmask = mswindows_create_resized_mask (ii, f, newx, newy);
702 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii))
703 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii));
704 if (IMAGE_INSTANCE_MSWINDOWS_MASK (ii))
705 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (ii));
707 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = newbmp;
708 IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = newmask;
709 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = newx;
710 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = newy;
716 /**********************************************************************
718 **********************************************************************/
728 static struct color_symbol*
729 extract_xpm_color_names (Lisp_Object device,
731 Lisp_Object color_symbol_alist,
734 /* This function can GC */
736 Lisp_Object results = Qnil;
738 struct color_symbol *colortbl;
739 struct gcpro gcpro1, gcpro2;
741 GCPRO2 (results, device);
743 /* We built up results to be (("name" . #<color>) ...) so that if an
744 error happens we don't lose any malloc()ed data, or more importantly,
745 leave any pixels allocated in the server. */
747 LIST_LOOP (rest, color_symbol_alist)
749 Lisp_Object cons = XCAR (rest);
750 Lisp_Object name = XCAR (cons);
751 Lisp_Object value = XCDR (cons);
757 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
760 assert (COLOR_SPECIFIERP (value));
761 value = Fspecifier_instance (value, domain, Qnil, Qnil);
765 results = noseeum_cons (noseeum_cons (name, value), results);
768 UNGCPRO; /* no more evaluation */
771 if (i == 0) return 0;
773 colortbl = xnew_array_and_zero (struct color_symbol, i);
777 Lisp_Object cons = XCAR (results);
779 COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
781 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (cons),
782 C_STRING_ALLOCA, colortbl[j].name,
784 colortbl[j].name = xstrdup (colortbl[j].name); /* mustn't lose this when we return */
785 free_cons (XCONS (cons));
787 results = XCDR (results);
788 free_cons (XCONS (cons));
793 static int xpm_to_eimage (Lisp_Object image, const Extbyte *buffer,
794 unsigned char** data,
795 int* width, int* height,
796 int* x_hot, int* y_hot,
798 struct color_symbol* color_symbols,
803 int result, i, j, transp_idx, maskbpline;
806 COLORREF color; /* the american spelling virus hits again .. */
811 xpminfo.valuemask=XpmHotspot;
814 result = XpmCreateXpmImageFromBuffer ((char*)buffer,
823 signal_simple_error ("Invalid XPM data", image);
827 signal_double_file_error ("Parsing pixmap data",
828 "out of memory", image);
832 signal_double_file_error_2 ("Parsing pixmap data",
834 make_int (result), image);
838 *width = xpmimage.width;
839 *height = xpmimage.height;
840 maskbpline = BPLINE ((~7UL & (unsigned long)(*width + 7)) / 8);
842 *data = xnew_array_and_zero (unsigned char, *width * *height * 3);
846 XpmFreeXpmImage (&xpmimage);
847 XpmFreeXpmInfo (&xpminfo);
851 /* build a color table to speed things up */
852 colortbl = xnew_array_and_zero (COLORREF, xpmimage.ncolors);
856 XpmFreeXpmImage (&xpmimage);
857 XpmFreeXpmInfo (&xpminfo);
861 for (i=0; i<xpmimage.ncolors; i++)
864 /* pick up symbolic colors in preference */
865 if (xpmimage.colorTable[i].symbolic)
867 if (!strcasecmp (xpmimage.colorTable[i].symbolic,"BgColor")
869 !strcasecmp (xpmimage.colorTable[i].symbolic,"None"))
872 colortbl[i]=transparent_color;
874 goto label_found_color;
876 else if (color_symbols)
878 for (j = 0; j<nsymbols; j++)
880 if (!strcmp (xpmimage.colorTable[i].symbolic,
881 color_symbols[j].name ))
883 colortbl[i]=color_symbols[j].color;
884 goto label_found_color;
888 else if (xpmimage.colorTable[i].c_color == 0)
893 /* pick up transparencies */
894 if (!strcasecmp (xpmimage.colorTable[i].c_color,"None"))
897 colortbl[i]=transparent_color;
899 goto label_found_color;
901 /* finally pick up a normal color spec */
902 if (xpmimage.colorTable[i].c_color)
905 mswindows_string_to_color (xpmimage.colorTable[i].c_color);
906 goto label_found_color;
912 XpmFreeXpmImage (&xpmimage);
913 XpmFreeXpmInfo (&xpminfo);
919 /* convert the image */
922 for (i = 0; i< *width * *height; i++)
924 color = colortbl[*sptr++];
926 /* split out the 0x02bbggrr colorref into an rgb triple */
927 *dptr++=GetRValue (color); /* red */
928 *dptr++=GetGValue (color); /* green */
929 *dptr++=GetBValue (color); /* blue */
932 *x_hot=xpminfo.x_hotspot;
933 *y_hot=xpminfo.y_hotspot;
935 XpmFreeXpmImage (&xpmimage);
936 XpmFreeXpmInfo (&xpminfo);
942 mswindows_xpm_instantiate (Lisp_Object image_instance,
943 Lisp_Object instantiator,
944 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
945 int dest_mask, Lisp_Object domain)
947 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
948 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
949 const Extbyte *bytes;
951 unsigned char *eimage;
952 int width, height, x_hot, y_hot;
953 BITMAPINFO* bmp_info;
954 unsigned char* bmp_data;
956 int nsymbols=0, transp;
957 struct color_symbol* color_symbols=NULL;
959 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
960 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
963 CHECK_MSGDI_DEVICE (device);
965 assert (!NILP (data));
967 TO_EXTERNAL_FORMAT (LISP_STRING, data,
968 ALLOCA, (bytes, len),
971 /* in case we have color symbols */
972 color_symbols = extract_xpm_color_names (device, domain,
973 color_symbol_alist, &nsymbols);
975 /* convert to an eimage to make processing easier */
976 if (!xpm_to_eimage (image_instance, bytes, &eimage, &width, &height,
977 &x_hot, &y_hot, &transp, color_symbols, nsymbols))
979 signal_simple_error ("XPM to EImage conversion failed",
987 xfree (color_symbols[nsymbols].name);
989 xfree(color_symbols);
992 /* build a bitmap from the eimage */
993 if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage,
994 &bmp_bits, &bmp_data)))
996 signal_simple_error ("XPM to EImage conversion failed",
1001 /* Now create the pixmap and set up the image instance */
1002 init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
1003 bmp_data, bmp_bits, 1, instantiator,
1004 x_hot, y_hot, transp);
1009 #endif /* HAVE_XPM */
1011 /**********************************************************************
1013 **********************************************************************/
1016 bmp_validate (Lisp_Object instantiator)
1018 file_or_data_must_be_present (instantiator);
1022 bmp_normalize (Lisp_Object inst, Lisp_Object console_type,
1023 Lisp_Object dest_mask)
1025 return simple_image_type_normalize (inst, console_type, Qbmp);
1029 bmp_possible_dest_types (void)
1031 return IMAGE_COLOR_PIXMAP_MASK;
1035 bmp_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1036 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1037 int dest_mask, Lisp_Object domain)
1039 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1040 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1041 const Extbyte *bytes;
1043 BITMAPFILEHEADER* bmp_file_header;
1044 BITMAPINFO* bmp_info;
1047 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1049 CHECK_MSGDI_DEVICE (device);
1051 assert (!NILP (data));
1053 TO_EXTERNAL_FORMAT (LISP_STRING, data,
1054 ALLOCA, (bytes, len),
1057 /* Then slurp the image into memory, decoding along the way.
1058 The result is the image in a simple one-byte-per-pixel
1061 bmp_file_header=(BITMAPFILEHEADER*)bytes;
1062 bmp_info = (BITMAPINFO*)(bytes + sizeof(BITMAPFILEHEADER));
1063 bmp_data = (Extbyte*)bytes + bmp_file_header->bfOffBits;
1064 bmp_bits = bmp_file_header->bfSize - bmp_file_header->bfOffBits;
1066 /* Now create the pixmap and set up the image instance */
1067 init_image_instance_from_dibitmap (ii, bmp_info, dest_mask,
1068 bmp_data, bmp_bits, 1, instantiator,
1073 /**********************************************************************
1075 **********************************************************************/
1078 mswindows_resource_validate (Lisp_Object instantiator)
1080 if ((NILP (find_keyword_in_vector (instantiator, Q_file))
1082 NILP (find_keyword_in_vector (instantiator, Q_resource_id)))
1084 NILP (find_keyword_in_vector (instantiator, Q_resource_type)))
1085 signal_simple_error ("Must supply :file, :resource-id and :resource-type",
1090 mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type,
1091 Lisp_Object dest_mask)
1093 /* This function can call lisp */
1094 Lisp_Object file = Qnil;
1095 struct gcpro gcpro1, gcpro2;
1096 Lisp_Object alist = Qnil;
1098 GCPRO2 (file, alist);
1100 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1103 if (CONSP (file)) /* failure locating filename */
1104 signal_double_file_error ("Opening pixmap file",
1105 "no such file or directory",
1108 if (NILP (file)) /* no conversion necessary */
1109 RETURN_UNGCPRO (inst);
1111 alist = tagged_vector_to_alist (inst);
1114 alist = remassq_no_quit (Q_file, alist);
1115 alist = Fcons (Fcons (Q_file, file), alist);
1119 Lisp_Object result = alist_to_tagged_vector (Qmswindows_resource, alist);
1121 RETURN_UNGCPRO (result);
1126 mswindows_resource_possible_dest_types (void)
1128 return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
1138 #define OCR_ICOCUR 32647
1139 #define OIC_SAMPLE 32512
1140 #define OIC_HAND 32513
1141 #define OIC_QUES 32514
1142 #define OIC_BANG 32515
1143 #define OIC_NOTE 32516
1144 #define OIC_WINLOGO 32517
1145 #if defined (CYGWIN) && CYGWIN_VERSION_DLL_MAJOR < 21
1146 #define LR_SHARED 0x8000
1150 static const resource_t bitmap_table[] =
1153 { "close", OBM_CLOSE },
1154 { "uparrow", OBM_UPARROW },
1155 { "dnarrow", OBM_DNARROW },
1156 { "rgarrow", OBM_RGARROW },
1157 { "lfarrow", OBM_LFARROW },
1158 { "reduce", OBM_REDUCE },
1159 { "zoom", OBM_ZOOM },
1160 { "restore", OBM_RESTORE },
1161 { "reduced", OBM_REDUCED },
1162 { "zoomd", OBM_ZOOMD },
1163 { "restored", OBM_RESTORED },
1164 { "uparrowd", OBM_UPARROWD },
1165 { "dnarrowd", OBM_DNARROWD },
1166 { "rgarrowd", OBM_RGARROWD },
1167 { "lfarrowd", OBM_LFARROWD },
1168 { "mnarrow", OBM_MNARROW },
1169 { "combo", OBM_COMBO },
1170 { "uparrowi", OBM_UPARROWI },
1171 { "dnarrowi", OBM_DNARROWI },
1172 { "rgarrowi", OBM_RGARROWI },
1173 { "lfarrowi", OBM_LFARROWI },
1174 { "size", OBM_SIZE },
1175 { "btsize", OBM_BTSIZE },
1176 { "check", OBM_CHECK },
1177 { "checkboxes", OBM_CHECKBOXES },
1178 { "btncorners" , OBM_BTNCORNERS },
1182 static const resource_t cursor_table[] =
1185 { "normal", OCR_NORMAL },
1186 { "ibeam", OCR_IBEAM },
1187 { "wait", OCR_WAIT },
1188 { "cross", OCR_CROSS },
1190 /* { "icon", OCR_ICON }, */
1191 { "sizenwse", OCR_SIZENWSE },
1192 { "sizenesw", OCR_SIZENESW },
1193 { "sizewe", OCR_SIZEWE },
1194 { "sizens", OCR_SIZENS },
1195 { "sizeall", OCR_SIZEALL },
1196 /* { "icour", OCR_ICOCUR }, */
1201 static const resource_t icon_table[] =
1204 { "sample", OIC_SAMPLE },
1205 { "hand", OIC_HAND },
1206 { "ques", OIC_QUES },
1207 { "bang", OIC_BANG },
1208 { "note", OIC_NOTE },
1209 { "winlogo", OIC_WINLOGO },
1213 static int resource_name_to_resource (Lisp_Object name, int type)
1215 const resource_t* res = (type == IMAGE_CURSOR ? cursor_table
1216 : type == IMAGE_ICON ? icon_table
1223 else if (!STRINGP (name))
1225 signal_simple_error ("invalid resource identifier", name);
1230 TO_EXTERNAL_FORMAT (LISP_STRING, name,
1231 C_STRING_ALLOCA, nm,
1233 if (!strcasecmp ((char*)res->name, nm))
1234 return res->resource_id;
1235 } while ((++res)->name);
1240 resource_symbol_to_type (Lisp_Object data)
1242 if (EQ (data, Qcursor))
1243 return IMAGE_CURSOR;
1244 else if (EQ (data, Qicon))
1246 else if (EQ (data, Qbitmap))
1247 return IMAGE_BITMAP;
1253 mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1254 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1255 int dest_mask, Lisp_Object domain)
1257 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1258 unsigned int type = 0;
1259 HANDLE himage = NULL;
1261 HINSTANCE hinst = NULL;
1263 enum image_instance_type iitype;
1265 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1267 Lisp_Object file = find_keyword_in_vector (instantiator, Q_file);
1268 Lisp_Object resource_type = find_keyword_in_vector (instantiator,
1270 Lisp_Object resource_id = find_keyword_in_vector (instantiator,
1275 CHECK_MSGDI_DEVICE (device);
1277 type = resource_symbol_to_type (resource_type);
1279 if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_CURSOR)
1280 iitype = IMAGE_POINTER;
1281 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1282 iitype = IMAGE_COLOR_PIXMAP;
1284 incompatible_image_types (instantiator, dest_mask,
1285 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
1287 /* mess with the keyword info we were provided with */
1291 TO_EXTERNAL_FORMAT (LISP_STRING, file,
1295 CYGWIN_WIN32_PATH (f, fname);
1300 if (NILP (resource_id))
1301 resid = (LPCTSTR)fname;
1304 hinst = LoadLibraryEx (fname, NULL,
1305 LOAD_LIBRARY_AS_DATAFILE);
1306 resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1310 TO_EXTERNAL_FORMAT (LISP_STRING, resource_id,
1311 C_STRING_ALLOCA, resid,
1315 else if (!(resid = MAKEINTRESOURCE (resource_name_to_resource (resource_id,
1317 signal_simple_error ("Invalid resource identifier", resource_id);
1319 /* load the image */
1320 if (xLoadImageA) /* not in NT 3.5 */
1322 if (!(himage = xLoadImageA (hinst, resid, type, 0, 0,
1323 LR_CREATEDIBSECTION | LR_DEFAULTSIZE |
1325 (!NILP (file) ? LR_LOADFROMFILE : 0))))
1326 signal_simple_error ("Cannot load image", instantiator);
1330 /* Is this correct? I don't really care. */
1334 himage = LoadBitmap (hinst, resid);
1337 himage = LoadCursor (hinst, resid);
1340 himage = LoadIcon (hinst, resid);
1345 signal_simple_error ("Cannot load image", instantiator);
1349 FreeLibrary (hinst);
1351 mswindows_initialize_dibitmap_image_instance (ii, 1, iitype);
1353 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file;
1354 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii) =
1355 GetSystemMetrics (type == IMAGE_CURSOR ? SM_CXCURSOR : SM_CXICON);
1356 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii) =
1357 GetSystemMetrics (type == IMAGE_CURSOR ? SM_CYCURSOR : SM_CYICON);
1358 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1359 init_image_instance_geometry (ii);
1361 /* hey, we've got an icon type thing so we can reverse engineer the
1363 if (type != IMAGE_BITMAP)
1365 GetIconInfo ((HICON)himage, &iconinfo);
1366 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = iconinfo.hbmColor;
1367 IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = iconinfo.hbmMask;
1368 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), iconinfo.xHotspot);
1369 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), iconinfo.yHotspot);
1370 IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = (HICON) himage;
1374 IMAGE_INSTANCE_MSWINDOWS_ICON (ii) = NULL;
1375 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = (HBITMAP) himage;
1376 IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL;
1377 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1378 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1383 check_valid_resource_symbol (Lisp_Object data)
1385 CHECK_SYMBOL (data);
1386 if (!resource_symbol_to_type (data))
1387 signal_simple_error ("invalid resource type", data);
1391 check_valid_resource_id (Lisp_Object data)
1393 if (!resource_name_to_resource (data, IMAGE_CURSOR)
1395 !resource_name_to_resource (data, IMAGE_ICON)
1397 !resource_name_to_resource (data, IMAGE_BITMAP))
1398 signal_simple_error ("invalid resource identifier", data);
1401 /**********************************************************************
1403 **********************************************************************/
1404 #ifndef HAVE_X_WINDOWS
1405 /* $XConsortium: RdBitF.c,v 1.10 94/04/17 20:16:13 kaleb Exp $ */
1409 Copyright (c) 1988 X Consortium
1411 Permission is hereby granted, free of charge, to any person obtaining a copy
1412 of this software and associated documentation files (the "Software"), to deal
1413 in the Software without restriction, including without limitation the rights
1414 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1415 copies of the Software, and to permit persons to whom the Software is
1416 furnished to do so, subject to the following conditions:
1418 The above copyright notice and this permission notice shall be included in
1419 all copies or substantial portions of the Software.
1421 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1422 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1423 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1424 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1425 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1426 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1428 Except as contained in this notice, the name of the X Consortium shall not be
1429 used in advertising or otherwise to promote the sale, use or other dealings
1430 in this Software without prior written authorization from the X Consortium.
1435 * This file contains miscellaneous utility routines and is not part of the
1438 * Public entry points:
1440 * XmuReadBitmapData read data from FILE descriptor
1441 * XmuReadBitmapDataFromFile read X10 or X11 format bitmap files
1444 * Note that this file and ../X/XRdBitF.c look very similar.... Keep them
1445 * that way (but don't use common source code so that people can have one
1446 * without the other).
1451 * Based on an optimized version provided by Jim Becker, August 5, 1988.
1453 #ifndef BitmapSuccess
1454 #define BitmapSuccess 0
1455 #define BitmapOpenFailed 1
1456 #define BitmapFileInvalid 2
1457 #define BitmapNoMemory 3
1459 #define MAX_SIZE 255
1461 /* shared data for the image read/parse logic */
1462 static short hexTable[256]; /* conversion value */
1463 static int initialized = FALSE; /* easier to fill in at run time */
1466 * Table index for the hex values. Initialized once, first time.
1467 * Used for translation value or delimiter significance lookup.
1473 * We build the table at run time for several reasons:
1475 * 1. portable to non-ASCII machines.
1476 * 2. still reentrant since we set the init flag after setting table.
1477 * 3. easier to extend.
1478 * 4. less prone to bugs.
1480 hexTable['0'] = 0; hexTable['1'] = 1;
1481 hexTable['2'] = 2; hexTable['3'] = 3;
1482 hexTable['4'] = 4; hexTable['5'] = 5;
1483 hexTable['6'] = 6; hexTable['7'] = 7;
1484 hexTable['8'] = 8; hexTable['9'] = 9;
1485 hexTable['A'] = 10; hexTable['B'] = 11;
1486 hexTable['C'] = 12; hexTable['D'] = 13;
1487 hexTable['E'] = 14; hexTable['F'] = 15;
1488 hexTable['a'] = 10; hexTable['b'] = 11;
1489 hexTable['c'] = 12; hexTable['d'] = 13;
1490 hexTable['e'] = 14; hexTable['f'] = 15;
1492 /* delimiters of significance are flagged w/ negative value */
1493 hexTable[' '] = -1; hexTable[','] = -1;
1494 hexTable['}'] = -1; hexTable['\n'] = -1;
1495 hexTable['\t'] = -1;
1501 * read next hex value in the input stream, return -1 if EOF
1504 NextInt (FILE *fstream)
1511 /* loop, accumulate hex value until find delimiter */
1512 /* skip any initial delimiters found in read stream */
1520 /* trim high bits, check type and accumulate */
1522 if (isascii(ch) && isxdigit(ch)) {
1523 value = (value << 4) + hexTable[ch];
1525 } else if ((hexTable[ch]) < 0 && gotone)
1534 * The data returned by the following routine is always in left-most byte
1535 * first and left-most bit first. If it doesn't return BitmapSuccess then
1536 * its arguments won't have been touched. This routine should look as much
1537 * like the Xlib routine XReadBitmapfile as possible.
1539 int read_bitmap_data (FILE* fstream, unsigned int *width,
1540 unsigned int *height, unsigned char **datap,
1541 int *x_hot, int *y_hot)
1543 unsigned char *data = NULL; /* working variable */
1544 char line[MAX_SIZE]; /* input line from file */
1545 int size; /* number of bytes of data */
1546 char name_and_type[MAX_SIZE]; /* an input line */
1547 char *type; /* for parsing */
1548 int value; /* from an input line */
1549 int version10p; /* boolean, old format */
1550 int padding; /* to handle alignment */
1551 int bytes_per_line; /* per scanline of data */
1552 unsigned int ww = 0; /* width */
1553 unsigned int hh = 0; /* height */
1554 int hx = -1; /* x hotspot */
1555 int hy = -1; /* y hotspot */
1557 #define Xmalloc(size) malloc(size)
1559 /* first time initialization */
1560 if (initialized == FALSE) initHexTable();
1562 /* error cleanup and return macro */
1563 #define RETURN(code) { if (data) free (data); return code; }
1565 while (fgets(line, MAX_SIZE, fstream)) {
1566 if (strlen(line) == MAX_SIZE-1) {
1567 RETURN (BitmapFileInvalid);
1569 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
1570 if (!(type = strrchr(name_and_type, '_')))
1571 type = name_and_type;
1575 if (!strcmp("width", type))
1576 ww = (unsigned int) value;
1577 if (!strcmp("height", type))
1578 hh = (unsigned int) value;
1579 if (!strcmp("hot", type)) {
1580 if (type-- == name_and_type || type-- == name_and_type)
1582 if (!strcmp("x_hot", type))
1584 if (!strcmp("y_hot", type))
1590 if (sscanf(line, "static short %s = {", name_and_type) == 1)
1592 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
1594 else if (sscanf(line, "static char %s = {", name_and_type) == 1)
1599 if (!(type = strrchr(name_and_type, '_')))
1600 type = name_and_type;
1604 if (strcmp("bits[]", type))
1608 RETURN (BitmapFileInvalid);
1610 if ((ww % 16) && ((ww % 16) < 9) && version10p)
1615 bytes_per_line = (ww+7)/8 + padding;
1617 size = bytes_per_line * hh;
1618 data = (unsigned char *) Xmalloc ((unsigned int) size);
1620 RETURN (BitmapNoMemory);
1626 for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
1627 if ((value = NextInt(fstream)) < 0)
1628 RETURN (BitmapFileInvalid);
1630 if (!padding || ((bytes+2) % bytes_per_line))
1631 *(ptr++) = value >> 8;
1637 for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
1638 if ((value = NextInt(fstream)) < 0)
1639 RETURN (BitmapFileInvalid);
1647 RETURN (BitmapFileInvalid);
1654 if (x_hot) *x_hot = hx;
1655 if (y_hot) *y_hot = hy;
1657 RETURN (BitmapSuccess);
1661 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
1662 unsigned int *height, unsigned char **datap,
1663 int *x_hot, int *y_hot)
1668 if ((fstream = fopen (filename, "r")) == NULL) {
1669 return BitmapOpenFailed;
1671 status = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
1675 #endif /* HAVE_X_WINDOWS */
1677 /* this table flips four bits around. */
1678 static int flip_table[] =
1680 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
1683 /* the bitmap data comes in the following format: Widths are padded to
1684 a multiple of 8. Scan lines are stored in increasing byte order
1685 from left to right, little-endian within a byte. 0 = white, 1 =
1686 black. It must be converted to the following format: Widths are
1687 padded to a multiple of 16. Scan lines are stored in increasing
1688 byte order from left to right, big-endian within a byte. 0 =
1689 black, 1 = white. */
1691 xbm_create_bitmap_from_data (HDC hdc, char *data,
1692 unsigned int width, unsigned int height,
1693 int mask, COLORREF fg, COLORREF bg)
1695 int old_width = (width + 7)/8;
1696 int new_width = BPLINE (2*((width + 15)/16));
1697 unsigned char *offset;
1699 unsigned char *new_data, *new_offset;
1701 BITMAPINFO *bmp_info =
1702 (BITMAPINFO*) xmalloc_and_zero (sizeof(BITMAPINFO) + sizeof(RGBQUAD));
1708 new_data = (unsigned char *) xmalloc_and_zero (height * new_width);
1716 for (i=0; i<height; i++)
1718 offset = data + i*old_width;
1719 new_offset = new_data + i*new_width;
1721 for (j=0; j<old_width; j++)
1723 int byte = offset[j];
1724 new_offset[j] = ~ (unsigned char)
1725 ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]);
1729 /* if we want a mask invert the bits */
1732 new_offset = &new_data[height * new_width];
1733 while (new_offset-- != new_data)
1735 *new_offset ^= 0xff;
1739 bmp_info->bmiHeader.biWidth=width;
1740 bmp_info->bmiHeader.biHeight=-(LONG)height;
1741 bmp_info->bmiHeader.biPlanes=1;
1742 bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
1743 bmp_info->bmiHeader.biBitCount=1;
1744 bmp_info->bmiHeader.biCompression=BI_RGB;
1745 bmp_info->bmiHeader.biClrUsed = 2;
1746 bmp_info->bmiHeader.biClrImportant = 2;
1747 bmp_info->bmiHeader.biSizeImage = height * new_width;
1748 bmp_info->bmiColors[0].rgbRed = GetRValue (fg);
1749 bmp_info->bmiColors[0].rgbGreen = GetGValue (fg);
1750 bmp_info->bmiColors[0].rgbBlue = GetBValue (fg);
1751 bmp_info->bmiColors[0].rgbReserved = 0;
1752 bmp_info->bmiColors[1].rgbRed = GetRValue (bg);
1753 bmp_info->bmiColors[1].rgbGreen = GetGValue (bg);
1754 bmp_info->bmiColors[1].rgbBlue = GetBValue (bg);
1755 bmp_info->bmiColors[1].rgbReserved = 0;
1757 bitmap = CreateDIBSection (hdc,
1765 if (!bitmap || !bmp_buf)
1771 /* copy in the actual bitmap */
1772 memcpy (bmp_buf, new_data, height * new_width);
1778 /* Given inline data for a mono pixmap, initialize the given
1779 image instance accordingly. */
1782 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1783 int width, int height,
1784 /* Note that data is in ext-format! */
1786 Lisp_Object instantiator,
1787 Lisp_Object pointer_fg,
1788 Lisp_Object pointer_bg,
1791 Lisp_Object mask_filename)
1793 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1794 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1795 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1796 enum image_instance_type type;
1797 COLORREF black = PALETTERGB (0,0,0);
1798 COLORREF white = PALETTERGB (255,255,255);
1801 CHECK_MSGDI_DEVICE (device);
1803 hdc = get_device_compdc (XDEVICE (device));
1805 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1806 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1808 if (!NILP (foreground) || !NILP (background))
1809 type = IMAGE_COLOR_PIXMAP;
1811 type = IMAGE_MONO_PIXMAP;
1813 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1814 type = IMAGE_MONO_PIXMAP;
1815 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1816 type = IMAGE_COLOR_PIXMAP;
1817 else if (dest_mask & IMAGE_POINTER_MASK)
1818 type = IMAGE_POINTER;
1820 incompatible_image_types (instantiator, dest_mask,
1821 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1822 | IMAGE_POINTER_MASK);
1824 mswindows_initialize_dibitmap_image_instance (ii, 1, type);
1826 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1827 find_keyword_in_vector (instantiator, Q_file);
1828 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii) = width;
1829 IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii) = height;
1830 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1831 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), 0);
1832 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), 0);
1833 init_image_instance_geometry (ii);
1835 IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = mask ? mask :
1836 xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1837 TRUE, black, white);
1841 case IMAGE_MONO_PIXMAP:
1842 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1843 xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1844 FALSE, black, black);
1847 case IMAGE_COLOR_PIXMAP:
1849 COLORREF fg = black;
1850 COLORREF bg = white;
1852 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1854 Fmake_color_instance (foreground, device,
1855 encode_error_behavior_flag (ERROR_ME));
1857 if (COLOR_INSTANCEP (foreground))
1858 fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1860 if (!NILP (background) && !COLOR_INSTANCEP (background))
1862 Fmake_color_instance (background, device,
1863 encode_error_behavior_flag (ERROR_ME));
1865 if (COLOR_INSTANCEP (background))
1866 bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1868 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1869 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1871 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1872 xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1879 COLORREF fg = black;
1880 COLORREF bg = white;
1882 if (NILP (foreground))
1883 foreground = pointer_fg;
1884 if (NILP (background))
1885 background = pointer_bg;
1887 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1888 find_keyword_in_vector (instantiator, Q_hotspot_x);
1889 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1890 find_keyword_in_vector (instantiator, Q_hotspot_y);
1891 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1892 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1893 if (COLOR_INSTANCEP (foreground))
1894 fg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (foreground));
1895 if (COLOR_INSTANCEP (background))
1896 bg = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (background));
1898 IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) =
1899 xbm_create_bitmap_from_data (hdc, (Extbyte *) bits, width, height,
1901 mswindows_initialize_image_instance_icon (ii, TRUE);
1911 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1912 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1913 int dest_mask, int width, int height,
1914 /* Note that data is in ext-format! */
1917 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1918 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1919 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1920 HDC hdc = get_device_compdc (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)));
1923 if (!NILP (mask_data))
1925 const char *ext_data;
1927 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
1928 C_STRING_ALLOCA, ext_data,
1930 mask = xbm_create_bitmap_from_data (hdc,
1931 (unsigned char *) ext_data,
1932 XINT (XCAR (mask_data)),
1933 XINT (XCAR (XCDR (mask_data))),
1936 PALETTERGB (255,255,255));
1939 init_image_instance_from_xbm_inline (ii, width, height, bits,
1940 instantiator, pointer_fg, pointer_bg,
1941 dest_mask, mask, mask_file);
1944 /* Instantiate method for XBM's. */
1947 mswindows_xbm_instantiate (Lisp_Object image_instance,
1948 Lisp_Object instantiator,
1949 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1950 int dest_mask, Lisp_Object domain)
1952 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1953 const char *ext_data;
1955 assert (!NILP (data));
1957 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
1958 C_STRING_ALLOCA, ext_data,
1961 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1962 pointer_bg, dest_mask, XINT (XCAR (data)),
1963 XINT (XCAR (XCDR (data))), ext_data);
1967 /**********************************************************************
1969 **********************************************************************/
1971 /* This is about to get redefined! */
1974 /* We have to define SYSV32 so that compface.h includes string.h
1975 instead of strings.h. */
1980 #include <compface.h>
1984 /* JMP_BUF cannot be used here because if it doesn't get defined
1985 to jmp_buf we end up with a conflicting type error with the
1986 definition in compface.h */
1987 extern jmp_buf comp_env;
1991 mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1992 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1993 int dest_mask, Lisp_Object domain)
1995 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1997 char *p, *bits, *bp;
1998 const char * volatile emsg = 0;
1999 const char * volatile dstring;
2001 assert (!NILP (data));
2003 TO_EXTERNAL_FORMAT (LISP_STRING, data,
2004 C_STRING_ALLOCA, dstring,
2007 if ((p = strchr (dstring, ':')))
2012 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
2013 if (!(stattis = setjmp (comp_env)))
2015 UnCompAll ((char *) dstring);
2022 emsg = "uncompface: internal error";
2025 emsg = "uncompface: insufficient or invalid data";
2028 emsg = "uncompface: excess data ignored";
2033 signal_simple_error_2 (emsg, data, Qimage);
2035 bp = bits = (char *) alloca (PIXELS / 8);
2037 /* the compface library exports char F[], which uses a single byte per
2038 pixel to represent a 48x48 bitmap. Yuck. */
2039 for (i = 0, p = F; i < (PIXELS / 8); ++i)
2042 /* reverse the bit order of each byte... */
2043 for (b = n = 0; b < 8; ++b)
2050 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
2051 pointer_bg, dest_mask, 48, 48, bits);
2053 #endif /* HAVE_XFACE */
2056 /************************************************************************/
2057 /* image instance methods */
2058 /************************************************************************/
2061 mswindows_print_image_instance (Lisp_Image_Instance *p,
2062 Lisp_Object printcharfun,
2067 switch (IMAGE_INSTANCE_TYPE (p))
2069 case IMAGE_MONO_PIXMAP:
2070 case IMAGE_COLOR_PIXMAP:
2072 sprintf (buf, " (0x%lx",
2073 (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
2074 write_c_string (buf, printcharfun);
2075 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2077 sprintf (buf, "/0x%lx",
2078 (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2079 write_c_string (buf, printcharfun);
2081 write_c_string (")", printcharfun);
2089 #ifdef DEBUG_WIDGETS
2090 extern int debug_widget_instances;
2094 finalize_destroy_window (void *win)
2096 DestroyWindow ((HWND) win);
2100 mswindows_finalize_image_instance (Lisp_Image_Instance *p)
2105 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
2107 if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (p))
2108 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
2110 #ifdef DEBUG_WIDGETS
2111 debug_widget_instances--;
2112 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
2114 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2116 /* DestroyWindow is not safe here, as it will send messages
2117 to our window proc. */
2118 register_post_gc_action
2119 (finalize_destroy_window,
2120 (void *) (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)));
2121 register_post_gc_action
2122 (finalize_destroy_window,
2123 (void *) (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
2124 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
2130 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
2131 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
2133 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p))
2135 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
2137 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i))
2138 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i));
2139 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0;
2141 xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p));
2142 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0;
2144 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2145 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2146 IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0;
2147 if (IMAGE_INSTANCE_MSWINDOWS_ICON (p))
2148 DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p));
2149 IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0;
2160 /************************************************************************/
2161 /* subwindow and widget support */
2162 /************************************************************************/
2165 mswindows_widget_hfont (Lisp_Image_Instance *p,
2168 Lisp_Object face = IMAGE_INSTANCE_WIDGET_FACE (p);
2169 int under = FACE_UNDERLINE_P (face, domain);
2170 int strike = FACE_STRIKETHRU_P (face, domain);
2171 Lisp_Object font = query_string_font (IMAGE_INSTANCE_WIDGET_TEXT (p),
2174 return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike);
2178 begin_defer_window_pos (struct frame *f)
2180 #ifdef DEFER_WINDOW_POS
2181 if (FRAME_MSWINDOWS_DATA (f)->hdwp == 0)
2182 FRAME_MSWINDOWS_DATA (f)->hdwp = BeginDeferWindowPos (10);
2184 return FRAME_MSWINDOWS_DATA (f)->hdwp;
2187 /* unmap the image if it is a widget. This is used by redisplay via
2188 redisplay_unmap_subwindows */
2190 mswindows_unmap_subwindow (Lisp_Image_Instance *p)
2192 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2194 #ifdef DEFER_WINDOW_POS
2195 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2196 HDWP hdwp = begin_defer_window_pos (f);
2198 new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2201 SWP_HIDEWINDOW | SWP_NOACTIVATE |
2202 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
2203 /* Setting this flag causes the call to
2204 DeferWindowPos to fail with
2205 "Invalid parameter". I don't understand
2206 why we bother to try and set this
2208 /* | SWP_NOSENDCHANGING */
2211 mswindows_output_last_error ("unmapping");
2214 FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
2216 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2219 SWP_HIDEWINDOW | SWP_NOACTIVATE |
2220 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER );
2222 if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))
2223 SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
2227 /* map the subwindow. This is used by redisplay via
2228 redisplay_output_subwindow */
2230 mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2231 struct display_glyph_area* dga)
2233 #ifdef DEFER_WINDOW_POS
2234 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2235 HDWP hdwp = begin_defer_window_pos (f);
2238 /* move the window before mapping it ... */
2239 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2241 x, y, dga->width, dga->height,
2243 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2244 /* ... adjust the child ... */
2245 SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2247 -dga->xoffset, -dga->yoffset, 0, 0,
2248 SWP_NOZORDER | SWP_NOSIZE
2249 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2250 /* ... now map it - we are not allowed to move it at the same time. */
2251 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2253 #ifdef DEFER_WINDOW_POS
2254 new_hdwp = DeferWindowPos
2256 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2258 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2260 /* | SWP_NOCOPYBITS */
2261 /* Setting this flag causes the call to
2262 DeferWindowPos to fail with
2263 "Invalid parameter". I don't understand
2264 why we bother to try and set this
2266 /* | SWP_NOSENDCHANGING */
2269 mswindows_output_last_error ("mapping");
2272 FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
2274 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2277 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2278 | SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOACTIVATE);
2280 /* Doing this once does not seem to be enough, for instance when
2281 mapping the search dialog this gets called four times. If we
2282 only set on the first time through then the subwindow never
2283 gets focus as intended. However, doing this everytime doesn't
2284 seem so bad, after all we only need to redo this after the
2285 focus changes - and if that happens resetting the initial
2286 focus doesn't seem so bad. */
2287 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p))
2288 SetFocus (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
2293 /* resize the subwindow instance */
2295 mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h)
2297 /* Set the size of the control .... */
2298 if (!SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2301 SWP_NOZORDER | SWP_NOMOVE
2302 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING))
2303 mswindows_output_last_error ("resizing");
2306 /* Simply resize the window here. */
2308 mswindows_redisplay_subwindow (Lisp_Image_Instance *p)
2310 mswindows_resize_subwindow (p,
2311 IMAGE_INSTANCE_WIDTH (p),
2312 IMAGE_INSTANCE_HEIGHT (p));
2315 /* when you click on a widget you may activate another widget this
2316 needs to be checked and all appropriate widgets updated */
2318 mswindows_redisplay_widget (Lisp_Image_Instance *p)
2320 /* Possibly update the face font and colors. */
2321 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (p))
2322 && (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2323 || XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2324 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)))
2326 /* set the widget font from the widget face */
2327 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2329 (WPARAM) mswindows_widget_hfont
2330 (p, IMAGE_INSTANCE_FRAME (p)),
2331 MAKELPARAM (TRUE, 0));
2333 /* Possibly update the dimensions. */
2334 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2336 mswindows_resize_subwindow (p,
2337 IMAGE_INSTANCE_WIDTH (p),
2338 IMAGE_INSTANCE_HEIGHT (p));
2340 /* Possibly update the text in the widget. */
2341 if (IMAGE_INSTANCE_TEXT_CHANGED (p)
2342 && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (p)))
2345 TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p),
2346 C_STRING_ALLOCA, lparam,
2348 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2349 WM_SETTEXT, 0, (LPARAM)lparam);
2351 /* Set active state. */
2352 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2354 Lisp_Object item = IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p);
2355 LONG style = GetWindowLong
2356 (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2362 if (gui_item_active_p (item))
2363 SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2364 GWL_STYLE, style & ~WS_DISABLED);
2366 SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2367 GWL_STYLE, style | WS_DISABLED);
2371 /* register widgets into our hashtable so that we can cope with the
2372 callbacks. The hashtable is weak so deregistration is handled
2375 mswindows_register_gui_item (Lisp_Object image_instance,
2376 Lisp_Object gui, Lisp_Object domain)
2378 Lisp_Object frame = DOMAIN_FRAME (domain);
2379 struct frame* f = XFRAME (frame);
2380 int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f),
2383 Fputhash (make_int (id), image_instance,
2384 FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f));
2385 Fputhash (make_int (id), XGUI_ITEM (gui)->callback,
2386 FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f));
2387 Fputhash (make_int (id), XGUI_ITEM (gui)->callback_ex,
2388 FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f));
2393 mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
2395 return mswindows_register_gui_item (instance,
2396 XIMAGE_INSTANCE_WIDGET_ITEM (instance),
2401 mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2402 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2403 int dest_mask, Lisp_Object domain)
2405 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2406 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2407 Lisp_Object frame = DOMAIN_FRAME (domain);
2410 CHECK_MSWINDOWS_DEVICE (device);
2412 /* have to set the type this late in case there is no device
2413 instantiation for a widget */
2414 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2415 /* Allocate space for the clip window */
2416 ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2418 if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2421 XEMACS_CONTROL_CLASS,
2423 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2424 0, /* starting x position */
2425 0, /* starting y position */
2426 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2427 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2429 FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2431 NULL, /* must be null for this class */
2433 signal_simple_error ("window creation failed with code",
2434 make_int (GetLastError()));
2436 wnd = CreateWindow( "STATIC",
2439 0, /* starting x position */
2440 0, /* starting y position */
2441 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2442 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2443 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2446 GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2450 SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2451 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2455 mswindows_image_instance_equal (Lisp_Image_Instance *p1,
2456 Lisp_Image_Instance *p2, int depth)
2458 switch (IMAGE_INSTANCE_TYPE (p1))
2460 case IMAGE_MONO_PIXMAP:
2461 case IMAGE_COLOR_PIXMAP:
2463 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1)
2464 != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2))
2475 static unsigned long
2476 mswindows_image_instance_hash (Lisp_Image_Instance *p, int depth)
2478 switch (IMAGE_INSTANCE_TYPE (p))
2480 case IMAGE_MONO_PIXMAP:
2481 case IMAGE_COLOR_PIXMAP:
2483 return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p);
2490 /* Set all the slots in an image instance structure to reasonable
2491 default values. This is used somewhere within an instantiate
2492 method. It is assumed that the device slot within the image
2493 instance is already set -- this is the case when instantiate
2494 methods are called. */
2497 mswindows_initialize_dibitmap_image_instance (Lisp_Image_Instance *ii,
2499 enum image_instance_type type)
2501 ii->data = xnew_and_zero (struct mswindows_image_instance_data);
2502 IMAGE_INSTANCE_TYPE (ii) = type;
2503 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
2504 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
2505 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
2506 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
2507 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
2508 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
2509 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
2510 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) =
2511 xnew_array_and_zero (HBITMAP, slices);
2517 /************************************************************************/
2519 /************************************************************************/
2521 mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2522 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2523 int dest_mask, Lisp_Object domain,
2524 const char* class, int flags, int exflags)
2526 /* this function can call lisp */
2527 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2528 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
2529 Lisp_Object frame = DOMAIN_FRAME (domain);
2533 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2534 Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2536 CHECK_MSWINDOWS_DEVICE (device);
2538 if (!gui_item_active_p (gui))
2539 flags |= WS_DISABLED;
2541 style = pgui->style;
2543 if (!NILP (pgui->callback) || !NILP (pgui->callback_ex))
2545 id = mswindows_register_widget_instance (image_instance, domain);
2548 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2549 TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
2550 C_STRING_ALLOCA, nm,
2553 /* allocate space for the clip window and then allocate the clip window */
2554 ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2556 if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2558 WS_EX_CONTROLPARENT, /* EX flags */
2559 XEMACS_CONTROL_CLASS,
2561 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2562 0, /* starting x position */
2563 0, /* starting y position */
2564 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2565 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2567 DOMAIN_MSWINDOWS_HANDLE (domain),
2568 (HMENU)id, /* No menu */
2569 NULL, /* must be null for this class */
2571 signal_simple_error ("window creation failed with code",
2572 make_int (GetLastError()));
2574 if ((wnd = CreateWindowEx(
2575 exflags /* | WS_EX_NOPARENTNOTIFY*/,
2578 flags | WS_CHILD | WS_VISIBLE,
2579 0, /* starting x position */
2580 0, /* starting y position */
2581 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2582 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2584 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2585 (HMENU)id, /* No menu */
2588 (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2591 signal_simple_error ("window creation failed with code",
2592 make_int (GetLastError()));
2594 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2595 SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2596 /* set the widget font from the widget face */
2597 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2598 SendMessage (wnd, WM_SETFONT,
2599 (WPARAM) mswindows_widget_hfont (ii, domain),
2600 MAKELPARAM (TRUE, 0));
2603 /* Instantiate a native layout widget. */
2605 mswindows_native_layout_instantiate (Lisp_Object image_instance,
2606 Lisp_Object instantiator,
2607 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2608 int dest_mask, Lisp_Object domain)
2610 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2612 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2613 pointer_bg, dest_mask, domain, "STATIC",
2614 /* Approximation to styles available with
2615 an XEmacs layout. */
2616 (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
2618 EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
2620 GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
2621 ? SS_ETCHEDFRAME : SS_SUNKEN) | DS_CONTROL,
2625 /* Instantiate a button widget. Unfortunately instantiated widgets are
2626 particular to a frame since they need to have a parent. It's not
2627 like images where you just select the image into the context you
2628 want to display it in and BitBlt it. So image instances can have a
2629 many-to-one relationship with things you see, whereas widgets can
2630 only be one-to-one (i.e. per frame) */
2632 mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2633 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2634 int dest_mask, Lisp_Object domain)
2636 /* This function can call lisp */
2637 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2639 int flags = WS_TABSTOP | BS_NOTIFY;
2640 /* BS_NOTIFY #### is needed to get exotic feedback only. Since we
2641 seem to want nothing beyond BN_CLICK, the style is perhaps not
2644 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2645 Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2646 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2650 if (!IMAGE_INSTANCEP (glyph))
2651 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2653 if (IMAGE_INSTANCEP (glyph))
2654 flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2655 BS_BITMAP : BS_ICON;
2658 style = pgui->style;
2660 /* #### consider using the default face for radio and toggle
2662 if (EQ (style, Qradio))
2664 flags |= BS_RADIOBUTTON;
2666 else if (EQ (style, Qtoggle))
2668 flags |= BS_AUTOCHECKBOX;
2672 flags |= BS_DEFPUSHBUTTON;
2675 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2676 pointer_bg, dest_mask, domain, "BUTTON",
2679 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2680 /* set the checked state */
2681 if (gui_item_selected_p (gui))
2682 SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2684 SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2685 /* add the image if one was given */
2686 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2688 IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2690 SendMessage (wnd, BM_SETIMAGE,
2691 (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2692 IMAGE_BITMAP : IMAGE_ICON),
2693 (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2694 (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
2695 (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
2699 /* Update the state of a button. */
2701 mswindows_button_redisplay (Lisp_Object image_instance)
2703 /* This function can GC if IN_REDISPLAY is false. */
2704 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2706 /* buttons checked or otherwise */
2707 if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
2708 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2709 BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2711 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2712 BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2715 /* instantiate an edit control */
2717 mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2718 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2719 int dest_mask, Lisp_Object domain)
2721 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2722 pointer_bg, dest_mask, domain, "EDIT",
2723 ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP
2724 | WS_BORDER, WS_EX_CLIENTEDGE);
2727 /* instantiate a progress gauge */
2729 mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2730 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2731 int dest_mask, Lisp_Object domain)
2734 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2736 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2737 pointer_bg, dest_mask, domain, PROGRESS_CLASS,
2738 WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE);
2739 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2740 /* set the colors */
2741 #ifdef PBS_SETBKCOLOR
2742 SendMessage (wnd, PBS_SETBKCOLOR, 0,
2743 (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2746 (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2747 XIMAGE_INSTANCE_FRAME (ii))))));
2749 #ifdef PBS_SETBARCOLOR
2750 SendMessage (wnd, PBS_SETBARCOLOR, 0,
2751 (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2754 (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2755 XIMAGE_INSTANCE_FRAME (ii))))));
2757 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEMS (ii))->value;
2759 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2760 PBM_SETPOS, (WPARAM)XINT (val), 0);
2763 /* instantiate a tree view widget */
2764 static HTREEITEM add_tree_item (Lisp_Object image_instance,
2765 HWND wnd, HTREEITEM parent, Lisp_Object item,
2766 int children, Lisp_Object domain)
2768 TV_INSERTSTRUCT tvitem;
2771 tvitem.hParent = parent;
2772 tvitem.hInsertAfter = TVI_LAST;
2773 tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
2774 tvitem.item.cChildren = children;
2776 if (GUI_ITEMP (item))
2778 tvitem.item.lParam = mswindows_register_gui_item (image_instance,
2780 tvitem.item.mask |= TVIF_PARAM;
2781 TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2782 C_STRING_ALLOCA, tvitem.item.pszText,
2786 TO_EXTERNAL_FORMAT (LISP_STRING, item,
2787 C_STRING_ALLOCA, tvitem.item.pszText,
2790 tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
2792 if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM,
2793 0, (LPARAM)&tvitem)) == 0)
2794 signal_simple_error ("error adding tree view entry", item);
2799 static void add_tree_item_list (Lisp_Object image_instance,
2800 HWND wnd, HTREEITEM parent, Lisp_Object list,
2805 /* get the first item */
2806 parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
2807 /* recursively add items to the tree view */
2808 LIST_LOOP (rest, XCDR (list))
2810 if (LISTP (XCAR (rest)))
2811 add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2813 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2818 mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2819 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2820 int dest_mask, Lisp_Object domain)
2825 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2826 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2827 pointer_bg, dest_mask, domain, WC_TREEVIEW,
2828 WS_TABSTOP | WS_BORDER | PBS_SMOOTH
2829 | TVS_HASLINES | TVS_HASBUTTONS,
2832 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2835 parent = add_tree_item (image_instance, wnd, NULL,
2836 XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
2839 /* recursively add items to the tree view */
2840 /* add items to the tab */
2841 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2843 if (LISTP (XCAR (rest)))
2844 add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2846 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2850 /* Set the properties of a tree view. */
2852 mswindows_tree_view_redisplay (Lisp_Object image_instance)
2854 /* This function can GC if IN_REDISPLAY is false. */
2855 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2857 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2859 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2862 /* Delete previous items. */
2863 SendMessage (wnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
2865 parent = add_tree_item (image_instance, wnd, NULL,
2866 XCAR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)),
2867 TRUE, IMAGE_INSTANCE_DOMAIN (ii));
2869 /* recursively add items to the tree view */
2870 /* add items to the tab */
2871 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
2873 if (LISTP (XCAR (rest)))
2874 add_tree_item_list (image_instance, wnd, parent, XCAR (rest),
2875 IMAGE_INSTANCE_DOMAIN (ii));
2877 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE,
2878 IMAGE_INSTANCE_DOMAIN (ii));
2883 /* instantiate a tab control */
2885 add_tab_item (Lisp_Object image_instance,
2886 HWND wnd, Lisp_Object item,
2887 Lisp_Object domain, int i)
2892 tvitem.mask = TCIF_TEXT;
2894 if (GUI_ITEMP (item))
2896 tvitem.lParam = mswindows_register_gui_item (image_instance,
2898 tvitem.mask |= TCIF_PARAM;
2899 TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2900 C_STRING_ALLOCA, tvitem.pszText,
2905 CHECK_STRING (item);
2906 TO_EXTERNAL_FORMAT (LISP_STRING, item,
2907 C_STRING_ALLOCA, tvitem.pszText,
2911 tvitem.cchTextMax = strlen (tvitem.pszText);
2913 if ((ret = SendMessage (wnd, TCM_INSERTITEM,
2914 i, (LPARAM)&tvitem)) < 0)
2915 signal_simple_error ("error adding tab entry", item);
2921 mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2922 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2923 int dest_mask, Lisp_Object domain)
2925 /* This function can call lisp */
2928 int i = 0, selected = 0;
2929 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2930 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
2931 unsigned int flags = WS_TABSTOP;
2933 if (EQ (orient, Qleft) || EQ (orient, Qright))
2935 flags |= TCS_VERTICAL | TCS_MULTILINE;
2937 if (EQ (orient, Qright) || EQ (orient, Qbottom))
2939 flags |= TCS_BOTTOM;
2942 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2943 pointer_bg, dest_mask, domain, WC_TABCONTROL,
2944 /* borders don't suit tabs so well */
2946 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2947 /* add items to the tab */
2948 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2950 int idx = add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
2952 if (gui_item_selected_p (XCAR (rest)))
2956 SendMessage (wnd, TCM_SETCURSEL, selected, 0);
2959 /* Set the properties of a tab control. */
2961 mswindows_tab_control_redisplay (Lisp_Object image_instance)
2963 /* This function can GC if IN_REDISPLAY is false. */
2964 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2965 #ifdef DEBUG_WIDGET_OUTPUT
2966 stderr_out ("tab control %p redisplayed\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
2968 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2970 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2972 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2973 int i = 0, selected_idx = 0;
2976 assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2978 /* If only the order has changed then simply select the first
2979 one. This stops horrendous rebuilding of the tabs each time
2980 you click on one. */
2981 if (tab_control_order_only_changed (image_instance))
2983 Lisp_Object selected =
2984 gui_item_list_find_selected
2985 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2986 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2987 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2989 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2991 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2993 Lisp_Object old_selected = gui_item_list_find_selected
2994 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2996 /* Pick up the new selected item. */
2997 XGUI_ITEM (old_selected)->selected =
2998 XGUI_ITEM (XCAR (rest))->selected;
2999 XGUI_ITEM (XCAR (rest))->selected =
3000 XGUI_ITEM (selected)->selected;
3001 /* We're not actually changing the items. */
3002 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
3003 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
3005 SendMessage (wnd, TCM_SETCURSEL, i, 0);
3006 #ifdef DEBUG_WIDGET_OUTPUT
3007 stderr_out ("tab control %p selected item %d\n",
3008 IMAGE_INSTANCE_SUBWINDOW_ID (ii), i);
3017 /* delete the pre-existing items */
3018 SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
3020 /* add items to the tab */
3021 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
3023 add_tab_item (image_instance, wnd, XCAR (rest),
3024 IMAGE_INSTANCE_FRAME (ii), i);
3025 if (gui_item_selected_p (XCAR (rest)))
3029 SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0);
3034 /* instantiate a static control possible for putting other things in */
3036 mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3037 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3038 int dest_mask, Lisp_Object domain)
3040 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3041 pointer_bg, dest_mask, domain, "STATIC",
3042 0, WS_EX_STATICEDGE);
3045 /* instantiate a scrollbar control */
3047 mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3048 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3049 int dest_mask, Lisp_Object domain)
3051 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3052 pointer_bg, dest_mask, domain, "SCROLLBAR",
3053 WS_TABSTOP, WS_EX_CLIENTEDGE);
3056 /* instantiate a combo control */
3058 mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3059 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3060 int dest_mask, Lisp_Object domain)
3062 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3065 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
3068 /* Maybe ought to generalise this more but it may be very windows
3069 specific. In windows the window height of a combo box is the
3070 height when the combo box is open. Thus we need to set the height
3071 before creating the window and then reset it to a single line
3072 after the window is created so that redisplay does the right
3074 widget_instantiate (image_instance, instantiator, pointer_fg,
3075 pointer_bg, dest_mask, domain);
3077 /* We now have everything right apart from the height. */
3078 default_face_font_info (domain, 0, 0, &height, 0, 0);
3079 GET_LIST_LENGTH (items, len);
3081 height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len;
3082 IMAGE_INSTANCE_HEIGHT (ii) = height;
3084 /* Now create the widget. */
3085 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3086 pointer_bg, dest_mask, domain, "COMBOBOX",
3087 WS_BORDER | WS_TABSTOP | CBS_DROPDOWN
3089 | CBS_HASSTRINGS | WS_VSCROLL,
3091 /* Reset the height. layout will probably do this safely, but better make sure. */
3092 image_instance_layout (image_instance,
3093 IMAGE_UNSPECIFIED_GEOMETRY,
3094 IMAGE_UNSPECIFIED_GEOMETRY,
3095 IMAGE_UNCHANGED_GEOMETRY,
3096 IMAGE_UNCHANGED_GEOMETRY,
3099 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3100 /* add items to the combo box */
3101 SendMessage (wnd, CB_RESETCONTENT, 0, 0);
3102 LIST_LOOP (rest, items)
3105 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest),
3106 C_STRING_ALLOCA, lparam,
3108 if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR)
3109 signal_simple_error ("error adding combo entries", instantiator);
3113 /* get properties of a control */
3115 mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
3117 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3118 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3119 /* get the text from a control */
3120 if (EQ (prop, Q_text))
3122 Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
3123 Extbyte *buf = (Extbyte*) alloca (len+1);
3125 SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf);
3126 return build_ext_string (buf, Qnative);
3131 /* get properties of a button */
3133 mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
3135 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3136 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3137 /* check the state of a button */
3138 if (EQ (prop, Q_selected))
3140 if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
3148 /* get properties of a combo box */
3150 mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
3152 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3153 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3154 /* get the text from a control */
3155 if (EQ (prop, Q_text))
3157 long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
3158 Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
3159 Extbyte* buf = (Extbyte*) alloca (len+1);
3160 SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf);
3161 return build_ext_string (buf, Qnative);
3166 /* set the properties of a progress gauge */
3168 mswindows_progress_gauge_redisplay (Lisp_Object image_instance)
3170 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3172 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
3175 #ifdef ERROR_CHECK_GLYPHS
3176 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
3178 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
3179 #ifdef DEBUG_WIDGET_OUTPUT
3180 stderr_out ("progress gauge displayed value on %p updated to %ld\n",
3181 WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
3185 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
3186 PBM_SETPOS, (WPARAM)XINT (val), 0);
3191 mswindows_control_wnd_proc (HWND hwnd, UINT msg,
3192 WPARAM wParam, LPARAM lParam)
3198 case WM_CTLCOLORBTN:
3199 case WM_CTLCOLORLISTBOX:
3200 case WM_CTLCOLOREDIT:
3201 case WM_CTLCOLORSTATIC:
3202 case WM_CTLCOLORSCROLLBAR:
3204 return mswindows_wnd_proc (GetParent (hwnd), msg, wParam, lParam);
3206 return DefWindowProc (hwnd, msg, wParam, lParam);
3210 #endif /* HAVE_WIDGETS */
3213 /************************************************************************/
3214 /* initialization */
3215 /************************************************************************/
3218 syms_of_glyphs_mswindows (void)
3220 defkeyword (&Q_resource_id, ":resource-id");
3221 defkeyword (&Q_resource_type, ":resource-type");
3225 console_type_create_glyphs_mswindows (void)
3227 /* image methods - display */
3228 CONSOLE_HAS_METHOD (mswindows, print_image_instance);
3229 CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
3230 CONSOLE_HAS_METHOD (mswindows, unmap_subwindow);
3231 CONSOLE_HAS_METHOD (mswindows, map_subwindow);
3232 CONSOLE_HAS_METHOD (mswindows, redisplay_subwindow);
3233 CONSOLE_HAS_METHOD (mswindows, resize_subwindow);
3234 CONSOLE_HAS_METHOD (mswindows, redisplay_widget);
3235 CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
3236 CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
3237 CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
3238 CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
3240 /* image methods - printer */
3241 CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_image_instance);
3242 CONSOLE_INHERITS_METHOD (msprinter, mswindows, finalize_image_instance);
3243 CONSOLE_INHERITS_METHOD (msprinter, mswindows, image_instance_equal);
3244 CONSOLE_INHERITS_METHOD (msprinter, mswindows, image_instance_hash);
3245 CONSOLE_INHERITS_METHOD (msprinter, mswindows, init_image_instance_from_eimage);
3246 CONSOLE_INHERITS_METHOD (msprinter, mswindows, locate_pixmap_file);
3250 image_instantiator_format_create_glyphs_mswindows (void)
3252 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, nothing);
3253 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, string);
3254 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, formatted_string);
3255 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, inherit);
3256 /* image-instantiator types */
3257 INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm);
3258 INITIALIZE_DEVICE_IIFORMAT (msprinter, xbm);
3259 IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate);
3260 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xbm, instantiate);
3262 INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm);
3263 INITIALIZE_DEVICE_IIFORMAT (msprinter, xpm);
3264 IIFORMAT_HAS_DEVMETHOD (mswindows, xpm, instantiate);
3265 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xpm, instantiate);
3268 INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
3269 INITIALIZE_DEVICE_IIFORMAT (msprinter, xface);
3270 IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
3271 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xface, instantiate);
3274 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, jpeg);
3277 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, tiff);
3280 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, png);
3283 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, gif);
3286 INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
3287 IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
3289 IIFORMAT_VALID_CONSOLE (mswindows, layout);
3290 INITIALIZE_DEVICE_IIFORMAT (mswindows, native_layout);
3291 IIFORMAT_HAS_DEVMETHOD (mswindows, native_layout, instantiate);
3293 INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
3294 IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
3295 IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
3296 IIFORMAT_HAS_DEVMETHOD (mswindows, button, redisplay);
3297 /* edit-field widget */
3298 INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
3299 IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
3301 INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
3302 IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
3304 INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
3305 IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
3307 INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
3308 IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
3309 IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
3311 INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
3312 IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
3313 /* progress gauge */
3314 INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
3315 IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, redisplay);
3316 IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
3317 /* tree view widget */
3318 INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
3319 IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
3320 IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, redisplay);
3321 /* tab control widget */
3322 INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
3323 IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
3324 IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, redisplay);
3326 /* windows bitmap format */
3327 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
3328 IIFORMAT_HAS_METHOD (bmp, validate);
3329 IIFORMAT_HAS_METHOD (bmp, normalize);
3330 IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
3331 IIFORMAT_HAS_METHOD (bmp, instantiate);
3333 IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
3334 IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
3335 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, bmp);
3337 /* mswindows resources */
3338 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
3339 "mswindows-resource");
3341 IIFORMAT_HAS_METHOD (mswindows_resource, validate);
3342 IIFORMAT_HAS_METHOD (mswindows_resource, normalize);
3343 IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types);
3344 IIFORMAT_HAS_METHOD (mswindows_resource, instantiate);
3346 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type,
3347 check_valid_resource_symbol);
3348 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
3349 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
3350 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, mswindows_resource);
3354 vars_of_glyphs_mswindows (void)
3356 DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
3357 A list of the directories in which mswindows bitmap files may be found.
3358 This is used by the `make-image-instance' function.
3360 Vmswindows_bitmap_file_path = Qnil;
3364 complex_vars_of_glyphs_mswindows (void)