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 hex_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;
1497 hex_initialized = TRUE;
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 (hex_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 bite = offset[j];
1724 new_offset[j] = ~ (unsigned char)
1725 ((flip_table[bite & 0xf] << 4) + flip_table[bite >> 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 #ifndef __STDC__ /* Needed to avoid prototype warnings */
1983 #include <compface.h>
1987 /* JMP_BUF cannot be used here because if it doesn't get defined
1988 to jmp_buf we end up with a conflicting type error with the
1989 definition in compface.h */
1990 extern jmp_buf comp_env;
1994 mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1995 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1996 int dest_mask, Lisp_Object domain)
1998 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2000 char *p, *bits, *bp;
2001 const char * volatile emsg = 0;
2002 const char * volatile dstring;
2004 assert (!NILP (data));
2006 TO_EXTERNAL_FORMAT (LISP_STRING, data,
2007 C_STRING_ALLOCA, dstring,
2010 if ((p = strchr (dstring, ':')))
2015 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
2016 if (!(stattis = setjmp (comp_env)))
2018 UnCompAll ((char *) dstring);
2025 emsg = "uncompface: internal error";
2028 emsg = "uncompface: insufficient or invalid data";
2031 emsg = "uncompface: excess data ignored";
2036 signal_simple_error_2 (emsg, data, Qimage);
2038 bp = bits = (char *) alloca (PIXELS / 8);
2040 /* the compface library exports char F[], which uses a single byte per
2041 pixel to represent a 48x48 bitmap. Yuck. */
2042 for (i = 0, p = F; i < (PIXELS / 8); ++i)
2045 /* reverse the bit order of each byte... */
2046 for (b = n = 0; b < 8; ++b)
2053 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
2054 pointer_bg, dest_mask, 48, 48, bits);
2056 #endif /* HAVE_XFACE */
2059 /************************************************************************/
2060 /* image instance methods */
2061 /************************************************************************/
2064 mswindows_print_image_instance (Lisp_Image_Instance *p,
2065 Lisp_Object printcharfun,
2070 switch (IMAGE_INSTANCE_TYPE (p))
2072 case IMAGE_MONO_PIXMAP:
2073 case IMAGE_COLOR_PIXMAP:
2075 sprintf (buf, " (0x%lx",
2076 (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p));
2077 write_c_string (buf, printcharfun);
2078 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2080 sprintf (buf, "/0x%lx",
2081 (unsigned long) IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2082 write_c_string (buf, printcharfun);
2084 write_c_string (")", printcharfun);
2092 #ifdef DEBUG_WIDGETS
2093 extern int debug_widget_instances;
2097 finalize_destroy_window (void *win)
2099 DestroyWindow ((HWND) win);
2103 mswindows_finalize_image_instance (Lisp_Image_Instance *p)
2108 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
2110 if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (p))
2111 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
2113 #ifdef DEBUG_WIDGETS
2114 debug_widget_instances--;
2115 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
2117 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2119 /* DestroyWindow is not safe here, as it will send messages
2120 to our window proc. */
2121 register_post_gc_action
2122 (finalize_destroy_window,
2123 (void *) (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)));
2124 register_post_gc_action
2125 (finalize_destroy_window,
2126 (void *) (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
2127 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
2133 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
2134 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
2136 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p))
2138 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
2140 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i))
2141 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i));
2142 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0;
2144 xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p));
2145 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0;
2147 if (IMAGE_INSTANCE_MSWINDOWS_MASK (p))
2148 DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p));
2149 IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0;
2150 if (IMAGE_INSTANCE_MSWINDOWS_ICON (p))
2151 DestroyIcon (IMAGE_INSTANCE_MSWINDOWS_ICON (p));
2152 IMAGE_INSTANCE_MSWINDOWS_ICON (p) = 0;
2163 /************************************************************************/
2164 /* subwindow and widget support */
2165 /************************************************************************/
2168 mswindows_widget_hfont (Lisp_Image_Instance *p,
2171 Lisp_Object face = IMAGE_INSTANCE_WIDGET_FACE (p);
2172 int under = FACE_UNDERLINE_P (face, domain);
2173 int strike = FACE_STRIKETHRU_P (face, domain);
2174 Lisp_Object font = query_string_font (IMAGE_INSTANCE_WIDGET_TEXT (p),
2177 return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike);
2181 begin_defer_window_pos (struct frame *f)
2183 #ifdef DEFER_WINDOW_POS
2184 if (FRAME_MSWINDOWS_DATA (f)->hdwp == 0)
2185 FRAME_MSWINDOWS_DATA (f)->hdwp = BeginDeferWindowPos (10);
2187 return FRAME_MSWINDOWS_DATA (f)->hdwp;
2190 /* unmap the image if it is a widget. This is used by redisplay via
2191 redisplay_unmap_subwindows */
2193 mswindows_unmap_subwindow (Lisp_Image_Instance *p)
2195 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
2197 #ifdef DEFER_WINDOW_POS
2198 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2199 HDWP hdwp = begin_defer_window_pos (f);
2201 new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2204 SWP_HIDEWINDOW | SWP_NOACTIVATE |
2205 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
2206 /* Setting this flag causes the call to
2207 DeferWindowPos to fail with
2208 "Invalid parameter". I don't understand
2209 why we bother to try and set this
2211 /* | SWP_NOSENDCHANGING */
2214 mswindows_output_last_error ("unmapping");
2217 FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
2219 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2222 SWP_HIDEWINDOW | SWP_NOACTIVATE |
2223 SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER );
2225 if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))
2226 SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
2230 /* map the subwindow. This is used by redisplay via
2231 redisplay_output_subwindow */
2233 mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2234 struct display_glyph_area* dga)
2236 #ifdef DEFER_WINDOW_POS
2237 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2238 HDWP hdwp = begin_defer_window_pos (f);
2241 /* move the window before mapping it ... */
2242 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2244 x, y, dga->width, dga->height,
2246 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2247 /* ... adjust the child ... */
2248 SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2250 -dga->xoffset, -dga->yoffset, 0, 0,
2251 SWP_NOZORDER | SWP_NOSIZE
2252 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
2253 /* ... now map it - we are not allowed to move it at the same time. */
2254 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2256 #ifdef DEFER_WINDOW_POS
2257 new_hdwp = DeferWindowPos
2259 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2261 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2263 /* | SWP_NOCOPYBITS */
2264 /* Setting this flag causes the call to
2265 DeferWindowPos to fail with
2266 "Invalid parameter". I don't understand
2267 why we bother to try and set this
2269 /* | SWP_NOSENDCHANGING */
2272 mswindows_output_last_error ("mapping");
2275 FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
2277 SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
2280 SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
2281 | SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOACTIVATE);
2283 /* Doing this once does not seem to be enough, for instance when
2284 mapping the search dialog this gets called four times. If we
2285 only set on the first time through then the subwindow never
2286 gets focus as intended. However, doing this everytime doesn't
2287 seem so bad, after all we only need to redo this after the
2288 focus changes - and if that happens resetting the initial
2289 focus doesn't seem so bad. */
2290 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p))
2291 SetFocus (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
2296 /* resize the subwindow instance */
2298 mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h)
2300 /* Set the size of the control .... */
2301 if (!SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2304 SWP_NOZORDER | SWP_NOMOVE
2305 | SWP_NOCOPYBITS | SWP_NOSENDCHANGING))
2306 mswindows_output_last_error ("resizing");
2309 /* Simply resize the window here. */
2311 mswindows_redisplay_subwindow (Lisp_Image_Instance *p)
2313 mswindows_resize_subwindow (p,
2314 IMAGE_INSTANCE_WIDTH (p),
2315 IMAGE_INSTANCE_HEIGHT (p));
2318 /* when you click on a widget you may activate another widget this
2319 needs to be checked and all appropriate widgets updated */
2321 mswindows_redisplay_widget (Lisp_Image_Instance *p)
2323 /* Possibly update the face font and colors. */
2324 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (p))
2325 && (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2326 || XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2327 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)))
2329 /* set the widget font from the widget face */
2330 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2332 (WPARAM) mswindows_widget_hfont
2333 (p, IMAGE_INSTANCE_FRAME (p)),
2334 MAKELPARAM (TRUE, 0));
2336 /* Possibly update the dimensions. */
2337 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2339 mswindows_resize_subwindow (p,
2340 IMAGE_INSTANCE_WIDTH (p),
2341 IMAGE_INSTANCE_HEIGHT (p));
2343 /* Possibly update the text in the widget. */
2344 if (IMAGE_INSTANCE_TEXT_CHANGED (p)
2345 && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (p)))
2348 TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p),
2349 C_STRING_ALLOCA, lparam,
2351 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2352 WM_SETTEXT, 0, (LPARAM)lparam);
2354 /* Set active state. */
2355 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2357 Lisp_Object item = IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p);
2358 LONG style = GetWindowLong
2359 (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2365 if (gui_item_active_p (item))
2366 SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2367 GWL_STYLE, style & ~WS_DISABLED);
2369 SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
2370 GWL_STYLE, style | WS_DISABLED);
2374 /* Account for some of the limitations with widget images. */
2376 mswindows_widget_border_width (void)
2378 return DEFAULT_WIDGET_BORDER_WIDTH;
2381 /* register widgets into our hashtable so that we can cope with the
2382 callbacks. The hashtable is weak so deregistration is handled
2385 mswindows_register_gui_item (Lisp_Object image_instance,
2386 Lisp_Object gui, Lisp_Object domain)
2388 Lisp_Object frame = DOMAIN_FRAME (domain);
2389 struct frame* f = XFRAME (frame);
2390 int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f),
2393 Fputhash (make_int (id), image_instance,
2394 FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f));
2395 Fputhash (make_int (id), XGUI_ITEM (gui)->callback,
2396 FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f));
2397 Fputhash (make_int (id), XGUI_ITEM (gui)->callback_ex,
2398 FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f));
2403 mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
2405 return mswindows_register_gui_item (instance,
2406 XIMAGE_INSTANCE_WIDGET_ITEM (instance),
2411 mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2412 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2413 int dest_mask, Lisp_Object domain)
2415 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2416 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2417 Lisp_Object frame = DOMAIN_FRAME (domain);
2420 CHECK_MSWINDOWS_DEVICE (device);
2422 /* have to set the type this late in case there is no device
2423 instantiation for a widget */
2424 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2425 /* Allocate space for the clip window */
2426 ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2428 if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2431 XEMACS_CONTROL_CLASS,
2433 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2434 0, /* starting x position */
2435 0, /* starting y position */
2436 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2437 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2439 FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2441 NULL, /* must be null for this class */
2443 signal_simple_error ("window creation failed with code",
2444 make_int (GetLastError()));
2446 wnd = CreateWindow( "STATIC",
2449 0, /* starting x position */
2450 0, /* starting y position */
2451 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2452 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2453 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2456 GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2460 SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2461 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2465 mswindows_image_instance_equal (Lisp_Image_Instance *p1,
2466 Lisp_Image_Instance *p2, int depth)
2468 switch (IMAGE_INSTANCE_TYPE (p1))
2470 case IMAGE_MONO_PIXMAP:
2471 case IMAGE_COLOR_PIXMAP:
2473 if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p1)
2474 != IMAGE_INSTANCE_MSWINDOWS_BITMAP (p2))
2485 static unsigned long
2486 mswindows_image_instance_hash (Lisp_Image_Instance *p, int depth)
2488 switch (IMAGE_INSTANCE_TYPE (p))
2490 case IMAGE_MONO_PIXMAP:
2491 case IMAGE_COLOR_PIXMAP:
2493 return (unsigned long) IMAGE_INSTANCE_MSWINDOWS_BITMAP (p);
2500 /* Set all the slots in an image instance structure to reasonable
2501 default values. This is used somewhere within an instantiate
2502 method. It is assumed that the device slot within the image
2503 instance is already set -- this is the case when instantiate
2504 methods are called. */
2507 mswindows_initialize_dibitmap_image_instance (Lisp_Image_Instance *ii,
2509 enum image_instance_type type)
2511 ii->data = xnew_and_zero (struct mswindows_image_instance_data);
2512 IMAGE_INSTANCE_TYPE (ii) = type;
2513 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
2514 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
2515 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
2516 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
2517 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
2518 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
2519 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
2520 IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) =
2521 xnew_array_and_zero (HBITMAP, slices);
2527 /************************************************************************/
2529 /************************************************************************/
2531 mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2532 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2533 int dest_mask, Lisp_Object domain,
2534 const char* class, int flags, int exflags)
2536 /* this function can call lisp */
2537 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2538 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
2539 Lisp_Object frame = DOMAIN_FRAME (domain);
2543 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2544 Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2546 CHECK_MSWINDOWS_DEVICE (device);
2548 if (!gui_item_active_p (gui))
2549 flags |= WS_DISABLED;
2551 style = pgui->style;
2553 if (!NILP (pgui->callback) || !NILP (pgui->callback_ex))
2555 id = mswindows_register_widget_instance (image_instance, domain);
2558 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2559 TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
2560 C_STRING_ALLOCA, nm,
2563 /* allocate space for the clip window and then allocate the clip window */
2564 ii->data = xnew_and_zero (struct mswindows_subwindow_data);
2566 if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
2568 WS_EX_CONTROLPARENT, /* EX flags */
2569 XEMACS_CONTROL_CLASS,
2571 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
2572 0, /* starting x position */
2573 0, /* starting y position */
2574 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2575 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2577 DOMAIN_MSWINDOWS_HANDLE (domain),
2578 (HMENU)id, /* No menu */
2579 NULL, /* must be null for this class */
2581 signal_simple_error ("window creation failed with code",
2582 make_int (GetLastError()));
2584 if ((wnd = CreateWindowEx(
2585 exflags /* | WS_EX_NOPARENTNOTIFY*/,
2588 flags | WS_CHILD | WS_VISIBLE,
2589 0, /* starting x position */
2590 0, /* starting y position */
2591 IMAGE_INSTANCE_WIDGET_WIDTH (ii),
2592 IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
2594 IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
2595 (HMENU)id, /* No menu */
2598 (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
2601 signal_simple_error ("window creation failed with code",
2602 make_int (GetLastError()));
2604 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
2605 SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
2606 /* set the widget font from the widget face */
2607 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2608 SendMessage (wnd, WM_SETFONT,
2609 (WPARAM) mswindows_widget_hfont (ii, domain),
2610 MAKELPARAM (TRUE, 0));
2613 /* Instantiate a native layout widget. */
2615 mswindows_native_layout_instantiate (Lisp_Object image_instance,
2616 Lisp_Object instantiator,
2617 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2618 int dest_mask, Lisp_Object domain)
2620 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2622 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2623 pointer_bg, dest_mask, domain, "STATIC",
2624 /* Approximation to styles available with
2625 an XEmacs layout. */
2626 (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
2628 EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
2630 GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
2631 ? SS_ETCHEDFRAME : SS_SUNKEN) | DS_CONTROL,
2635 /* Instantiate a button widget. Unfortunately instantiated widgets are
2636 particular to a frame since they need to have a parent. It's not
2637 like images where you just select the image into the context you
2638 want to display it in and BitBlt it. So image instances can have a
2639 many-to-one relationship with things you see, whereas widgets can
2640 only be one-to-one (i.e. per frame) */
2642 mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2643 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2644 int dest_mask, Lisp_Object domain)
2646 /* This function can call lisp */
2647 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2649 int flags = WS_TABSTOP | BS_NOTIFY;
2650 /* BS_NOTIFY #### is needed to get exotic feedback only. Since we
2651 seem to want nothing beyond BN_CLICK, the style is perhaps not
2654 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2655 Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
2656 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2660 if (!IMAGE_INSTANCEP (glyph))
2661 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2663 if (IMAGE_INSTANCEP (glyph))
2664 flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2665 BS_BITMAP : BS_ICON;
2668 style = pgui->style;
2670 /* #### consider using the default face for radio and toggle
2672 if (EQ (style, Qradio))
2674 flags |= BS_RADIOBUTTON;
2676 else if (EQ (style, Qtoggle))
2678 flags |= BS_AUTOCHECKBOX;
2682 flags |= BS_DEFPUSHBUTTON;
2685 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2686 pointer_bg, dest_mask, domain, "BUTTON",
2689 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2690 /* set the checked state */
2691 if (gui_item_selected_p (gui))
2692 SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2694 SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2695 /* add the image if one was given */
2696 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2698 IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2700 SendMessage (wnd, BM_SETIMAGE,
2701 (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2702 IMAGE_BITMAP : IMAGE_ICON),
2703 (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
2704 (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
2705 (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
2709 /* Update the state of a button. */
2711 mswindows_button_redisplay (Lisp_Object image_instance)
2713 /* This function can GC if IN_REDISPLAY is false. */
2714 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2716 /* buttons checked or otherwise */
2717 if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
2718 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2719 BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2721 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2722 BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
2725 /* instantiate an edit control */
2727 mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2728 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2729 int dest_mask, Lisp_Object domain)
2731 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2732 pointer_bg, dest_mask, domain, "EDIT",
2733 ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP
2734 | WS_BORDER, WS_EX_CLIENTEDGE);
2737 /* instantiate a progress gauge */
2739 mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2740 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2741 int dest_mask, Lisp_Object domain)
2744 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2746 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2747 pointer_bg, dest_mask, domain, PROGRESS_CLASS,
2748 WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE);
2749 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2750 /* set the colors */
2751 #ifdef PBS_SETBKCOLOR
2752 SendMessage (wnd, PBS_SETBKCOLOR, 0,
2753 (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2756 (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2757 XIMAGE_INSTANCE_FRAME (ii))))));
2759 #ifdef PBS_SETBARCOLOR
2760 SendMessage (wnd, PBS_SETBARCOLOR, 0,
2761 (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
2764 (XIMAGE_INSTANCE_WIDGET_FACE (ii),
2765 XIMAGE_INSTANCE_FRAME (ii))))));
2767 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEMS (ii))->value;
2769 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
2770 PBM_SETPOS, (WPARAM)XINT (val), 0);
2773 /* instantiate a tree view widget */
2774 static HTREEITEM add_tree_item (Lisp_Object image_instance,
2775 HWND wnd, HTREEITEM parent, Lisp_Object item,
2776 int children, Lisp_Object domain)
2778 TV_INSERTSTRUCT tvitem;
2781 tvitem.hParent = parent;
2782 tvitem.hInsertAfter = TVI_LAST;
2783 tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
2784 tvitem.item.cChildren = children;
2786 if (GUI_ITEMP (item))
2788 tvitem.item.lParam = mswindows_register_gui_item (image_instance,
2790 tvitem.item.mask |= TVIF_PARAM;
2791 TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2792 C_STRING_ALLOCA, tvitem.item.pszText,
2796 TO_EXTERNAL_FORMAT (LISP_STRING, item,
2797 C_STRING_ALLOCA, tvitem.item.pszText,
2800 tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
2802 if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM,
2803 0, (LPARAM)&tvitem)) == 0)
2804 signal_simple_error ("error adding tree view entry", item);
2809 static void add_tree_item_list (Lisp_Object image_instance,
2810 HWND wnd, HTREEITEM parent, Lisp_Object list,
2815 /* get the first item */
2816 parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
2817 /* recursively add items to the tree view */
2818 LIST_LOOP (rest, XCDR (list))
2820 if (LISTP (XCAR (rest)))
2821 add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2823 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2828 mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2829 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2830 int dest_mask, Lisp_Object domain)
2835 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2836 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2837 pointer_bg, dest_mask, domain, WC_TREEVIEW,
2838 WS_TABSTOP | WS_BORDER | PBS_SMOOTH
2839 | TVS_HASLINES | TVS_HASBUTTONS,
2842 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2845 parent = add_tree_item (image_instance, wnd, NULL,
2846 XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
2849 /* recursively add items to the tree view */
2850 /* add items to the tab */
2851 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2853 if (LISTP (XCAR (rest)))
2854 add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
2856 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
2860 /* Set the properties of a tree view. */
2862 mswindows_tree_view_redisplay (Lisp_Object image_instance)
2864 /* This function can GC if IN_REDISPLAY is false. */
2865 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2867 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2869 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2872 /* Delete previous items. */
2873 SendMessage (wnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
2875 parent = add_tree_item (image_instance, wnd, NULL,
2876 XCAR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)),
2877 TRUE, IMAGE_INSTANCE_DOMAIN (ii));
2879 /* recursively add items to the tree view */
2880 /* add items to the tab */
2881 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
2883 if (LISTP (XCAR (rest)))
2884 add_tree_item_list (image_instance, wnd, parent, XCAR (rest),
2885 IMAGE_INSTANCE_DOMAIN (ii));
2887 add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE,
2888 IMAGE_INSTANCE_DOMAIN (ii));
2893 /* instantiate a tab control */
2895 add_tab_item (Lisp_Object image_instance,
2896 HWND wnd, Lisp_Object item,
2897 Lisp_Object domain, int i)
2902 tvitem.mask = TCIF_TEXT;
2904 if (GUI_ITEMP (item))
2906 tvitem.lParam = mswindows_register_gui_item (image_instance,
2908 tvitem.mask |= TCIF_PARAM;
2909 TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
2910 C_STRING_ALLOCA, tvitem.pszText,
2915 CHECK_STRING (item);
2916 TO_EXTERNAL_FORMAT (LISP_STRING, item,
2917 C_STRING_ALLOCA, tvitem.pszText,
2921 tvitem.cchTextMax = strlen (tvitem.pszText);
2923 if ((ret = SendMessage (wnd, TCM_INSERTITEM,
2924 i, (LPARAM)&tvitem)) < 0)
2925 signal_simple_error ("error adding tab entry", item);
2931 mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2932 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2933 int dest_mask, Lisp_Object domain)
2935 /* This function can call lisp */
2938 int i = 0, selected = 0;
2939 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2940 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
2941 unsigned int flags = WS_TABSTOP;
2943 if (EQ (orient, Qleft) || EQ (orient, Qright))
2945 flags |= TCS_VERTICAL | TCS_MULTILINE;
2947 if (EQ (orient, Qright) || EQ (orient, Qbottom))
2949 flags |= TCS_BOTTOM;
2952 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
2953 pointer_bg, dest_mask, domain, WC_TABCONTROL,
2954 /* borders don't suit tabs so well */
2956 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2957 /* add items to the tab */
2958 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2960 int idx = add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
2962 if (gui_item_selected_p (XCAR (rest)))
2966 SendMessage (wnd, TCM_SETCURSEL, selected, 0);
2969 /* Set the properties of a tab control. */
2971 mswindows_tab_control_redisplay (Lisp_Object image_instance)
2973 /* This function can GC if IN_REDISPLAY is false. */
2974 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2975 #ifdef DEBUG_WIDGET_OUTPUT
2976 stderr_out ("tab control %p redisplayed\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
2978 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2980 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2982 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
2983 int i = 0, selected_idx = 0;
2986 assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2988 /* If only the order has changed then simply select the first
2989 one. This stops horrendous rebuilding of the tabs each time
2990 you click on one. */
2991 if (tab_control_order_only_changed (image_instance))
2993 Lisp_Object selected =
2994 gui_item_list_find_selected
2995 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2996 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2997 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2999 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
3001 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
3003 Lisp_Object old_selected = gui_item_list_find_selected
3004 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
3006 /* Pick up the new selected item. */
3007 XGUI_ITEM (old_selected)->selected =
3008 XGUI_ITEM (XCAR (rest))->selected;
3009 XGUI_ITEM (XCAR (rest))->selected =
3010 XGUI_ITEM (selected)->selected;
3011 /* We're not actually changing the items. */
3012 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
3013 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
3015 SendMessage (wnd, TCM_SETCURSEL, i, 0);
3016 #ifdef DEBUG_WIDGET_OUTPUT
3017 stderr_out ("tab control %p selected item %d\n",
3018 IMAGE_INSTANCE_SUBWINDOW_ID (ii), i);
3027 /* delete the pre-existing items */
3028 SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
3030 /* add items to the tab */
3031 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
3033 add_tab_item (image_instance, wnd, XCAR (rest),
3034 IMAGE_INSTANCE_FRAME (ii), i);
3035 if (gui_item_selected_p (XCAR (rest)))
3039 SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0);
3044 /* instantiate a static control possible for putting other things in */
3046 mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3047 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3048 int dest_mask, Lisp_Object domain)
3050 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3051 pointer_bg, dest_mask, domain, "STATIC",
3052 0, WS_EX_STATICEDGE);
3055 /* instantiate a scrollbar control */
3057 mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3058 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3059 int dest_mask, Lisp_Object domain)
3061 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3062 pointer_bg, dest_mask, domain, "SCROLLBAR",
3063 WS_TABSTOP, WS_EX_CLIENTEDGE);
3066 /* instantiate a combo control */
3068 mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3069 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3070 int dest_mask, Lisp_Object domain)
3072 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3075 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
3078 /* Maybe ought to generalise this more but it may be very windows
3079 specific. In windows the window height of a combo box is the
3080 height when the combo box is open. Thus we need to set the height
3081 before creating the window and then reset it to a single line
3082 after the window is created so that redisplay does the right
3084 widget_instantiate (image_instance, instantiator, pointer_fg,
3085 pointer_bg, dest_mask, domain);
3087 /* We now have everything right apart from the height. */
3088 default_face_font_info (domain, 0, 0, &height, 0, 0);
3089 GET_LIST_LENGTH (items, len);
3091 height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len;
3092 IMAGE_INSTANCE_HEIGHT (ii) = height;
3094 /* Now create the widget. */
3095 mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
3096 pointer_bg, dest_mask, domain, "COMBOBOX",
3097 WS_BORDER | WS_TABSTOP | CBS_DROPDOWN
3099 | CBS_HASSTRINGS | WS_VSCROLL,
3101 /* Reset the height. layout will probably do this safely, but better make sure. */
3102 image_instance_layout (image_instance,
3103 IMAGE_UNSPECIFIED_GEOMETRY,
3104 IMAGE_UNSPECIFIED_GEOMETRY,
3105 IMAGE_UNCHANGED_GEOMETRY,
3106 IMAGE_UNCHANGED_GEOMETRY,
3109 wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3110 /* add items to the combo box */
3111 SendMessage (wnd, CB_RESETCONTENT, 0, 0);
3112 LIST_LOOP (rest, items)
3115 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest),
3116 C_STRING_ALLOCA, lparam,
3118 if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR)
3119 signal_simple_error ("error adding combo entries", instantiator);
3123 /* get properties of a control */
3125 mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
3127 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3128 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3129 /* get the text from a control */
3130 if (EQ (prop, Q_text))
3132 Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
3133 Extbyte *buf = (Extbyte*) alloca (len+1);
3135 SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf);
3136 return build_ext_string (buf, Qnative);
3141 /* get properties of a button */
3143 mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
3145 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3146 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3147 /* check the state of a button */
3148 if (EQ (prop, Q_selected))
3150 if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
3158 /* get properties of a combo box */
3160 mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
3162 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3163 HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
3164 /* get the text from a control */
3165 if (EQ (prop, Q_text))
3167 long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
3168 Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
3169 Extbyte* buf = (Extbyte*) alloca (len+1);
3170 SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf);
3171 return build_ext_string (buf, Qnative);
3176 /* set the properties of a progress gauge */
3178 mswindows_progress_gauge_redisplay (Lisp_Object image_instance)
3180 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3182 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
3185 #ifdef ERROR_CHECK_GLYPHS
3186 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
3188 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
3189 #ifdef DEBUG_WIDGET_OUTPUT
3190 stderr_out ("progress gauge displayed value on %p updated to %ld\n",
3191 WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
3195 SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
3196 PBM_SETPOS, (WPARAM)XINT (val), 0);
3201 mswindows_control_wnd_proc (HWND hwnd, UINT msg,
3202 WPARAM wParam, LPARAM lParam)
3208 case WM_CTLCOLORBTN:
3209 case WM_CTLCOLORLISTBOX:
3210 case WM_CTLCOLOREDIT:
3211 case WM_CTLCOLORSTATIC:
3212 case WM_CTLCOLORSCROLLBAR:
3214 return mswindows_wnd_proc (GetParent (hwnd), msg, wParam, lParam);
3216 return DefWindowProc (hwnd, msg, wParam, lParam);
3220 #endif /* HAVE_WIDGETS */
3223 /************************************************************************/
3224 /* initialization */
3225 /************************************************************************/
3228 syms_of_glyphs_mswindows (void)
3230 defkeyword (&Q_resource_id, ":resource-id");
3231 defkeyword (&Q_resource_type, ":resource-type");
3235 console_type_create_glyphs_mswindows (void)
3237 /* image methods - display */
3238 CONSOLE_HAS_METHOD (mswindows, print_image_instance);
3239 CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
3240 CONSOLE_HAS_METHOD (mswindows, unmap_subwindow);
3241 CONSOLE_HAS_METHOD (mswindows, map_subwindow);
3242 CONSOLE_HAS_METHOD (mswindows, redisplay_subwindow);
3243 CONSOLE_HAS_METHOD (mswindows, resize_subwindow);
3244 CONSOLE_HAS_METHOD (mswindows, redisplay_widget);
3245 CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
3246 CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
3247 CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
3248 CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
3249 CONSOLE_HAS_METHOD (mswindows, widget_border_width);
3251 /* image methods - printer */
3252 CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_image_instance);
3253 CONSOLE_INHERITS_METHOD (msprinter, mswindows, finalize_image_instance);
3254 CONSOLE_INHERITS_METHOD (msprinter, mswindows, image_instance_equal);
3255 CONSOLE_INHERITS_METHOD (msprinter, mswindows, image_instance_hash);
3256 CONSOLE_INHERITS_METHOD (msprinter, mswindows, init_image_instance_from_eimage);
3257 CONSOLE_INHERITS_METHOD (msprinter, mswindows, locate_pixmap_file);
3261 image_instantiator_format_create_glyphs_mswindows (void)
3263 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, nothing);
3264 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, string);
3265 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, formatted_string);
3266 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, inherit);
3267 /* image-instantiator types */
3268 INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm);
3269 INITIALIZE_DEVICE_IIFORMAT (msprinter, xbm);
3270 IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate);
3271 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xbm, instantiate);
3273 INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm);
3274 INITIALIZE_DEVICE_IIFORMAT (msprinter, xpm);
3275 IIFORMAT_HAS_DEVMETHOD (mswindows, xpm, instantiate);
3276 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xpm, instantiate);
3279 INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
3280 INITIALIZE_DEVICE_IIFORMAT (msprinter, xface);
3281 IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
3282 IIFORMAT_INHERITS_DEVMETHOD (msprinter, mswindows, xface, instantiate);
3285 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, jpeg);
3288 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, tiff);
3291 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, png);
3294 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, gif);
3297 INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
3298 IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
3300 IIFORMAT_VALID_CONSOLE (mswindows, layout);
3301 INITIALIZE_DEVICE_IIFORMAT (mswindows, native_layout);
3302 IIFORMAT_HAS_DEVMETHOD (mswindows, native_layout, instantiate);
3304 INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
3305 IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
3306 IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
3307 IIFORMAT_HAS_DEVMETHOD (mswindows, button, redisplay);
3308 /* edit-field widget */
3309 INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
3310 IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
3312 INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
3313 IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
3315 INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
3316 IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
3318 INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
3319 IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
3320 IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
3322 INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
3323 IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
3324 /* progress gauge */
3325 INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
3326 IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, redisplay);
3327 IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
3328 /* tree view widget */
3329 INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
3330 IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
3331 IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, redisplay);
3332 /* tab control widget */
3333 INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
3334 IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
3335 IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, redisplay);
3337 /* windows bitmap format */
3338 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
3339 IIFORMAT_HAS_METHOD (bmp, validate);
3340 IIFORMAT_HAS_METHOD (bmp, normalize);
3341 IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
3342 IIFORMAT_HAS_METHOD (bmp, instantiate);
3344 IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
3345 IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
3346 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, bmp);
3348 /* mswindows resources */
3349 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
3350 "mswindows-resource");
3352 IIFORMAT_HAS_METHOD (mswindows_resource, validate);
3353 IIFORMAT_HAS_METHOD (mswindows_resource, normalize);
3354 IIFORMAT_HAS_METHOD (mswindows_resource, possible_dest_types);
3355 IIFORMAT_HAS_METHOD (mswindows_resource, instantiate);
3357 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_type,
3358 check_valid_resource_symbol);
3359 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
3360 IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
3361 IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, mswindows_resource);
3365 vars_of_glyphs_mswindows (void)
3367 DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
3368 A list of the directories in which mswindows bitmap files may be found.
3369 This is used by the `make-image-instance' function.
3371 Vmswindows_bitmap_file_path = Qnil;
3375 complex_vars_of_glyphs_mswindows (void)