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
8 This file is part of XEmacs.
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
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
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. */
25 /* Synched up with: Not in FSF. */
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
46 Support the GrayScale, StaticColor and StaticGray visual classes.
47 Convert images.el to C and stick it in here?
53 #include "console-gtk.h"
55 #include "glyphs-gtk.h"
56 #include "objects-gtk.h"
74 #include "file-coding.h"
78 # define FOUR_BYTE_TYPE unsigned int
80 # define FOUR_BYTE_TYPE unsigned long
82 # define FOUR_BYTE_TYPE unsigned short
84 #error What kind of strange-ass system are we running on?
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);
92 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
95 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
105 DEFINE_DEVICE_IIFORMAT (gtk, xface);
110 DEFINE_DEVICE_IIFORMAT (gtk, xpm);
113 DEFINE_DEVICE_IIFORMAT (gtk, xbm);
114 DEFINE_DEVICE_IIFORMAT (gtk, subwindow);
116 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
117 Lisp_Object Qcursor_font;
119 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
121 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
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);
135 static void update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
137 static void cursor_font_instantiate (Lisp_Object image_instance,
138 Lisp_Object instantiator,
139 Lisp_Object pointer_fg,
140 Lisp_Object pointer_bg,
144 static gint cursor_name_to_index (const char *name);
146 #ifndef BitmapSuccess
147 #define BitmapSuccess 0
148 #define BitmapOpenFailed 1
149 #define BitmapFileInvalid 2
150 #define BitmapNoMemory 3
155 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource);
156 Lisp_Object Q_resource_type, Q_resource_id;
157 Lisp_Object Qgtk_resource;
159 Lisp_Object Qgtk_widget_instantiate_internal, Qgtk_widget_property_internal;
160 Lisp_Object Qgtk_widget_redisplay_internal, Qgtk_widget_set_style;
166 /************************************************************************/
167 /* image instance methods */
168 /************************************************************************/
170 /************************************************************************/
171 /* convert from a series of RGB triples to an XImage formated for the */
173 /************************************************************************/
175 convert_EImage_to_GDKImage (Lisp_Object device, int width, int height,
176 unsigned char *pic, unsigned long **pixtbl,
182 int depth, byte_cnt, i, j;
184 unsigned char *data, *ip, *dp = NULL;
185 quant_table *qtable = NULL;
191 cmap = DEVICE_GTK_COLORMAP (XDEVICE(device));
192 vis = DEVICE_GTK_VISUAL (XDEVICE(device));
193 depth = DEVICE_GTK_DEPTH(XDEVICE(device));
195 if (vis->type == GDK_VISUAL_GRAYSCALE || vis->type == GDK_VISUAL_STATIC_COLOR ||
196 vis->type == GDK_VISUAL_STATIC_GRAY)
198 /* #### Implement me!!! */
202 if (vis->type == GDK_VISUAL_PSEUDO_COLOR)
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;
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);
214 if (!outimg) return NULL;
216 byte_cnt = outimg->bpp;
218 data = (unsigned char *) outimg->mem;
222 gdk_image_destroy (outimg);
226 if (vis->type == GDK_VISUAL_PSEUDO_COLOR)
228 unsigned long pixarray[256];
230 /* use our quantize table to allocate the colors */
232 *pixtbl = xnew_array (unsigned long, pixcount);
235 /* ### should implement a sort by popularity to assure proper allocation */
237 for (i = 0; i < qtable->num_active_colors; i++)
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)
248 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
249 (*pixtbl)[n] = color.pixel;
252 pixarray[i] = color.pixel;
256 for (i = 0; i < height; i++)
258 dp = data + (i * outimg->bpl);
259 for (j = 0; j < width; j++)
264 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
266 if (outimg->byte_order == GDK_MSB_FIRST)
267 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
269 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
271 if (outimg->byte_order == GDK_MSB_FIRST)
272 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
274 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
280 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
281 junk = vis->red_mask;
283 while ((junk & 0x1) == 0)
294 junk = vis->green_mask;
296 while ((junk & 0x1) == 0)
307 junk = vis->blue_mask;
309 while ((junk & 0x1) == 0)
321 for (i = 0; i < height; i++)
323 dp = data + (i * outimg->bpl);
324 for (j = 0; j < width; j++)
327 rd = *ip++ << (rbits - 8);
329 rd = *ip++ >> (8 - rbits);
331 gr = *ip++ << (gbits - 8);
333 gr = *ip++ >> (8 - gbits);
335 bl = *ip++ << (bbits - 8);
337 bl = *ip++ >> (8 - bbits);
339 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
341 if (outimg->byte_order == GDK_MSB_FIRST)
342 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
344 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
346 if (outimg->byte_order == GDK_MSB_FIRST)
347 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
349 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
358 gtk_print_image_instance (struct Lisp_Image_Instance *p,
359 Lisp_Object printcharfun,
364 switch (IMAGE_INSTANCE_TYPE (p))
366 case IMAGE_MONO_PIXMAP:
367 case IMAGE_COLOR_PIXMAP:
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))
373 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_GTK_MASK (p));
374 write_c_string (buf, printcharfun);
376 write_c_string (")", printcharfun);
379 case IMAGE_SUBWINDOW:
380 /* #### implement me */
388 gtk_finalize_image_instance (struct Lisp_Image_Instance *p)
393 if (DEVICE_LIVE_P (XDEVICE (p->device)))
398 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
400 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
402 gtk_widget_destroy (IMAGE_INSTANCE_SUBWINDOW_ID (p));
404 /* We can release the callbacks again. */
406 /* ungcpro_popup_callbacks (...); */
408 /* IMAGE_INSTANCE_GTK_WIDGET_ID (p) = 0; */
409 IMAGE_INSTANCE_GTK_CLIPWIDGET (p) = 0;
413 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
420 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
421 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
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;
428 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p))
430 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
431 if (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i))
433 gdk_pixmap_unref (IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p,i));
434 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (p, i) = 0;
436 xfree (IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p));
437 IMAGE_INSTANCE_GTK_PIXMAP_SLICES (p) = 0;
440 if (IMAGE_INSTANCE_GTK_CURSOR (p))
442 gdk_cursor_destroy (IMAGE_INSTANCE_GTK_CURSOR (p));
443 IMAGE_INSTANCE_GTK_CURSOR (p) = 0;
449 if (IMAGE_INSTANCE_GTK_NPIXELS (p) != 0)
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;
460 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
461 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
462 && IMAGE_INSTANCE_GTK_PIXELS (p))
464 xfree (IMAGE_INSTANCE_GTK_PIXELS (p));
465 IMAGE_INSTANCE_GTK_PIXELS (p) = 0;
473 gtk_image_instance_equal (struct Lisp_Image_Instance *p1,
474 struct Lisp_Image_Instance *p2, int depth)
476 switch (IMAGE_INSTANCE_TYPE (p1))
478 case IMAGE_MONO_PIXMAP:
479 case IMAGE_COLOR_PIXMAP:
481 if (IMAGE_INSTANCE_GTK_COLORMAP (p1) != IMAGE_INSTANCE_GTK_COLORMAP (p2) ||
482 IMAGE_INSTANCE_GTK_NPIXELS (p1) != IMAGE_INSTANCE_GTK_NPIXELS (p2))
485 case IMAGE_SUBWINDOW:
486 /* #### implement me */
497 gtk_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
499 switch (IMAGE_INSTANCE_TYPE (p))
501 case IMAGE_MONO_PIXMAP:
502 case IMAGE_COLOR_PIXMAP:
504 return IMAGE_INSTANCE_GTK_NPIXELS (p);
506 case IMAGE_SUBWINDOW:
507 /* #### implement me */
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. */
522 gtk_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
524 enum image_instance_type type)
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;
540 /************************************************************************/
541 /* pixmap file functions */
542 /************************************************************************/
544 /* Where bitmaps are; initialized from resource database */
545 Lisp_Object Vgtk_bitmap_file_path;
548 #define BITMAPDIR "/usr/include/X11/bitmaps"
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. */
556 gtk_locate_pixmap_file (Lisp_Object name)
558 /* This function can GC if IN_REDISPLAY is false */
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) == '/')))))
569 if (!NILP (Ffile_readable_p (name)))
575 if (NILP (Vdefault_gtk_device))
576 /* This may occur during intialization. */
579 if (NILP (Vgtk_bitmap_file_path))
581 Vgtk_bitmap_file_path = nconc2 (Vgtk_bitmap_file_path,
582 (decode_path (BITMAPDIR)));
587 if (locate_file (Vgtk_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
589 Lisp_Object temp = list1 (Vdata_directory);
593 locate_file (temp, name, Qnil, &found, R_OK);
602 locate_pixmap_file (Lisp_Object name)
604 return gtk_locate_pixmap_file (name);
608 /************************************************************************/
609 /* cursor functions */
610 /************************************************************************/
612 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
613 not, signal an error. INSTANTIATOR is only used in the error
617 check_pointer_sizes (unsigned int width, unsigned int height,
618 Lisp_Object instantiator)
620 /* #### BILL!!! There is no way to call XQueryBestCursor from Gdk! */
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);
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);
638 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
639 Lisp_Object *background, GdkColor *xfg, GdkColor *xbg)
641 if (!NILP (*foreground) && !COLOR_INSTANCEP (*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));
650 xfg->red = xfg->green = xfg->blue = 0;
653 if (!NILP (*background) && !COLOR_INSTANCEP (*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));
662 xbg->red = xbg->green = xbg->blue = ~0;
667 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
668 Lisp_Object background)
672 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
675 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
676 if (!NILP (foreground) || !NILP (background))
678 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
679 XIMAGE_INSTANCE_GTK_CURSOR (image_instance),
681 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
682 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
685 /* stderr_out ("Don't know how to recolor cursors in Gtk!\n"); */
690 /************************************************************************/
691 /* color pixmap functions */
692 /************************************************************************/
694 /* Initialize an image instance from an XImage.
696 DEST_MASK specifies the mask of allowed image types.
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
708 If this fails, signal an error. INSTANTIATOR is only used
709 in the error message.
711 #### This should be able to handle conversion into `pointer'.
712 Use the same code as for `xpm'. */
715 init_image_instance_from_gdk_image (struct Lisp_Image_Instance *ii,
719 unsigned long *pixels,
722 Lisp_Object instantiator)
724 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
729 if (!DEVICE_GTK_P (XDEVICE (device)))
730 signal_simple_error ("Not a Gtk device", device);
732 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
734 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
735 incompatible_image_types (instantiator, dest_mask,
736 IMAGE_COLOR_PIXMAP_MASK);
738 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth);
740 signal_simple_error ("Unable to create pixmap", instantiator);
742 gc = gdk_gc_new (pixmap);
745 gdk_pixmap_unref (pixmap);
746 signal_simple_error ("Unable to create GC", instantiator);
749 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image,
750 0, 0, 0, 0, gdk_image->width, gdk_image->height);
754 gtk_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
756 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
757 find_keyword_in_vector (instantiator, Q_file);
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;
770 void init_image_instance_from_gdk_pixmap (struct Lisp_Image_Instance *ii,
771 struct device *device,
772 GdkPixmap *gdk_pixmap,
774 Lisp_Object instantiator)
777 gint width, height, depth;
779 if (!DEVICE_GTK_P (device))
782 IMAGE_INSTANCE_DEVICE (ii) = device;
783 IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP;
785 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (device));
787 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
788 incompatible_image_types (instantiator, dest_mask,
789 IMAGE_COLOR_PIXMAP_MASK);
791 gtk_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
793 gdk_window_get_geometry (gdk_pixmap, NULL, NULL, &width, &height, &depth);
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;
808 image_instance_add_gdk_image (Lisp_Image_Instance *ii,
811 Lisp_Object instantiator)
813 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
818 d = GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device)));
820 pixmap = gdk_pixmap_new (d, gdk_image->width, gdk_image->height, gdk_image->depth);
823 signal_simple_error ("Unable to create pixmap", instantiator);
825 gc = gdk_gc_new (pixmap);
829 gdk_pixmap_unref (pixmap);
830 signal_simple_error ("Unable to create GC", instantiator);
833 gdk_draw_image (GDK_DRAWABLE (pixmap), gc, gdk_image, 0, 0, 0, 0,
834 gdk_image->width, gdk_image->height);
838 IMAGE_INSTANCE_GTK_PIXMAP_SLICE (ii, slice) = pixmap;
842 gtk_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
843 int width, int height,
845 unsigned char *eimage,
847 Lisp_Object instantiator,
850 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
851 GdkColormap *cmap = DEVICE_GTK_COLORMAP (XDEVICE(device));
852 unsigned long *pixtbl = NULL;
858 for (slice = 0; slice < slices; slice++)
860 gdk_image = convert_EImage_to_GDKImage (device, width, height, eimage,
864 if (pixtbl) xfree (pixtbl);
865 signal_image_error("EImage to GdkImage conversion failed", instantiator);
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,
874 image_instance_add_gdk_image (ii, gdk_image, slice, instantiator);
878 gdk_image_destroy (gdk_image);
884 /* Given inline data for a mono pixmap, create and return the
885 corresponding X object. */
888 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
889 /* Note that data is in ext-format! */
892 return (gdk_bitmap_create_from_data (GET_GTK_WIDGET_WINDOW (DEVICE_GTK_APP_SHELL (XDEVICE (device))),
893 (char *) bits, width, height));
896 /* Given inline data for a mono pixmap, initialize the given
897 image instance accordingly. */
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! */
904 Lisp_Object instantiator,
905 Lisp_Object pointer_fg,
906 Lisp_Object pointer_bg,
909 Lisp_Object mask_filename)
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);
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));
922 gdk_color_black(cmap, &black);
923 gdk_color_white(cmap, &white);
925 if (!DEVICE_GTK_P (XDEVICE (device)))
926 signal_simple_error ("Not a Gtk device", device);
928 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
929 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
931 if (!NILP (foreground) || !NILP (background))
932 type = IMAGE_COLOR_PIXMAP;
934 type = IMAGE_MONO_PIXMAP;
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;
943 incompatible_image_types (instantiator, dest_mask,
944 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
945 | IMAGE_POINTER_MASK);
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);
955 case IMAGE_MONO_PIXMAP:
957 IMAGE_INSTANCE_GTK_PIXMAP (ii) =
958 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
962 case IMAGE_COLOR_PIXMAP:
964 gint d = DEVICE_GTK_DEPTH (XDEVICE(device));
966 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
968 Fmake_color_instance (foreground, device,
969 encode_error_behavior_flag (ERROR_ME));
971 if (COLOR_INSTANCEP (foreground))
972 fg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (foreground));
974 if (!NILP (background) && !COLOR_INSTANCEP (background))
976 Fmake_color_instance (background, device,
977 encode_error_behavior_flag (ERROR_ME));
979 if (COLOR_INSTANCEP (background))
980 bg = * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (background));
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
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;
996 GdkColor fg_color, bg_color;
999 check_pointer_sizes (width, height, instantiator);
1001 source = gdk_pixmap_create_from_data (draw, (char *) bits, width, height, 1, &black, &white);
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);
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);
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! */
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;
1043 if (!NILP (mask_data))
1045 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
1046 C_STRING_ALLOCA, gcc_may_you_rot_in_hell,
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);
1056 init_image_instance_from_xbm_inline (ii, width, height, bits,
1057 instantiator, pointer_fg, pointer_bg,
1058 dest_mask, mask, mask_file);
1061 /* Instantiate method for XBM's. */
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)
1068 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1069 CONST char *gcc_go_home;
1071 assert (!NILP (data));
1073 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
1074 C_STRING_ALLOCA, gcc_go_home,
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);
1084 /**********************************************************************
1086 **********************************************************************/
1088 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
1090 Lisp_Object instream, outstream;
1091 Lstream *istr, *ostr;
1092 char tempbuf[1024]; /* some random amount */
1095 static Extbyte_dynarr *conversion_out_dynarr;
1096 Bytecount bstart, bend;
1097 struct gcpro gcpro1, gcpro2;
1099 Lisp_Object conv_out_stream;
1101 struct gcpro gcpro3;
1104 /* This function can GC */
1105 if (!conversion_out_dynarr)
1106 conversion_out_dynarr = Dynarr_new (Extbyte);
1108 Dynarr_reset (conversion_out_dynarr);
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");
1118 int old_errno = errno;
1120 unlink (filename_out);
1123 report_file_error ("Creating temp file",
1124 list1 (build_string (filename_out)));
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);
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);
1141 GCPRO2 (instream, outstream);
1144 /* Get the data while doing the conversion */
1147 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
1150 /* It does seem the flushes are necessary... */
1152 Lstream_write (costr, tempbuf, size_in_bytes);
1153 Lstream_flush (costr);
1155 Lstream_write (ostr, tempbuf, size_in_bytes);
1157 Lstream_flush (ostr);
1158 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
1159 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
1164 /* reset the dynarr */
1165 Lstream_rewind(ostr);
1168 if (fclose (tmpfil) != 0)
1170 Lstream_close (istr);
1172 Lstream_close (costr);
1174 Lstream_close (ostr);
1177 Lstream_delete (istr);
1178 Lstream_delete (ostr);
1180 Lstream_delete (costr);
1184 report_file_error ("Writing temp file",
1185 list1 (build_string (filename_out)));
1194 static struct color_symbol*
1195 extract_xpm_color_names (Lisp_Object device,
1197 Lisp_Object color_symbol_alist,
1200 /* This function can GC */
1202 Lisp_Object results = Qnil;
1204 struct color_symbol *colortbl;
1205 struct gcpro gcpro1, gcpro2;
1207 GCPRO2 (results, device);
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. */
1213 LIST_LOOP (rest, color_symbol_alist)
1215 Lisp_Object cons = XCAR (rest);
1216 Lisp_Object name = XCAR (cons);
1217 Lisp_Object value = XCDR (cons);
1220 if (STRINGP (value))
1222 Fmake_color_instance
1223 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1226 assert (COLOR_SPECIFIERP (value));
1227 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1231 results = noseeum_cons (noseeum_cons (name, value), results);
1234 UNGCPRO; /* no more evaluation */
1237 if (i == 0) return 0;
1239 colortbl = xnew_array_and_zero (struct color_symbol, i);
1243 Lisp_Object cons = XCAR (results);
1245 * COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1247 colortbl[j].name = (char *) XSTRING_DATA (XCAR (cons));
1248 free_cons (XCONS (cons));
1250 results = XCDR (results);
1251 free_cons (XCONS (cons));
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)
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);
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,
1277 enum image_instance_type type;
1281 if (!DEVICE_GTK_P (XDEVICE (device)))
1282 signal_simple_error ("Not a Gtk device", device);
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;
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);
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));
1301 gtk_initialize_pixmap_image_instance (ii, 1, type);
1303 assert (!NILP (data));
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++)
1309 if (!strcasecmp ("BgColor", color_symbols[i].name) ||
1310 !strcasecmp ("None", color_symbols[i].name))
1312 transparent_color = &color_symbols[i].color;
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);
1320 if (color_symbols) xfree (color_symbols);
1324 signal_image_error ("Error reading pixmap", data);
1327 gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth);
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);
1341 case IMAGE_MONO_PIXMAP:
1344 case IMAGE_COLOR_PIXMAP:
1346 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1353 unsigned int xhot, yhot;
1355 /* #### Gtk does not give us access to the hotspots of a pixmap */
1357 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xhot);
1358 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), yhot);
1360 check_pointer_sizes (w, h, instantiator);
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.
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);
1374 generate_cursor_fg_bg (device, &pointer_fg, &pointer_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);
1388 #endif /* HAVE_XPM */
1393 /**********************************************************************
1395 **********************************************************************/
1397 /* This is about to get redefined! */
1400 /* We have to define SYSV32 so that compface.h includes string.h
1401 instead of strings.h. */
1406 #include <compface.h>
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;
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)
1421 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1423 char *p, *bits, *bp;
1424 CONST char * volatile emsg = 0;
1425 CONST char * volatile dstring;
1427 assert (!NILP (data));
1429 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1431 if ((p = strchr (dstring, ':')))
1436 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1437 if (!(stattis = setjmp (comp_env)))
1439 UnCompAll ((char *) dstring);
1446 emsg = "uncompface: internal error";
1449 emsg = "uncompface: insufficient or invalid data";
1452 emsg = "uncompface: excess data ignored";
1457 signal_simple_error_2 (emsg, data, Qimage);
1459 bp = bits = (char *) alloca (PIXELS / 8);
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)
1466 /* reverse the bit order of each byte... */
1467 for (b = n = 0; b < 8; ++b)
1474 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1475 pointer_bg, dest_mask, 48, 48, bits);
1478 #endif /* HAVE_XFACE */
1480 /**********************************************************************
1482 **********************************************************************/
1485 gtk_resource_validate (Lisp_Object instantiator)
1487 if ((NILP (find_keyword_in_vector (instantiator, Q_file))
1489 NILP (find_keyword_in_vector (instantiator, Q_resource_id)))
1491 NILP (find_keyword_in_vector (instantiator, Q_resource_type)))
1492 signal_simple_error ("Must supply :file, :resource-id and :resource-type",
1497 gtk_resource_normalize (Lisp_Object inst, Lisp_Object console_type, Lisp_Object dest_mask)
1499 /* This function can call lisp */
1500 Lisp_Object file = Qnil;
1501 struct gcpro gcpro1, gcpro2;
1502 Lisp_Object alist = Qnil;
1504 GCPRO2 (file, alist);
1506 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1509 if (CONSP (file)) /* failure locating filename */
1510 signal_double_file_error ("Opening pixmap file",
1511 "no such file or directory",
1514 if (NILP (file)) /* no conversion necessary */
1515 RETURN_UNGCPRO (inst);
1517 alist = tagged_vector_to_alist (inst);
1520 alist = remassq_no_quit (Q_file, alist);
1521 alist = Fcons (Fcons (Q_file, file), alist);
1525 Lisp_Object result = alist_to_tagged_vector (Qgtk_resource, alist);
1527 RETURN_UNGCPRO (result);
1532 gtk_resource_possible_dest_types (void)
1534 return IMAGE_POINTER_MASK | IMAGE_COLOR_PIXMAP_MASK;
1537 extern guint symbol_to_enum (Lisp_Object, GtkType);
1539 static guint resource_name_to_resource (Lisp_Object name, int type)
1541 if (type == IMAGE_POINTER)
1542 return (symbol_to_enum (name, GTK_TYPE_GDK_CURSOR_TYPE));
1548 resource_symbol_to_type (Lisp_Object data)
1550 if (EQ (data, Qcursor))
1551 return IMAGE_POINTER;
1553 else if (EQ (data, Qicon))
1555 else if (EQ (data, Qbitmap))
1556 return IMAGE_BITMAP;
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)
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);
1574 if (!DEVICE_GTK_P (XDEVICE (device)))
1575 signal_simple_error ("Not a GTK device", device);
1577 type = resource_symbol_to_type (resource_type);
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;
1584 // incompatible_image_types (instantiator, dest_mask,
1585 // IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK);
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;
1598 check_valid_resource_symbol (Lisp_Object data)
1600 CHECK_SYMBOL (data);
1601 if (!resource_symbol_to_type (data))
1602 signal_simple_error ("invalid resource type", data);
1606 check_valid_resource_id (Lisp_Object data)
1608 if (!resource_name_to_resource (data, IMAGE_POINTER)
1610 !resource_name_to_resource (data, IMAGE_COLOR_PIXMAP)
1613 !resource_name_to_resource (data, IMAGE_BITMAP)
1616 signal_simple_error ("invalid resource identifier", data);
1621 check_valid_string_or_int (Lisp_Object data)
1624 CHECK_STRING (data);
1631 /**********************************************************************
1633 **********************************************************************/
1636 autodetect_validate (Lisp_Object instantiator)
1638 data_must_be_present (instantiator);
1642 autodetect_normalize (Lisp_Object instantiator,
1643 Lisp_Object console_type,
1644 Lisp_Object dest_mask)
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;
1652 GCPRO3 (filename, data, alist);
1654 if (NILP (file)) /* no conversion necessary */
1655 RETURN_UNGCPRO (instantiator);
1657 alist = tagged_vector_to_alist (instantiator);
1659 filename = locate_pixmap_file (file);
1660 if (!NILP (filename))
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. */
1669 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1673 alist = remassq_no_quit (Q_data, alist);
1674 alist = Fcons (Fcons (Q_file, filename),
1675 Fcons (Fcons (Q_data, data), alist));
1677 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1680 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1683 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1686 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1688 RETURN_UNGCPRO (result);
1693 data = pixmap_to_lisp_data (filename, 1);
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 ()),
1704 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1706 RETURN_UNGCPRO (result);
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.) */
1717 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1719 RETURN_UNGCPRO (result);
1724 autodetect_possible_dest_types (void)
1727 IMAGE_MONO_PIXMAP_MASK |
1728 IMAGE_COLOR_PIXMAP_MASK |
1729 IMAGE_POINTER_MASK |
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)
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;
1746 GCPRO3 (data, alist, result);
1748 alist = tagged_vector_to_alist (instantiator);
1749 if (dest_mask & IMAGE_POINTER_MASK)
1751 CONST char *name_ext;
1753 TO_EXTERNAL_FORMAT (LISP_STRING, data,
1754 C_STRING_ALLOCA, name_ext,
1757 if (cursor_name_to_index (name_ext) != -1)
1759 result = alist_to_tagged_vector (Qcursor_font, alist);
1764 if (!is_cursor_font)
1765 result = alist_to_tagged_vector (Qstring, alist);
1769 cursor_font_instantiate (image_instance, result, pointer_fg,
1770 pointer_bg, dest_mask, domain);
1772 string_instantiate (image_instance, result, pointer_fg,
1773 pointer_bg, dest_mask, domain);
1779 /**********************************************************************
1781 **********************************************************************/
1784 font_validate (Lisp_Object instantiator)
1786 data_must_be_present (instantiator);
1790 font_possible_dest_types (void)
1792 return IMAGE_POINTER_MASK;
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)
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);
1805 GdkFont *source, *mask;
1806 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1807 int source_char, mask_char;
1809 Lisp_Object foreground, background;
1811 if (!DEVICE_GTK_P (XDEVICE (device)))
1812 signal_simple_error ("Not a Gtk device", device);
1814 if (!STRINGP (data) ||
1815 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1816 signal_simple_error ("Invalid font-glyph instantiator",
1819 if (!(dest_mask & IMAGE_POINTER_MASK))
1820 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
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;
1829 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
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;
1839 if (count != 2 && count != 4)
1840 signal_simple_error ("invalid cursor specification", data);
1841 source = gdk_font_load (source_name);
1843 signal_simple_error_2 ("couldn't load font",
1844 build_string (source_name),
1848 else if (!mask_name[0])
1852 mask = gdk_font_load (mask_name);
1855 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1856 build_string (mask_name), data));
1861 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1863 gtk_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
1865 IMAGE_INSTANCE_GTK_CURSOR (ii) = NULL;
1868 /* #### BILL!!! There is no way to call this function from Gdk */
1869 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1872 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1873 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1875 gdk_font_unref (source);
1876 if (mask && mask != source) gdk_font_unref (mask);
1880 /**********************************************************************
1882 **********************************************************************/
1885 cursor_font_validate (Lisp_Object instantiator)
1887 data_must_be_present (instantiator);
1891 cursor_font_possible_dest_types (void)
1893 return IMAGE_POINTER_MASK;
1896 static char *__downcase (const char *name)
1898 char *converted = strdup(name);
1899 char *work = converted;
1903 *work = tolower(*work);
1909 /* This is basically the equivalent of XmuCursorNameToIndex */
1911 cursor_name_to_index (const char *name)
1914 static char *the_gdk_cursors[GDK_NUM_GLYPHS];
1916 if (!the_gdk_cursors[GDK_BASED_ARROW_UP])
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++)
1923 the_gdk_cursors[i] = NULL;
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);
1969 for (i = 0; i < GDK_NUM_GLYPHS; i++)
1971 if (!the_gdk_cursors[i]) continue;
1972 if (!strcmp (the_gdk_cursors[i], name))
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)
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);
1990 CONST char *name_ext;
1991 Lisp_Object foreground, background;
1993 if (!DEVICE_GTK_P (XDEVICE (device)))
1994 signal_simple_error ("Not a Gtk device", device);
1996 if (!(dest_mask & IMAGE_POINTER_MASK))
1997 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1999 TO_EXTERNAL_FORMAT (LISP_STRING, data,
2000 C_STRING_ALLOCA, name_ext,
2003 if ((i = cursor_name_to_index (name_ext)) == -1)
2004 signal_simple_error ("Unrecognized cursor-font name", data);
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);
2018 gtk_colorize_image_instance (Lisp_Object image_instance,
2019 Lisp_Object foreground, Lisp_Object background);
2022 /************************************************************************/
2023 /* subwindow and widget support */
2024 /************************************************************************/
2026 /* unmap the image if it is a widget. This is used by redisplay via
2027 redisplay_unmap_subwindows */
2029 gtk_unmap_subwindow (Lisp_Image_Instance *p)
2031 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2033 /* We don't support subwindows, but we do support widgets... */
2036 else /* must be a widget */
2038 /* Since we are being unmapped we want the enclosing frame to
2039 get focus. The losing with simple scrolling but is the safest
2041 if (IMAGE_INSTANCE_GTK_CLIPWIDGET (p))
2042 gtk_widget_unmap (IMAGE_INSTANCE_GTK_CLIPWIDGET (p));
2046 /* map the subwindow. This is used by redisplay via
2047 redisplay_output_subwindow */
2049 gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2050 struct display_glyph_area* dga)
2052 assert (dga->width > 0 && dga->height > 0);
2054 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2056 /* No subwindow support... */
2059 else /* must be a widget */
2061 struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
2062 GtkWidget *wid = IMAGE_INSTANCE_GTK_CLIPWIDGET (p);
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;
2072 if ((a.width != wid->allocation.width) ||
2073 (a.height != wid->allocation.height))
2075 gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a);
2078 /* #### FIXME DAMMIT */
2079 if ((wid->allocation.x != -dga->xoffset) ||
2080 (wid->allocation.y != -dga->yoffset))
2082 guint32 old_flags = GTK_WIDGET_FLAGS (FRAME_GTK_TEXT_WIDGET (f));
2084 /* Fucking GtkFixed widget queues a resize when you add a widget.
2085 ** But only if it is visible.
2088 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) &= ~GTK_VISIBLE;
2089 if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p))
2091 gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)),
2093 -dga->xoffset, -dga->yoffset);
2097 IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE;
2098 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)),
2100 -dga->xoffset, -dga->yoffset);
2102 GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) = old_flags;
2105 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2107 gtk_widget_map (wid);
2110 gtk_widget_draw (wid, NULL);
2114 /* when you click on a widget you may activate another widget this
2115 needs to be checked and all appropriate widgets updated */
2117 gtk_redisplay_subwindow (Lisp_Image_Instance *p)
2119 /* Update the subwindow size if necessary. */
2120 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
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));
2131 /* Update all attributes that have changed. */
2133 gtk_redisplay_widget (Lisp_Image_Instance *p)
2135 /* This function can GC if IN_REDISPLAY is false. */
2137 if (!IMAGE_INSTANCE_GTK_CLIPWIDGET (p))
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))
2147 Lisp_Object image_instance;
2149 XSETIMAGE_INSTANCE (image_instance, p);
2151 /* Need to update GtkArgs that might have changed... */
2157 /* No items changed, so do nothing, right? */
2160 /* Possibly update the colors and font */
2161 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
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
2169 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
2171 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2173 /* #### Write this function BILL! */
2174 update_widget_face (NULL, p, IMAGE_INSTANCE_FRAME (p));
2177 /* Possibly update the text. */
2178 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2181 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2182 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2184 /* #### Need to special case each type of GtkWidget here! */
2187 /* Possibly update the size. */
2188 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2190 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2192 IMAGE_INSTANCE_TEXT_CHANGED (p))
2194 assert (IMAGE_INSTANCE_GTK_WIDGET_ID (p) &&
2195 IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) ;
2197 /* #### Resize the widget! */
2198 /* gtk_widget_size_allocate () */
2201 /* Adjust offsets within the frame. */
2202 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2204 /* I don't think we need to do anything for Gtk here... */
2207 /* now modify the widget */
2211 /* instantiate and gtk type subwindow */
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)
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);
2222 if (!DEVICE_GTK_P (XDEVICE (device)))
2223 signal_simple_error ("Not a GTK device", device);
2225 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2227 ii->data = xnew_and_zero (struct gtk_subwindow_data);
2229 /* Create a window for clipping */
2230 IMAGE_INSTANCE_GTK_CLIPWINDOW (ii) = NULL;
2232 /* Now put the subwindow inside the clip window. */
2233 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) NULL;
2238 /************************************************************************/
2240 /************************************************************************/
2242 update_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
2247 GtkStyle *style = gtk_widget_get_style (w);
2248 Lisp_Object pixel = Qnil;
2249 GdkColor *fcolor, *bcolor;
2251 style = gtk_style_copy (style);
2253 /* Update the foreground. */
2254 pixel = FACE_FOREGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain);
2255 fcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel));
2257 /* Update the background. */
2258 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), domain);
2259 bcolor = COLOR_INSTANCE_GTK_COLOR (XCOLOR_INSTANCE (pixel));
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...
2265 gtk_widget_set_style (w, style);
2267 /* #### Megahack - but its just getting too complicated to do this
2268 in the right place. */
2270 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2271 update_tab_widget_face (wv, ii, domain);
2278 update_tab_widget_face (GtkWidget *w, Lisp_Image_Instance *ii,
2283 widget_value* val = wv->contents, *cur;
2285 /* Give each child label the correct foreground color. */
2286 Lisp_Object pixel = FACE_FOREGROUND
2287 (IMAGE_INSTANCE_WIDGET_FACE (ii),
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;
2294 for (cur = val->next; cur; cur = cur->next)
2296 cur->change = VISIBLE_CHANGE;
2299 lw_copy_widget_value_args (val, cur);
2307 gtk_widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
2308 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2311 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2312 Lisp_Object widget = Qnil;
2314 GtkWidget *w = NULL;
2315 struct gcpro gcpro1;
2317 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2319 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2321 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2324 ii->data = xnew_and_zero (struct gtk_subwindow_data);
2326 /* Create a clipping widget */
2327 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = NULL;
2328 IMAGE_INSTANCE_GTK_ALREADY_PUT(ii) = FALSE;
2330 /* Create the actual widget */
2332 widget = call5 (Qgtk_widget_instantiate_internal,
2333 image_instance, instantiator,
2334 pointer_fg, pointer_bg,
2339 CHECK_GTK_OBJECT (widget);
2340 w = GTK_WIDGET (XGTK_OBJECT (widget)->object);
2344 stderr_out ("Lisp-level creation of widget failed... falling back\n");
2345 w = gtk_label_new ("Widget Creation Failed...");
2350 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void *) w;
2352 /* #### HACK!!!! We should make this do the right thing if we
2353 ** really need a clip widget!
2355 IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = w;
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)
2365 call_with_suspended_errors ((lisp_fn_t) gtk_widget_instantiate_1,
2368 image_instance, instantiator,
2374 /* get properties of a control */
2376 gtk_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2378 /* Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); */
2380 /* get the text from a control */
2381 if (EQ (prop, Q_text))
2388 #define FAKE_GTK_WIDGET_INSTANTIATOR(x) \
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) \
2396 gtk_widget_instantiate (image_instance, instantiator, pointer_fg, \
2397 pointer_bg, dest_mask, domain); \
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);
2408 /* Update a button's clicked state. */
2410 gtk_button_redisplay (Lisp_Object image_instance)
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);
2416 if (GTK_WIDGET_TYPE (w) == gtk_button_get_type ())
2419 else if (GTK_WIDGET_TYPE (w) == gtk_check_button_get_type ())
2422 else if (GTK_WIDGET_TYPE (w) == gtk_radio_button_get_type ())
2427 /* Unknown button type... */
2432 /* get properties of a button */
2434 gtk_button_property (Lisp_Object image_instance, Lisp_Object prop)
2436 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2438 /* check the state of a button */
2439 if (EQ (prop, Q_selected))
2441 if (GTK_WIDGET_HAS_FOCUS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)))
2449 /* set the properties of a progress gauge */
2451 gtk_progress_gauge_redisplay (Lisp_Object image_instance)
2453 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2455 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2460 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2461 f = XFLOATINT (val);
2463 gtk_progress_set_value (GTK_PROGRESS (IMAGE_INSTANCE_SUBWINDOW_ID (ii)),
2468 /* Set the properties of a tab control */
2470 gtk_tab_control_redisplay (Lisp_Object image_instance)
2472 /* #### Convert this to GTK baby! */
2473 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2475 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) ||
2476 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
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
2482 if (tab_control_order_only_changed (image_instance))
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)));
2490 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2492 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2494 Lisp_Object old_selected =gui_item_list_find_selected
2495 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2497 /* Need to focus on the widget... */
2498 stderr_out ("Hey, change the tab-focus you boob...\n");
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;
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);
2522 for (i = num_pages; i >= 0; --i)
2524 gtk_notebook_remove_page (nb, i);
2528 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2530 Lisp_Gui_Item *pgui = XGUI_ITEM (XCAR (rest));
2531 char *c_name = NULL;
2533 if (!STRINGP (pgui->name))
2534 pgui->name = Feval (pgui->name);
2536 CHECK_STRING (pgui->name);
2538 TO_EXTERNAL_FORMAT (LISP_STRING, pgui->name,
2539 C_STRING_ALLOCA, c_name,
2542 gtk_notebook_append_page (nb,
2543 gtk_vbox_new (FALSE, 3),
2544 gtk_label_new (c_name));
2547 /* Show all the new widgets we just added... */
2548 gtk_widget_show_all (GTK_WIDGET (nb));
2552 /* Possibly update the face. */
2554 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2556 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2558 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2560 update_tab_widget_face (wv, ii,
2561 IMAGE_INSTANCE_FRAME (ii));
2565 #endif /* HAVE_WIDGETS */
2568 /************************************************************************/
2569 /* initialization */
2570 /************************************************************************/
2572 syms_of_glyphs_gtk (void)
2574 defkeyword (&Q_resource_id, ":resource-id");
2575 defkeyword (&Q_resource_type, ":resource-type");
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");
2585 console_type_create_glyphs_gtk (void)
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);
2602 image_instantiator_format_create_glyphs_gtk (void)
2604 IIFORMAT_VALID_CONSOLE (gtk, nothing);
2605 IIFORMAT_VALID_CONSOLE (gtk, string);
2607 IIFORMAT_VALID_CONSOLE (gtk, layout);
2609 IIFORMAT_VALID_CONSOLE (gtk, formatted_string);
2610 IIFORMAT_VALID_CONSOLE (gtk, inherit);
2612 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm);
2613 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate);
2616 IIFORMAT_VALID_CONSOLE (gtk, jpeg);
2619 IIFORMAT_VALID_CONSOLE (gtk, tiff);
2622 IIFORMAT_VALID_CONSOLE (gtk, png);
2625 IIFORMAT_VALID_CONSOLE (gtk, gif);
2628 INITIALIZE_DEVICE_IIFORMAT (gtk, subwindow);
2629 IIFORMAT_HAS_DEVMETHOD (gtk, subwindow, instantiate);
2633 INITIALIZE_DEVICE_IIFORMAT (gtk, native_layout);
2634 IIFORMAT_HAS_DEVMETHOD (gtk, native_layout, instantiate);
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);
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);
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);
2660 INITIALIZE_DEVICE_IIFORMAT (gtk, label);
2661 IIFORMAT_HAS_DEVMETHOD (gtk, label, instantiate);
2664 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2665 IIFORMAT_VALID_CONSOLE (gtk, cursor_font);
2667 IIFORMAT_HAS_METHOD (cursor_font, validate);
2668 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2669 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
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);
2675 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2676 IIFORMAT_VALID_CONSOLE (gtk, font);
2678 IIFORMAT_HAS_METHOD (font, validate);
2679 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2680 IIFORMAT_HAS_METHOD (font, instantiate);
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);
2687 INITIALIZE_DEVICE_IIFORMAT (gtk, xpm);
2688 IIFORMAT_HAS_DEVMETHOD (gtk, xpm, instantiate);
2692 INITIALIZE_DEVICE_IIFORMAT (gtk, xface);
2693 IIFORMAT_HAS_DEVMETHOD (gtk, xface, instantiate);
2696 INITIALIZE_DEVICE_IIFORMAT (gtk, xbm);
2697 IIFORMAT_HAS_DEVMETHOD (gtk, xbm, instantiate);
2698 IIFORMAT_VALID_CONSOLE (gtk, xbm);
2700 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gtk_resource, "gtk-resource");
2701 IIFORMAT_VALID_CONSOLE (gtk, gtk_resource);
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);
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);
2712 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect, "autodetect");
2713 IIFORMAT_VALID_CONSOLE (gtk, autodetect);
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);
2720 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2724 vars_of_glyphs_gtk (void)
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).
2736 Vgtk_bitmap_file_path = Qnil;
2740 complex_vars_of_glyphs_gtk (void)
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), \
2751 Qglobal, Qgtk, Qnil)
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);
2758 #undef BUILD_GLYPH_INST
2762 /* Ripped off from glyphs-msw.c */
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.
2769 #define MAX_SIZE 1024
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 */
2776 * Table index for the hex values. Initialized once, first time.
2777 * Used for translation value or delimiter significance lookup.
2779 static void initHexTable()
2782 * We build the table at run time for several reasons:
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.
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;
2801 /* delimiters of significance are flagged w/ negative value */
2802 hexTable[' '] = -1; hexTable[','] = -1;
2803 hexTable['}'] = -1; hexTable['\n'] = -1;
2804 hexTable['\t'] = -1;
2810 * read next hex value in the input stream, return -1 if EOF
2812 static int NextInt ( FILE *fstream )
2819 /* loop, accumulate hex value until find delimiter */
2820 /* skip any initial delimiters found in read stream */
2828 /* trim high bits, check type and accumulate */
2830 if (isascii(ch) && isxdigit(ch)) {
2831 value = (value << 4) + hexTable[ch];
2833 } else if ((hexTable[ch]) < 0 && gotone)
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 */
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 */
2860 #define Xmalloc(size) malloc(size)
2862 /* first time initialization */
2863 if (initialized == FALSE) initHexTable();
2865 /* error cleanup and return macro */
2866 #define RETURN(code) { if (data) free (data); return code; }
2868 while (fgets(line, MAX_SIZE, fstream)) {
2869 if (strlen(line) == MAX_SIZE-1) {
2870 RETURN (BitmapFileInvalid);
2872 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
2873 if (!(type = strrchr(name_and_type, '_')))
2874 type = name_and_type;
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)
2885 if (!strcmp("x_hot", type))
2887 if (!strcmp("y_hot", type))
2893 if (sscanf(line, "static short %s = {", name_and_type) == 1)
2895 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
2897 else if (sscanf(line, "static char %s = {", name_and_type) == 1)
2902 if (!(type = strrchr(name_and_type, '_')))
2903 type = name_and_type;
2907 if (strcmp("bits[]", type))
2911 RETURN (BitmapFileInvalid);
2913 if ((ww % 16) && ((ww % 16) < 9) && version10p)
2918 bytes_per_line = (ww+7)/8 + padding;
2920 size = bytes_per_line * hh;
2921 data = (unsigned char *) Xmalloc ((unsigned int) size);
2923 RETURN (BitmapNoMemory);
2929 for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
2930 if ((value = NextInt(fstream)) < 0)
2931 RETURN (BitmapFileInvalid);
2933 if (!padding || ((bytes+2) % bytes_per_line))
2934 *(ptr++) = value >> 8;
2940 for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
2941 if ((value = NextInt(fstream)) < 0)
2942 RETURN (BitmapFileInvalid);
2950 RETURN (BitmapFileInvalid);
2957 if (x_hot) *x_hot = hx;
2958 if (y_hot) *y_hot = hy;
2960 RETURN (BitmapSuccess);
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)
2971 if ((fstream = fopen (filename, "r")) == NULL) {
2972 return BitmapOpenFailed;
2974 rval = read_bitmap_data (fstream, width, height, datap, x_hot, y_hot);
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. */
2984 gtk_colorize_image_instance (Lisp_Object image_instance,
2985 Lisp_Object foreground, Lisp_Object background)
2987 struct Lisp_Image_Instance *p;
2989 p = XIMAGE_INSTANCE (image_instance);
2991 switch (IMAGE_INSTANCE_TYPE (p))
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;
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))));
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);
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),
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;