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