Mercurial > hg > xemacs-beta
annotate src/glyphs-x.c @ 4528:726060ee587c g++-warning-removal-2008-10-28
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
author | Stephen J. Turnbull <stephen@xemacs.org> |
---|---|
date | Wed, 29 Oct 2008 04:06:33 +0900 |
parents | fc7067b7f407 |
children | 5460287a3327 |
rev | line source |
---|---|
428 | 1 /* X-specific Lisp objects. |
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
4 Copyright (C) 1995 Tinker Systems | |
2959 | 5 Copyright (C) 1995, 1996, 2001, 2002, 2003, 2004, 2005 Ben Wing |
428 | 6 Copyright (C) 1995 Sun Microsystems |
863 | 7 Copyright (C) 1999, 2000, 2002 Andy Piper |
428 | 8 |
9 This file is part of XEmacs. | |
10 | |
11 XEmacs is free software; you can redistribute it and/or modify it | |
12 under the terms of the GNU General Public License as published by the | |
13 Free Software Foundation; either version 2, or (at your option) any | |
14 later version. | |
15 | |
16 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
19 for more details. | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
1204 | 27 /* 7-8-00 This file is more or less Mule-ized. */ |
442 | 28 |
428 | 29 /* Original author: Jamie Zawinski for 19.8 |
30 font-truename stuff added by Jamie Zawinski for 19.10 | |
31 subwindow support added by Chuck Thompson | |
32 additional XPM support added by Chuck Thompson | |
33 initial X-Face support added by Stig | |
34 rewritten/restructured by Ben Wing for 19.12/19.13 | |
35 GIF/JPEG support added by Ben Wing for 19.14 | |
36 PNG support added by Bill Perry for 19.14 | |
37 Improved GIF/JPEG support added by Bill Perry for 19.14 | |
38 Cleanup/simplification of error handling by Ben Wing for 19.14 | |
39 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 | |
40 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0 | |
41 Many changes for color work and optimizations by Jareth Hein for 21.0 | |
42 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0 | |
43 TIFF code by Jareth Hein for 21.0 | |
44 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0 | |
45 Subwindow and Widget support by Andy Piper for 21.2 | |
46 | |
47 TODO: | |
430 | 48 Support the GrayScale, StaticColor and StaticGray visual classes. |
428 | 49 Convert images.el to C and stick it in here? |
50 */ | |
51 | |
771 | 52 /* Mule-ized last 6-22-00 */ |
53 | |
428 | 54 #include <config.h> |
55 #include "lisp.h" | |
800 | 56 |
57 #include "buffer.h" | |
872 | 58 #include "device-impl.h" |
800 | 59 #include "faces.h" |
60 #include "file-coding.h" | |
872 | 61 #include "frame-impl.h" |
800 | 62 #include "gui.h" |
63 #include "imgproc.h" | |
64 #include "insdel.h" | |
428 | 65 #include "lstream.h" |
800 | 66 #include "opaque.h" |
872 | 67 #include "process.h" /* egetenv() */ |
800 | 68 #include "window.h" |
69 | |
872 | 70 #include "console-x-impl.h" |
428 | 71 #include "glyphs-x.h" |
872 | 72 #include "objects-x-impl.h" |
428 | 73 #include "xmu.h" |
74 | |
75 #include "sysfile.h" | |
771 | 76 #include "sysproc.h" /* for qxe_getpid() */ |
428 | 77 |
78 #include <setjmp.h> | |
79 | |
80 #ifdef LWLIB_WIDGETS_MOTIF | |
1315 | 81 #include "xmotif.h" |
639 | 82 #include <Xm/Scale.h> |
428 | 83 #endif |
84 #include <X11/IntrinsicP.h> | |
85 | |
86 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) | |
87 | |
88 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); | |
89 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); | |
90 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); | |
91 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); | |
92 #ifdef HAVE_JPEG | |
93 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); | |
94 #endif | |
95 #ifdef HAVE_TIFF | |
96 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff); | |
438 | 97 #endif |
428 | 98 #ifdef HAVE_PNG |
99 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png); | |
438 | 100 #endif |
428 | 101 #ifdef HAVE_GIF |
102 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif); | |
438 | 103 #endif |
428 | 104 #ifdef HAVE_XPM |
105 DEFINE_DEVICE_IIFORMAT (x, xpm); | |
106 #endif | |
107 DEFINE_DEVICE_IIFORMAT (x, xbm); | |
108 DEFINE_DEVICE_IIFORMAT (x, subwindow); | |
109 #ifdef HAVE_XFACE | |
110 DEFINE_DEVICE_IIFORMAT (x, xface); | |
111 #endif | |
112 | |
113 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); | |
114 Lisp_Object Qcursor_font; | |
115 | |
116 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font); | |
117 | |
118 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect); | |
119 | |
771 | 120 #ifdef HAVE_X_WIDGETS |
442 | 121 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); |
428 | 122 DEFINE_DEVICE_IIFORMAT (x, widget); |
442 | 123 DEFINE_DEVICE_IIFORMAT (x, native_layout); |
428 | 124 DEFINE_DEVICE_IIFORMAT (x, button); |
125 DEFINE_DEVICE_IIFORMAT (x, progress_gauge); | |
126 DEFINE_DEVICE_IIFORMAT (x, edit_field); | |
127 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 | |
128 DEFINE_DEVICE_IIFORMAT (x, combo_box); | |
129 #endif | |
130 DEFINE_DEVICE_IIFORMAT (x, tab_control); | |
131 DEFINE_DEVICE_IIFORMAT (x, label); | |
132 #endif | |
133 | |
134 static void cursor_font_instantiate (Lisp_Object image_instance, | |
135 Lisp_Object instantiator, | |
136 Lisp_Object pointer_fg, | |
137 Lisp_Object pointer_bg, | |
138 int dest_mask, | |
139 Lisp_Object domain); | |
140 | |
771 | 141 #ifdef HAVE_X_WIDGETS |
1111 | 142 static void update_widget_face (widget_value* wv, |
143 Lisp_Image_Instance* ii, Lisp_Object domain); | |
144 static void update_tab_widget_face (widget_value* wv, | |
145 Lisp_Image_Instance* ii, | |
146 Lisp_Object domain); | |
428 | 147 #endif |
1111 | 148 void emacs_Xt_handle_widget_losing_focus (struct frame* f, |
149 Widget losing_widget); | |
150 void emacs_Xt_enqueue_focus_event (Widget wants_it, Lisp_Object frame, | |
151 int in_p); | |
428 | 152 |
153 #include "bitmaps.h" | |
154 | |
155 | |
156 /************************************************************************/ | |
157 /* image instance methods */ | |
158 /************************************************************************/ | |
159 | |
160 /************************************************************************/ | |
161 /* convert from a series of RGB triples to an XImage formated for the */ | |
4252 | 162 /* proper display */ |
428 | 163 /************************************************************************/ |
164 static XImage * | |
165 convert_EImage_to_XImage (Lisp_Object device, int width, int height, | |
2367 | 166 Binbyte *pic, unsigned long **pixtbl, |
428 | 167 int *npixels) |
168 { | |
169 Display *dpy; | |
170 Colormap cmap; | |
171 Visual *vis; | |
172 XImage *outimg; | |
173 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j; | |
174 int rd,gr,bl,q; | |
2367 | 175 Binbyte *data, *ip, *dp; |
428 | 176 quant_table *qtable = 0; |
177 union { | |
826 | 178 UINT_32_BIT val; |
428 | 179 char cp[4]; |
180 } conv; | |
181 | |
182 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
183 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
184 vis = DEVICE_X_VISUAL (XDEVICE(device)); | |
185 depth = DEVICE_X_DEPTH(XDEVICE(device)); | |
186 | |
1204 | 187 if (vis->X_CLASSFIELD == GrayScale || vis->X_CLASSFIELD == StaticColor || |
188 vis->X_CLASSFIELD == StaticGray) | |
430 | 189 { |
190 /* #### Implement me!!! */ | |
191 return NULL; | |
192 } | |
193 | |
1204 | 194 if (vis->X_CLASSFIELD == PseudoColor) |
428 | 195 { |
196 /* Quantize the image and get a histogram while we're at it. | |
197 Do this first to save memory */ | |
198 qtable = build_EImage_quantable(pic, width, height, 256); | |
199 if (qtable == NULL) return NULL; | |
200 } | |
201 | |
202 bitmap_pad = ((depth > 16) ? 32 : | |
203 (depth > 8) ? 16 : | |
204 8); | |
205 | |
206 outimg = XCreateImage (dpy, vis, | |
207 depth, ZPixmap, 0, 0, width, height, | |
208 bitmap_pad, 0); | |
209 if (!outimg) return NULL; | |
210 | |
211 bits_per_pixel = outimg->bits_per_pixel; | |
212 byte_cnt = bits_per_pixel >> 3; | |
213 | |
2367 | 214 data = xnew_binbytes (outimg->bytes_per_line * height); |
428 | 215 if (!data) |
216 { | |
217 XDestroyImage (outimg); | |
218 return NULL; | |
219 } | |
220 outimg->data = (char *) data; | |
221 | |
1204 | 222 if (vis->X_CLASSFIELD == PseudoColor) |
428 | 223 { |
224 unsigned long pixarray[256]; | |
225 int pixcount, n; | |
226 /* use our quantize table to allocate the colors */ | |
227 pixcount = 32; | |
228 *pixtbl = xnew_array (unsigned long, pixcount); | |
229 *npixels = 0; | |
230 | |
440 | 231 /* #### should implement a sort by popularity to assure proper allocation */ |
428 | 232 n = *npixels; |
233 for (i = 0; i < qtable->num_active_colors; i++) | |
234 { | |
235 XColor color; | |
236 int res; | |
237 | |
238 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0; | |
239 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0; | |
240 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0; | |
241 color.flags = DoRed | DoGreen | DoBlue; | |
3094 | 242 res = x_allocate_nearest_color (dpy, cmap, vis, &color); |
428 | 243 if (res > 0 && res < 3) |
244 { | |
245 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long); | |
246 (*pixtbl)[n] = color.pixel; | |
247 n++; | |
248 } | |
249 pixarray[i] = color.pixel; | |
250 } | |
251 *npixels = n; | |
252 ip = pic; | |
253 for (i = 0; i < height; i++) | |
254 { | |
255 dp = data + (i * outimg->bytes_per_line); | |
256 for (j = 0; j < width; j++) | |
257 { | |
258 rd = *ip++; | |
259 gr = *ip++; | |
260 bl = *ip++; | |
261 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)]; | |
442 | 262 #ifdef WORDS_BIGENDIAN |
428 | 263 if (outimg->byte_order == MSBFirst) |
264 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
265 else | |
266 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
267 #else | |
268 if (outimg->byte_order == MSBFirst) | |
269 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
270 else | |
271 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
272 #endif | |
273 } | |
274 } | |
1726 | 275 xfree (qtable, quant_table *); |
428 | 276 } else { |
277 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk; | |
278 junk = vis->red_mask; | |
279 rshift = 0; | |
280 while ((junk & 0x1) == 0) | |
281 { | |
282 junk = junk >> 1; | |
283 rshift ++; | |
284 } | |
285 rbits = 0; | |
286 while (junk != 0) | |
287 { | |
288 junk = junk >> 1; | |
289 rbits++; | |
290 } | |
291 junk = vis->green_mask; | |
292 gshift = 0; | |
293 while ((junk & 0x1) == 0) | |
294 { | |
295 junk = junk >> 1; | |
296 gshift ++; | |
297 } | |
298 gbits = 0; | |
299 while (junk != 0) | |
300 { | |
301 junk = junk >> 1; | |
302 gbits++; | |
303 } | |
304 junk = vis->blue_mask; | |
305 bshift = 0; | |
306 while ((junk & 0x1) == 0) | |
307 { | |
308 junk = junk >> 1; | |
309 bshift ++; | |
310 } | |
311 bbits = 0; | |
312 while (junk != 0) | |
313 { | |
314 junk = junk >> 1; | |
315 bbits++; | |
316 } | |
317 ip = pic; | |
318 for (i = 0; i < height; i++) | |
319 { | |
320 dp = data + (i * outimg->bytes_per_line); | |
321 for (j = 0; j < width; j++) | |
322 { | |
323 if (rbits > 8) | |
324 rd = *ip++ << (rbits - 8); | |
325 else | |
326 rd = *ip++ >> (8 - rbits); | |
327 if (gbits > 8) | |
328 gr = *ip++ << (gbits - 8); | |
329 else | |
330 gr = *ip++ >> (8 - gbits); | |
331 if (bbits > 8) | |
332 bl = *ip++ << (bbits - 8); | |
333 else | |
334 bl = *ip++ >> (8 - bbits); | |
335 | |
336 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift); | |
442 | 337 #ifdef WORDS_BIGENDIAN |
428 | 338 if (outimg->byte_order == MSBFirst) |
339 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q]; | |
340 else | |
341 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q]; | |
342 #else | |
343 if (outimg->byte_order == MSBFirst) | |
344 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q]; | |
345 else | |
346 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q]; | |
347 #endif | |
348 } | |
349 } | |
350 } | |
351 return outimg; | |
352 } | |
353 | |
354 | |
355 | |
356 static void | |
440 | 357 x_print_image_instance (Lisp_Image_Instance *p, |
428 | 358 Lisp_Object printcharfun, |
2286 | 359 int UNUSED (escapeflag)) |
428 | 360 { |
361 switch (IMAGE_INSTANCE_TYPE (p)) | |
362 { | |
363 case IMAGE_MONO_PIXMAP: | |
364 case IMAGE_COLOR_PIXMAP: | |
365 case IMAGE_POINTER: | |
800 | 366 write_fmt_string (printcharfun, " (0x%lx", |
367 (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p)); | |
428 | 368 if (IMAGE_INSTANCE_X_MASK (p)) |
369 { | |
800 | 370 write_fmt_string (printcharfun, "/0x%lx", |
371 (unsigned long) IMAGE_INSTANCE_X_MASK (p)); | |
428 | 372 } |
826 | 373 write_c_string (printcharfun, ")"); |
428 | 374 break; |
375 default: | |
376 break; | |
377 } | |
378 } | |
379 | |
380 #ifdef DEBUG_WIDGETS | |
381 extern int debug_widget_instances; | |
382 #endif | |
383 | |
384 static void | |
440 | 385 x_finalize_image_instance (Lisp_Image_Instance *p) |
428 | 386 { |
387 if (!p->data) | |
388 return; | |
389 | |
442 | 390 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))) |
428 | 391 { |
442 | 392 Display *dpy = DEVICE_X_DISPLAY |
393 (XDEVICE (IMAGE_INSTANCE_DEVICE (p))); | |
394 if (0) | |
395 ; | |
771 | 396 #ifdef HAVE_X_WIDGETS |
442 | 397 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) |
428 | 398 { |
399 if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) | |
400 { | |
401 #ifdef DEBUG_WIDGETS | |
402 debug_widget_instances--; | |
403 stderr_out ("widget destroyed, %d left\n", debug_widget_instances); | |
404 #endif | |
405 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p)); | |
406 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); | |
442 | 407 |
408 /* We can release the callbacks again. */ | |
409 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p)); | |
410 | |
411 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0; | |
412 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0; | |
428 | 413 } |
414 } | |
442 | 415 #endif |
428 | 416 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) |
417 { | |
418 if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) | |
419 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p)); | |
420 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; | |
421 } | |
422 else | |
423 { | |
424 int i; | |
425 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) | |
426 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); | |
427 | |
428 if (IMAGE_INSTANCE_X_MASK (p) && | |
429 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p)) | |
430 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p)); | |
431 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; | |
438 | 432 |
428 | 433 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p)) |
434 { | |
435 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) | |
436 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i)) | |
437 { | |
438 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i)); | |
439 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0; | |
440 } | |
1726 | 441 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p), Pixmap *); |
428 | 442 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0; |
443 } | |
444 | |
445 if (IMAGE_INSTANCE_X_CURSOR (p)) | |
446 { | |
447 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p)); | |
448 IMAGE_INSTANCE_X_CURSOR (p) = 0; | |
449 } | |
438 | 450 |
428 | 451 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0) |
452 { | |
453 XFreeColors (dpy, | |
454 IMAGE_INSTANCE_X_COLORMAP (p), | |
455 IMAGE_INSTANCE_X_PIXELS (p), | |
456 IMAGE_INSTANCE_X_NPIXELS (p), 0); | |
457 IMAGE_INSTANCE_X_NPIXELS (p) = 0; | |
458 } | |
459 } | |
460 } | |
461 /* You can sometimes have pixels without a live device. I forget | |
462 why, but that's why we free them here if we have a pixmap type | |
463 image instance. It probably means that we might also get a memory | |
464 leak with widgets. */ | |
465 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET | |
466 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW | |
467 && IMAGE_INSTANCE_X_PIXELS (p)) | |
468 { | |
1726 | 469 xfree (IMAGE_INSTANCE_X_PIXELS (p), unsigned long *); |
428 | 470 IMAGE_INSTANCE_X_PIXELS (p) = 0; |
471 } | |
472 | |
1726 | 473 xfree (p->data, void *); |
428 | 474 p->data = 0; |
475 } | |
476 | |
477 static int | |
440 | 478 x_image_instance_equal (Lisp_Image_Instance *p1, |
2286 | 479 Lisp_Image_Instance *p2, int UNUSED (depth)) |
428 | 480 { |
481 switch (IMAGE_INSTANCE_TYPE (p1)) | |
482 { | |
483 case IMAGE_MONO_PIXMAP: | |
484 case IMAGE_COLOR_PIXMAP: | |
485 case IMAGE_POINTER: | |
486 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) || | |
487 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2)) | |
488 return 0; | |
489 break; | |
490 default: | |
491 break; | |
492 } | |
493 | |
494 return 1; | |
495 } | |
496 | |
665 | 497 static Hashcode |
2286 | 498 x_image_instance_hash (Lisp_Image_Instance *p, int UNUSED (depth)) |
428 | 499 { |
500 switch (IMAGE_INSTANCE_TYPE (p)) | |
501 { | |
502 case IMAGE_MONO_PIXMAP: | |
503 case IMAGE_COLOR_PIXMAP: | |
504 case IMAGE_POINTER: | |
505 return IMAGE_INSTANCE_X_NPIXELS (p); | |
506 default: | |
507 return 0; | |
508 } | |
509 } | |
510 | |
511 /* Set all the slots in an image instance structure to reasonable | |
512 default values. This is used somewhere within an instantiate | |
513 method. It is assumed that the device slot within the image | |
514 instance is already set -- this is the case when instantiate | |
515 methods are called. */ | |
516 | |
517 static void | |
440 | 518 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii, |
428 | 519 int slices, |
520 enum image_instance_type type) | |
521 { | |
522 ii->data = xnew_and_zero (struct x_image_instance_data); | |
523 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; | |
438 | 524 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) = |
428 | 525 xnew_array_and_zero (Pixmap, slices); |
526 IMAGE_INSTANCE_TYPE (ii) = type; | |
527 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; | |
528 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; | |
529 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil; | |
530 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; | |
531 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; | |
532 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; | |
533 } | |
534 | |
535 | |
536 /************************************************************************/ | |
537 /* pixmap file functions */ | |
538 /************************************************************************/ | |
539 | |
540 /* Where bitmaps are; initialized from resource database */ | |
541 Lisp_Object Vx_bitmap_file_path; | |
542 | |
543 #ifndef BITMAPDIR | |
544 #define BITMAPDIR "/usr/include/X11/bitmaps" | |
545 #endif | |
546 | |
547 #define USE_XBMLANGPATH | |
548 | |
549 /* Given a pixmap filename, look through all of the "standard" places | |
550 where the file might be located. Return a full pathname if found; | |
551 otherwise, return Qnil. */ | |
552 | |
4226 | 553 /* #### FIXME: when Qnil is returned, the caller can't make a difference |
554 #### between a non existing X device, an unreadable file, or an actual | |
555 #### failure to locate the file, so the issued message is really not | |
556 #### informative. -- dvl */ | |
428 | 557 static Lisp_Object |
558 x_locate_pixmap_file (Lisp_Object name) | |
559 { | |
560 /* This function can GC if IN_REDISPLAY is false */ | |
561 Display *display; | |
562 | |
563 /* #### Unix-specific */ | |
4226 | 564 if (string_byte (name, 0) == '~' || |
565 string_byte (name, 0) == '/' || | |
826 | 566 (string_byte (name, 0) == '.' && |
567 (string_byte (name, 1) == '/' || | |
568 (string_byte (name, 1) == '.' && | |
569 (string_byte (name, 2) == '/'))))) | |
428 | 570 { |
571 if (!NILP (Ffile_readable_p (name))) | |
440 | 572 return Fexpand_file_name (name, Qnil); |
428 | 573 else |
574 return Qnil; | |
575 } | |
576 | |
4226 | 577 /* Check non-absolute pathnames with a directory component relative to |
578 the search path; that's the way Xt does it. */ | |
872 | 579 { |
580 Lisp_Object defx = get_default_device (Qx); | |
581 if (NILP (defx)) | |
582 /* This may occur during initialization. */ | |
583 return Qnil; | |
584 else | |
585 /* We only check the bitmapFilePath resource on the original X device. */ | |
586 display = DEVICE_X_DISPLAY (XDEVICE (defx)); | |
587 } | |
428 | 588 |
589 #ifdef USE_XBMLANGPATH | |
590 { | |
867 | 591 Ibyte *path = egetenv ("XBMLANGPATH"); |
940 | 592 if (path) |
428 | 593 { |
4252 | 594 Extbyte *pathext; |
940 | 595 SubstitutionRec subs[1]; |
596 subs[0].match = 'B'; | |
597 LISP_STRING_TO_EXTERNAL (name, subs[0].substitution, Qfile_name); | |
598 C_STRING_TO_EXTERNAL (path, pathext, Qfile_name); | |
599 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set. | |
4252 | 600 We don't. If you want it used, set it. */ |
940 | 601 if (pathext && |
602 (pathext = XtResolvePathname (display, "bitmaps", 0, 0, pathext, | |
603 subs, XtNumber (subs), 0))) | |
4252 | 604 { |
605 name = build_ext_string (pathext, Qfile_name); | |
940 | 606 XtFree (pathext); |
607 return (name); | |
608 } | |
428 | 609 } |
610 } | |
611 #endif | |
612 | |
613 if (NILP (Vx_bitmap_file_path)) | |
614 { | |
615 char *type = 0; | |
616 XrmValue value; | |
617 if (XrmGetResource (XtDatabase (display), | |
618 "bitmapFilePath", "BitmapFilePath", &type, &value) | |
619 && !strcmp (type, "String")) | |
771 | 620 { |
867 | 621 Ibyte *path; |
771 | 622 |
623 EXTERNAL_TO_C_STRING (value.addr, path, Qfile_name); | |
624 Vx_bitmap_file_path = split_env_path (0, path); | |
625 } | |
428 | 626 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path, |
771 | 627 (split_external_path (BITMAPDIR))); |
428 | 628 } |
629 | |
630 { | |
631 Lisp_Object found; | |
632 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0) | |
633 { | |
634 Lisp_Object temp = list1 (Vdata_directory); | |
635 struct gcpro gcpro1; | |
636 | |
637 GCPRO1 (temp); | |
638 locate_file (temp, name, Qnil, &found, R_OK); | |
639 UNGCPRO; | |
640 } | |
641 | |
642 return found; | |
643 } | |
644 } | |
645 | |
646 static Lisp_Object | |
647 locate_pixmap_file (Lisp_Object name) | |
648 { | |
649 return x_locate_pixmap_file (name); | |
650 } | |
651 | |
652 | |
653 /************************************************************************/ | |
654 /* cursor functions */ | |
655 /************************************************************************/ | |
656 | |
657 /* Check that this server supports cursors of size WIDTH * HEIGHT. If | |
658 not, signal an error. INSTANTIATOR is only used in the error | |
659 message. */ | |
660 | |
661 static void | |
647 | 662 check_pointer_sizes (Screen *xs, int width, int height, |
428 | 663 Lisp_Object instantiator) |
664 { | |
665 unsigned int best_width, best_height; | |
666 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs), | |
667 width, height, &best_width, &best_height)) | |
668 /* this means that an X error of some sort occurred (we trap | |
669 these so they're not fatal). */ | |
563 | 670 gui_error ("XQueryBestCursor() failed?", instantiator); |
428 | 671 |
647 | 672 if (width > (int) best_width || height > (int) best_height) |
563 | 673 signal_ferror_with_frob (Qgui_error, instantiator, |
674 "pointer too large (%dx%d): " | |
675 "server requires %dx%d or smaller", | |
676 width, height, best_width, best_height); | |
428 | 677 } |
678 | |
679 | |
680 static void | |
681 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground, | |
682 Lisp_Object *background, XColor *xfg, XColor *xbg) | |
683 { | |
684 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground)) | |
685 *foreground = | |
686 Fmake_color_instance (*foreground, device, | |
687 encode_error_behavior_flag (ERROR_ME)); | |
688 if (COLOR_INSTANCEP (*foreground)) | |
689 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground)); | |
690 else | |
691 { | |
692 xfg->pixel = 0; | |
693 xfg->red = xfg->green = xfg->blue = 0; | |
694 } | |
695 | |
696 if (!NILP (*background) && !COLOR_INSTANCEP (*background)) | |
697 *background = | |
698 Fmake_color_instance (*background, device, | |
699 encode_error_behavior_flag (ERROR_ME)); | |
700 if (COLOR_INSTANCEP (*background)) | |
701 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background)); | |
702 else | |
703 { | |
704 xbg->pixel = 0; | |
460 | 705 xbg->red = xbg->green = xbg->blue = USHRT_MAX; |
428 | 706 } |
707 } | |
708 | |
709 static void | |
710 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground, | |
711 Lisp_Object background) | |
712 { | |
713 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance); | |
714 XColor xfg, xbg; | |
715 | |
716 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg); | |
717 if (!NILP (foreground) || !NILP (background)) | |
718 { | |
719 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)), | |
720 XIMAGE_INSTANCE_X_CURSOR (image_instance), | |
721 &xfg, &xbg); | |
722 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
723 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
724 } | |
725 } | |
726 | |
727 | |
728 /************************************************************************/ | |
729 /* color pixmap functions */ | |
730 /************************************************************************/ | |
731 | |
2959 | 732 /* Create a pointer from a color pixmap. */ |
733 | |
734 static void | |
735 image_instance_convert_to_pointer (Lisp_Image_Instance *ii, | |
736 Lisp_Object instantiator, | |
737 Lisp_Object pointer_fg, | |
738 Lisp_Object pointer_bg) | |
739 { | |
740 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
741 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
742 Screen *xs = DefaultScreenOfDisplay (dpy); | |
743 int npixels = IMAGE_INSTANCE_X_NPIXELS (ii); | |
744 unsigned long *pixels = IMAGE_INSTANCE_X_PIXELS (ii); | |
745 Pixmap pixmap = IMAGE_INSTANCE_X_PIXMAP (ii); | |
746 Pixmap mask = (Pixmap) IMAGE_INSTANCE_PIXMAP_MASK (ii); | |
747 Colormap cmap; | |
748 XColor fg, bg; | |
749 int i; | |
750 int xhot = 0, yhot = 0; | |
751 int w, h; | |
752 | |
753 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii))) | |
754 xhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)); | |
755 if (INTP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii))) | |
756 yhot = XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)); | |
757 w = IMAGE_INSTANCE_PIXMAP_WIDTH (ii); | |
758 h = IMAGE_INSTANCE_PIXMAP_HEIGHT (ii); | |
759 | |
760 #if 1 | |
761 /* Although I haven't found it documented yet, it appears that pointers are | |
762 always colored via the default window colormap... Sigh. */ | |
763 cmap = DefaultColormap (dpy, DefaultScreen (dpy)); | |
764 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap; | |
765 #else | |
766 cmap = IMAGE_INSTANCE_X_COLORMAP (ii); | |
767 #endif | |
768 | |
769 check_pointer_sizes (xs, w, h, instantiator); | |
770 | |
771 /* If the loaded pixmap has colors allocated (meaning it came from an | |
772 XPM file), then use those as the default colors for the cursor we | |
773 create. Otherwise, default to pointer_fg and pointer_bg. | |
774 */ | |
775 if (npixels >= 2) | |
776 { | |
777 /* With an XBM file, it's obvious which bit is foreground | |
778 and which is background, or rather, it's implicit: in | |
779 an XBM file, a 1 bit is foreground, and a 0 bit is | |
780 background. | |
781 | |
782 XCreatePixmapCursor() assumes this property of the | |
783 pixmap it is called with as well; the `foreground' | |
784 color argument is used for the 1 bits. | |
785 | |
786 With an XPM file, it's tricker, since the elements of | |
787 the pixmap don't represent FG and BG, but are actual | |
788 pixel values. So we need to figure out which of those | |
789 pixels is the foreground color and which is the | |
790 background. We do it by comparing RGB and assuming | |
791 that the darker color is the foreground. This works | |
792 with the result of xbmtopbm|ppmtoxpm, at least. | |
793 | |
794 It might be nice if there was some way to tag the | |
795 colors in the XPM file with whether they are the | |
796 foreground - perhaps with logical color names somehow? | |
797 | |
798 Once we have decided which color is the foreground, we | |
799 need to ensure that that color corresponds to a `1' bit | |
800 in the Pixmap. The XPM library wrote into the (1-bit) | |
801 pixmap with XPutPixel, which will ignore all but the | |
802 least significant bit. | |
803 | |
804 This means that a 1 bit in the image corresponds to | |
805 `fg' only if `fg.pixel' is odd. | |
806 | |
807 (This also means that the image will be all the same | |
808 color if both `fg' and `bg' are odd or even, but we can | |
809 safely assume that that won't happen if the XPM file is | |
810 sensible I think.) | |
811 | |
812 The desired result is that the image use `1' to | |
813 represent the foreground color, and `0' to represent | |
814 the background color. So, we may need to invert the | |
815 image to accomplish this; we invert if fg is | |
816 odd. (Remember that WhitePixel and BlackPixel are not | |
817 necessarily 1 and 0 respectively, though I think it | |
818 might be safe to assume that one of them is always 1 | |
819 and the other is always 0. We also pretty much need to | |
820 assume that one is even and the other is odd.) | |
821 */ | |
822 | |
823 fg.pixel = pixels[0]; /* pick a pixel at random. */ | |
824 bg.pixel = fg.pixel; | |
825 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/ | |
826 { | |
827 bg.pixel = pixels[i]; | |
828 if (fg.pixel != bg.pixel) | |
829 break; | |
830 } | |
831 | |
832 /* If (fg.pixel == bg.pixel) then probably something has | |
833 gone wrong, but I don't think signalling an error would | |
834 be appropriate. */ | |
835 | |
836 XQueryColor (dpy, cmap, &fg); | |
837 XQueryColor (dpy, cmap, &bg); | |
838 | |
839 /* If the foreground is lighter than the background, swap them. | |
840 (This occurs semi-randomly, depending on the ordering of the | |
841 color list in the XPM file.) | |
842 */ | |
843 { | |
844 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3) | |
845 + (fg.blue / 3)); | |
846 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3) | |
847 + (bg.blue / 3)); | |
848 if (fg_total > bg_total) | |
849 { | |
850 XColor swap; | |
851 swap = fg; | |
852 fg = bg; | |
853 bg = swap; | |
854 } | |
855 } | |
856 | |
857 /* If the fg pixel corresponds to a `0' in the bitmap, invert it. | |
858 (This occurs (only?) on servers with Black=0, White=1.) | |
859 */ | |
860 if ((fg.pixel & 1) == 0) | |
861 { | |
862 XGCValues gcv; | |
863 GC gc; | |
864 gcv.function = GXxor; | |
865 gcv.foreground = 1; | |
866 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground), | |
867 &gcv); | |
868 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h); | |
869 XFreeGC (dpy, gc); | |
870 } | |
871 } | |
872 else | |
873 { | |
874 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg, | |
875 &fg, &bg); | |
876 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg; | |
877 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg; | |
878 } | |
879 | |
880 IMAGE_INSTANCE_X_CURSOR (ii) = | |
881 XCreatePixmapCursor | |
882 (dpy, pixmap, mask, &fg, &bg, xhot, yhot); | |
883 } | |
884 | |
428 | 885 /* Initialize an image instance from an XImage. |
886 | |
887 DEST_MASK specifies the mask of allowed image types. | |
888 | |
889 PIXELS and NPIXELS specify an array of pixels that are used in | |
890 the image. These need to be kept around for the duration of the | |
891 image. When the image instance is freed, XFreeColors() will | |
892 automatically be called on all the pixels specified here; thus, | |
893 you should have allocated the pixels yourself using XAllocColor() | |
894 or the like. The array passed in is used directly without | |
895 being copied, so it should be heap data created with xmalloc(). | |
896 It will be freed using xfree() when the image instance is | |
897 destroyed. | |
898 | |
899 If this fails, signal an error. INSTANTIATOR is only used | |
900 in the error message. | |
2959 | 901 */ |
428 | 902 |
903 static void | |
440 | 904 init_image_instance_from_x_image (Lisp_Image_Instance *ii, |
428 | 905 XImage *ximage, |
906 int dest_mask, | |
907 Colormap cmap, | |
908 unsigned long *pixels, | |
909 int npixels, | |
910 int slices, | |
2959 | 911 Lisp_Object instantiator, |
912 Lisp_Object pointer_fg, | |
913 Lisp_Object pointer_bg) | |
428 | 914 { |
915 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
916 Display *dpy; | |
917 GC gc; | |
918 Drawable d; | |
919 Pixmap pixmap; | |
2959 | 920 enum image_instance_type type; |
428 | 921 |
922 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 923 gui_error ("Not an X device", device); |
428 | 924 |
925 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
2959 | 926 d = XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))); |
927 | |
928 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
929 type = IMAGE_COLOR_PIXMAP; | |
930 else if (dest_mask & IMAGE_POINTER_MASK) | |
931 type = IMAGE_POINTER; | |
932 else | |
428 | 933 incompatible_image_types (instantiator, dest_mask, |
2959 | 934 IMAGE_COLOR_PIXMAP_MASK |
935 | IMAGE_POINTER_MASK); | |
428 | 936 |
937 pixmap = XCreatePixmap (dpy, d, ximage->width, | |
938 ximage->height, ximage->depth); | |
939 if (!pixmap) | |
563 | 940 gui_error ("Unable to create pixmap", instantiator); |
428 | 941 |
942 gc = XCreateGC (dpy, pixmap, 0, NULL); | |
943 if (!gc) | |
944 { | |
945 XFreePixmap (dpy, pixmap); | |
563 | 946 gui_error ("Unable to create GC", instantiator); |
428 | 947 } |
948 | |
949 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, | |
950 ximage->width, ximage->height); | |
951 | |
952 XFreeGC (dpy, gc); | |
953 | |
954 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP); | |
955 | |
956 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
957 find_keyword_in_vector (instantiator, Q_file); | |
958 | |
959 /* Fixup a set of pixmaps. */ | |
960 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap; | |
961 | |
962 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; | |
963 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width; | |
964 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height; | |
965 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth; | |
966 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap; | |
967 IMAGE_INSTANCE_X_PIXELS (ii) = pixels; | |
968 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels; | |
2959 | 969 |
970 if (type == IMAGE_POINTER) | |
971 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, | |
972 pointer_bg); | |
428 | 973 } |
974 | |
975 static void | |
440 | 976 image_instance_add_x_image (Lisp_Image_Instance *ii, |
428 | 977 XImage *ximage, |
978 int slice, | |
979 Lisp_Object instantiator) | |
980 { | |
981 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
982 Display *dpy; | |
983 GC gc; | |
984 Drawable d; | |
985 Pixmap pixmap; | |
986 | |
987 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
988 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device))); | |
989 | |
990 pixmap = XCreatePixmap (dpy, d, ximage->width, | |
991 ximage->height, ximage->depth); | |
992 if (!pixmap) | |
563 | 993 gui_error ("Unable to create pixmap", instantiator); |
428 | 994 |
995 gc = XCreateGC (dpy, pixmap, 0, NULL); | |
996 if (!gc) | |
997 { | |
998 XFreePixmap (dpy, pixmap); | |
563 | 999 gui_error ("Unable to create GC", instantiator); |
428 | 1000 } |
1001 | |
1002 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, | |
1003 ximage->width, ximage->height); | |
1004 | |
1005 XFreeGC (dpy, gc); | |
1006 | |
1007 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap; | |
1008 } | |
1009 | |
1010 static void | |
440 | 1011 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii, |
428 | 1012 int width, int height, |
1013 int slices, | |
2367 | 1014 Binbyte *eimage, |
428 | 1015 int dest_mask, |
1016 Lisp_Object instantiator, | |
2959 | 1017 Lisp_Object pointer_fg, |
1018 Lisp_Object pointer_bg, | |
2286 | 1019 Lisp_Object UNUSED (domain)) |
428 | 1020 { |
1021 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
1022 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
1023 unsigned long *pixtbl = NULL; | |
1024 int npixels = 0; | |
1025 int slice; | |
1026 XImage* ximage; | |
1027 | |
1028 for (slice = 0; slice < slices; slice++) | |
1029 { | |
438 | 1030 ximage = convert_EImage_to_XImage (device, width, height, |
428 | 1031 eimage + (width * height * 3 * slice), |
1032 &pixtbl, &npixels); | |
1033 if (!ximage) | |
1034 { | |
1726 | 1035 if (pixtbl) |
1036 xfree (pixtbl, unsigned long *); | |
2959 | 1037 signal_image_error ("EImage to XImage conversion failed", |
1038 instantiator); | |
428 | 1039 } |
1040 | |
1041 /* Now create the pixmap and set up the image instance */ | |
1042 if (slice == 0) | |
1043 init_image_instance_from_x_image (ii, ximage, dest_mask, | |
1044 cmap, pixtbl, npixels, slices, | |
2959 | 1045 instantiator, pointer_fg, |
1046 pointer_bg); | |
428 | 1047 else |
1048 image_instance_add_x_image (ii, ximage, slice, instantiator); | |
1049 | |
1050 if (ximage) | |
1051 { | |
1052 if (ximage->data) | |
1053 { | |
1726 | 1054 xfree (ximage->data, char *); |
428 | 1055 ximage->data = 0; |
1056 } | |
1057 XDestroyImage (ximage); | |
1058 ximage = 0; | |
1059 } | |
1060 } | |
1061 } | |
1062 | |
1063 /* Given inline data for a mono pixmap, create and return the | |
1064 corresponding X object. */ | |
1065 | |
1066 static Pixmap | |
1067 pixmap_from_xbm_inline (Lisp_Object device, int width, int height, | |
2367 | 1068 CBinbyte *bits) |
428 | 1069 { |
771 | 1070 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE (device)), |
1071 XtWindow (DEVICE_XT_APP_SHELL | |
1072 (XDEVICE (device))), | |
1073 bits, width, height, | |
1074 1, 0, 1); | |
428 | 1075 } |
1076 | |
1077 /* Given inline data for a mono pixmap, initialize the given | |
1078 image instance accordingly. */ | |
1079 | |
1080 static void | |
440 | 1081 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii, |
428 | 1082 int width, int height, |
2367 | 1083 CBinbyte *bits, |
428 | 1084 Lisp_Object instantiator, |
1085 Lisp_Object pointer_fg, | |
1086 Lisp_Object pointer_bg, | |
1087 int dest_mask, | |
1088 Pixmap mask, | |
2286 | 1089 Lisp_Object UNUSED (mask_filename)) |
428 | 1090 { |
1091 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); | |
1092 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
1093 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background); | |
1094 Display *dpy; | |
1095 Screen *scr; | |
1096 Drawable draw; | |
1097 enum image_instance_type type; | |
1098 | |
1099 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 1100 gui_error ("Not an X device", device); |
428 | 1101 |
1102 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
1103 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device))); | |
1104 scr = DefaultScreenOfDisplay (dpy); | |
1105 | |
1106 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) && | |
1107 (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) | |
1108 { | |
1109 if (!NILP (foreground) || !NILP (background)) | |
1110 type = IMAGE_COLOR_PIXMAP; | |
1111 else | |
1112 type = IMAGE_MONO_PIXMAP; | |
1113 } | |
1114 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
1115 type = IMAGE_MONO_PIXMAP; | |
1116 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
1117 type = IMAGE_COLOR_PIXMAP; | |
1118 else if (dest_mask & IMAGE_POINTER_MASK) | |
1119 type = IMAGE_POINTER; | |
1120 else | |
1121 incompatible_image_types (instantiator, dest_mask, | |
1122 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
1123 | IMAGE_POINTER_MASK); | |
1124 | |
1125 x_initialize_pixmap_image_instance (ii, 1, type); | |
1126 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; | |
1127 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; | |
1128 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
1129 find_keyword_in_vector (instantiator, Q_file); | |
1130 | |
1131 switch (type) | |
1132 { | |
1133 case IMAGE_MONO_PIXMAP: | |
1134 { | |
1135 IMAGE_INSTANCE_X_PIXMAP (ii) = | |
771 | 1136 pixmap_from_xbm_inline (device, width, height, bits); |
428 | 1137 } |
1138 break; | |
1139 | |
1140 case IMAGE_COLOR_PIXMAP: | |
1141 { | |
1142 Dimension d = DEVICE_X_DEPTH (XDEVICE(device)); | |
1143 unsigned long fg = BlackPixelOfScreen (scr); | |
1144 unsigned long bg = WhitePixelOfScreen (scr); | |
1145 | |
1146 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground)) | |
1147 foreground = | |
1148 Fmake_color_instance (foreground, device, | |
1149 encode_error_behavior_flag (ERROR_ME)); | |
1150 | |
1151 if (COLOR_INSTANCEP (foreground)) | |
1152 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel; | |
1153 | |
1154 if (!NILP (background) && !COLOR_INSTANCEP (background)) | |
1155 background = | |
1156 Fmake_color_instance (background, device, | |
1157 encode_error_behavior_flag (ERROR_ME)); | |
1158 | |
1159 if (COLOR_INSTANCEP (background)) | |
1160 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel; | |
1161 | |
1162 /* We used to duplicate the pixels using XAllocColor(), to protect | |
1163 against their getting freed. Just as easy to just store the | |
1164 color instances here and GC-protect them, so this doesn't | |
1165 happen. */ | |
1166 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
1167 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
1168 IMAGE_INSTANCE_X_PIXMAP (ii) = | |
1169 XCreatePixmapFromBitmapData (dpy, draw, | |
2367 | 1170 (CBinbyte *) bits, width, height, |
428 | 1171 fg, bg, d); |
1172 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d; | |
1173 } | |
1174 break; | |
1175 | |
1176 case IMAGE_POINTER: | |
1177 { | |
1178 XColor fg_color, bg_color; | |
1179 Pixmap source; | |
1180 | |
1181 check_pointer_sizes (scr, width, height, instantiator); | |
1182 | |
1183 source = | |
1184 XCreatePixmapFromBitmapData (dpy, draw, | |
2367 | 1185 (CBinbyte *) bits, width, height, |
428 | 1186 1, 0, 1); |
1187 | |
1188 if (NILP (foreground)) | |
1189 foreground = pointer_fg; | |
1190 if (NILP (background)) | |
1191 background = pointer_bg; | |
1192 generate_cursor_fg_bg (device, &foreground, &background, | |
1193 &fg_color, &bg_color); | |
1194 | |
1195 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground; | |
1196 IMAGE_INSTANCE_PIXMAP_BG (ii) = background; | |
1197 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = | |
1198 find_keyword_in_vector (instantiator, Q_hotspot_x); | |
1199 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = | |
1200 find_keyword_in_vector (instantiator, Q_hotspot_y); | |
1201 IMAGE_INSTANCE_X_CURSOR (ii) = | |
1202 XCreatePixmapCursor | |
1203 (dpy, source, mask, &fg_color, &bg_color, | |
1204 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ? | |
1205 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0, | |
1206 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ? | |
1207 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0); | |
1208 } | |
1209 break; | |
1210 | |
1211 default: | |
2500 | 1212 ABORT (); |
428 | 1213 } |
1214 } | |
1215 | |
1216 static void | |
1217 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, | |
1218 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
1219 int dest_mask, int width, int height, | |
2367 | 1220 CBinbyte *bits) |
428 | 1221 { |
1222 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data); | |
1223 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file); | |
440 | 1224 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 1225 Pixmap mask = 0; |
1226 | |
1227 if (!NILP (mask_data)) | |
1228 { | |
2367 | 1229 CBinbyte *ext_data; |
771 | 1230 |
1231 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, | |
1232 Qbinary); | |
440 | 1233 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii), |
1234 XINT (XCAR (mask_data)), | |
1235 XINT (XCAR (XCDR (mask_data))), | |
444 | 1236 ext_data); |
428 | 1237 } |
1238 | |
1239 init_image_instance_from_xbm_inline (ii, width, height, bits, | |
1240 instantiator, pointer_fg, pointer_bg, | |
1241 dest_mask, mask, mask_file); | |
1242 } | |
1243 | |
1244 /* Instantiate method for XBM's. */ | |
1245 | |
1246 static void | |
1247 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1248 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1249 int dest_mask, Lisp_Object UNUSED (domain)) |
428 | 1250 { |
1251 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2367 | 1252 CBinbyte *ext_data; |
428 | 1253 |
1254 assert (!NILP (data)); | |
1255 | |
442 | 1256 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary); |
428 | 1257 |
1258 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
1259 pointer_bg, dest_mask, XINT (XCAR (data)), | |
440 | 1260 XINT (XCAR (XCDR (data))), ext_data); |
428 | 1261 } |
1262 | |
1263 | |
1264 #ifdef HAVE_XPM | |
1265 | |
1266 /********************************************************************** | |
1267 * XPM * | |
1268 **********************************************************************/ | |
1269 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()... | |
1270 There was no version number in xpm.h before 3.3, but this should do. | |
1271 */ | |
1272 #if (XpmVersion >= 3) || defined(XpmExactColors) | |
1273 # define XPM_DOES_BUFFERS | |
1274 #endif | |
1275 | |
1276 #ifndef XPM_DOES_BUFFERS | |
1277 Your version of XPM is too old. You cannot compile with it. | |
1278 Upgrade to version 3.2g or better or compile with --with-xpm=no. | |
1279 #endif /* !XPM_DOES_BUFFERS */ | |
1280 | |
1281 static XpmColorSymbol * | |
1282 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device, | |
1283 Lisp_Object domain, | |
1284 Lisp_Object color_symbol_alist) | |
1285 { | |
1286 /* This function can GC */ | |
1287 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device)); | |
1288 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device)); | |
1289 XColor color; | |
1290 Lisp_Object rest; | |
1291 Lisp_Object results = Qnil; | |
1292 int i; | |
1293 XpmColorSymbol *symbols; | |
1294 struct gcpro gcpro1, gcpro2; | |
1295 | |
1296 GCPRO2 (results, device); | |
1297 | |
1298 /* We built up results to be (("name" . #<color>) ...) so that if an | |
1299 error happens we don't lose any malloc()ed data, or more importantly, | |
1300 leave any pixels allocated in the server. */ | |
1301 i = 0; | |
1302 LIST_LOOP (rest, color_symbol_alist) | |
1303 { | |
1304 Lisp_Object cons = XCAR (rest); | |
1305 Lisp_Object name = XCAR (cons); | |
1306 Lisp_Object value = XCDR (cons); | |
1307 if (NILP (value)) | |
1308 continue; | |
1309 if (STRINGP (value)) | |
1310 value = | |
1311 Fmake_color_instance | |
793 | 1312 (value, device, encode_error_behavior_flag (ERROR_ME_DEBUG_WARN)); |
428 | 1313 else |
4252 | 1314 { |
1315 assert (COLOR_SPECIFIERP (value)); | |
1316 value = Fspecifier_instance (value, domain, Qnil, Qnil); | |
1317 } | |
428 | 1318 if (NILP (value)) |
4252 | 1319 continue; |
428 | 1320 results = noseeum_cons (noseeum_cons (name, value), results); |
1321 i++; | |
1322 } | |
1323 UNGCPRO; /* no more evaluation */ | |
1324 | |
1325 if (i == 0) return 0; | |
1326 | |
1327 symbols = xnew_array (XpmColorSymbol, i); | |
1328 xpmattrs->valuemask |= XpmColorSymbols; | |
1329 xpmattrs->colorsymbols = symbols; | |
1330 xpmattrs->numsymbols = i; | |
1331 | |
1332 while (--i >= 0) | |
1333 { | |
1334 Lisp_Object cons = XCAR (results); | |
1335 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons))); | |
1336 /* Duplicate the pixel value so that we still have a lock on it if | |
1337 the pixel we were passed is later freed. */ | |
1338 if (! XAllocColor (dpy, cmap, &color)) | |
2500 | 1339 ABORT (); /* it must be allocable since we're just duplicating it */ |
428 | 1340 |
771 | 1341 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (cons), C_STRING_MALLOC, |
1342 symbols[i].name, Qctext); | |
1343 symbols[i].pixel = color.pixel; | |
1344 symbols[i].value = 0; | |
853 | 1345 free_cons (cons); |
428 | 1346 cons = results; |
1347 results = XCDR (results); | |
853 | 1348 free_cons (cons); |
428 | 1349 } |
1350 return symbols; | |
1351 } | |
1352 | |
1353 static void | |
1354 xpm_free (XpmAttributes *xpmattrs) | |
1355 { | |
1356 /* Could conceivably lose if XpmXXX returned an error without first | |
1357 initializing this structure, if we didn't know that initializing it | |
1358 to all zeros was ok (and also that it's ok to call XpmFreeAttributes() | |
1359 multiple times, since it zeros slots as it frees them...) */ | |
1360 XpmFreeAttributes (xpmattrs); | |
1361 } | |
1362 | |
1363 static void | |
1364 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
438 | 1365 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
1366 int dest_mask, Lisp_Object domain) | |
428 | 1367 { |
1368 /* This function can GC */ | |
440 | 1369 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 1370 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
1371 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1372 Display *dpy; | |
1373 Screen *xs; | |
1374 Colormap cmap; | |
1375 int depth; | |
1376 Visual *visual; | |
1377 Pixmap pixmap; | |
1378 Pixmap mask = 0; | |
1379 XpmAttributes xpmattrs; | |
1380 int result; | |
1381 XpmColorSymbol *color_symbols; | |
1382 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, | |
1383 Q_color_symbols); | |
1384 enum image_instance_type type; | |
1385 int force_mono; | |
647 | 1386 int w, h; |
428 | 1387 |
1388 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 1389 gui_error ("Not an X device", device); |
428 | 1390 |
1391 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
1392 xs = DefaultScreenOfDisplay (dpy); | |
1393 | |
1394 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) | |
1395 type = IMAGE_COLOR_PIXMAP; | |
1396 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) | |
1397 type = IMAGE_MONO_PIXMAP; | |
1398 else if (dest_mask & IMAGE_POINTER_MASK) | |
1399 type = IMAGE_POINTER; | |
1400 else | |
1401 incompatible_image_types (instantiator, dest_mask, | |
1402 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | |
1403 | IMAGE_POINTER_MASK); | |
1404 force_mono = (type != IMAGE_COLOR_PIXMAP); | |
1405 | |
1406 #if 1 | |
1407 /* Although I haven't found it documented yet, it appears that pointers are | |
1408 always colored via the default window colormap... Sigh. */ | |
1409 if (type == IMAGE_POINTER) | |
1410 { | |
2959 | 1411 cmap = DefaultColormap (dpy, DefaultScreen (dpy)); |
428 | 1412 depth = DefaultDepthOfScreen (xs); |
1413 visual = DefaultVisualOfScreen (xs); | |
1414 } | |
1415 else | |
1416 { | |
2959 | 1417 cmap = DEVICE_X_COLORMAP (XDEVICE (device)); |
1418 depth = DEVICE_X_DEPTH (XDEVICE (device)); | |
1419 visual = DEVICE_X_VISUAL (XDEVICE (device)); | |
428 | 1420 } |
1421 #else | |
2959 | 1422 cmap = DEVICE_X_COLORMAP (XDEVICE (device)); |
1423 depth = DEVICE_X_DEPTH (XDEVICE (device)); | |
1424 visual = DEVICE_X_VISUAL (XDEVICE (device)); | |
428 | 1425 #endif |
1426 | |
1427 x_initialize_pixmap_image_instance (ii, 1, type); | |
1428 | |
1429 assert (!NILP (data)); | |
1430 | |
1431 retry: | |
1432 | |
1433 xzero (xpmattrs); /* want XpmInitAttributes() */ | |
1434 xpmattrs.valuemask = XpmReturnPixels; | |
1435 if (force_mono) | |
1436 { | |
1437 /* Without this, we get a 1-bit version of the color image, which | |
1438 isn't quite right. With this, we get the mono image, which might | |
1439 be very different looking. */ | |
1440 xpmattrs.valuemask |= XpmColorKey; | |
1441 xpmattrs.color_key = XPM_MONO; | |
1442 xpmattrs.depth = 1; | |
1443 xpmattrs.valuemask |= XpmDepth; | |
1444 } | |
1445 else | |
1446 { | |
1447 xpmattrs.closeness = 65535; | |
1448 xpmattrs.valuemask |= XpmCloseness; | |
1449 xpmattrs.depth = depth; | |
1450 xpmattrs.valuemask |= XpmDepth; | |
1451 xpmattrs.visual = visual; | |
1452 xpmattrs.valuemask |= XpmVisual; | |
1453 xpmattrs.colormap = cmap; | |
1454 xpmattrs.valuemask |= XpmColormap; | |
1455 } | |
1456 | |
1457 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain, | |
1458 color_symbol_alist); | |
1459 | |
771 | 1460 { |
1461 Extbyte *dataext; | |
1462 | |
1463 LISP_STRING_TO_EXTERNAL (data, dataext, Qctext); | |
1464 | |
1465 result = | |
1466 XpmCreatePixmapFromBuffer (dpy, | |
1467 XtWindow | |
1468 (DEVICE_XT_APP_SHELL (XDEVICE(device))), | |
1469 dataext, &pixmap, &mask, &xpmattrs); | |
1470 } | |
428 | 1471 |
1472 if (color_symbols) | |
1473 { | |
771 | 1474 int i; |
1475 | |
1476 for (i = 0; i < (int) xpmattrs.numsymbols; i++) | |
1726 | 1477 xfree (color_symbols[i].name, char *); |
1478 xfree (color_symbols, XpmColorSymbol *); | |
428 | 1479 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */ |
1480 xpmattrs.numsymbols = 0; | |
1481 } | |
1482 | |
1483 switch (result) | |
1484 { | |
1485 case XpmSuccess: | |
1486 break; | |
1487 case XpmFileInvalid: | |
1488 { | |
1489 xpm_free (&xpmattrs); | |
1490 signal_image_error ("invalid XPM data", data); | |
1491 } | |
1492 case XpmColorFailed: | |
1493 case XpmColorError: | |
1494 { | |
1495 xpm_free (&xpmattrs); | |
1496 if (force_mono) | |
1497 { | |
1498 /* second time; blow out. */ | |
563 | 1499 gui_error ("XPM color allocation failed", data); |
428 | 1500 } |
1501 else | |
1502 { | |
563 | 1503 /* second time; blow out. */ |
428 | 1504 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK)) |
563 | 1505 gui_error ("XPM color allocation failed", data); |
428 | 1506 force_mono = 1; |
1507 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP; | |
1508 goto retry; | |
1509 } | |
1510 } | |
1511 case XpmNoMemory: | |
1512 { | |
1513 xpm_free (&xpmattrs); | |
563 | 1514 out_of_memory ("Parsing pixmap data", data); |
428 | 1515 } |
1516 default: | |
1517 { | |
1518 xpm_free (&xpmattrs); | |
563 | 1519 signal_error_2 (Qgui_error, |
1520 "Parsing pixmap data: unknown error code", | |
1521 make_int (result), data); | |
428 | 1522 } |
1523 } | |
1524 | |
1525 w = xpmattrs.width; | |
1526 h = xpmattrs.height; | |
1527 | |
1528 { | |
1529 int npixels = xpmattrs.npixels; | |
1530 Pixel *pixels; | |
1531 | |
1532 if (npixels != 0) | |
1533 { | |
1534 pixels = xnew_array (Pixel, npixels); | |
1535 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel)); | |
1536 } | |
1537 else | |
1538 pixels = NULL; | |
1539 | |
1540 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap; | |
1541 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask; | |
1542 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap; | |
1543 IMAGE_INSTANCE_X_PIXELS (ii) = pixels; | |
1544 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels; | |
1545 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w; | |
1546 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h; | |
1547 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = | |
1548 find_keyword_in_vector (instantiator, Q_file); | |
1549 } | |
1550 | |
1551 switch (type) | |
1552 { | |
1553 case IMAGE_MONO_PIXMAP: | |
1554 break; | |
1555 | |
1556 case IMAGE_COLOR_PIXMAP: | |
2959 | 1557 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth; |
428 | 1558 break; |
1559 | |
1560 case IMAGE_POINTER: | |
2959 | 1561 if (xpmattrs.valuemask & XpmHotspot) |
1562 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = make_int (xpmattrs.x_hotspot); | |
1563 if (xpmattrs.valuemask & XpmHotspot) | |
1564 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = make_int (xpmattrs.y_hotspot); | |
4252 | 1565 |
2959 | 1566 image_instance_convert_to_pointer (ii, instantiator, pointer_fg, |
1567 pointer_bg); | |
428 | 1568 break; |
1569 | |
1570 default: | |
2500 | 1571 ABORT (); |
428 | 1572 } |
1573 | |
1574 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */ | |
1575 } | |
1576 | |
1577 #endif /* HAVE_XPM */ | |
1578 | |
1579 | |
1580 #ifdef HAVE_XFACE | |
1581 | |
1582 /********************************************************************** | |
1583 * X-Face * | |
1584 **********************************************************************/ | |
1585 #if defined(EXTERN) | |
1586 /* This is about to get redefined! */ | |
1587 #undef EXTERN | |
1588 #endif | |
1589 /* We have to define SYSV32 so that compface.h includes string.h | |
1590 instead of strings.h. */ | |
1591 #define SYSV32 | |
1743 | 1592 BEGIN_C_DECLS |
428 | 1593 #include <compface.h> |
1743 | 1594 END_C_DECLS |
1595 | |
428 | 1596 /* JMP_BUF cannot be used here because if it doesn't get defined |
1597 to jmp_buf we end up with a conflicting type error with the | |
1598 definition in compface.h */ | |
1599 extern jmp_buf comp_env; | |
1600 #undef SYSV32 | |
1601 | |
1602 static void | |
1603 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1604 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1605 int dest_mask, Lisp_Object UNUSED (domain)) |
428 | 1606 { |
1607 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1608 int i, stattis; | |
2367 | 1609 Binbyte *p, *bits, *bp; |
867 | 1610 const CIbyte * volatile emsg = 0; |
2367 | 1611 const Binbyte * volatile dstring; |
428 | 1612 |
1613 assert (!NILP (data)); | |
1614 | |
853 | 1615 TO_EXTERNAL_FORMAT (LISP_STRING, data, |
1616 C_STRING_ALLOCA, dstring, | |
1617 Qbinary); | |
1618 | |
2367 | 1619 if ((p = (Binbyte *) strchr ((char *) dstring, ':'))) |
428 | 1620 { |
1621 dstring = p + 1; | |
1622 } | |
1623 | |
1624 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */ | |
1625 if (!(stattis = setjmp (comp_env))) | |
1626 { | |
853 | 1627 UnCompAll ((char *) dstring); |
428 | 1628 UnGenFace (); |
1629 } | |
1630 | |
1631 switch (stattis) | |
1632 { | |
1633 case -2: | |
1634 emsg = "uncompface: internal error"; | |
1635 break; | |
1636 case -1: | |
1637 emsg = "uncompface: insufficient or invalid data"; | |
1638 break; | |
1639 case 1: | |
1640 emsg = "uncompface: excess data ignored"; | |
1641 break; | |
1642 } | |
1643 | |
1644 if (emsg) | |
853 | 1645 signal_image_error_2 (emsg, data, Qimage); |
1646 | |
2367 | 1647 bp = bits = alloca_binbytes (PIXELS / 8); |
428 | 1648 |
1649 /* the compface library exports char F[], which uses a single byte per | |
1650 pixel to represent a 48x48 bitmap. Yuck. */ | |
2367 | 1651 for (i = 0, p = (Binbyte *) F; i < (PIXELS / 8); ++i) |
428 | 1652 { |
1653 int n, b; | |
1654 /* reverse the bit order of each byte... */ | |
1655 for (b = n = 0; b < 8; ++b) | |
1656 { | |
1657 n |= ((*p++) << b); | |
1658 } | |
2367 | 1659 *bp++ = (Binbyte) n; |
428 | 1660 } |
1661 | |
1662 xbm_instantiate_1 (image_instance, instantiator, pointer_fg, | |
2367 | 1663 pointer_bg, dest_mask, 48, 48, (CBinbyte *) bits); |
428 | 1664 } |
1665 | |
1666 #endif /* HAVE_XFACE */ | |
1667 | |
1668 | |
1669 /********************************************************************** | |
1670 * Autodetect * | |
1671 **********************************************************************/ | |
1672 | |
1673 static void | |
1674 autodetect_validate (Lisp_Object instantiator) | |
1675 { | |
1676 data_must_be_present (instantiator); | |
1677 } | |
1678 | |
1679 static Lisp_Object | |
1680 autodetect_normalize (Lisp_Object instantiator, | |
442 | 1681 Lisp_Object console_type, |
2286 | 1682 Lisp_Object UNUSED (dest_mask)) |
428 | 1683 { |
1684 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data); | |
1685 Lisp_Object filename = Qnil; | |
1686 Lisp_Object data = Qnil; | |
1687 struct gcpro gcpro1, gcpro2, gcpro3; | |
1688 Lisp_Object alist = Qnil; | |
1689 | |
1690 GCPRO3 (filename, data, alist); | |
1691 | |
1692 if (NILP (file)) /* no conversion necessary */ | |
1693 RETURN_UNGCPRO (instantiator); | |
1694 | |
1695 alist = tagged_vector_to_alist (instantiator); | |
1696 | |
1697 filename = locate_pixmap_file (file); | |
1698 if (!NILP (filename)) | |
1699 { | |
1700 int xhot, yhot; | |
1701 /* #### Apparently some versions of XpmReadFileToData, which is | |
1702 called by pixmap_to_lisp_data, don't return an error value | |
1703 if the given file is not a valid XPM file. Instead, they | |
1704 just seg fault. It is definitely caused by passing a | |
1705 bitmap. To try and avoid this we check for bitmaps first. */ | |
1706 | |
1707 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1); | |
1708 | |
1709 if (!EQ (data, Qt)) | |
1710 { | |
1711 alist = remassq_no_quit (Q_data, alist); | |
1712 alist = Fcons (Fcons (Q_file, filename), | |
1713 Fcons (Fcons (Q_data, data), alist)); | |
1714 if (xhot != -1) | |
1715 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)), | |
1716 alist); | |
1717 if (yhot != -1) | |
1718 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)), | |
1719 alist); | |
1720 | |
4252 | 1721 alist = xbm_mask_file_munging (alist, filename, Qt, console_type); |
428 | 1722 |
1723 { | |
1724 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist); | |
1725 free_alist (alist); | |
1726 RETURN_UNGCPRO (result); | |
1727 } | |
1728 } | |
1729 | |
1730 #ifdef HAVE_XPM | |
1731 data = pixmap_to_lisp_data (filename, 1); | |
1732 | |
1733 if (!EQ (data, Qt)) | |
1734 { | |
1735 alist = remassq_no_quit (Q_data, alist); | |
1736 alist = Fcons (Fcons (Q_file, filename), | |
1737 Fcons (Fcons (Q_data, data), alist)); | |
1738 alist = Fcons (Fcons (Q_color_symbols, | |
1739 evaluate_xpm_color_symbols ()), | |
1740 alist); | |
1741 { | |
1742 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist); | |
1743 free_alist (alist); | |
1744 RETURN_UNGCPRO (result); | |
1745 } | |
1746 } | |
1747 #endif | |
1748 } | |
1749 | |
1750 /* If we couldn't convert it, just put it back as it is. | |
1751 We might try to further frob it later as a cursor-font | |
1752 specification. (We can't do that now because we don't know | |
1753 what dest-types it's going to be instantiated into.) */ | |
1754 { | |
1755 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist); | |
1756 free_alist (alist); | |
1757 RETURN_UNGCPRO (result); | |
1758 } | |
1759 } | |
1760 | |
1761 static int | |
1762 autodetect_possible_dest_types (void) | |
1763 { | |
1764 return | |
1765 IMAGE_MONO_PIXMAP_MASK | | |
1766 IMAGE_COLOR_PIXMAP_MASK | | |
1767 IMAGE_POINTER_MASK | | |
1768 IMAGE_TEXT_MASK; | |
1769 } | |
1770 | |
1771 static void | |
1772 autodetect_instantiate (Lisp_Object image_instance, | |
438 | 1773 Lisp_Object instantiator, |
1774 Lisp_Object pointer_fg, | |
1775 Lisp_Object pointer_bg, | |
1776 int dest_mask, Lisp_Object domain) | |
428 | 1777 { |
1778 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1779 struct gcpro gcpro1, gcpro2, gcpro3; | |
1780 Lisp_Object alist = Qnil; | |
1781 Lisp_Object result = Qnil; | |
1782 int is_cursor_font = 0; | |
1783 | |
1784 GCPRO3 (data, alist, result); | |
1785 | |
1786 alist = tagged_vector_to_alist (instantiator); | |
1787 if (dest_mask & IMAGE_POINTER_MASK) | |
1788 { | |
442 | 1789 const char *name_ext; |
1790 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name); | |
428 | 1791 if (XmuCursorNameToIndex (name_ext) != -1) |
4252 | 1792 { |
1793 result = alist_to_tagged_vector (Qcursor_font, alist); | |
1794 is_cursor_font = 1; | |
1795 } | |
428 | 1796 } |
1797 | |
1798 if (!is_cursor_font) | |
1799 result = alist_to_tagged_vector (Qstring, alist); | |
1800 free_alist (alist); | |
1801 | |
1802 if (is_cursor_font) | |
1803 cursor_font_instantiate (image_instance, result, pointer_fg, | |
1804 pointer_bg, dest_mask, domain); | |
1805 else | |
1806 string_instantiate (image_instance, result, pointer_fg, | |
1807 pointer_bg, dest_mask, domain); | |
1808 | |
1809 UNGCPRO; | |
1810 } | |
1811 | |
1812 | |
1813 /********************************************************************** | |
1814 * Font * | |
1815 **********************************************************************/ | |
1816 | |
1817 static void | |
1818 font_validate (Lisp_Object instantiator) | |
1819 { | |
1820 data_must_be_present (instantiator); | |
1821 } | |
1822 | |
1823 /* XmuCvtStringToCursor is bogus in the following ways: | |
1824 | |
1825 - When it can't convert the given string to a real cursor, it will | |
1826 sometimes return a "success" value, after triggering a BadPixmap | |
1827 error. It then gives you a cursor that will itself generate BadCursor | |
1828 errors. So we install this error handler to catch/notice the X error | |
1829 and take that as meaning "couldn't convert." | |
1830 | |
1831 - When you tell it to find a cursor file that doesn't exist, it prints | |
1832 an error message on stderr. You can't make it not do that. | |
1833 | |
1834 - Also, using Xmu means we can't properly hack Lisp_Image_Instance | |
1835 objects, or XPM files, or $XBMLANGPATH. | |
1836 */ | |
1837 | |
1838 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */ | |
1839 | |
1840 static int XLoadFont_got_error; | |
1841 | |
1842 static int | |
2286 | 1843 XLoadFont_error_handler (Display *UNUSED (dpy), XErrorEvent *UNUSED (xerror)) |
428 | 1844 { |
1845 XLoadFont_got_error = 1; | |
1846 return 0; | |
1847 } | |
1848 | |
1849 static Font | |
867 | 1850 safe_XLoadFont (Display *dpy, Ibyte *name) |
428 | 1851 { |
1852 Font font; | |
1853 int (*old_handler) (Display *, XErrorEvent *); | |
771 | 1854 Extbyte *nameext; |
1855 | |
428 | 1856 XLoadFont_got_error = 0; |
1857 XSync (dpy, 0); | |
1858 old_handler = XSetErrorHandler (XLoadFont_error_handler); | |
771 | 1859 C_STRING_TO_EXTERNAL (name, nameext, Qfile_name); |
1860 font = XLoadFont (dpy, nameext); | |
428 | 1861 XSync (dpy, 0); |
1862 XSetErrorHandler (old_handler); | |
1863 if (XLoadFont_got_error) return 0; | |
1864 return font; | |
1865 } | |
1866 | |
1867 static int | |
1868 font_possible_dest_types (void) | |
1869 { | |
1870 return IMAGE_POINTER_MASK; | |
1871 } | |
1872 | |
1873 static void | |
1874 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1875 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1876 int dest_mask, Lisp_Object UNUSED (domain)) |
428 | 1877 { |
1878 /* This function can GC */ | |
1879 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
440 | 1880 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 1881 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
1882 Display *dpy; | |
1883 XColor fg, bg; | |
1884 Font source, mask; | |
2421 | 1885 Ibyte source_name[PATH_MAX_INTERNAL], mask_name[PATH_MAX_INTERNAL], dummy; |
428 | 1886 int source_char, mask_char; |
1887 int count; | |
1888 Lisp_Object foreground, background; | |
1889 | |
1890 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 1891 gui_error ("Not an X device", device); |
428 | 1892 |
1893 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
1894 | |
1895 if (!STRINGP (data) || | |
1896 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5)) | |
563 | 1897 invalid_argument ("Invalid font-glyph instantiator", |
428 | 1898 instantiator); |
1899 | |
1900 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
1901 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
1902 | |
1903 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
1904 if (NILP (foreground)) | |
1905 foreground = pointer_fg; | |
1906 background = find_keyword_in_vector (instantiator, Q_background); | |
1907 if (NILP (background)) | |
1908 background = pointer_bg; | |
1909 | |
1910 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg); | |
1911 | |
1912 count = sscanf ((char *) XSTRING_DATA (data), | |
1913 "FONT %s %d %s %d %c", | |
1914 source_name, &source_char, | |
1915 mask_name, &mask_char, &dummy); | |
1916 /* Allow "%s %d %d" as well... */ | |
771 | 1917 if (count == 3 && (1 == sscanf ((char *) mask_name, "%d %c", &mask_char, |
1918 &dummy))) | |
428 | 1919 count = 4, mask_name[0] = 0; |
1920 | |
1921 if (count != 2 && count != 4) | |
563 | 1922 syntax_error ("invalid cursor specification", data); |
428 | 1923 source = safe_XLoadFont (dpy, source_name); |
1924 if (! source) | |
563 | 1925 signal_error_2 (Qgui_error, |
771 | 1926 "couldn't load font", build_intstring (source_name), data); |
428 | 1927 if (count == 2) |
1928 mask = 0; | |
1929 else if (!mask_name[0]) | |
1930 mask = source; | |
1931 else | |
1932 { | |
1933 mask = safe_XLoadFont (dpy, mask_name); | |
1934 if (!mask) | |
563 | 1935 signal_continuable_error_2 (Qgui_error, |
1936 "couldn't load font", | |
771 | 1937 build_intstring (mask_name), data); |
428 | 1938 } |
1939 if (!mask) | |
1940 mask_char = 0; | |
1941 | |
1942 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */ | |
1943 | |
1944 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
1945 IMAGE_INSTANCE_X_CURSOR (ii) = | |
1946 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char, | |
1947 &fg, &bg); | |
1948 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground; | |
1949 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background; | |
1950 XUnloadFont (dpy, source); | |
1951 if (mask && mask != source) XUnloadFont (dpy, mask); | |
1952 } | |
1953 | |
1954 | |
1955 /********************************************************************** | |
1956 * Cursor-Font * | |
1957 **********************************************************************/ | |
1958 | |
1959 static void | |
1960 cursor_font_validate (Lisp_Object instantiator) | |
1961 { | |
1962 data_must_be_present (instantiator); | |
1963 } | |
1964 | |
1965 static int | |
1966 cursor_font_possible_dest_types (void) | |
1967 { | |
1968 return IMAGE_POINTER_MASK; | |
1969 } | |
1970 | |
1971 static void | |
1972 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
1973 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2286 | 1974 int dest_mask, Lisp_Object UNUSED (domain)) |
428 | 1975 { |
1976 /* This function can GC */ | |
1977 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
440 | 1978 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 1979 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
1980 Display *dpy; | |
1981 int i; | |
771 | 1982 const Extbyte *name_ext; |
428 | 1983 Lisp_Object foreground, background; |
1984 | |
1985 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 1986 gui_error ("Not an X device", device); |
428 | 1987 |
1988 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
1989 | |
1990 if (!(dest_mask & IMAGE_POINTER_MASK)) | |
1991 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK); | |
1992 | |
442 | 1993 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name); |
428 | 1994 if ((i = XmuCursorNameToIndex (name_ext)) == -1) |
563 | 1995 invalid_argument ("Unrecognized cursor-font name", data); |
428 | 1996 |
1997 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); | |
1998 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i); | |
1999 foreground = find_keyword_in_vector (instantiator, Q_foreground); | |
2000 if (NILP (foreground)) | |
2001 foreground = pointer_fg; | |
2002 background = find_keyword_in_vector (instantiator, Q_background); | |
2003 if (NILP (background)) | |
2004 background = pointer_bg; | |
2005 maybe_recolor_cursor (image_instance, foreground, background); | |
2006 } | |
2007 | |
2008 static int | |
2009 x_colorize_image_instance (Lisp_Object image_instance, | |
2010 Lisp_Object foreground, Lisp_Object background) | |
2011 { | |
440 | 2012 Lisp_Image_Instance *p; |
428 | 2013 |
2014 p = XIMAGE_INSTANCE (image_instance); | |
2015 | |
2016 switch (IMAGE_INSTANCE_TYPE (p)) | |
2017 { | |
2018 case IMAGE_MONO_PIXMAP: | |
2019 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP; | |
2020 /* Make sure there aren't two pointers to the same mask, causing | |
2021 it to get freed twice. */ | |
2022 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; | |
2023 break; | |
2024 | |
2025 default: | |
2026 return 0; | |
2027 } | |
2028 | |
2029 { | |
2030 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p))); | |
2031 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p)))); | |
2032 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p))); | |
2959 | 2033 Pixmap new_ = XCreatePixmap (dpy, draw, |
428 | 2034 IMAGE_INSTANCE_PIXMAP_WIDTH (p), |
2035 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d); | |
2036 XColor color; | |
2037 XGCValues gcv; | |
2038 GC gc; | |
2039 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)); | |
2040 gcv.foreground = color.pixel; | |
2041 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)); | |
2042 gcv.background = color.pixel; | |
2959 | 2043 gc = XCreateGC (dpy, new_, GCBackground|GCForeground, &gcv); |
2044 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new_, gc, 0, 0, | |
428 | 2045 IMAGE_INSTANCE_PIXMAP_WIDTH (p), |
2046 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), | |
2047 0, 0, 1); | |
2048 XFreeGC (dpy, gc); | |
2959 | 2049 IMAGE_INSTANCE_X_PIXMAP (p) = new_; |
428 | 2050 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d; |
2051 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground; | |
2052 IMAGE_INSTANCE_PIXMAP_BG (p) = background; | |
2053 return 1; | |
2054 } | |
2055 } | |
2056 | |
2057 | |
2058 /************************************************************************/ | |
2059 /* subwindow and widget support */ | |
2060 /************************************************************************/ | |
2061 | |
2062 /* unmap the image if it is a widget. This is used by redisplay via | |
2063 redisplay_unmap_subwindows */ | |
2064 static void | |
440 | 2065 x_unmap_subwindow (Lisp_Image_Instance *p) |
428 | 2066 { |
2067 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) | |
2068 { | |
438 | 2069 XUnmapWindow |
2070 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
428 | 2071 IMAGE_INSTANCE_X_CLIPWINDOW (p)); |
914 | 2072 XUnmapSubwindows |
2073 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2074 IMAGE_INSTANCE_X_CLIPWINDOW (p)); | |
428 | 2075 } |
2076 else /* must be a widget */ | |
2077 { | |
450 | 2078 /* Since we are being unmapped we want the enclosing frame to |
2079 get focus. The losing with simple scrolling but is the safest | |
2080 thing to do. */ | |
4252 | 2081 emacs_Xt_handle_widget_losing_focus |
450 | 2082 ( XFRAME (IMAGE_INSTANCE_FRAME (p)), |
2083 IMAGE_INSTANCE_X_WIDGET_ID (p)); | |
428 | 2084 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); |
2085 } | |
2086 } | |
2087 | |
2088 /* map the subwindow. This is used by redisplay via | |
2089 redisplay_output_subwindow */ | |
2090 static void | |
440 | 2091 x_map_subwindow (Lisp_Image_Instance *p, int x, int y, |
428 | 2092 struct display_glyph_area* dga) |
2093 { | |
448 | 2094 assert (dga->width > 0 && dga->height > 0); |
428 | 2095 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) |
2096 { | |
2097 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p); | |
2098 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
438 | 2099 IMAGE_INSTANCE_X_CLIPWINDOW (p), |
428 | 2100 x, y, dga->width, dga->height); |
2101 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2102 subwindow, -dga->xoffset, -dga->yoffset); | |
442 | 2103 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) |
914 | 2104 { |
2105 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2106 IMAGE_INSTANCE_X_CLIPWINDOW (p)); | |
2107 XMapSubwindows (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2108 IMAGE_INSTANCE_X_CLIPWINDOW (p)); | |
2109 } | |
428 | 2110 } |
2111 else /* must be a widget */ | |
2112 { | |
438 | 2113 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p), |
428 | 2114 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p), |
2115 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p), | |
2116 dga->width, dga->height, 0); | |
2117 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p), | |
2118 -dga->xoffset, -dga->yoffset); | |
442 | 2119 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) |
2120 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); | |
863 | 2121 /* See comments in glyphs-msw.c about keyboard focus. */ |
1111 | 2122 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p)) |
2123 { | |
2124 /* #### FIXME to pop-up the find dialog we map the text-field | |
2125 seven times! This doesn't show on a fast linux box but does | |
2126 under X on windows. */ | |
2127 emacs_Xt_enqueue_focus_event (IMAGE_INSTANCE_X_WIDGET_ID (p), | |
2128 IMAGE_INSTANCE_FRAME (p), 1); | |
2129 } | |
428 | 2130 } |
2131 } | |
2132 | |
2133 /* when you click on a widget you may activate another widget this | |
2134 needs to be checked and all appropriate widgets updated */ | |
2135 static void | |
442 | 2136 x_redisplay_subwindow (Lisp_Image_Instance *p) |
2137 { | |
2138 /* Update the subwindow size if necessary. */ | |
2139 if (IMAGE_INSTANCE_SIZE_CHANGED (p)) | |
2140 { | |
2141 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), | |
2142 IMAGE_INSTANCE_X_SUBWINDOW_ID (p), | |
2143 IMAGE_INSTANCE_WIDTH (p), | |
2144 IMAGE_INSTANCE_HEIGHT (p)); | |
2145 } | |
2146 } | |
2147 | |
2148 /* Update all attributes that have changed. Lwlib actually does most | |
2149 of this for us. */ | |
2150 static void | |
2151 x_redisplay_widget (Lisp_Image_Instance *p) | |
428 | 2152 { |
442 | 2153 /* This function can GC if IN_REDISPLAY is false. */ |
771 | 2154 #ifdef HAVE_X_WIDGETS |
442 | 2155 widget_value* wv = 0; |
2156 | |
2157 /* First get the items if they have changed since this is a | |
2158 structural change. As such it will nuke all added values so we | |
2159 need to update most other things after the items have changed.*/ | |
2160 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
2161 { | |
793 | 2162 Lisp_Object image_instance = wrap_image_instance (p); |
2163 | |
442 | 2164 wv = gui_items_to_widget_values |
2165 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p), | |
2166 /* #### this is not right; we need to keep track of which widgets | |
2167 want accelerators and which don't */ 0); | |
2168 wv->change = STRUCTURAL_CHANGE; | |
2169 } | |
2170 else | |
428 | 2171 { |
442 | 2172 /* Assume the lotus position, breath deeply and chant to |
2173 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a | |
2174 reference to the real values rather than a copy thus any | |
2175 changes we make to the values we get back will look like they | |
2176 have already been applied. If we rebuild the widget tree then | |
444 | 2177 we may lose properties. */ |
4252 | 2178 wv = copy_widget_value_tree (lw_get_all_values |
442 | 2179 (IMAGE_INSTANCE_X_WIDGET_LWID (p)), |
2180 NO_CHANGE); | |
2181 } | |
2182 | |
2183 /* Possibly update the colors and font */ | |
2184 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) | |
2185 || | |
454 | 2186 /* #### This is not sufficient because it will not cope with widgets |
2187 that are not currently visible. Once redisplay has done the | |
2188 visible ones it will clear this flag so that when new ones | |
2189 become visible they will not be updated. */ | |
442 | 2190 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed |
2191 || | |
454 | 2192 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed |
2193 || | |
442 | 2194 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) |
2195 { | |
2196 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p)); | |
2197 } | |
2198 | |
2199 /* Possibly update the text. */ | |
2200 if (IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
2201 { | |
771 | 2202 Extbyte* str; |
442 | 2203 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p); |
2204 LISP_STRING_TO_EXTERNAL (val, str, Qnative); | |
2205 wv->value = str; | |
2206 } | |
2207 | |
2208 /* Possibly update the size. */ | |
2209 if (IMAGE_INSTANCE_SIZE_CHANGED (p) | |
2210 || | |
2211 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p) | |
2212 || | |
2213 IMAGE_INSTANCE_TEXT_CHANGED (p)) | |
2214 { | |
2215 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) && | |
2216 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ; | |
2217 | |
2218 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed | |
2219 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p))) | |
428 | 2220 { |
793 | 2221 Lisp_Object sw = wrap_image_instance (p); |
2222 | |
563 | 2223 signal_error (Qinternal_error, |
2224 "XEmacs bug: subwindow is deleted", sw); | |
434 | 2225 } |
442 | 2226 |
2227 lw_add_widget_value_arg (wv, XtNwidth, | |
2228 (Dimension)IMAGE_INSTANCE_WIDTH (p)); | |
2229 lw_add_widget_value_arg (wv, XtNheight, | |
2230 (Dimension)IMAGE_INSTANCE_HEIGHT (p)); | |
428 | 2231 } |
442 | 2232 |
448 | 2233 /* Adjust offsets within the frame. */ |
450 | 2234 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed) |
448 | 2235 { |
2236 Arg al[2]; | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2237 Xt_SET_ARG (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p)); |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2238 Xt_SET_ARG (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p)); |
4252 | 2239 XtGetValues (FRAME_X_TEXT_WIDGET |
448 | 2240 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2); |
2241 } | |
2242 | |
442 | 2243 /* now modify the widget */ |
1346 | 2244 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), wv, True); |
442 | 2245 free_widget_value_tree (wv); |
1346 | 2246 gcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p)); |
428 | 2247 #endif |
2248 } | |
2249 | |
2250 /* instantiate and x type subwindow */ | |
2251 static void | |
2286 | 2252 x_subwindow_instantiate (Lisp_Object image_instance, |
2253 Lisp_Object UNUSED (instantiator), | |
2254 Lisp_Object UNUSED (pointer_fg), | |
2255 Lisp_Object UNUSED (pointer_bg), | |
2256 int UNUSED (dest_mask), Lisp_Object domain) | |
428 | 2257 { |
2258 /* This function can GC */ | |
440 | 2259 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2260 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
442 | 2261 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 2262 struct frame* f = XFRAME (frame); |
2263 Display *dpy; | |
2264 Screen *xs; | |
2265 Window pw, win; | |
2266 XSetWindowAttributes xswa; | |
2267 Mask valueMask = 0; | |
647 | 2268 int w = IMAGE_INSTANCE_WIDTH (ii), h = IMAGE_INSTANCE_HEIGHT (ii); |
428 | 2269 |
2270 if (!DEVICE_X_P (XDEVICE (device))) | |
563 | 2271 gui_error ("Not an X device", device); |
428 | 2272 |
2273 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); | |
2274 xs = DefaultScreenOfDisplay (dpy); | |
2275 | |
2276 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW; | |
2277 | |
2278 pw = XtWindow (FRAME_X_TEXT_WIDGET (f)); | |
2279 | |
2280 ii->data = xnew_and_zero (struct x_subwindow_data); | |
2281 | |
2282 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw; | |
2283 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs); | |
2284 | |
2285 xswa.backing_store = Always; | |
2286 valueMask |= CWBackingStore; | |
2287 xswa.colormap = DefaultColormapOfScreen (xs); | |
2288 valueMask |= CWColormap; | |
438 | 2289 |
428 | 2290 /* Create a window for clipping */ |
438 | 2291 IMAGE_INSTANCE_X_CLIPWINDOW (ii) = |
428 | 2292 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent, |
2293 InputOutput, CopyFromParent, valueMask, | |
2294 &xswa); | |
2295 | |
2296 /* Now put the subwindow inside the clip window. */ | |
2297 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii), | |
2298 0, 0, w, h, 0, CopyFromParent, | |
2299 InputOutput, CopyFromParent, valueMask, | |
2300 &xswa); | |
438 | 2301 |
428 | 2302 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win; |
2303 } | |
2304 | |
863 | 2305 /* Account for some of the limitations with widget images. */ |
2306 static int | |
2307 x_widget_border_width (void) | |
2308 { | |
2309 return DEFAULT_WIDGET_BORDER_WIDTH * 2; | |
2310 } | |
2311 | |
2312 | |
428 | 2313 #if 0 |
2314 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */ | |
2315 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /* | |
2316 For the given SUBWINDOW, set PROPERTY to DATA, which is a string. | |
2317 Subwindows are not currently implemented. | |
2318 */ | |
2319 (subwindow, property, data)) | |
2320 { | |
2321 Atom property_atom; | |
440 | 2322 Lisp_Subwindow *sw; |
428 | 2323 Display *dpy; |
771 | 2324 Extbyte *propext, *dataext; |
2325 Bytecount datalen; | |
428 | 2326 |
2327 CHECK_SUBWINDOW (subwindow); | |
2328 CHECK_STRING (property); | |
2329 CHECK_STRING (data); | |
2330 | |
2331 sw = XSUBWINDOW (subwindow); | |
2332 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN | |
2333 (FRAME_DEVICE (XFRAME (sw->frame)))); | |
2334 | |
771 | 2335 LISP_TO_EXTERNAL (property, propext, Qctext); |
2336 TO_EXTERNAL_FORMAT (LISP_STRING, data, | |
2337 ALLOCA, (dataext, datalen), Qctext); | |
2338 property_atom = XInternAtom (dpy, propext, False); | |
428 | 2339 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8, |
771 | 2340 PropModeReplace, dataext, datalen); |
428 | 2341 return property; |
2342 } | |
2343 #endif | |
2344 | |
2345 | |
771 | 2346 #ifdef HAVE_X_WIDGETS |
428 | 2347 |
2348 /************************************************************************/ | |
2349 /* widgets */ | |
2350 /************************************************************************/ | |
2351 | |
2352 static void | |
440 | 2353 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii, |
434 | 2354 Lisp_Object domain) |
428 | 2355 { |
2356 #ifdef LWLIB_WIDGETS_MOTIF | |
2357 XmFontList fontList; | |
2358 #endif | |
438 | 2359 /* Update the foreground. */ |
2360 Lisp_Object pixel = FACE_FOREGROUND | |
428 | 2361 (IMAGE_INSTANCE_WIDGET_FACE (ii), |
434 | 2362 domain); |
438 | 2363 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor; |
434 | 2364 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel); |
438 | 2365 |
2366 /* Update the background. */ | |
2367 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), | |
2368 domain); | |
2369 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); | |
2370 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel); | |
2371 | |
3094 | 2372 { |
2373 Lisp_Object face = IMAGE_INSTANCE_WIDGET_FACE (ii); | |
2374 Lisp_Font_Instance *fi = | |
2375 XFONT_INSTANCE (query_string_font (IMAGE_INSTANCE_WIDGET_TEXT (ii), | |
2376 face, | |
2377 domain)); | |
2378 XFontStruct *fs = FONT_INSTANCE_X_FONT (fi); | |
2379 #ifdef USE_XFT | |
2380 XftFont *rf = FONT_INSTANCE_X_XFTFONT (fi); | |
2381 | |
2382 if (rf) | |
2383 { | |
2384 /* #### What to do about Motif? */ | |
2385 lw_add_widget_value_arg (wv, XtNxftFont, (XtArgVal) rf); | |
2386 } | |
2387 #endif | |
2388 | |
2389 if (fs) | |
2390 { | |
428 | 2391 #ifdef LWLIB_WIDGETS_MOTIF |
3094 | 2392 fontList = XmFontListCreate (fs, XmSTRING_DEFAULT_CHARSET); |
2393 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal) fontList); | |
428 | 2394 #endif |
3094 | 2395 lw_add_widget_value_arg (wv, XtNfont, (XtArgVal) fs); |
2396 } | |
2397 | |
2398 #ifdef USE_XFT | |
2399 /* #### sanity check, should wrap in appropriate ERROR_CHECK macro */ | |
2400 if (!rf && !fs) | |
2401 warn_when_safe_lispobj | |
2402 (intern ("xft"), Qdebug, | |
2403 Fcons (build_string ("missing font in update_widget_face"), | |
2404 Fface_name (face))); | |
2405 #endif | |
2406 } | |
442 | 2407 wv->change = VISIBLE_CHANGE; |
2408 /* #### Megahack - but its just getting too complicated to do this | |
2409 in the right place. */ | |
2410 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control)) | |
2411 update_tab_widget_face (wv, ii, domain); | |
434 | 2412 } |
2413 | |
2414 static void | |
440 | 2415 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii, |
434 | 2416 Lisp_Object domain) |
2417 { | |
2418 if (wv->contents) | |
2419 { | |
2420 widget_value* val = wv->contents, *cur; | |
438 | 2421 |
434 | 2422 /* Give each child label the correct foreground color. */ |
438 | 2423 Lisp_Object pixel = FACE_FOREGROUND |
434 | 2424 (IMAGE_INSTANCE_WIDGET_FACE (ii), |
2425 domain); | |
2426 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2427 lw_add_widget_value_arg (val, (String) XtNtabForeground, fcolor.pixel); |
442 | 2428 wv->change = VISIBLE_CHANGE; |
2429 val->change = VISIBLE_CHANGE; | |
434 | 2430 |
2431 for (cur = val->next; cur; cur = cur->next) | |
2432 { | |
442 | 2433 cur->change = VISIBLE_CHANGE; |
434 | 2434 if (cur->value) |
2435 { | |
2436 lw_copy_widget_value_args (val, cur); | |
2437 } | |
2438 } | |
2439 } | |
428 | 2440 } |
2441 | |
2442 static void | |
2286 | 2443 x_widget_instantiate (Lisp_Object image_instance, |
2444 Lisp_Object UNUSED (instantiator), | |
2445 Lisp_Object UNUSED (pointer_fg), | |
2446 Lisp_Object UNUSED (pointer_bg), | |
2447 int UNUSED (dest_mask), Lisp_Object domain, | |
442 | 2448 const char* type, widget_value* wv) |
428 | 2449 { |
440 | 2450 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2451 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel; |
2452 struct device* d = XDEVICE (device); | |
442 | 2453 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 2454 struct frame* f = XFRAME (frame); |
2455 char* nm=0; | |
2456 Widget wid; | |
2457 Arg al [32]; | |
2458 int ac = 0; | |
2459 int id = new_lwlib_id (); | |
2460 widget_value* clip_wv; | |
2461 XColor fcolor, bcolor; | |
2462 | |
2463 if (!DEVICE_X_P (d)) | |
563 | 2464 gui_error ("Not an X device", device); |
428 | 2465 |
2466 /* have to set the type this late in case there is no device | |
2467 instantiation for a widget. But we can go ahead and do it without | |
2468 checking because there is always a generic instantiator. */ | |
2469 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; | |
2470 | |
2471 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) | |
442 | 2472 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative); |
428 | 2473 |
2474 ii->data = xnew_and_zero (struct x_subwindow_data); | |
2475 | |
2476 /* Create a clip window to contain the subwidget. Incredibly the | |
2477 XEmacs manager seems to be the most appropriate widget for | |
2478 this. Nothing else is simple enough and yet does what is | |
2479 required. */ | |
2480 clip_wv = xmalloc_widget_value (); | |
2481 | |
434 | 2482 lw_add_widget_value_arg (clip_wv, XtNresize, False); |
438 | 2483 lw_add_widget_value_arg (clip_wv, XtNwidth, |
442 | 2484 (Dimension)IMAGE_INSTANCE_WIDTH (ii)); |
438 | 2485 lw_add_widget_value_arg (clip_wv, XtNheight, |
442 | 2486 (Dimension)IMAGE_INSTANCE_HEIGHT (ii)); |
428 | 2487 clip_wv->enabled = True; |
434 | 2488 |
428 | 2489 clip_wv->name = xstrdup ("clip-window"); |
2490 clip_wv->value = xstrdup ("clip-window"); | |
2491 | |
2492 IMAGE_INSTANCE_X_CLIPWIDGET (ii) | |
2493 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (), | |
2494 clip_wv, FRAME_X_CONTAINER_WIDGET (f), | |
2495 False, 0, 0, 0); | |
2496 | |
2497 free_widget_value_tree (clip_wv); | |
2498 | |
863 | 2499 /* create a sensible name. */ |
2500 if (wv->name == 0 || strcmp(wv->name, "") == 0) | |
2501 wv->name = xstrdup (type); | |
2502 | |
428 | 2503 /* copy any args we were given */ |
2504 ac = 0; | |
434 | 2505 lw_add_value_args_to_args (wv, al, &ac); |
428 | 2506 |
2507 /* Fixup the colors. We have to do this *before* the widget gets | |
2508 created so that Motif will fix up the shadow colors | |
2509 correctly. Once the widget is created Motif won't do this | |
2510 anymore...*/ | |
438 | 2511 pixel = FACE_FOREGROUND |
428 | 2512 (IMAGE_INSTANCE_WIDGET_FACE (ii), |
442 | 2513 IMAGE_INSTANCE_FRAME (ii)); |
428 | 2514 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); |
2515 | |
2516 pixel = FACE_BACKGROUND | |
2517 (IMAGE_INSTANCE_WIDGET_FACE (ii), | |
442 | 2518 IMAGE_INSTANCE_FRAME (ii)); |
428 | 2519 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); |
2520 | |
434 | 2521 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel); |
2522 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel); | |
428 | 2523 /* we cannot allow widgets to resize themselves */ |
434 | 2524 lw_add_widget_value_arg (wv, XtNresize, False); |
438 | 2525 lw_add_widget_value_arg (wv, XtNwidth, |
442 | 2526 (Dimension)IMAGE_INSTANCE_WIDTH (ii)); |
438 | 2527 lw_add_widget_value_arg (wv, XtNheight, |
442 | 2528 (Dimension)IMAGE_INSTANCE_HEIGHT (ii)); |
434 | 2529 /* update the font. */ |
2530 update_widget_face (wv, ii, domain); | |
428 | 2531 |
1318 | 2532 wid = lw_create_widget (type, wv->name, id, wv, |
2533 IMAGE_INSTANCE_X_CLIPWIDGET (ii), | |
428 | 2534 False, 0, popup_selection_callback, 0); |
2535 | |
2536 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid; | |
2537 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id; | |
2538 /* because the EmacsManager is the widgets parent we have to | |
2539 offset the redisplay of the widget by the amount the text | |
2540 widget is inside the manager. */ | |
2541 ac = 0; | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2542 Xt_SET_ARG (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++; |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2543 Xt_SET_ARG (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++; |
428 | 2544 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac); |
2545 | |
436 | 2546 XtSetMappedWhenManaged (wid, TRUE); |
428 | 2547 |
2548 free_widget_value_tree (wv); | |
442 | 2549 /* A kludgy but simple way to make sure the callback for a widget |
2550 doesn't get deleted. */ | |
2551 gcpro_popup_callbacks (id); | |
428 | 2552 } |
2553 | |
2554 /* get properties of a control */ | |
2555 static Lisp_Object | |
2556 x_widget_property (Lisp_Object image_instance, Lisp_Object prop) | |
2557 { | |
440 | 2558 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2559 /* get the text from a control */ |
2560 if (EQ (prop, Q_text)) | |
2561 { | |
2562 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); | |
440 | 2563 return build_ext_string (wv->value, Qnative); |
428 | 2564 } |
2565 return Qunbound; | |
2566 } | |
2567 | |
442 | 2568 /* Instantiate a layout control for putting other widgets in. */ |
2569 static void | |
771 | 2570 x_native_layout_instantiate (Lisp_Object image_instance, |
2571 Lisp_Object instantiator, | |
442 | 2572 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2573 int dest_mask, Lisp_Object domain) | |
2574 { | |
2575 x_widget_instantiate (image_instance, instantiator, pointer_fg, | |
2576 pointer_bg, dest_mask, domain, "layout", 0); | |
2577 } | |
2578 | |
428 | 2579 /* Instantiate a button widget. Unfortunately instantiated widgets are |
2580 particular to a frame since they need to have a parent. It's not | |
2581 like images where you just select the image into the context you | |
2582 want to display it in and BitBlt it. So images instances can have a | |
2583 many-to-one relationship with things you see, whereas widgets can | |
2584 only be one-to-one (i.e. per frame) */ | |
2585 static void | |
2586 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2587 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2588 int dest_mask, Lisp_Object domain) | |
2589 { | |
440 | 2590 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2591 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); |
2592 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); | |
442 | 2593 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1); |
428 | 2594 |
2595 if (!NILP (glyph)) | |
2596 { | |
2597 if (!IMAGE_INSTANCEP (glyph)) | |
2598 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1); | |
2599 } | |
2600 | |
2601 x_widget_instantiate (image_instance, instantiator, pointer_fg, | |
2602 pointer_bg, dest_mask, domain, "button", wv); | |
2603 | |
2604 /* add the image if one was given */ | |
440 | 2605 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph) |
2606 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph))) | |
428 | 2607 { |
2608 Arg al [2]; | |
2609 int ac =0; | |
2610 #ifdef LWLIB_WIDGETS_MOTIF | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2611 Xt_SET_ARG (al [ac], XmNlabelType, XmPIXMAP); ac++; |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2612 Xt_SET_ARG (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); |
1318 | 2613 ac++; |
428 | 2614 #else |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2615 Xt_SET_ARG (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++; |
428 | 2616 #endif |
2617 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac); | |
2618 } | |
2619 } | |
2620 | |
442 | 2621 /* Update a button's clicked state. |
2622 | |
2623 #### This is overkill, but it works. Right now this causes all | |
2624 button instances to flash for some reason buried deep in lwlib. In | |
2625 theory this should be the Right Thing to do since lwlib should only | |
2626 merge in changed values - and if nothing has changed then nothing | |
2627 should get done. This may be because of the args stuff, | |
2628 i.e. although the arg contents may be the same the args look | |
2629 different and so are re-applied to the widget. */ | |
2630 static void | |
2631 x_button_redisplay (Lisp_Object image_instance) | |
2632 { | |
2633 /* This function can GC if IN_REDISPLAY is false. */ | |
2634 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); | |
2635 widget_value* wv = | |
2636 gui_items_to_widget_values (image_instance, | |
2637 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1); | |
2638 | |
2639 /* now modify the widget */ | |
1346 | 2640 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), wv, True); |
442 | 2641 free_widget_value_tree (wv); |
1346 | 2642 gcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p)); |
442 | 2643 } |
2644 | |
428 | 2645 /* get properties of a button */ |
2646 static Lisp_Object | |
2647 x_button_property (Lisp_Object image_instance, Lisp_Object prop) | |
2648 { | |
440 | 2649 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2650 /* check the state of a button */ |
2651 if (EQ (prop, Q_selected)) | |
2652 { | |
2653 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); | |
2654 | |
2655 if (wv->selected) | |
2656 return Qt; | |
2657 else | |
2658 return Qnil; | |
2659 } | |
2660 return Qunbound; | |
2661 } | |
2662 | |
2663 /* instantiate a progress gauge */ | |
2664 static void | |
1318 | 2665 x_progress_gauge_instantiate (Lisp_Object image_instance, |
2666 Lisp_Object instantiator, | |
2667 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2668 int dest_mask, Lisp_Object domain) | |
428 | 2669 { |
440 | 2670 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2671 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); |
442 | 2672 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0); |
428 | 2673 |
2674 x_widget_instantiate (image_instance, instantiator, pointer_fg, | |
2675 pointer_bg, dest_mask, domain, "progress", wv); | |
2676 } | |
2677 | |
442 | 2678 /* set the properties of a progress gauge */ |
2679 static void | |
2680 x_progress_gauge_redisplay (Lisp_Object image_instance) | |
428 | 2681 { |
639 | 2682 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); |
2683 | |
2684 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
428 | 2685 { |
442 | 2686 Lisp_Object val; |
639 | 2687 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p))->value; |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2688 Xt_SET_VALUE (IMAGE_INSTANCE_X_WIDGET_ID (p), XtNvalue, XINT (val)); |
428 | 2689 } |
2690 } | |
2691 | |
2692 /* instantiate an edit control */ | |
2693 static void | |
2694 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
771 | 2695 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2696 int dest_mask, Lisp_Object domain) | |
428 | 2697 { |
440 | 2698 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2699 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); |
442 | 2700 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0); |
438 | 2701 |
428 | 2702 x_widget_instantiate (image_instance, instantiator, pointer_fg, |
2703 pointer_bg, dest_mask, domain, "text-field", wv); | |
2704 } | |
2705 | |
2706 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 | |
2707 /* instantiate a combo control */ | |
2708 static void | |
2709 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
771 | 2710 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2711 int dest_mask, Lisp_Object domain) | |
428 | 2712 { |
440 | 2713 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2714 widget_value * wv = 0; |
2715 /* This is not done generically because of sizing problems under | |
2716 mswindows. */ | |
438 | 2717 widget_instantiate (image_instance, instantiator, pointer_fg, |
2718 pointer_bg, dest_mask, domain); | |
428 | 2719 |
442 | 2720 wv = gui_items_to_widget_values (image_instance, |
2721 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0); | |
438 | 2722 |
428 | 2723 x_widget_instantiate (image_instance, instantiator, pointer_fg, |
2724 pointer_bg, dest_mask, domain, "combo-box", wv); | |
2725 } | |
2726 #endif | |
2727 | |
2728 static void | |
1318 | 2729 x_tab_control_instantiate (Lisp_Object image_instance, |
2730 Lisp_Object instantiator, | |
428 | 2731 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2732 int dest_mask, Lisp_Object domain) | |
2733 { | |
440 | 2734 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
438 | 2735 widget_value * wv = |
442 | 2736 gui_items_to_widget_values (image_instance, |
2737 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0); | |
438 | 2738 update_tab_widget_face (wv, ii, |
442 | 2739 IMAGE_INSTANCE_FRAME (ii)); |
428 | 2740 x_widget_instantiate (image_instance, instantiator, pointer_fg, |
2741 pointer_bg, dest_mask, domain, "tab-control", wv); | |
2742 } | |
2743 | |
442 | 2744 /* Set the properties of a tab control */ |
2745 static void | |
2746 x_tab_control_redisplay (Lisp_Object image_instance) | |
428 | 2747 { |
440 | 2748 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
438 | 2749 |
1318 | 2750 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) || |
442 | 2751 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii)) |
428 | 2752 { |
442 | 2753 /* If only the order has changed then simply select the first |
2754 one of the pending set. This stops horrendous rebuilding - | |
2755 and hence flicker - of the tabs each time you click on | |
2756 one. */ | |
2757 if (tab_control_order_only_changed (image_instance)) | |
2758 { | |
2759 Lisp_Object rest, selected = | |
2760 gui_item_list_find_selected | |
2761 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ? | |
2762 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) : | |
2763 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); | |
2764 | |
2765 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
2766 { | |
1913 | 2767 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0)) |
442 | 2768 { |
2769 /* There may be an encapsulated way of doing this, | |
2770 but I couldn't find it. */ | |
1318 | 2771 Lisp_Object old_selected = |
2772 gui_item_list_find_selected | |
442 | 2773 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); |
2774 char* name; | |
2775 unsigned int num_children, i; | |
2776 Widget* children; | |
2777 | |
2778 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name, | |
2779 name, Qnative); | |
2780 /* The name may contain a `.' which confuses | |
2781 XtNameToWidget, so we do it ourselves. */ | |
1318 | 2782 children = |
2783 XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii), | |
2784 &num_children); | |
442 | 2785 for (i = 0; i < num_children; i++) |
2786 { | |
2787 if (!strcmp (XtName (children [i]), name)) | |
2788 { | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2789 Xt_SET_VALUE (IMAGE_INSTANCE_X_WIDGET_ID (ii), |
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
2790 XtNtopWidget, children [i]); |
442 | 2791 break; |
2792 } | |
2793 } | |
2794 /* Pick up the new selected item. */ | |
2795 XGUI_ITEM (old_selected)->selected = | |
2796 XGUI_ITEM (XCAR (rest))->selected; | |
2797 XGUI_ITEM (XCAR (rest))->selected = | |
2798 XGUI_ITEM (selected)->selected; | |
2799 /* We're not actually changing the items anymore. */ | |
2800 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; | |
2801 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; | |
2802 break; | |
2803 } | |
2804 } | |
2805 } | |
2806 } | |
2807 /* Possibly update the face. */ | |
2808 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) | |
2809 || | |
2810 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed | |
2811 || | |
2812 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
2813 { | |
2814 /* See previous comments on the brokeness of lwlib. | |
2815 | |
2816 #### There's actually not much point in doing this here | |
2817 since, colors will have been set appropriately by | |
2818 x_redisplay_widget. */ | |
2819 widget_value* wv =copy_widget_value_tree | |
2820 (lw_get_all_values | |
2821 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)), | |
2822 NO_CHANGE); | |
438 | 2823 |
2824 update_tab_widget_face (wv, ii, | |
442 | 2825 IMAGE_INSTANCE_FRAME (ii)); |
428 | 2826 |
2827 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True); | |
2828 free_widget_value_tree (wv); | |
1346 | 2829 gcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); |
428 | 2830 } |
2831 } | |
2832 | |
2833 /* instantiate a static control possible for putting other things in */ | |
2834 static void | |
2835 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2836 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
2837 int dest_mask, Lisp_Object domain) | |
2838 { | |
440 | 2839 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 2840 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); |
442 | 2841 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0); |
438 | 2842 |
428 | 2843 x_widget_instantiate (image_instance, instantiator, pointer_fg, |
2844 pointer_bg, dest_mask, domain, "button", wv); | |
2845 } | |
771 | 2846 #endif /* HAVE_X_WIDGETS */ |
428 | 2847 |
2848 | |
2849 /************************************************************************/ | |
2850 /* initialization */ | |
2851 /************************************************************************/ | |
2852 | |
2853 void | |
2854 syms_of_glyphs_x (void) | |
2855 { | |
2856 #if 0 | |
2857 DEFSUBR (Fchange_subwindow_property); | |
2858 #endif | |
2859 } | |
2860 | |
2861 void | |
2862 console_type_create_glyphs_x (void) | |
2863 { | |
2864 /* image methods */ | |
2865 | |
2866 CONSOLE_HAS_METHOD (x, print_image_instance); | |
2867 CONSOLE_HAS_METHOD (x, finalize_image_instance); | |
2868 CONSOLE_HAS_METHOD (x, image_instance_equal); | |
2869 CONSOLE_HAS_METHOD (x, image_instance_hash); | |
2870 CONSOLE_HAS_METHOD (x, colorize_image_instance); | |
2871 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage); | |
2872 CONSOLE_HAS_METHOD (x, locate_pixmap_file); | |
2873 CONSOLE_HAS_METHOD (x, unmap_subwindow); | |
2874 CONSOLE_HAS_METHOD (x, map_subwindow); | |
442 | 2875 CONSOLE_HAS_METHOD (x, redisplay_widget); |
2876 CONSOLE_HAS_METHOD (x, redisplay_subwindow); | |
863 | 2877 CONSOLE_HAS_METHOD (x, widget_border_width); |
428 | 2878 } |
2879 | |
2880 void | |
2881 image_instantiator_format_create_glyphs_x (void) | |
2882 { | |
2883 IIFORMAT_VALID_CONSOLE (x, nothing); | |
2884 IIFORMAT_VALID_CONSOLE (x, string); | |
771 | 2885 #ifdef HAVE_X_WIDGETS |
428 | 2886 IIFORMAT_VALID_CONSOLE (x, layout); |
442 | 2887 #endif |
428 | 2888 IIFORMAT_VALID_CONSOLE (x, formatted_string); |
2889 IIFORMAT_VALID_CONSOLE (x, inherit); | |
2890 #ifdef HAVE_XPM | |
2891 INITIALIZE_DEVICE_IIFORMAT (x, xpm); | |
2892 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate); | |
2893 #endif | |
2894 #ifdef HAVE_JPEG | |
2895 IIFORMAT_VALID_CONSOLE (x, jpeg); | |
2896 #endif | |
2897 #ifdef HAVE_TIFF | |
2898 IIFORMAT_VALID_CONSOLE (x, tiff); | |
438 | 2899 #endif |
428 | 2900 #ifdef HAVE_PNG |
2901 IIFORMAT_VALID_CONSOLE (x, png); | |
438 | 2902 #endif |
428 | 2903 #ifdef HAVE_GIF |
2904 IIFORMAT_VALID_CONSOLE (x, gif); | |
438 | 2905 #endif |
428 | 2906 INITIALIZE_DEVICE_IIFORMAT (x, xbm); |
2907 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate); | |
2908 | |
2909 INITIALIZE_DEVICE_IIFORMAT (x, subwindow); | |
2910 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate); | |
771 | 2911 #ifdef HAVE_X_WIDGETS |
442 | 2912 /* layout widget */ |
2913 INITIALIZE_DEVICE_IIFORMAT (x, native_layout); | |
2914 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate); | |
428 | 2915 /* button widget */ |
2916 INITIALIZE_DEVICE_IIFORMAT (x, button); | |
2917 IIFORMAT_HAS_DEVMETHOD (x, button, property); | |
2918 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate); | |
442 | 2919 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay); |
2920 /* general widget methods. */ | |
428 | 2921 INITIALIZE_DEVICE_IIFORMAT (x, widget); |
2922 IIFORMAT_HAS_DEVMETHOD (x, widget, property); | |
2923 /* progress gauge */ | |
2924 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge); | |
442 | 2925 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay); |
428 | 2926 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate); |
2927 /* text field */ | |
2928 INITIALIZE_DEVICE_IIFORMAT (x, edit_field); | |
2929 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate); | |
2930 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 | |
2931 /* combo box */ | |
2932 INITIALIZE_DEVICE_IIFORMAT (x, combo_box); | |
2933 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate); | |
442 | 2934 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control); |
428 | 2935 #endif |
2936 /* tab control widget */ | |
2937 INITIALIZE_DEVICE_IIFORMAT (x, tab_control); | |
2938 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate); | |
442 | 2939 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay); |
428 | 2940 /* label */ |
2941 INITIALIZE_DEVICE_IIFORMAT (x, label); | |
2942 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate); | |
2943 #endif | |
2944 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font"); | |
2945 IIFORMAT_VALID_CONSOLE (x, cursor_font); | |
2946 | |
2947 IIFORMAT_HAS_METHOD (cursor_font, validate); | |
2948 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types); | |
2949 IIFORMAT_HAS_METHOD (cursor_font, instantiate); | |
2950 | |
2951 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string); | |
2952 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string); | |
2953 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string); | |
2954 | |
2955 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font"); | |
2956 | |
2957 IIFORMAT_HAS_METHOD (font, validate); | |
2958 IIFORMAT_HAS_METHOD (font, possible_dest_types); | |
2959 IIFORMAT_HAS_METHOD (font, instantiate); | |
2960 IIFORMAT_VALID_CONSOLE (x, font); | |
2961 | |
2962 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); | |
2963 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); | |
2964 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); | |
2965 | |
2966 #ifdef HAVE_XFACE | |
2967 INITIALIZE_DEVICE_IIFORMAT (x, xface); | |
2968 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate); | |
2969 #endif | |
2970 | |
2971 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect, | |
2972 "autodetect"); | |
2973 | |
2974 IIFORMAT_HAS_METHOD (autodetect, validate); | |
2975 IIFORMAT_HAS_METHOD (autodetect, normalize); | |
2976 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types); | |
4252 | 2977 /* #### autodetect is flawed IMO: |
446 | 2978 1. It makes the assumption that you can detect whether the user |
2979 wanted a cursor or a string based on the data, since the data is a | |
2980 string you have to prioritise cursors. Instead we will force users | |
2981 to pick the appropriate image type, this is what we do under | |
2982 MS-Windows anyway. | |
2983 2. It doesn't fit with the new domain model - you cannot tell which | |
2984 domain it needs to be instantiated in until you've actually | |
2985 instantiated it, which mucks up caching. | |
2986 3. It only copes with cursors and strings which seems bogus. */ | |
2987 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow); | |
428 | 2988 IIFORMAT_HAS_METHOD (autodetect, instantiate); |
2989 IIFORMAT_VALID_CONSOLE (x, autodetect); | |
2990 | |
2991 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string); | |
2992 } | |
2993 | |
2994 void | |
2995 vars_of_glyphs_x (void) | |
2996 { | |
2997 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /* | |
2998 A list of the directories in which X bitmap files may be found. | |
2999 If nil, this is initialized from the "*bitmapFilePath" resource. | |
3000 This is used by the `make-image-instance' function (however, note that if | |
3001 the environment variable XBMLANGPATH is set, it is consulted first). | |
3002 */ ); | |
3003 Vx_bitmap_file_path = Qnil; | |
3004 } | |
3005 | |
3006 void | |
3007 complex_vars_of_glyphs_x (void) | |
3008 { | |
3009 #define BUILD_GLYPH_INST(variable, name) \ | |
3010 Fadd_spec_to_specifier \ | |
3011 (GLYPH_IMAGE (XGLYPH (variable)), \ | |
3012 vector3 (Qxbm, Q_data, \ | |
3013 list3 (make_int (name##_width), \ | |
3014 make_int (name##_height), \ | |
444 | 3015 make_ext_string ((Extbyte *) name##_bits, \ |
428 | 3016 sizeof (name##_bits), \ |
440 | 3017 Qbinary))), \ |
428 | 3018 Qglobal, Qx, Qnil) |
3019 | |
3020 BUILD_GLYPH_INST (Vtruncation_glyph, truncator); | |
3021 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer); | |
3022 BUILD_GLYPH_INST (Vxemacs_logo, xemacs); | |
3023 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll); | |
3024 | |
3025 #undef BUILD_GLYPH_INST | |
3026 } |