comparison src/glyphs-gtk.c @ 462:0784d089fdc9 r21-2-46

Import from CVS: tag r21-2-46
author cvs
date Mon, 13 Aug 2007 11:44:37 +0200
parents
children 183866b06e0b
comparison
equal deleted inserted replaced
461:120ed4009e51 462:0784d089fdc9
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
5 Copyright (C) 1995, 1996 Ben Wing
6 Copyright (C) 1995 Sun Microsystems
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
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
27 /* Original author: Jamie Zawinski for 19.8
28 font-truename stuff added by Jamie Zawinski for 19.10
29 subwindow support added by Chuck Thompson
30 additional XPM support added by Chuck Thompson
31 initial X-Face support added by Stig
32 rewritten/restructured by Ben Wing for 19.12/19.13
33 GIF/JPEG support added by Ben Wing for 19.14
34 PNG support added by Bill Perry for 19.14
35 Improved GIF/JPEG support added by Bill Perry for 19.14
36 Cleanup/simplification of error handling by Ben Wing for 19.14
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
39 Many changes for color work and optimizations by Jareth Hein for 21.0
40 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
41 TIFF code by Jareth Hein for 21.0
42 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c for 21.0
43 Gtk version by William Perry for 21.1
44
45 TODO:
46 Support the GrayScale, StaticColor and StaticGray visual classes.
47 Convert images.el to C and stick it in here?
48 */
49
50 #include <config.h>
51 #include "lisp.h"
52 #include "lstream.h"
53 #include "console-gtk.h"
54 #include "glyphs.h"
55 #include "glyphs-gtk.h"
56 #include "objects-gtk.h"
57 #include "gui-gtk.h"
58 #include "ui-gtk.h"
59
60 #include "buffer.h"
61 #include "window.h"
62 #include "frame.h"
63 #include "insdel.h"
64 #include "opaque.h"
65 #include "faces.h"
66
67 #include "imgproc.h"
68
69 #include "sysfile.h"
70
71 #include <setjmp.h>
72
73 #ifdef FILE_CODING
74 #include "file-coding.h"
75 #endif
76
77 #if INTBITS == 32
78 # define FOUR_BYTE_TYPE unsigned int
79 #elif LONGBITS == 32
80 # define FOUR_BYTE_TYPE unsigned long
81 #elif SHORTBITS == 32
82 # define FOUR_BYTE_TYPE unsigned short
83 #else
84 #error What kind of strange-ass system are we running on?
85 #endif
86
87 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
88 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
89 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
90 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
91 #ifdef HAVE_JPEG
92 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
93 #endif
94 #ifdef HAVE_TIFF
95 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
96 #endif
97 #ifdef HAVE_PNG
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
99 #endif
100 #ifdef HAVE_GIF
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
102 #endif
103
104 #ifdef HAVE_XFACE
105 DEFINE_DEVICE_IIFORMAT (gtk, xface);
106 Lisp_Object Qxface;
107 #endif
108
109 #ifdef HAVE_XPM
110 DEFINE_DEVICE_IIFORMAT (gtk, xpm);
111 #endif
112
113 DEFINE_DEVICE_IIFORMAT (gtk, xbm);
114 DEFINE_DEVICE_IIFORMAT (gtk, subwindow);
115
116 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
117 Lisp_Object Qcursor_font;
118
119 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
120
121 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
122
123 #ifdef HAVE_WIDGETS
124 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
125 DEFINE_DEVICE_IIFORMAT (gtk, widget);
126 DEFINE_DEVICE_IIFORMAT (gtk, native_layout);
127 DEFINE_DEVICE_IIFORMAT (gtk, button);
128 DEFINE_DEVICE_IIFORMAT (gtk, progress_gauge);
129 DEFINE_DEVICE_IIFORMAT (gtk, edit_field);
130 DEFINE_DEVICE_IIFORMAT (gtk, combo_box);
131 DEFINE_DEVICE_IIFORMAT (gtk, tab_control);
132 DEFINE_DEVICE_IIFORMAT (gtk, label);
133 #endif
134
135 static void update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
136 Lisp_Object domain);
137 static void cursor_font_instantiate (Lisp_Object image_instance,
138 Lisp_Object instantiator,
139 Lisp_Object pointer_fg,
140 Lisp_Object pointer_bg,
141 int dest_mask,
142 Lisp_Object domain);
143
144 static gint cursor_name_to_index (const char *name);
145
146 #ifndef BitmapSuccess
147 #define BitmapSuccess 0
148 #define BitmapOpenFailed 1
149 #define BitmapFileInvalid 2
150 #define BitmapNoMemory 3
151 #endif
152
153 #include "bitmaps.h"
154
155 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource);
156 Lisp_Object Q_resource_type, Q_resource_id;
157 Lisp_Object Qgtk_resource;
158 #ifdef HAVE_WIDGETS
159 Lisp_Object Qgtk_widget_instantiate_internal, Qgtk_widget_property_internal;
160 Lisp_Object Qgtk_widget_redisplay_internal, Qgtk_widget_set_style;
161 #endif
162
163 #define CONST const
164
165
166 /************************************************************************/
167 /* image instance methods */
168 /************************************************************************/
169
170 /************************************************************************/
171 /* convert from a series of RGB triples to an XImage formated for the */
172 /* proper display */
173 /************************************************************************/
174 static GdkImage *
175 convert_EImage_to_GDKImage (Lisp_Object device, int width, int height,
176 unsigned char *pic, unsigned long **pixtbl,
177 int *npixels)
178 {
179 GdkColormap *cmap;
180 GdkVisual *vis;
181 GdkImage *outimg;
182 int depth, byte_cnt, i, j;
183 int rd,gr,bl,q;
184 unsigned char *data, *ip, *dp = NULL;
185 quant_table *qtable = NULL;
186 union {
187 FOUR_BYTE_TYPE val;
188 char cp[4];
189 } conv;
190
191 cmap = DEVICE_GTK_COLORMAP (XDEVICE(device));
192 vis = DEVICE_GTK_VISUAL (XDEVICE(device));
193 depth = DEVICE_GTK_DEPTH(XDEVICE(device));
194
195 if (vis->type == GDK_VISUAL_GRAYSCALE || vis->type == GDK_VISUAL_STATIC_COLOR ||
196 vis->type == GDK_VISUAL_STATIC_GRAY)
197 {
198 /* #### Implement me!!! */
199 return NULL;
200 }
201
202 if (vis->type == GDK_VISUAL_PSEUDO_COLOR)
203 {
204 /* Quantize the image and get a histogram while we're at it.
205 Do this first to save memory */
206 qtable = build_EImage_quantable(pic, width, height, 256);
207 if (qtable == NULL) return NULL;
208 }
209
210 /* The first parameter (GdkWindow *) is allowed to be NULL if we
211 ** specify the depth */
212 outimg = gdk_image_new (GDK_IMAGE_FASTEST, vis, width, height);
213
214 if (!outimg) return NULL;
215
216 byte_cnt = outimg->bpp;
217
218 data = (unsigned char *) outimg->mem;
219
220 if (!data)
221 {
222 gdk_image_destroy (outimg);
223 return NULL;
224 }
225
226 if (vis->type == GDK_VISUAL_PSEUDO_COLOR)
227 {
228 unsigned long pixarray[256];
229 int pixcount, n;
230 /* use our quantize table to allocate the colors */
231 pixcount = 32;
232 *pixtbl = xnew_array (unsigned long, pixcount);
233 *npixels = 0;
234
235 /* ### should implement a sort by popularity to assure proper allocation */
236 n = *npixels;
237 for (i = 0; i < qtable->num_active_colors; i++)
238 {
239 GdkColor color;
240 int res;
241
242 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
243 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
244 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
245 res = allocate_nearest_color (cmap, vis, &color);
246 if (res > 0 && res < 3)
247 {
248 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
249 (*pixtbl)[n] = color.pixel;
250 n++;
251 }
252 pixarray[i] = color.pixel;
253 }
254 *npixels = n;
255 ip = pic;
256 for (i = 0; i < height; i++)
257 {
258 dp = data + (i * outimg->bpl);
259 for (j = 0; j < width; j++)
260 {
261 rd = *ip++;
262 gr = *ip++;
263 bl = *ip++;
264 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
265 #if WORDS_BIGENDIAN
266 if (outimg->byte_order == GDK_MSB_FIRST)
267 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
268 else
269 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
270 #else
271 if (outimg->byte_order == GDK_MSB_FIRST)
272 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
273 else
274 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
275 #endif
276 }
277 }
278 xfree(qtable);
279 } else {
280 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
281 junk = vis->red_mask;
282 rshift = 0;
283 while ((junk & 0x1) == 0)
284 {
285 junk = junk >> 1;
286 rshift ++;
287 }
288 rbits = 0;
289 while (junk != 0)
290 {
291 junk = junk >> 1;
292 rbits++;
293 }
294 junk = vis->green_mask;
295 gshift = 0;
296 while ((junk & 0x1) == 0)
297 {
298 junk = junk >> 1;
299 gshift ++;
300 }
301 gbits = 0;
302 while (junk != 0)
303 {
304 junk = junk >> 1;
305 gbits++;
306 }
307 junk = vis->blue_mask;
308 bshift = 0;
309 while ((junk & 0x1) == 0)
310 {
311 junk = junk >> 1;
312 bshift ++;
313 }
314 bbits = 0;
315 while (junk != 0)
316 {
317 junk = junk >> 1;
318 bbits++;
319 }
320 ip = pic;
321 for (i = 0; i < height; i++)
322 {
323 dp = data + (i * outimg->bpl);
324 for (j = 0; j < width; j++)
325 {
326 if (rbits > 8)
327 rd = *ip++ << (rbits - 8);
328 else
329 rd = *ip++ >> (8 - rbits);
330 if (gbits > 8)
331 gr = *ip++ << (gbits - 8);
332 else
333 gr = *ip++ >> (8 - gbits);
334 if (bbits > 8)
335 bl = *ip++ << (bbits - 8);
336 else
337 bl = *ip++ >> (8 - bbits);
338
339 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
340 #if WORDS_BIGENDIAN
341 if (outimg->byte_order == GDK_MSB_FIRST)
342 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
343 else
344 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
345 #else
346 if (outimg->byte_order == GDK_MSB_FIRST)
347 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
348 else
349 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
350 #endif
351 }
352 }
353 }
354 return outimg;
355 }
356
357 static void
358 gtk_print_image_instance (struct Lisp_Image_Instance *p,
359 Lisp_Object printcharfun,
360 int escapeflag)
361 {
362 char buf[100];
363
364 switch (IMAGE_INSTANCE_TYPE (p))
365 {
366 case IMAGE_MONO_PIXMAP:
367 case IMAGE_COLOR_PIXMAP:
368 case IMAGE_POINTER:
369 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_GTK_PIXMAP (p));
370 write_c_string (buf, printcharfun);
371 if (IMAGE_INSTANCE_GTK_MASK (p))
372 {
373 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_GTK_MASK (p));
374 write_c_string (buf, printcharfun);
375 }
376 write_c_string (")", printcharfun);
377 break;
378 #if HAVE_SUBWINDOWS
379 case IMAGE_SUBWINDOW:
380 /* #### implement me */
381 #endif
382 default:
383 break;
384 }
385 }
386
387 static void
388 gtk_finalize_image_instance (struct Lisp_Image_Instance *p)
389 {
390 if (!p->data)
391 return;
392
393 if (DEVICE_LIVE_P (XDEVICE (p->device)))
394 {
395 if (0)
396 ;
397 #ifdef HAVE_WIDGETS
398 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
399 {
400 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
401 {
402 gtk_widget_destroy (IMAGE_INSTANCE_SUBWINDOW_ID (p));
403
404 /* We can release the callbacks again. */
405 /* #### FIXME! */
406 /* ungcpro_popup_callbacks (...); */
407
408 /* IMAGE_INSTANCE_GTK_WIDGET_ID (p) = 0; */
409 IMAGE_INSTANCE_GTK_CLIPWIDGET (p) = 0;
410 }
411 }
412 #endif
413 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
414 {
415 abort();
416 }
417 else
418 {
419 int i;
420 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
421 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
422
423 if (IMAGE_INSTANCE_GTK_MASK (p) &&
424 IMAGE_INSTANCE_GTK_MASK (p) != IMAGE_INSTANCE_GTK_PIXMAP (p))
425 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_MASK (p));
426 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
427
428 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p))
429 {
430 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
431 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i))
432 {
433 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i));
434 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p, i) = 0;
435 }
436 xfree (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p));
437 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p) = 0;
438 }
439
440 if (IMAGE_INSTANCE_GTK_CURSOR (p))
441 {
442 gdk_cursor_destroy (IMAGE_INSTANCE_GTK_CURSOR (p));
443 IMAGE_INSTANCE_GTK_CURSOR (p) = 0;
444 }
445 }
446
447 #if 0
448 /* #### BILL!!! */
449 if (IMAGE_INSTANCE_GTK_NPIXELS (p) != 0)
450 {
451 XFreeColors (dpy,
452 IMAGE_INSTANCE_GTK_COLORMAP (p),
453 IMAGE_INSTANCE_GTK_PIXELS (p),
454 IMAGE_INSTANCE_GTK_NPIXELS (p), 0);
455 IMAGE_INSTANCE_GTK_NPIXELS (p) = 0;
456 }
457 #endif
458 }
459
460 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
461 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
462 && IMAGE_INSTANCE_GTK_PIXELS (p))
463 {
464 xfree (IMAGE_INSTANCE_GTK_PIXELS (p));
465 IMAGE_INSTANCE_GTK_PIXELS (p) = 0;
466 }
467
468 xfree (p->data);
469 p->data = 0;
470 }
471
472 static int
473 gtk_image_instance_equal (struct Lisp_Image_Instance *p1,
474 struct Lisp_Image_Instance *p2, int depth)
475 {
476 switch (IMAGE_INSTANCE_TYPE (p1))
477 {
478 case IMAGE_MONO_PIXMAP:
479 case IMAGE_COLOR_PIXMAP:
480 case IMAGE_POINTER:
481 if (IMAGE_INSTANCE_GTK_COLORMAP (p1) != IMAGE_INSTANCE_GTK_COLORMAP (p2) ||
482 IMAGE_INSTANCE_GTK_NPIXELS (p1) != IMAGE_INSTANCE_GTK_NPIXELS (p2))
483 return 0;
484 #if HAVE_SUBWINDOWS
485 case IMAGE_SUBWINDOW:
486 /* #### implement me */
487 #endif
488 break;
489 default:
490 break;
491 }
492
493 return 1;
494 }
495
496 static unsigned long
497 gtk_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
498 {
499 switch (IMAGE_INSTANCE_TYPE (p))
500 {
501 case IMAGE_MONO_PIXMAP:
502 case IMAGE_COLOR_PIXMAP:
503 case IMAGE_POINTER:
504 return IMAGE_INSTANCE_GTK_NPIXELS (p);
505 #if HAVE_SUBWINDOWS
506 case IMAGE_SUBWINDOW:
507 /* #### implement me */
508 return 0;
509 #endif
510 default:
511 return 0;
512 }
513 }
514
515 /* Set all the slots in an image instance structure to reasonable
516 default values. This is used somewhere within an instantiate
517 method. It is assumed that the device slot within the image
518 instance is already set -- this is the case when instantiate
519 methods are called. */
520
521 static void
522 gtk_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
523 int slices,
524 enum image_instance_type type)
525 {
526 ii->data = xnew_and_zero (struct gtk_image_instance_data);
527 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
528 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (ii) =
529 xnew_array_and_zero (GdkPixmap *, slices);
530 IMAGE_INSTANCE_TYPE (ii) = type;
531 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
532 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
533 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
534 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
535 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
536 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
537 }
538
539
540 /************************************************************************/
541 /* pixmap file functions */
542 /************************************************************************/
543
544 /* Where bitmaps are; initialized from resource database */
545 Lisp_Object Vgtk_bitmap_file_path;
546
547 #ifndef BITMAPDIR
548 #define BITMAPDIR "/usr/include/X11/bitmaps"
549 #endif
550
551 /* Given a pixmap filename, look through all of the "standard" places
552 where the file might be located. Return a full pathname if found;
553 otherwise, return Qnil. */
554
555 static Lisp_Object
556 gtk_locate_pixmap_file (Lisp_Object name)
557 {
558 /* This function can GC if IN_REDISPLAY is false */
559
560 /* Check non-absolute pathnames with a directory component relative to
561 the search path; that's the way Xt does it. */
562 /* #### Unix-specific */
563 if (XSTRING_BYTE (name, 0) == '/' ||
564 (XSTRING_BYTE (name, 0) == '.' &&
565 (XSTRING_BYTE (name, 1) == '/' ||
566 (XSTRING_BYTE (name, 1) == '.' &&
567 (XSTRING_BYTE (name, 2) == '/')))))
568 {
569 if (!NILP (Ffile_readable_p (name)))
570 return name;
571 else
572 return Qnil;
573 }
574
575 if (NILP (Vdefault_gtk_device))
576 /* This may occur during intialization. */
577 return Qnil;
578
579 if (NILP (Vgtk_bitmap_file_path))
580 {
581 Vgtk_bitmap_file_path = nconc2 (Vgtk_bitmap_file_path,
582 (decode_path (BITMAPDIR)));
583 }
584
585 {
586 Lisp_Object found;
587 if (locate_file (Vgtk_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
588 {
589 Lisp_Object temp = list1 (Vdata_directory);
590 struct gcpro gcpro1;
591
592 GCPRO1 (temp);
593 locate_file (temp, name, Qnil, &found, R_OK);
594 UNGCPRO;
595 }
596
597 return found;
598 }
599 }
600
601 static Lisp_Object
602 locate_pixmap_file (Lisp_Object name)
603 {
604 return gtk_locate_pixmap_file (name);
605 }
606
607
608 /************************************************************************/
609 /* cursor functions */
610 /************************************************************************/
611
612 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
613 not, signal an error. INSTANTIATOR is only used in the error
614 message. */
615
616 static void
617 check_pointer_sizes (unsigned int width, unsigned int height,
618 Lisp_Object instantiator)
619 {
620 /* #### BILL!!! There is no way to call XQueryBestCursor from Gdk! */
621 #if 0
622 unsigned int best_width, best_height;
623 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
624 width, height, &best_width, &best_height))
625 /* this means that an X error of some sort occurred (we trap
626 these so they're not fatal). */
627 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
628
629 if (width > best_width || height > best_height)
630 error_with_frob (instantiator,
631 "pointer too large (%dx%d): "
632 "server requires %dx%d or smaller",
633 width, height, best_width, best_height);
634 #endif
635 }
636
637 static void
638 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
639 Lisp_Object *background, GdkColor *xfg, GdkColor *xbg)
640 {
641 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
642 *foreground =
643 Fmake_color_instance (*foreground, device,
644 encode_error_behavior_flag (ERROR_ME));
645 if (COLOR_INSTANCEP (*foreground))
646 *xfg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*foreground));
647 else
648 {
649 xfg->pixel = 0;
650 xfg->red = xfg->green = xfg->blue = 0;
651 }
652
653 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
654 *background =
655 Fmake_color_instance (*background, device,
656 encode_error_behavior_flag (ERROR_ME));
657 if (COLOR_INSTANCEP (*background))
658 *xbg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (*background));
659 else
660 {
661 xbg->pixel = 0;
662 xbg->red = xbg->green = xbg->blue = ~0;
663 }
664 }
665
666 static void
667 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
668 Lisp_Object background)
669 {
670 #if 0
671 /* #### BILL!!! */
672 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
673 GdkColor xfg, xbg;
674
675 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
676 if (!NILP (foreground) || !NILP (background))
677 {
678 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
679 XIMAGE_INSTANCE_GTK_CURSOR (image_instance),
680 &xfg, &xbg);
681 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
682 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
683 }
684 #else
685 /* stderr_out ("Don't know how to recolor cursors in Gtk!\n"); */
686 #endif
687 }
688
689
690 /************************************************************************/
691 /* color pixmap functions */
692 /************************************************************************/
693
694 /* Initialize an image instance from an XImage.
695
696 DEST_MASK specifies the mask of allowed image types.
697
698 PIXELS and NPIXELS specify an array of pixels that are used in
699 the image. These need to be kept around for the duration of the
700 image. When the image instance is freed, XFreeColors() will
701 automatically be called on all the pixels specified here; thus,
702 you should have allocated the pixels yourself using XAllocColor()
703 or the like. The array passed in is used directly without
704 being copied, so it should be heap data created with xmalloc().
705 It will be freed using xfree() when the image instance is
706 destroyed.
707
708 If this fails, signal an error. INSTANTIATOR is only used
709 in the error message.
710
711 #### This should be able to handle conversion into `pointer'.
712 Use the same code as for `xpm'. */
713
714 static void
715 init_image_instance_from_gdk_image (struct Lisp_Image_Instance *ii,
716 GdkImage *gdk_image,
717 int dest_mask,
718 GdkColormap *cmap,
719 unsigned long *pixels,
720 int npixels,
721 int slices,
722 Lisp_Object instantiator)
723 {
724 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
725 GdkGC *gc;
726 GdkWindow *d;
727 GdkPixmap *pixmap;
728
729 if (!DEVICE_GTK_P (XDEVICE (device)))
730 signal_simple_error ("Not a Gtk device", device);
731
732 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
733
734 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
735 incompatible_image_types (instantiator, dest_mask,
736 IMAGE_COLOR_PIXMAP_MASK);
737
738 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth);
739 if (!pixmap)
740 signal_simple_error ("Unable to create pixmap", instantiator);
741
742 gc = gdk_gc_new (pixmap);
743 if (!gc)
744 {
745 gdk_pixmap_unref (pixmap);
746 signal_simple_error ("Unable to create GC", instantiator);
747 }
748
749 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image,
750 0, 0, 0, 0, gdk_image->width, gdk_image->height);
751
752 gdk_gc_destroy (gc);
753
754 gtk_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
755
756 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
757 find_keyword_in_vector (instantiator, Q_file);
758
759 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap;
760 IMAGE_INSTANCE_GTK_MASK (ii) = 0;
761 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = gdk_image->width;
762 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = gdk_image->height;
763 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = gdk_image->depth;
764 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap;
765 IMAGE_INSTANCE_GTK_PIXELS (ii) = pixels;
766 IMAGE_INSTANCE_GTK_NPIXELS (ii) = npixels;
767 }
768
769 #if 0
770 void init_image_instance_from_gdk_pixmap (struct Lisp_Image_Instance *ii,
771 struct device *device,
772 GdkPixmap *gdk_pixmap,
773 int dest_mask,
774 Lisp_Object instantiator)
775 {
776 GdkWindow *d;
777 gint width, height, depth;
778
779 if (!DEVICE_GTK_P (device))
780 abort ();
781
782 IMAGE_INSTANCE_DEVICE (ii) = device;
783 IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP;
784
785 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (device));
786
787 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
788 incompatible_image_types (instantiator, dest_mask,
789 IMAGE_COLOR_PIXMAP_MASK);
790
791 gtk_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
792
793 gdk_window_get_geometry (gdk_pixmap, NULL, NULL, &width, &height, &depth);
794
795 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
796 IMAGE_INSTANCE_GTK_PIXMAP (ii) = gdk_pixmap;
797 IMAGE_INSTANCE_GTK_MASK (ii) = 0;
798 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
799 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
800 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
801 IMAGE_INSTANCE_GTK_COLORMAP (ii) = gdk_window_get_colormap (gdk_pixmap);
802 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0;
803 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0;
804 }
805 #endif
806
807 static void
808 image_instance_add_gdk_image (Lisp_Image_Instance *ii,
809 GdkImage *gdk_image,
810 int slice,
811 Lisp_Object instantiator)
812 {
813 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
814 GdkWindow *d;
815 GdkPixmap *pixmap;
816 GdkGC *gc;
817
818 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
819
820 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth);
821
822 if (!pixmap)
823 signal_simple_error ("Unable to create pixmap", instantiator);
824
825 gc = gdk_gc_new (pixmap);
826
827 if (!gc)
828 {
829 gdk_pixmap_unref (pixmap);
830 signal_simple_error ("Unable to create GC", instantiator);
831 }
832
833 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, 0, 0, 0, 0,
834 gdk_image->width, gdk_image->height);
835
836 gdk_gc_destroy (gc);
837
838 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (ii, slice) = pixmap;
839 }
840
841 static void
842 gtk_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
843 int width, int height,
844 int slices,
845 unsigned char *eimage,
846 int dest_mask,
847 Lisp_Object instantiator,
848 Lisp_Object domain)
849 {
850 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
851 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device));
852 unsigned long *pixtbl = NULL;
853 int npixels = 0;
854 int slice;
855 GdkImage* gdk_image;
856
857
858 for (slice = 0; slice < slices; slice++)
859 {
860 gdk_image = convert_EImage_to_GDKImage (device, width, height, eimage,
861 &pixtbl, &npixels);
862 if (!gdk_image)
863 {
864 if (pixtbl) xfree (pixtbl);
865 signal_image_error("EImage to GdkImage conversion failed", instantiator);
866 }
867
868 if (slice == 0)
869 /* Now create the pixmap and set up the image instance */
870 init_image_instance_from_gdk_image (ii, gdk_image, dest_mask,
871 cmap, pixtbl, npixels, slices,
872 instantiator);
873 else
874 image_instance_add_gdk_image (ii, gdk_image, slice, instantiator);
875
876 if (gdk_image)
877 {
878 gdk_image_destroy (gdk_image);
879 }
880 gdk_image = 0;
881 }
882 }
883
884 /* Given inline data for a mono pixmap, create and return the
885 corresponding X object. */
886
887 static GdkPixmap *
888 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
889 /* Note that data is in ext-format! */
890 CONST Extbyte *bits)
891 {
892 return (gdk_bitmap_create_from_data (GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))),
893 (char *) bits, width, height));
894 }
895
896 /* Given inline data for a mono pixmap, initialize the given
897 image instance accordingly. */
898
899 static void
900 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
901 int width, int height,
902 /* Note that data is in ext-format! */
903 CONST char *bits,
904 Lisp_Object instantiator,
905 Lisp_Object pointer_fg,
906 Lisp_Object pointer_bg,
907 int dest_mask,
908 GdkPixmap *mask,
909 Lisp_Object mask_filename)
910 {
911 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
912 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
913 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
914 GdkColor fg;
915 GdkColor bg;
916 enum image_instance_type type;
917 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
918 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device));
919 GdkColor black;
920 GdkColor white;
921
922 gdk_color_black(cmap, &black);
923 gdk_color_white(cmap, &white);
924
925 if (!DEVICE_GTK_P (XDEVICE (device)))
926 signal_simple_error ("Not a Gtk device", device);
927
928 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
929 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
930 {
931 if (!NILP (foreground) || !NILP (background))
932 type = IMAGE_COLOR_PIXMAP;
933 else
934 type = IMAGE_MONO_PIXMAP;
935 }
936 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
937 type = IMAGE_MONO_PIXMAP;
938 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
939 type = IMAGE_COLOR_PIXMAP;
940 else if (dest_mask & IMAGE_POINTER_MASK)
941 type = IMAGE_POINTER;
942 else
943 incompatible_image_types (instantiator, dest_mask,
944 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
945 | IMAGE_POINTER_MASK);
946
947 gtk_initialize_pixmap_image_instance (ii, 1, type);
948 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
949 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
950 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
951 find_keyword_in_vector (instantiator, Q_file);
952
953 switch (type)
954 {
955 case IMAGE_MONO_PIXMAP:
956 {
957 IMAGE_INSTANCE_GTK_PIXMAP (ii) =
958 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
959 }
960 break;
961
962 case IMAGE_COLOR_PIXMAP:
963 {
964 gint d = DEVICE_GTK_DEPTH (XDEVICE(device));
965
966 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
967 foreground =
968 Fmake_color_instance (foreground, device,
969 encode_error_behavior_flag (ERROR_ME));
970
971 if (COLOR_INSTANCEP (foreground))
972 fg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground));
973
974 if (!NILP (background) && !COLOR_INSTANCEP (background))
975 background =
976 Fmake_color_instance (background, device,
977 encode_error_behavior_flag (ERROR_ME));
978
979 if (COLOR_INSTANCEP (background))
980 bg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background));
981
982 /* We used to duplicate the pixels using XAllocColor(), to protect
983 against their getting freed. Just as easy to just store the
984 color instances here and GC-protect them, so this doesn't
985 happen. */
986 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
987 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
988 IMAGE_INSTANCE_GTK_PIXMAP (ii) =
989 gdk_pixmap_create_from_data (draw, (char *) bits, width, height, d, &fg, &bg);
990 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
991 }
992 break;
993
994 case IMAGE_POINTER:
995 {
996 GdkColor fg_color, bg_color;
997 GdkPixmap *source;
998
999 check_pointer_sizes (width, height, instantiator);
1000
1001 source = gdk_pixmap_create_from_data (draw, (char *) bits, width, height, 1, &black, &white);
1002
1003 if (NILP (foreground))
1004 foreground = pointer_fg;
1005 if (NILP (background))
1006 background = pointer_bg;
1007 generate_cursor_fg_bg (device, &foreground, &background,
1008 &fg_color, &bg_color);
1009
1010 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1011 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1012 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1013 find_keyword_in_vector (instantiator, Q_hotspot_x);
1014 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1015 find_keyword_in_vector (instantiator, Q_hotspot_y);
1016 IMAGE_INSTANCE_GTK_CURSOR (ii) =
1017 gdk_cursor_new_from_pixmap (source, mask, &fg_color, &bg_color,
1018 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1019 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1020 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1021 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1022 }
1023 break;
1024
1025 default:
1026 abort ();
1027 }
1028 }
1029
1030 static void
1031 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1032 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1033 int dest_mask, int width, int height,
1034 /* Note that data is in ext-format! */
1035 CONST char *bits)
1036 {
1037 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1038 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1039 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1040 GdkPixmap *mask = 0;
1041 CONST char *gcc_may_you_rot_in_hell;
1042
1043 if (!NILP (mask_data))
1044 {
1045 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
1046 C_STRING_ALLOCA, gcc_may_you_rot_in_hell,
1047 Qfile_name);
1048 mask =
1049 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1050 XINT (XCAR (mask_data)),
1051 XINT (XCAR (XCDR (mask_data))),
1052 (CONST unsigned char *)
1053 gcc_may_you_rot_in_hell);
1054 }
1055
1056 init_image_instance_from_xbm_inline (ii, width, height, bits,
1057 instantiator, pointer_fg, pointer_bg,
1058 dest_mask, mask, mask_file);
1059 }
1060
1061 /* Instantiate method for XBM's. */
1062
1063 static void
1064 gtk_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1065 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1066 int dest_mask, Lisp_Object domain)
1067 {
1068 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1069 CONST char *gcc_go_home;
1070
1071 assert (!NILP (data));
1072
1073 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
1074 C_STRING_ALLOCA, gcc_go_home,
1075 Qbinary);
1076
1077 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1078 pointer_bg, dest_mask, XINT (XCAR (data)),
1079 XINT (XCAR (XCDR (data))), gcc_go_home);
1080 }
1081
1082
1083 #ifdef HAVE_XPM
1084 /**********************************************************************
1085 * XPM *
1086 **********************************************************************/
1087 static void
1088 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
1089 {
1090 Lisp_Object instream, outstream;
1091 Lstream *istr, *ostr;
1092 char tempbuf[1024]; /* some random amount */
1093 int fubar = 0;
1094 FILE *tmpfil;
1095 static Extbyte_dynarr *conversion_out_dynarr;
1096 Bytecount bstart, bend;
1097 struct gcpro gcpro1, gcpro2;
1098 #ifdef FILE_CODING
1099 Lisp_Object conv_out_stream;
1100 Lstream *costr;
1101 struct gcpro gcpro3;
1102 #endif
1103
1104 /* This function can GC */
1105 if (!conversion_out_dynarr)
1106 conversion_out_dynarr = Dynarr_new (Extbyte);
1107 else
1108 Dynarr_reset (conversion_out_dynarr);
1109
1110 /* Create the temporary file ... */
1111 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
1112 mktemp (filename_out);
1113 tmpfil = fopen (filename_out, "w");
1114 if (!tmpfil)
1115 {
1116 if (tmpfil)
1117 {
1118 int old_errno = errno;
1119 fclose (tmpfil);
1120 unlink (filename_out);
1121 errno = old_errno;
1122 }
1123 report_file_error ("Creating temp file",
1124 list1 (build_string (filename_out)));
1125 }
1126
1127 CHECK_STRING (string);
1128 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
1129 GB_HISTORICAL_STRING_BEHAVIOR);
1130 instream = make_lisp_string_input_stream (string, bstart, bend);
1131 istr = XLSTREAM (instream);
1132 /* setup the out stream */
1133 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
1134 ostr = XLSTREAM (outstream);
1135 #ifdef FILE_CODING
1136 /* setup the conversion stream */
1137 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
1138 costr = XLSTREAM (conv_out_stream);
1139 GCPRO3 (instream, outstream, conv_out_stream);
1140 #else
1141 GCPRO2 (instream, outstream);
1142 #endif
1143
1144 /* Get the data while doing the conversion */
1145 while (1)
1146 {
1147 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
1148 if (!size_in_bytes)
1149 break;
1150 /* It does seem the flushes are necessary... */
1151 #ifdef FILE_CODING
1152 Lstream_write (costr, tempbuf, size_in_bytes);
1153 Lstream_flush (costr);
1154 #else
1155 Lstream_write (ostr, tempbuf, size_in_bytes);
1156 #endif
1157 Lstream_flush (ostr);
1158 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
1159 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
1160 {
1161 fubar = 1;
1162 break;
1163 }
1164 /* reset the dynarr */
1165 Lstream_rewind(ostr);
1166 }
1167
1168 if (fclose (tmpfil) != 0)
1169 fubar = 1;
1170 Lstream_close (istr);
1171 #ifdef FILE_CODING
1172 Lstream_close (costr);
1173 #endif
1174 Lstream_close (ostr);
1175
1176 UNGCPRO;
1177 Lstream_delete (istr);
1178 Lstream_delete (ostr);
1179 #ifdef FILE_CODING
1180 Lstream_delete (costr);
1181 #endif
1182
1183 if (fubar)
1184 report_file_error ("Writing temp file",
1185 list1 (build_string (filename_out)));
1186 }
1187
1188 struct color_symbol
1189 {
1190 char* name;
1191 GdkColor color;
1192 };
1193
1194 static struct color_symbol*
1195 extract_xpm_color_names (Lisp_Object device,
1196 Lisp_Object domain,
1197 Lisp_Object color_symbol_alist,
1198 int* nsymbols)
1199 {
1200 /* This function can GC */
1201 Lisp_Object rest;
1202 Lisp_Object results = Qnil;
1203 int i, j;
1204 struct color_symbol *colortbl;
1205 struct gcpro gcpro1, gcpro2;
1206
1207 GCPRO2 (results, device);
1208
1209 /* We built up results to be (("name" . #<color>) ...) so that if an
1210 error happens we don't lose any malloc()ed data, or more importantly,
1211 leave any pixels allocated in the server. */
1212 i = 0;
1213 LIST_LOOP (rest, color_symbol_alist)
1214 {
1215 Lisp_Object cons = XCAR (rest);
1216 Lisp_Object name = XCAR (cons);
1217 Lisp_Object value = XCDR (cons);
1218 if (NILP (value))
1219 continue;
1220 if (STRINGP (value))
1221 value =
1222 Fmake_color_instance
1223 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1224 else
1225 {
1226 assert (COLOR_SPECIFIERP (value));
1227 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1228 }
1229 if (NILP (value))
1230 continue;
1231 results = noseeum_cons (noseeum_cons (name, value), results);
1232 i++;
1233 }
1234 UNGCPRO; /* no more evaluation */
1235
1236 *nsymbols=i;
1237 if (i == 0) return 0;
1238
1239 colortbl = xnew_array_and_zero (struct color_symbol, i);
1240
1241 for (j=0; j<i; j++)
1242 {
1243 Lisp_Object cons = XCAR (results);
1244 colortbl[j].color =
1245 * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1246
1247 colortbl[j].name = (char *) XSTRING_DATA (XCAR (cons));
1248 free_cons (XCONS (cons));
1249 cons = results;
1250 results = XCDR (results);
1251 free_cons (XCONS (cons));
1252 }
1253 return colortbl;
1254 }
1255
1256 static void
1257 gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1258 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1259 int dest_mask, Lisp_Object domain)
1260 {
1261 /* This function can GC */
1262 char temp_file_name[1024];
1263 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1264 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1265 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1266 GdkColormap *cmap;
1267 int depth;
1268 GdkVisual *visual;
1269 GdkPixmap *pixmap;
1270 GdkPixmap *mask = 0;
1271 GdkWindow *window = 0;
1272 int nsymbols = 0, i = 0;
1273 struct color_symbol *color_symbols = NULL;
1274 GdkColor *transparent_color = NULL;
1275 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1276 Q_color_symbols);
1277 enum image_instance_type type;
1278 int force_mono;
1279 unsigned int w, h;
1280
1281 if (!DEVICE_GTK_P (XDEVICE (device)))
1282 signal_simple_error ("Not a Gtk device", device);
1283
1284 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1285 type = IMAGE_COLOR_PIXMAP;
1286 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1287 type = IMAGE_MONO_PIXMAP;
1288 else if (dest_mask & IMAGE_POINTER_MASK)
1289 type = IMAGE_POINTER;
1290 else
1291 incompatible_image_types (instantiator, dest_mask,
1292 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1293 | IMAGE_POINTER_MASK);
1294 force_mono = (type != IMAGE_COLOR_PIXMAP);
1295
1296 window = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
1297 cmap = DEVICE_GTK_COLORMAP (XDEVICE (device));
1298 depth = DEVICE_GTK_DEPTH (XDEVICE (device));
1299 visual = DEVICE_GTK_VISUAL (XDEVICE (device));
1300
1301 gtk_initialize_pixmap_image_instance (ii, 1, type);
1302
1303 assert (!NILP (data));
1304
1305 /* Need to get the transparent color here */
1306 color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, &nsymbols);
1307 for (i = 0; i < nsymbols; i++)
1308 {
1309 if (!strcasecmp ("BgColor", color_symbols[i].name) ||
1310 !strcasecmp ("None", color_symbols[i].name))
1311 {
1312 transparent_color = &color_symbols[i].color;
1313 }
1314 }
1315
1316 write_lisp_string_to_temp_file (data, temp_file_name);
1317 pixmap = gdk_pixmap_create_from_xpm (window, &mask, transparent_color, temp_file_name);
1318 unlink (temp_file_name);
1319
1320 if (color_symbols) xfree (color_symbols);
1321
1322 if (!pixmap)
1323 {
1324 signal_image_error ("Error reading pixmap", data);
1325 }
1326
1327 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth);
1328
1329 IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap;
1330 IMAGE_INSTANCE_GTK_MASK (ii) = mask;
1331 IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap;
1332 IMAGE_INSTANCE_GTK_PIXELS (ii) = 0;
1333 IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0;
1334 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1335 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1336 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1337 find_keyword_in_vector (instantiator, Q_file);
1338
1339 switch (type)
1340 {
1341 case IMAGE_MONO_PIXMAP:
1342 break;
1343
1344 case IMAGE_COLOR_PIXMAP:
1345 {
1346 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1347 }
1348 break;
1349
1350 case IMAGE_POINTER:
1351 {
1352 GdkColor fg, bg;
1353 unsigned int xhot, yhot;
1354
1355 /* #### Gtk does not give us access to the hotspots of a pixmap */
1356 xhot = yhot = 1;
1357 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xhot);
1358 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), yhot);
1359
1360 check_pointer_sizes (w, h, instantiator);
1361
1362 /* If the loaded pixmap has colors allocated (meaning it came from an
1363 XPM file), then use those as the default colors for the cursor we
1364 create. Otherwise, default to pointer_fg and pointer_bg.
1365 */
1366 if (depth > 1)
1367 {
1368 warn_when_safe (Qunimplemented, Qnotice,
1369 "GTK does not support XPM cursors...\n");
1370 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (GDK_COFFEE_MUG);
1371 }
1372 else
1373 {
1374 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1375 &fg, &bg);
1376 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1377 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1378 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, xhot, yhot);
1379 }
1380 }
1381
1382 break;
1383
1384 default:
1385 abort ();
1386 }
1387 }
1388 #endif /* HAVE_XPM */
1389
1390
1391 #ifdef HAVE_XFACE
1392
1393 /**********************************************************************
1394 * X-Face *
1395 **********************************************************************/
1396 #if defined(EXTERN)
1397 /* This is about to get redefined! */
1398 #undef EXTERN
1399 #endif
1400 /* We have to define SYSV32 so that compface.h includes string.h
1401 instead of strings.h. */
1402 #define SYSV32
1403 #ifdef __cplusplus
1404 extern "C" {
1405 #endif
1406 #include <compface.h>
1407 #ifdef __cplusplus
1408 }
1409 #endif
1410 /* JMP_BUF cannot be used here because if it doesn't get defined
1411 to jmp_buf we end up with a conflicting type error with the
1412 definition in compface.h */
1413 extern jmp_buf comp_env;
1414 #undef SYSV32
1415
1416 static void
1417 gtk_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1418 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1419 int dest_mask, Lisp_Object domain)
1420 {
1421 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1422 int i, stattis;
1423 char *p, *bits, *bp;
1424 CONST char * volatile emsg = 0;
1425 CONST char * volatile dstring;
1426
1427 assert (!NILP (data));
1428
1429 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1430
1431 if ((p = strchr (dstring, ':')))
1432 {
1433 dstring = p + 1;
1434 }
1435
1436 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1437 if (!(stattis = setjmp (comp_env)))
1438 {
1439 UnCompAll ((char *) dstring);
1440 UnGenFace ();
1441 }
1442
1443 switch (stattis)
1444 {
1445 case -2:
1446 emsg = "uncompface: internal error";
1447 break;
1448 case -1:
1449 emsg = "uncompface: insufficient or invalid data";
1450 break;
1451 case 1:
1452 emsg = "uncompface: excess data ignored";
1453 break;
1454 }
1455
1456 if (emsg)
1457 signal_simple_error_2 (emsg, data, Qimage);
1458
1459 bp = bits = (char *) alloca (PIXELS / 8);
1460
1461 /* the compface library exports char F[], which uses a single byte per
1462 pixel to represent a 48x48 bitmap. Yuck. */
1463 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1464 {
1465 int n, b;
1466 /* reverse the bit order of each byte... */
1467 for (b = n = 0; b < 8; ++b)
1468 {
1469 n |= ((*p++) << b);
1470 }
1471 *bp++ = (char) n;
1472 }
1473
1474 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1475 pointer_bg, dest_mask, 48, 48, bits);
1476 }
1477
1478 #endif /* HAVE_XFACE */
1479
1480 /**********************************************************************
1481 * RESOURCES *
1482 **********************************************************************/
1483
1484 static void
1485 gtk_resource_validate (Lisp_Object instantiator)
1486 {
1487 if ((NILP (find_keyword_in_vector (instantiator, Q_file))
1488 &&
1489 NILP (find_keyword_in_vector (instantiator, Q_resource_id)))
1490 ||
1491 NILP (find_keyword_in_vector (instantiator, Q_resource_type)))
1492 signal_simple_error ("Must supply :file, :resource-id and :resource-type",
1493 instantiator);
1494 }
1495
1496 static Lisp_Object
1497 gtk_resource_normalize (Lisp_Object inst, Lisp_Object console_type, Lisp_Object dest_mask)
1498 {
1499 /* This function can call lisp */
1500 Lisp_Object file = Qnil;
1501 struct gcpro gcpro1, gcpro2;
1502 Lisp_Object alist = Qnil;
1503
1504 GCPRO2 (file, alist);
1505
1506 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1507 console_type);
1508
1509 if (CONSP (file)) /* failure locating filename */
1510 signal_double_file_error ("Opening pixmap file",
1511 "no such file or directory",
1512 Fcar (file));
1513
1514 if (NILP (file)) /* no conversion necessary */
1515 RETURN_UNGCPRO (inst);
1516
1517 alist = tagged_vector_to_alist (inst);
1518
1519 {
1520 alist = remassq_no_quit (Q_file, alist);
1521 alist = Fcons (Fcons (Q_file, file), alist);
1522 }
1523
1524 {
1525 Lisp_Object result = alist_to_tagged_vector (Qgtk_resource, alist);
1526 free_alist (alist);
1527 RETURN_UNGCPRO (result);
1528 }
1529 }
1530
1531 static int
1532 gtk_resource_possible_dest_types (void)
1533 {
1534 return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
1535 }
1536
1537 extern guint symbol_to_enum (Lisp_Object, GtkType);
1538
1539 static guint resource_name_to_resource (Lisp_Object name, int type)
1540 {
1541 if (type == IMAGE_POINTER)
1542 return (symbol_to_enum (name, GTK_TYPE_GDK_CURSOR_TYPE));
1543 else
1544 return (0);
1545 }
1546
1547 static int
1548 resource_symbol_to_type (Lisp_Object data)
1549 {
1550 if (EQ (data, Qcursor))
1551 return IMAGE_POINTER;
1552 #if 0
1553 else if (EQ (data, Qicon))
1554 return IMAGE_ICON;
1555 else if (EQ (data, Qbitmap))
1556 return IMAGE_BITMAP;
1557 #endif
1558 else
1559 return 0;
1560 }
1561
1562 static void
1563 gtk_resource_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1564 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1565 int dest_mask, Lisp_Object domain)
1566 {
1567 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1568 GdkCursor *c = NULL;
1569 unsigned int type = 0;
1570 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1571 Lisp_Object resource_type = find_keyword_in_vector (instantiator, Q_resource_type);
1572 Lisp_Object resource_id = find_keyword_in_vector (instantiator, Q_resource_id);
1573
1574 if (!DEVICE_GTK_P (XDEVICE (device)))
1575 signal_simple_error ("Not a GTK device", device);
1576
1577 type = resource_symbol_to_type (resource_type);
1578
1579 // if (dest_mask & IMAGE_POINTER_MASK && type == IMAGE_POINTER_MASK)
1580 // iitype = IMAGE_POINTER;
1581 // else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1582 // iitype = IMAGE_COLOR_PIXMAP;
1583 // else
1584 // incompatible_image_types (instantiator, dest_mask,
1585 // IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
1586
1587 /* mess with the keyword info we were provided with */
1588 gtk_initialize_pixmap_image_instance (ii, 1, type);
1589 c = gdk_cursor_new (resource_name_to_resource (resource_id, type));
1590 IMAGE_INSTANCE_GTK_CURSOR (ii) = c;
1591 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = resource_id;
1592 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = 10;
1593 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = 10;
1594 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = 1;
1595 }
1596
1597 static void
1598 check_valid_resource_symbol (Lisp_Object data)
1599 {
1600 CHECK_SYMBOL (data);
1601 if (!resource_symbol_to_type (data))
1602 signal_simple_error ("invalid resource type", data);
1603 }
1604
1605 static void
1606 check_valid_resource_id (Lisp_Object data)
1607 {
1608 if (!resource_name_to_resource (data, IMAGE_POINTER)
1609 &&
1610 !resource_name_to_resource (data, IMAGE_COLOR_PIXMAP)
1611 #if 0
1612 &&
1613 !resource_name_to_resource (data, IMAGE_BITMAP)
1614 #endif
1615 )
1616 signal_simple_error ("invalid resource identifier", data);
1617 }
1618
1619 #if 0
1620 void
1621 check_valid_string_or_int (Lisp_Object data)
1622 {
1623 if (!INTP (data))
1624 CHECK_STRING (data);
1625 else
1626 CHECK_INT (data);
1627 }
1628 #endif
1629
1630
1631 /**********************************************************************
1632 * Autodetect *
1633 **********************************************************************/
1634
1635 static void
1636 autodetect_validate (Lisp_Object instantiator)
1637 {
1638 data_must_be_present (instantiator);
1639 }
1640
1641 static Lisp_Object
1642 autodetect_normalize (Lisp_Object instantiator,
1643 Lisp_Object console_type,
1644 Lisp_Object dest_mask)
1645 {
1646 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1647 Lisp_Object filename = Qnil;
1648 Lisp_Object data = Qnil;
1649 struct gcpro gcpro1, gcpro2, gcpro3;
1650 Lisp_Object alist = Qnil;
1651
1652 GCPRO3 (filename, data, alist);
1653
1654 if (NILP (file)) /* no conversion necessary */
1655 RETURN_UNGCPRO (instantiator);
1656
1657 alist = tagged_vector_to_alist (instantiator);
1658
1659 filename = locate_pixmap_file (file);
1660 if (!NILP (filename))
1661 {
1662 int xhot, yhot;
1663 /* #### Apparently some versions of XpmReadFileToData, which is
1664 called by pixmap_to_lisp_data, don't return an error value
1665 if the given file is not a valid XPM file. Instead, they
1666 just seg fault. It is definitely caused by passing a
1667 bitmap. To try and avoid this we check for bitmaps first. */
1668
1669 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1670
1671 if (!EQ (data, Qt))
1672 {
1673 alist = remassq_no_quit (Q_data, alist);
1674 alist = Fcons (Fcons (Q_file, filename),
1675 Fcons (Fcons (Q_data, data), alist));
1676 if (xhot != -1)
1677 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1678 alist);
1679 if (yhot != -1)
1680 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1681 alist);
1682
1683 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1684
1685 {
1686 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1687 free_alist (alist);
1688 RETURN_UNGCPRO (result);
1689 }
1690 }
1691
1692 #ifdef HAVE_XPM
1693 data = pixmap_to_lisp_data (filename, 1);
1694
1695 if (!EQ (data, Qt))
1696 {
1697 alist = remassq_no_quit (Q_data, alist);
1698 alist = Fcons (Fcons (Q_file, filename),
1699 Fcons (Fcons (Q_data, data), alist));
1700 alist = Fcons (Fcons (Q_color_symbols,
1701 evaluate_xpm_color_symbols ()),
1702 alist);
1703 {
1704 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1705 free_alist (alist);
1706 RETURN_UNGCPRO (result);
1707 }
1708 }
1709 #endif
1710 }
1711
1712 /* If we couldn't convert it, just put it back as it is.
1713 We might try to further frob it later as a cursor-font
1714 specification. (We can't do that now because we don't know
1715 what dest-types it's going to be instantiated into.) */
1716 {
1717 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1718 free_alist (alist);
1719 RETURN_UNGCPRO (result);
1720 }
1721 }
1722
1723 static int
1724 autodetect_possible_dest_types (void)
1725 {
1726 return
1727 IMAGE_MONO_PIXMAP_MASK |
1728 IMAGE_COLOR_PIXMAP_MASK |
1729 IMAGE_POINTER_MASK |
1730 IMAGE_TEXT_MASK;
1731 }
1732
1733 static void
1734 autodetect_instantiate (Lisp_Object image_instance,
1735 Lisp_Object instantiator,
1736 Lisp_Object pointer_fg,
1737 Lisp_Object pointer_bg,
1738 int dest_mask, Lisp_Object domain)
1739 {
1740 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1741 struct gcpro gcpro1, gcpro2, gcpro3;
1742 Lisp_Object alist = Qnil;
1743 Lisp_Object result = Qnil;
1744 int is_cursor_font = 0;
1745
1746 GCPRO3 (data, alist, result);
1747
1748 alist = tagged_vector_to_alist (instantiator);
1749 if (dest_mask & IMAGE_POINTER_MASK)
1750 {
1751 CONST char *name_ext;
1752
1753 TO_EXTERNAL_FORMAT (LISP_STRING, data,
1754 C_STRING_ALLOCA, name_ext,
1755 Qfile_name);
1756
1757 if (cursor_name_to_index (name_ext) != -1)
1758 {
1759 result = alist_to_tagged_vector (Qcursor_font, alist);
1760 is_cursor_font = 1;
1761 }
1762 }
1763
1764 if (!is_cursor_font)
1765 result = alist_to_tagged_vector (Qstring, alist);
1766 free_alist (alist);
1767
1768 if (is_cursor_font)
1769 cursor_font_instantiate (image_instance, result, pointer_fg,
1770 pointer_bg, dest_mask, domain);
1771 else
1772 string_instantiate (image_instance, result, pointer_fg,
1773 pointer_bg, dest_mask, domain);
1774
1775 UNGCPRO;
1776 }
1777
1778
1779 /**********************************************************************
1780 * Font *
1781 **********************************************************************/
1782
1783 static void
1784 font_validate (Lisp_Object instantiator)
1785 {
1786 data_must_be_present (instantiator);
1787 }
1788
1789 static int
1790 font_possible_dest_types (void)
1791 {
1792 return IMAGE_POINTER_MASK;
1793 }
1794
1795 static void
1796 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1797 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1798 int dest_mask, Lisp_Object domain)
1799 {
1800 /* This function can GC */
1801 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1802 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1803 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1804 GdkColor fg, bg;
1805 GdkFont *source, *mask;
1806 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1807 int source_char, mask_char;
1808 int count;
1809 Lisp_Object foreground, background;
1810
1811 if (!DEVICE_GTK_P (XDEVICE (device)))
1812 signal_simple_error ("Not a Gtk device", device);
1813
1814 if (!STRINGP (data) ||
1815 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1816 signal_simple_error ("Invalid font-glyph instantiator",
1817 instantiator);
1818
1819 if (!(dest_mask & IMAGE_POINTER_MASK))
1820 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1821
1822 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1823 if (NILP (foreground))
1824 foreground = pointer_fg;
1825 background = find_keyword_in_vector (instantiator, Q_background);
1826 if (NILP (background))
1827 background = pointer_bg;
1828
1829 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1830
1831 count = sscanf ((char *) XSTRING_DATA (data),
1832 "FONT %s %d %s %d %c",
1833 source_name, &source_char,
1834 mask_name, &mask_char, &dummy);
1835 /* Allow "%s %d %d" as well... */
1836 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1837 count = 4, mask_name[0] = 0;
1838
1839 if (count != 2 && count != 4)
1840 signal_simple_error ("invalid cursor specification", data);
1841 source = gdk_font_load (source_name);
1842 if (! source)
1843 signal_simple_error_2 ("couldn't load font",
1844 build_string (source_name),
1845 data);
1846 if (count == 2)
1847 mask = 0;
1848 else if (!mask_name[0])
1849 mask = source;
1850 else
1851 {
1852 mask = gdk_font_load (mask_name);
1853 if (!mask)
1854 /* continuable */
1855 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1856 build_string (mask_name), data));
1857 }
1858 if (!mask)
1859 mask_char = 0;
1860
1861 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1862
1863 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
1864
1865 IMAGE_INSTANCE_GTK_CURSOR (ii) = NULL;
1866
1867 #if 0
1868 /* #### BILL!!! There is no way to call this function from Gdk */
1869 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1870 &fg, &bg);
1871 #endif
1872 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1873 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1874
1875 gdk_font_unref (source);
1876 if (mask && mask != source) gdk_font_unref (mask);
1877 }
1878
1879
1880 /**********************************************************************
1881 * Cursor-Font *
1882 **********************************************************************/
1883
1884 static void
1885 cursor_font_validate (Lisp_Object instantiator)
1886 {
1887 data_must_be_present (instantiator);
1888 }
1889
1890 static int
1891 cursor_font_possible_dest_types (void)
1892 {
1893 return IMAGE_POINTER_MASK;
1894 }
1895
1896 static char *__downcase (const char *name)
1897 {
1898 char *converted = strdup(name);
1899 char *work = converted;
1900
1901 while (*work)
1902 {
1903 *work = tolower(*work);
1904 work++;
1905 }
1906 return(converted);
1907 }
1908
1909 /* This is basically the equivalent of XmuCursorNameToIndex */
1910 static gint
1911 cursor_name_to_index (const char *name)
1912 {
1913 int i;
1914 static char *the_gdk_cursors[GDK_NUM_GLYPHS];
1915
1916 if (!the_gdk_cursors[GDK_BASED_ARROW_UP])
1917 {
1918 /* Need to initialize the array */
1919 /* Supposedly since this array is static it should be
1920 initialized to NULLs for us, but I'm very paranoid. */
1921 for (i = 0; i < GDK_NUM_GLYPHS; i++)
1922 {
1923 the_gdk_cursors[i] = NULL;
1924 }
1925
1926 #define FROB_CURSOR(x) the_gdk_cursors[GDK_##x] = __downcase(#x)
1927 FROB_CURSOR(ARROW); FROB_CURSOR(BASED_ARROW_DOWN);
1928 FROB_CURSOR(BASED_ARROW_UP); FROB_CURSOR(BOAT);
1929 FROB_CURSOR(BOGOSITY); FROB_CURSOR(BOTTOM_LEFT_CORNER);
1930 FROB_CURSOR(BOTTOM_RIGHT_CORNER); FROB_CURSOR(BOTTOM_SIDE);
1931 FROB_CURSOR(BOTTOM_TEE); FROB_CURSOR(BOX_SPIRAL);
1932 FROB_CURSOR(CENTER_PTR); FROB_CURSOR(CIRCLE);
1933 FROB_CURSOR(CLOCK); FROB_CURSOR(COFFEE_MUG);
1934 FROB_CURSOR(CROSS); FROB_CURSOR(CROSS_REVERSE);
1935 FROB_CURSOR(CROSSHAIR); FROB_CURSOR(DIAMOND_CROSS);
1936 FROB_CURSOR(DOT); FROB_CURSOR(DOTBOX);
1937 FROB_CURSOR(DOUBLE_ARROW); FROB_CURSOR(DRAFT_LARGE);
1938 FROB_CURSOR(DRAFT_SMALL); FROB_CURSOR(DRAPED_BOX);
1939 FROB_CURSOR(EXCHANGE); FROB_CURSOR(FLEUR);
1940 FROB_CURSOR(GOBBLER); FROB_CURSOR(GUMBY);
1941 FROB_CURSOR(HAND1); FROB_CURSOR(HAND2);
1942 FROB_CURSOR(HEART); FROB_CURSOR(ICON);
1943 FROB_CURSOR(IRON_CROSS); FROB_CURSOR(LEFT_PTR);
1944 FROB_CURSOR(LEFT_SIDE); FROB_CURSOR(LEFT_TEE);
1945 FROB_CURSOR(LEFTBUTTON); FROB_CURSOR(LL_ANGLE);
1946 FROB_CURSOR(LR_ANGLE); FROB_CURSOR(MAN);
1947 FROB_CURSOR(MIDDLEBUTTON); FROB_CURSOR(MOUSE);
1948 FROB_CURSOR(PENCIL); FROB_CURSOR(PIRATE);
1949 FROB_CURSOR(PLUS); FROB_CURSOR(QUESTION_ARROW);
1950 FROB_CURSOR(RIGHT_PTR); FROB_CURSOR(RIGHT_SIDE);
1951 FROB_CURSOR(RIGHT_TEE); FROB_CURSOR(RIGHTBUTTON);
1952 FROB_CURSOR(RTL_LOGO); FROB_CURSOR(SAILBOAT);
1953 FROB_CURSOR(SB_DOWN_ARROW); FROB_CURSOR(SB_H_DOUBLE_ARROW);
1954 FROB_CURSOR(SB_LEFT_ARROW); FROB_CURSOR(SB_RIGHT_ARROW);
1955 FROB_CURSOR(SB_UP_ARROW); FROB_CURSOR(SB_V_DOUBLE_ARROW);
1956 FROB_CURSOR(SHUTTLE); FROB_CURSOR(SIZING);
1957 FROB_CURSOR(SPIDER); FROB_CURSOR(SPRAYCAN);
1958 FROB_CURSOR(STAR); FROB_CURSOR(TARGET);
1959 FROB_CURSOR(TCROSS); FROB_CURSOR(TOP_LEFT_ARROW);
1960 FROB_CURSOR(TOP_LEFT_CORNER); FROB_CURSOR(TOP_RIGHT_CORNER);
1961 FROB_CURSOR(TOP_SIDE); FROB_CURSOR(TOP_TEE);
1962 FROB_CURSOR(TREK); FROB_CURSOR(UL_ANGLE);
1963 FROB_CURSOR(UMBRELLA); FROB_CURSOR(UR_ANGLE);
1964 FROB_CURSOR(WATCH); FROB_CURSOR(XTERM);
1965 FROB_CURSOR(X_CURSOR);
1966 #undef FROB_CURSOR
1967 }
1968
1969 for (i = 0; i < GDK_NUM_GLYPHS; i++)
1970 {
1971 if (!the_gdk_cursors[i]) continue;
1972 if (!strcmp (the_gdk_cursors[i], name))
1973 {
1974 return (i);
1975 }
1976 }
1977 return(-1);
1978 }
1979
1980 static void
1981 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1982 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1983 int dest_mask, Lisp_Object domain)
1984 {
1985 /* This function can GC */
1986 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1987 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1988 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1989 int i;
1990 CONST char *name_ext;
1991 Lisp_Object foreground, background;
1992
1993 if (!DEVICE_GTK_P (XDEVICE (device)))
1994 signal_simple_error ("Not a Gtk device", device);
1995
1996 if (!(dest_mask & IMAGE_POINTER_MASK))
1997 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1998
1999 TO_EXTERNAL_FORMAT (LISP_STRING, data,
2000 C_STRING_ALLOCA, name_ext,
2001 Qfile_name);
2002
2003 if ((i = cursor_name_to_index (name_ext)) == -1)
2004 signal_simple_error ("Unrecognized cursor-font name", data);
2005
2006 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2007 IMAGE_INSTANCE_GTK_CURSOR (ii) = gdk_cursor_new (i);
2008 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2009 if (NILP (foreground))
2010 foreground = pointer_fg;
2011 background = find_keyword_in_vector (instantiator, Q_background);
2012 if (NILP (background))
2013 background = pointer_bg;
2014 maybe_recolor_cursor (image_instance, foreground, background);
2015 }
2016
2017 static int
2018 gtk_colorize_image_instance (Lisp_Object image_instance,
2019 Lisp_Object foreground, Lisp_Object background);
2020
2021
2022 /************************************************************************/
2023 /* subwindow and widget support */
2024 /************************************************************************/
2025
2026 /* unmap the image if it is a widget. This is used by redisplay via
2027 redisplay_unmap_subwindows */
2028 static void
2029 gtk_unmap_subwindow (Lisp_Image_Instance *p)
2030 {
2031 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2032 {
2033 /* We don't support subwindows, but we do support widgets... */
2034 abort ();
2035 }
2036 else /* must be a widget */
2037 {
2038 /* Since we are being unmapped we want the enclosing frame to
2039 get focus. The losing with simple scrolling but is the safest
2040 thing to do. */
2041 if (IMAGE_INSTANCE_GTK_CLIPWIDGET (p))
2042 gtk_widget_unmap (IMAGE_INSTANCE_GTK_CLIPWIDGET (p));
2043 }
2044 }
2045
2046 /* map the subwindow. This is used by redisplay via
2047 redisplay_output_subwindow */
2048 static void
2049 gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2050 struct display_glyph_area* dga)
2051 {
2052 assert (dga->width > 0 && dga->height > 0);
2053
2054 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2055 {
2056 /* No subwindow support... */
2057 abort ();
2058 }
2059 else /* must be a widget */
2060 {
2061 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2062 GtkWidget *wid = IMAGE_INSTANCE_GTK_CLIPWIDGET (p);
2063 GtkAllocation a;
2064
2065 if (!wid) return;
2066
2067 a.x = x + IMAGE_INSTANCE_GTK_WIDGET_XOFFSET (p);
2068 a.y = y + IMAGE_INSTANCE_GTK_WIDGET_YOFFSET (p);
2069 a.width = dga->width;
2070 a.height = dga->height;
2071
2072 if ((a.width != wid->allocation.width) ||
2073 (a.height != wid->allocation.height))
2074 {
2075 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a);
2076 }
2077
2078 /* #### FIXME DAMMIT */
2079 if ((wid->allocation.x != -dga->xoffset) ||
2080 (wid->allocation.y != -dga->yoffset))
2081 {
2082 guint32 old_flags = GTK_WIDGET_FLAGS (FRAME_GTK_TEXT_WIDGET (f));
2083
2084 /* Fucking GtkFixed widget queues a resize when you add a widget.
2085 ** But only if it is visible.
2086 ** losers.
2087 */
2088 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) &= ~GTK_VISIBLE;
2089 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p))
2090 {
2091 gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)),
2092 wid,
2093 -dga->xoffset, -dga->yoffset);
2094 }
2095 else
2096 {
2097 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE;
2098 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)),
2099 wid,
2100 -dga->xoffset, -dga->yoffset);
2101 }
2102 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) = old_flags;
2103 }
2104
2105 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2106 {
2107 gtk_widget_map (wid);
2108 }
2109
2110 gtk_widget_draw (wid, NULL);
2111 }
2112 }
2113
2114 /* when you click on a widget you may activate another widget this
2115 needs to be checked and all appropriate widgets updated */
2116 static void
2117 gtk_redisplay_subwindow (Lisp_Image_Instance *p)
2118 {
2119 /* Update the subwindow size if necessary. */
2120 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2121 {
2122 #if 0
2123 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2124 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2125 IMAGE_INSTANCE_WIDTH (p),
2126 IMAGE_INSTANCE_HEIGHT (p));
2127 #endif
2128 }
2129 }
2130
2131 /* Update all attributes that have changed. */
2132 static void
2133 gtk_redisplay_widget (Lisp_Image_Instance *p)
2134 {
2135 /* This function can GC if IN_REDISPLAY is false. */
2136
2137 if (!IMAGE_INSTANCE_GTK_CLIPWIDGET (p))
2138 return;
2139
2140 #ifdef HAVE_WIDGETS
2141 /* First get the items if they have changed since this is a
2142 structural change. As such it will nuke all added values so we
2143 need to update most other things after the items have changed.*/
2144 gtk_widget_show_all (IMAGE_INSTANCE_GTK_CLIPWIDGET (p));
2145 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2146 {
2147 Lisp_Object image_instance;
2148
2149 XSETIMAGE_INSTANCE (image_instance, p);
2150
2151 /* Need to update GtkArgs that might have changed... */
2152 /* #### FIXME!!! */
2153 }
2154 else
2155 {
2156 /* #### FIXME!!! */
2157 /* No items changed, so do nothing, right? */
2158 }
2159
2160 /* Possibly update the colors and font */
2161 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2162 ||
2163 /* #### This is not sufficient because it will not cope with widgets
2164 that are not currently visible. Once redisplay has done the
2165 visible ones it will clear this flag so that when new ones
2166 become visible they will not be updated. */
2167 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2168 ||
2169 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
2170 ||
2171 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2172 {
2173 /* #### Write this function BILL! */
2174 update_widget_face (NULL, p, IMAGE_INSTANCE_FRAME (p));
2175 }
2176
2177 /* Possibly update the text. */
2178 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2179 {
2180 char* str;
2181 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2182 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2183
2184 /* #### Need to special case each type of GtkWidget here! */
2185 }
2186
2187 /* Possibly update the size. */
2188 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2189 ||
2190 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2191 ||
2192 IMAGE_INSTANCE_TEXT_CHANGED (p))
2193 {
2194 assert (IMAGE_INSTANCE_GTK_WIDGET_ID (p) &&
2195 IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) ;
2196
2197 /* #### Resize the widget! */
2198 /* gtk_widget_size_allocate () */
2199 }
2200
2201 /* Adjust offsets within the frame. */
2202 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2203 {
2204 /* I don't think we need to do anything for Gtk here... */
2205 }
2206
2207 /* now modify the widget */
2208 #endif
2209 }
2210
2211 /* instantiate and gtk type subwindow */
2212 static void
2213 gtk_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2214 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2215 int dest_mask, Lisp_Object domain)
2216 {
2217 /* This function can GC */
2218 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2219 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2220 Lisp_Object frame = DOMAIN_FRAME (domain);
2221
2222 if (!DEVICE_GTK_P (XDEVICE (device)))
2223 signal_simple_error ("Not a GTK device", device);
2224
2225 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2226
2227 ii->data = xnew_and_zero (struct gtk_subwindow_data);
2228
2229 /* Create a window for clipping */
2230 IMAGE_INSTANCE_GTK_CLIPWINDOW (ii) = NULL;
2231
2232 /* Now put the subwindow inside the clip window. */
2233 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) NULL;
2234 }
2235
2236 #ifdef HAVE_WIDGETS
2237
2238 /************************************************************************/
2239 /* widgets */
2240 /************************************************************************/
2241 static void
2242 update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
2243 Lisp_Object domain)
2244 {
2245 if (0)
2246 {
2247 GtkStyle *style = gtk_widget_get_style (w);
2248 Lisp_Object pixel = Qnil;
2249 GdkColor *fcolor, *bcolor;
2250
2251 style = gtk_style_copy (style);
2252
2253 /* Update the foreground. */
2254 pixel = FACE_FOREGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain);
2255 fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel));
2256
2257 /* Update the background. */
2258 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain);
2259 bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel));
2260
2261 /* Update the font */
2262 /* #### FIXME!!! Need to copy the widgets style, dick with it, and
2263 ** set the widgets style to the new style...
2264 */
2265 gtk_widget_set_style (w, style);
2266
2267 /* #### Megahack - but its just getting too complicated to do this
2268 in the right place. */
2269 #if 0
2270 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2271 update_tab_widget_face (wv, ii, domain);
2272 #endif
2273 }
2274 }
2275
2276 #if 0
2277 static void
2278 update_tab_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
2279 Lisp_Object domain)
2280 {
2281 if (wv->contents)
2282 {
2283 widget_value* val = wv->contents, *cur;
2284
2285 /* Give each child label the correct foreground color. */
2286 Lisp_Object pixel = FACE_FOREGROUND
2287 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2288 domain);
2289 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2290 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2291 wv->change = VISIBLE_CHANGE;
2292 val->change = VISIBLE_CHANGE;
2293
2294 for (cur = val->next; cur; cur = cur->next)
2295 {
2296 cur->change = VISIBLE_CHANGE;
2297 if (cur->value)
2298 {
2299 lw_copy_widget_value_args (val, cur);
2300 }
2301 }
2302 }
2303 }
2304 #endif
2305
2306 static Lisp_Object
2307 gtk_widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
2308 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2309 Lisp_Object domain)
2310 {
2311 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2312 Lisp_Object widget = Qnil;
2313 char *nm = NULL;
2314 GtkWidget *w = NULL;
2315 struct gcpro gcpro1;
2316
2317 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2318
2319 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2320 {
2321 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2322 }
2323
2324 ii->data = xnew_and_zero (struct gtk_subwindow_data);
2325
2326 /* Create a clipping widget */
2327 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = NULL;
2328 IMAGE_INSTANCE_GTK_ALREADY_PUT(ii) = FALSE;
2329
2330 /* Create the actual widget */
2331 GCPRO1 (widget);
2332 widget = call5 (Qgtk_widget_instantiate_internal,
2333 image_instance, instantiator,
2334 pointer_fg, pointer_bg,
2335 domain);
2336
2337 if (!NILP (widget))
2338 {
2339 CHECK_GTK_OBJECT (widget);
2340 w = GTK_WIDGET (XGTK_OBJECT (widget)->object);
2341 }
2342 else
2343 {
2344 stderr_out ("Lisp-level creation of widget failed... falling back\n");
2345 w = gtk_label_new ("Widget Creation Failed...");
2346 }
2347
2348 UNGCPRO;
2349
2350 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) w;
2351
2352 /* #### HACK!!!! We should make this do the right thing if we
2353 ** really need a clip widget!
2354 */
2355 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = w;
2356
2357 return (Qt);
2358 }
2359
2360 static void
2361 gtk_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2362 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2363 int dest_mask, Lisp_Object domain)
2364 {
2365 call_with_suspended_errors ((lisp_fn_t) gtk_widget_instantiate_1,
2366 Qnil, Qimage,
2367 ERROR_ME_WARN, 5,
2368 image_instance, instantiator,
2369 pointer_fg,
2370 pointer_bg,
2371 domain);
2372 }
2373
2374 /* get properties of a control */
2375 static Lisp_Object
2376 gtk_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2377 {
2378 /* Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); */
2379
2380 /* get the text from a control */
2381 if (EQ (prop, Q_text))
2382 {
2383 return Qnil;
2384 }
2385 return Qunbound;
2386 }
2387
2388 #define FAKE_GTK_WIDGET_INSTANTIATOR(x) \
2389 static void \
2390 gtk_##x##_instantiate (Lisp_Object image_instance, \
2391 Lisp_Object instantiator, \
2392 Lisp_Object pointer_fg, \
2393 Lisp_Object pointer_bg, \
2394 int dest_mask, Lisp_Object domain) \
2395 { \
2396 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, \
2397 pointer_bg, dest_mask, domain); \
2398 }
2399
2400 FAKE_GTK_WIDGET_INSTANTIATOR(native_layout);
2401 FAKE_GTK_WIDGET_INSTANTIATOR(button);
2402 FAKE_GTK_WIDGET_INSTANTIATOR(progress_gauge);
2403 FAKE_GTK_WIDGET_INSTANTIATOR(edit_field);
2404 FAKE_GTK_WIDGET_INSTANTIATOR(combo_box);
2405 FAKE_GTK_WIDGET_INSTANTIATOR(tab_control);
2406 FAKE_GTK_WIDGET_INSTANTIATOR(label);
2407
2408 /* Update a button's clicked state. */
2409 static void
2410 gtk_button_redisplay (Lisp_Object image_instance)
2411 {
2412 /* This function can GC if IN_REDISPLAY is false. */
2413 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2414 GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p);
2415
2416 if (GTK_WIDGET_TYPE (w) == gtk_button_get_type ())
2417 {
2418 }
2419 else if (GTK_WIDGET_TYPE (w) == gtk_check_button_get_type ())
2420 {
2421 }
2422 else if (GTK_WIDGET_TYPE (w) == gtk_radio_button_get_type ())
2423 {
2424 }
2425 else
2426 {
2427 /* Unknown button type... */
2428 abort();
2429 }
2430 }
2431
2432 /* get properties of a button */
2433 static Lisp_Object
2434 gtk_button_property (Lisp_Object image_instance, Lisp_Object prop)
2435 {
2436 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2437
2438 /* check the state of a button */
2439 if (EQ (prop, Q_selected))
2440 {
2441 if (GTK_WIDGET_HAS_FOCUS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)))
2442 return Qt;
2443 else
2444 return Qnil;
2445 }
2446 return Qunbound;
2447 }
2448
2449 /* set the properties of a progress gauge */
2450 static void
2451 gtk_progress_gauge_redisplay (Lisp_Object image_instance)
2452 {
2453 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2454
2455 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2456 {
2457 gfloat f;
2458 Lisp_Object val;
2459
2460 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2461 f = XFLOATINT (val);
2462
2463 gtk_progress_set_value (GTK_PROGRESS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)),
2464 f);
2465 }
2466 }
2467
2468 /* Set the properties of a tab control */
2469 static void
2470 gtk_tab_control_redisplay (Lisp_Object image_instance)
2471 {
2472 /* #### Convert this to GTK baby! */
2473 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2474
2475 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) ||
2476 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2477 {
2478 /* If only the order has changed then simply select the first
2479 one of the pending set. This stops horrendous rebuilding -
2480 and hence flicker - of the tabs each time you click on
2481 one. */
2482 if (tab_control_order_only_changed (image_instance))
2483 {
2484 Lisp_Object rest, selected =
2485 gui_item_list_find_selected
2486 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2487 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2488 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2489
2490 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2491 {
2492 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2493 {
2494 Lisp_Object old_selected =gui_item_list_find_selected
2495 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2496
2497 /* Need to focus on the widget... */
2498 stderr_out ("Hey, change the tab-focus you boob...\n");
2499
2500 /* Pick up the new selected item. */
2501 XGUI_ITEM (old_selected)->selected =
2502 XGUI_ITEM (XCAR (rest))->selected;
2503 XGUI_ITEM (XCAR (rest))->selected =
2504 XGUI_ITEM (selected)->selected;
2505 /* We're not actually changing the items anymore. */
2506 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2507 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2508 break;
2509 }
2510 }
2511 }
2512 else
2513 {
2514 /* More than just the order has changed... let's get busy! */
2515 GtkNotebook *nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii));
2516 guint num_pages = g_list_length (nb->children);
2517 Lisp_Object rest;
2518
2519 if (num_pages >= 0)
2520 {
2521 int i;
2522 for (i = num_pages; i >= 0; --i)
2523 {
2524 gtk_notebook_remove_page (nb, i);
2525 }
2526 }
2527
2528 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2529 {
2530 Lisp_Gui_Item *pgui = XGUI_ITEM (XCAR (rest));
2531 char *c_name = NULL;
2532
2533 if (!STRINGP (pgui->name))
2534 pgui->name = Feval (pgui->name);
2535
2536 CHECK_STRING (pgui->name);
2537
2538 TO_EXTERNAL_FORMAT (LISP_STRING, pgui->name,
2539 C_STRING_ALLOCA, c_name,
2540 Qctext);
2541
2542 gtk_notebook_append_page (nb,
2543 gtk_vbox_new (FALSE, 3),
2544 gtk_label_new (c_name));
2545 }
2546
2547 /* Show all the new widgets we just added... */
2548 gtk_widget_show_all (GTK_WIDGET (nb));
2549 }
2550 }
2551
2552 /* Possibly update the face. */
2553 #if 0
2554 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2555 ||
2556 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2557 ||
2558 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2559 {
2560 update_tab_widget_face (wv, ii,
2561 IMAGE_INSTANCE_FRAME (ii));
2562 }
2563 #endif
2564 }
2565 #endif /* HAVE_WIDGETS */
2566
2567
2568 /************************************************************************/
2569 /* initialization */
2570 /************************************************************************/
2571 void
2572 syms_of_glyphs_gtk (void)
2573 {
2574 defkeyword (&Q_resource_id, ":resource-id");
2575 defkeyword (&Q_resource_type, ":resource-type");
2576 #ifdef HAVE_WIDGETS
2577 defsymbol (&Qgtk_widget_instantiate_internal, "gtk-widget-instantiate-internal");
2578 defsymbol (&Qgtk_widget_property_internal, "gtk-widget-property-internal");
2579 defsymbol (&Qgtk_widget_redisplay_internal, "gtk-widget-redisplay-internal");
2580 defsymbol (&Qgtk_widget_set_style, "gtk-widget-set-style");
2581 #endif
2582 }
2583
2584 void
2585 console_type_create_glyphs_gtk (void)
2586 {
2587 /* image methods */
2588 CONSOLE_HAS_METHOD (gtk, print_image_instance);
2589 CONSOLE_HAS_METHOD (gtk, finalize_image_instance);
2590 CONSOLE_HAS_METHOD (gtk, image_instance_equal);
2591 CONSOLE_HAS_METHOD (gtk, image_instance_hash);
2592 CONSOLE_HAS_METHOD (gtk, colorize_image_instance);
2593 CONSOLE_HAS_METHOD (gtk, init_image_instance_from_eimage);
2594 CONSOLE_HAS_METHOD (gtk, locate_pixmap_file);
2595 CONSOLE_HAS_METHOD (gtk, unmap_subwindow);
2596 CONSOLE_HAS_METHOD (gtk, map_subwindow);
2597 CONSOLE_HAS_METHOD (gtk, redisplay_widget);
2598 CONSOLE_HAS_METHOD (gtk, redisplay_subwindow);
2599 }
2600
2601 void
2602 image_instantiator_format_create_glyphs_gtk (void)
2603 {
2604 IIFORMAT_VALID_CONSOLE (gtk, nothing);
2605 IIFORMAT_VALID_CONSOLE (gtk, string);
2606 #ifdef HAVE_WIDGETS
2607 IIFORMAT_VALID_CONSOLE (gtk, layout);
2608 #endif
2609 IIFORMAT_VALID_CONSOLE (gtk, formatted_string);
2610 IIFORMAT_VALID_CONSOLE (gtk, inherit);
2611 #ifdef HAVE_XPM
2612 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm);
2613 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate);
2614 #endif
2615 #ifdef HAVE_JPEG
2616 IIFORMAT_VALID_CONSOLE (gtk, jpeg);
2617 #endif
2618 #ifdef HAVE_TIFF
2619 IIFORMAT_VALID_CONSOLE (gtk, tiff);
2620 #endif
2621 #ifdef HAVE_PNG
2622 IIFORMAT_VALID_CONSOLE (gtk, png);
2623 #endif
2624 #ifdef HAVE_GIF
2625 IIFORMAT_VALID_CONSOLE (gtk, gif);
2626 #endif
2627
2628 INITIALIZE_DEVICE_IIFORMAT (gtk, subwindow);
2629 IIFORMAT_HAS_DEVMETHOD (gtk, subwindow, instantiate);
2630
2631 #ifdef HAVE_WIDGETS
2632 /* layout widget */
2633 INITIALIZE_DEVICE_IIFORMAT (gtk, native_layout);
2634 IIFORMAT_HAS_DEVMETHOD (gtk, native_layout, instantiate);
2635
2636 /* button widget */
2637 INITIALIZE_DEVICE_IIFORMAT (gtk, button);
2638 IIFORMAT_HAS_DEVMETHOD (gtk, button, property);
2639 IIFORMAT_HAS_DEVMETHOD (gtk, button, instantiate);
2640 IIFORMAT_HAS_DEVMETHOD (gtk, button, redisplay);
2641 /* general widget methods. */
2642 INITIALIZE_DEVICE_IIFORMAT (gtk, widget);
2643 IIFORMAT_HAS_DEVMETHOD (gtk, widget, property);
2644
2645 /* progress gauge */
2646 INITIALIZE_DEVICE_IIFORMAT (gtk, progress_gauge);
2647 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, redisplay);
2648 IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, instantiate);
2649 /* text field */
2650 INITIALIZE_DEVICE_IIFORMAT (gtk, edit_field);
2651 IIFORMAT_HAS_DEVMETHOD (gtk, edit_field, instantiate);
2652 INITIALIZE_DEVICE_IIFORMAT (gtk, combo_box);
2653 IIFORMAT_HAS_DEVMETHOD (gtk, combo_box, instantiate);
2654 IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, combo_box, redisplay, tab_control);
2655 /* tab control widget */
2656 INITIALIZE_DEVICE_IIFORMAT (gtk, tab_control);
2657 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, instantiate);
2658 IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, redisplay);
2659 /* label */
2660 INITIALIZE_DEVICE_IIFORMAT (gtk, label);
2661 IIFORMAT_HAS_DEVMETHOD (gtk, label, instantiate);
2662 #endif
2663
2664 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2665 IIFORMAT_VALID_CONSOLE (gtk, cursor_font);
2666
2667 IIFORMAT_HAS_METHOD (cursor_font, validate);
2668 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2669 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2670
2671 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2672 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2673 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2674
2675 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2676 IIFORMAT_VALID_CONSOLE (gtk, font);
2677
2678 IIFORMAT_HAS_METHOD (font, validate);
2679 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2680 IIFORMAT_HAS_METHOD (font, instantiate);
2681
2682 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2683 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2684 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2685
2686 #ifdef HAVE_XPM
2687 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm);
2688 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate);
2689 #endif
2690
2691 #ifdef HAVE_XFACE
2692 INITIALIZE_DEVICE_IIFORMAT (gtk, xface);
2693 IIFORMAT_HAS_DEVMETHOD (gtk, xface, instantiate);
2694 #endif
2695
2696 INITIALIZE_DEVICE_IIFORMAT (gtk, xbm);
2697 IIFORMAT_HAS_DEVMETHOD (gtk, xbm, instantiate);
2698 IIFORMAT_VALID_CONSOLE (gtk, xbm);
2699
2700 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource, "gtk-resource");
2701 IIFORMAT_VALID_CONSOLE (gtk, gtk_resource);
2702
2703 IIFORMAT_HAS_METHOD (gtk_resource, validate);
2704 IIFORMAT_HAS_METHOD (gtk_resource, normalize);
2705 IIFORMAT_HAS_METHOD (gtk_resource, possible_dest_types);
2706 IIFORMAT_HAS_METHOD (gtk_resource, instantiate);
2707
2708 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_type, check_valid_resource_symbol);
2709 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_resource_id, check_valid_resource_id);
2710 IIFORMAT_VALID_KEYWORD (gtk_resource, Q_file, check_valid_string);
2711
2712 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect, "autodetect");
2713 IIFORMAT_VALID_CONSOLE (gtk, autodetect);
2714
2715 IIFORMAT_HAS_METHOD (autodetect, validate);
2716 IIFORMAT_HAS_METHOD (autodetect, normalize);
2717 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2718 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2719
2720 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2721 }
2722
2723 void
2724 vars_of_glyphs_gtk (void)
2725 {
2726 #ifdef HAVE_XFACE
2727 Fprovide (Qxface);
2728 #endif
2729
2730 DEFVAR_LISP ("gtk-bitmap-file-path", &Vgtk_bitmap_file_path /*
2731 A list of the directories in which X bitmap files may be found.
2732 If nil, this is initialized from the "*bitmapFilePath" resource.
2733 This is used by the `make-image-instance' function (however, note that if
2734 the environment variable XBMLANGPATH is set, it is consulted first).
2735 */ );
2736 Vgtk_bitmap_file_path = Qnil;
2737 }
2738
2739 void
2740 complex_vars_of_glyphs_gtk (void)
2741 {
2742 #define BUILD_GLYPH_INST(variable, name) \
2743 Fadd_spec_to_specifier \
2744 (GLYPH_IMAGE (XGLYPH (variable)), \
2745 vector3 (Qxbm, Q_data, \
2746 list3 (make_int (name##_width), \
2747 make_int (name##_height), \
2748 make_ext_string (name##_bits, \
2749 sizeof (name##_bits), \
2750 Qbinary))), \
2751 Qglobal, Qgtk, Qnil)
2752
2753 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2754 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2755 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2756 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2757
2758 #undef BUILD_GLYPH_INST
2759 }
2760
2761
2762 /* Ripped off from glyphs-msw.c */
2763 /*
2764 * The data returned by the following routine is always in left-most byte
2765 * first and left-most bit first. If it doesn't return BitmapSuccess then
2766 * its arguments won't have been touched. This routine should look as much
2767 * like the Xlib routine XReadBitmapfile as possible.
2768 */
2769 #define MAX_SIZE 1024
2770
2771 /* shared data for the image read/parse logic */
2772 static short hexTable[256]; /* conversion value */
2773 static int initialized = FALSE; /* easier to fill in at run time */
2774
2775 /*
2776 * Table index for the hex values. Initialized once, first time.
2777 * Used for translation value or delimiter significance lookup.
2778 */
2779 static void initHexTable()
2780 {
2781 /*
2782 * We build the table at run time for several reasons:
2783 *
2784 * 1. portable to non-ASCII machines.
2785 * 2. still reentrant since we set the init flag after setting table.
2786 * 3. easier to extend.
2787 * 4. less prone to bugs.
2788 */
2789 hexTable['0'] = 0; hexTable['1'] = 1;
2790 hexTable['2'] = 2; hexTable['3'] = 3;
2791 hexTable['4'] = 4; hexTable['5'] = 5;
2792 hexTable['6'] = 6; hexTable['7'] = 7;
2793 hexTable['8'] = 8; hexTable['9'] = 9;
2794 hexTable['A'] = 10; hexTable['B'] = 11;
2795 hexTable['C'] = 12; hexTable['D'] = 13;
2796 hexTable['E'] = 14; hexTable['F'] = 15;
2797 hexTable['a'] = 10; hexTable['b'] = 11;
2798 hexTable['c'] = 12; hexTable['d'] = 13;
2799 hexTable['e'] = 14; hexTable['f'] = 15;
2800
2801 /* delimiters of significance are flagged w/ negative value */
2802 hexTable[' '] = -1; hexTable[','] = -1;
2803 hexTable['}'] = -1; hexTable['\n'] = -1;
2804 hexTable['\t'] = -1;
2805
2806 initialized = TRUE;
2807 }
2808
2809 /*
2810 * read next hex value in the input stream, return -1 if EOF
2811 */
2812 static int NextInt ( FILE *fstream )
2813 {
2814 int ch;
2815 int value = 0;
2816 int gotone = 0;
2817 int done = 0;
2818
2819 /* loop, accumulate hex value until find delimiter */
2820 /* skip any initial delimiters found in read stream */
2821
2822 while (!done) {
2823 ch = getc(fstream);
2824 if (ch == EOF) {
2825 value = -1;
2826 done++;
2827 } else {
2828 /* trim high bits, check type and accumulate */
2829 ch &= 0xff;
2830 if (isascii(ch) && isxdigit(ch)) {
2831 value = (value << 4) + hexTable[ch];
2832 gotone++;
2833 } else if ((hexTable[ch]) < 0 && gotone)
2834 done++;
2835 }
2836 }
2837 return value;
2838 }
2839
2840 int read_bitmap_data (fstream, width, height, datap, x_hot, y_hot)
2841 FILE *fstream; /* handle on file */
2842 unsigned int *width, *height; /* RETURNED */
2843 unsigned char **datap; /* RETURNED */
2844 int *x_hot, *y_hot; /* RETURNED */
2845 {
2846 unsigned char *data = NULL; /* working variable */
2847 char line[MAX_SIZE]; /* input line from file */
2848 int size; /* number of bytes of data */
2849 char name_and_type[MAX_SIZE]; /* an input line */
2850 char *type; /* for parsing */
2851 int value; /* from an input line */
2852 int version10p; /* boolean, old format */
2853 int padding; /* to handle alignment */
2854 int bytes_per_line; /* per scanline of data */
2855 unsigned int ww = 0; /* width */
2856 unsigned int hh = 0; /* height */
2857 int hx = -1; /* x hotspot */
2858 int hy = -1; /* y hotspot */
2859
2860 #define Xmalloc(size) malloc(size)
2861
2862 /* first time initialization */
2863 if (initialized == FALSE) initHexTable();
2864
2865 /* error cleanup and return macro */
2866 #define RETURN(code) { if (data) free (data); return code; }
2867
2868 while (fgets(line, MAX_SIZE, fstream)) {
2869 if (strlen(line) == MAX_SIZE-1) {
2870 RETURN (BitmapFileInvalid);
2871 }
2872 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
2873 if (!(type = strrchr(name_and_type, '_')))
2874 type = name_and_type;
2875 else
2876 type++;
2877
2878 if (!strcmp("width", type))
2879 ww = (unsigned int) value;
2880 if (!strcmp("height", type))
2881 hh = (unsigned int) value;
2882 if (!strcmp("hot", type)) {
2883 if (type-- == name_and_type || type-- == name_and_type)
2884 continue;
2885 if (!strcmp("x_hot", type))
2886 hx = value;
2887 if (!strcmp("y_hot", type))
2888 hy = value;
2889 }
2890 continue;
2891 }
2892
2893 if (sscanf(line, "static short %s = {", name_and_type) == 1)
2894 version10p = 1;
2895 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
2896 version10p = 0;
2897 else if (sscanf(line, "static char %s = {", name_and_type) == 1)
2898 version10p = 0;
2899 else
2900 continue;
2901
2902 if (!(type = strrchr(name_and_type, '_')))
2903 type = name_and_type;
2904 else
2905 type++;
2906
2907 if (strcmp("bits[]", type))
2908 continue;
2909
2910 if (!ww || !hh)
2911 RETURN (BitmapFileInvalid);
2912
2913 if ((ww % 16) && ((ww % 16) < 9) && version10p)
2914 padding = 1;
2915 else
2916 padding = 0;
2917
2918 bytes_per_line = (ww+7)/8 + padding;
2919
2920 size = bytes_per_line * hh;
2921 data = (unsigned char *) Xmalloc ((unsigned int) size);
2922 if (!data)
2923 RETURN (BitmapNoMemory);
2924
2925 if (version10p) {
2926 unsigned char *ptr;
2927 int bytes;
2928
2929 for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
2930 if ((value = NextInt(fstream)) < 0)
2931 RETURN (BitmapFileInvalid);
2932 *(ptr++) = value;
2933 if (!padding || ((bytes+2) % bytes_per_line))
2934 *(ptr++) = value >> 8;
2935 }
2936 } else {
2937 unsigned char *ptr;
2938 int bytes;
2939
2940 for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
2941 if ((value = NextInt(fstream)) < 0)
2942 RETURN (BitmapFileInvalid);
2943 *ptr=value;
2944 }
2945 }
2946 break;
2947 } /* end while */
2948
2949 if (data == NULL) {
2950 RETURN (BitmapFileInvalid);
2951 }
2952
2953 *datap = data;
2954 data = NULL;
2955 *width = ww;
2956 *height = hh;
2957 if (x_hot) *x_hot = hx;
2958 if (y_hot) *y_hot = hy;
2959
2960 RETURN (BitmapSuccess);
2961 }
2962
2963
2964 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width,
2965 unsigned int *height, unsigned char **datap,
2966 int *x_hot, int *y_hot)
2967 {
2968 FILE *fstream;
2969 int rval;
2970
2971 if ((fstream = fopen (filename, "r")) == NULL) {
2972 return BitmapOpenFailed;
2973 }
2974 rval = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
2975 fclose (fstream);
2976 return rval;
2977 }
2978
2979 /* X specific crap */
2980 #include <gdk/gdkx.h>
2981 /* #### Should remove all this X specific stuff when GTK/GDK matures a
2982 bit more and provides an abstraction for it. */
2983 static int
2984 gtk_colorize_image_instance (Lisp_Object image_instance,
2985 Lisp_Object foreground, Lisp_Object background)
2986 {
2987 struct Lisp_Image_Instance *p;
2988
2989 p = XIMAGE_INSTANCE (image_instance);
2990
2991 switch (IMAGE_INSTANCE_TYPE (p))
2992 {
2993 case IMAGE_MONO_PIXMAP:
2994 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2995 /* Make sure there aren't two pointers to the same mask, causing
2996 it to get freed twice. */
2997 IMAGE_INSTANCE_GTK_MASK (p) = 0;
2998 break;
2999
3000 default:
3001 return 0;
3002 }
3003
3004 {
3005 GdkWindow *draw = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
3006 GdkPixmap *new_pxmp = gdk_pixmap_new (draw,
3007 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
3008 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
3009 DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
3010 GdkGCValues gcv;
3011 GdkGC *gc;
3012
3013 gcv.foreground = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground));
3014 gcv.background = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background));
3015 gc = gdk_gc_new_with_values (new_pxmp, &gcv, GDK_GC_BACKGROUND | GDK_GC_FOREGROUND);
3016
3017 XCopyPlane (GDK_WINDOW_XDISPLAY (draw),
3018 GDK_WINDOW_XWINDOW (IMAGE_INSTANCE_GTK_PIXMAP (p)),
3019 GDK_WINDOW_XWINDOW (new_pxmp),
3020 GDK_GC_XGC (gc), 0, 0,
3021 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
3022 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
3023 0, 0, 1);
3024
3025 gdk_gc_destroy (gc);
3026 IMAGE_INSTANCE_GTK_PIXMAP (p) = new_pxmp;
3027 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = DEVICE_GTK_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
3028 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
3029 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
3030 return 1;
3031 }
3032 }
3033