Mercurial > hg > xemacs-beta
annotate src/glyphs-x.c @ 4539:061e030e3270
Fix some bugs in load-history construction, built-in symbol file names.
lib-src/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* make-docfile.c (main): Allow more than one -d argument, followed
by a directory to change to.
(put_filename): Don't strip directory information; with previous
change, allows retrieval of Lisp function and variable origin
files from #'built-in-symbol-file relative to lisp-directory.
(scan_lisp_file): Don't add an extraneous newline after the file
name, put_filename has added the newline already.
lisp/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* loadup.el (load-history):
Add the contents of current-load-list to load-history before
clearing it. Move the variable declarations earlier in the file to
a format understood by make-docfile.c.
* custom.el (custom-declare-variable): Add the variable's symbol
to the current file's load history entry correctly, don't use a
cons. Eliminate a comment that we don't need to worry about, we
don't need to check the `initialized' C variable in Lisp.
* bytecomp.el (byte-compile-output-file-form):
Merge Andreas Schwab's pre-GPLv3 GNU change of 19970831 here;
treat #'custom-declare-variable correctly, generating the
docstrings in a format understood by make-docfile.c.
* loadhist.el (symbol-file): Correct behaviour for checking
autoloaded macros and functions when supplied with a TYPE
argument. Accept fully-qualified paths from
#'built-in-symbol-file; if a path is not fully-qualified, return
it relative to lisp-directory if the filename corresponds to a
Lisp file, and relative to (concat source-directory "/src/")
otherwise.
* make-docfile.el (preloaded-file-list):
Rationalise some let bindings a little. Use the "-d" argument to
make-docfile.c to supply Lisp paths relative to lisp-directory,
not absolutely. Add in loadup.el explicitly to the list of files
to be processed by make-docfile.c--it doesn't make sense to add it
to preloaded-file-list, since that is used for purposes of
byte-compilation too.
src/ChangeLog addition:
2008-12-27 Aidan Kehoe <kehoea@parhasard.net>
* doc.c (Fbuilt_in_symbol_file):
Return a subr's filename immediately if we've found it. Check for
compiled function and compiled macro docstrings in DOC too, and
return them if they exist.
The branch of the if statement focused on functions may have
executed, but we may still want to check variable bindings; an
else clause isn't appropriate.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 27 Dec 2008 14:05:50 +0000 |
parents | 726060ee587c |
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 } |