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
45 Convert images.el to C and stick it in here?
51 #include "console-x.h"
53 #include "objects-x.h"
72 #include "file-coding.h"
75 #ifdef LWLIB_USES_MOTIF
78 #include <X11/IntrinsicP.h>
81 # define FOUR_BYTE_TYPE unsigned int
83 # define FOUR_BYTE_TYPE unsigned long
85 # define FOUR_BYTE_TYPE unsigned short
87 #error What kind of strange-ass system are we running on?
90 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
93 DEFINE_DEVICE_IIFORMAT (x, xpm);
95 DEFINE_DEVICE_IIFORMAT (x, xbm);
96 DEFINE_DEVICE_IIFORMAT (x, subwindow);
98 DEFINE_DEVICE_IIFORMAT (x, xface);
101 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
102 Lisp_Object Qcursor_font;
104 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
106 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
108 DEFINE_DEVICE_IIFORMAT (x, widget);
109 DEFINE_DEVICE_IIFORMAT (x, button);
110 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
111 DEFINE_DEVICE_IIFORMAT (x, edit_field);
112 DEFINE_DEVICE_IIFORMAT (x, combo_box);
114 static void cursor_font_instantiate (Lisp_Object image_instance,
115 Lisp_Object instantiator,
116 Lisp_Object pointer_fg,
117 Lisp_Object pointer_bg,
124 /************************************************************************/
125 /* image instance methods */
126 /************************************************************************/
128 /************************************************************************/
129 /* convert from a series of RGB triples to an XImage formated for the */
131 /************************************************************************/
133 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
134 unsigned char *pic, unsigned long **pixtbl,
141 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
143 unsigned char *data, *ip, *dp;
144 quant_table *qtable = 0;
150 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
151 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
152 vis = DEVICE_X_VISUAL (XDEVICE(device));
153 depth = DEVICE_X_DEPTH(XDEVICE(device));
155 if (vis->class == PseudoColor)
157 /* Quantize the image and get a histogram while we're at it.
158 Do this first to save memory */
159 qtable = build_EImage_quantable(pic, width, height, 256);
160 if (qtable == NULL) return NULL;
163 bitmap_pad = ((depth > 16) ? 32 :
167 outimg = XCreateImage (dpy, vis,
168 depth, ZPixmap, 0, 0, width, height,
170 if (!outimg) return NULL;
172 bits_per_pixel = outimg->bits_per_pixel;
173 byte_cnt = bits_per_pixel >> 3;
175 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
178 XDestroyImage (outimg);
181 outimg->data = (char *) data;
183 if (vis->class == PseudoColor)
185 unsigned long pixarray[256];
187 /* use our quantize table to allocate the colors */
189 *pixtbl = xnew_array (unsigned long, pixcount);
192 /* ### should implement a sort by popularity to assure proper allocation */
194 for (i = 0; i < qtable->num_active_colors; i++)
199 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
200 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
201 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
202 color.flags = DoRed | DoGreen | DoBlue;
203 res = allocate_nearest_color (dpy, cmap, vis, &color);
204 if (res > 0 && res < 3)
206 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
207 (*pixtbl)[n] = color.pixel;
210 pixarray[i] = color.pixel;
214 for (i = 0; i < height; i++)
216 dp = data + (i * outimg->bytes_per_line);
217 for (j = 0; j < width; j++)
222 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
224 if (outimg->byte_order == MSBFirst)
225 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
227 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
229 if (outimg->byte_order == MSBFirst)
230 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
232 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
238 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
239 junk = vis->red_mask;
241 while ((junk & 0x1) == 0)
252 junk = vis->green_mask;
254 while ((junk & 0x1) == 0)
265 junk = vis->blue_mask;
267 while ((junk & 0x1) == 0)
279 for (i = 0; i < height; i++)
281 dp = data + (i * outimg->bytes_per_line);
282 for (j = 0; j < width; j++)
285 rd = *ip++ << (rbits - 8);
287 rd = *ip++ >> (8 - rbits);
289 gr = *ip++ << (gbits - 8);
291 gr = *ip++ >> (8 - gbits);
293 bl = *ip++ << (bbits - 8);
295 bl = *ip++ >> (8 - bbits);
297 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
299 if (outimg->byte_order == MSBFirst)
300 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
302 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
304 if (outimg->byte_order == MSBFirst)
305 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
307 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
318 x_print_image_instance (struct Lisp_Image_Instance *p,
319 Lisp_Object printcharfun,
324 switch (IMAGE_INSTANCE_TYPE (p))
326 case IMAGE_MONO_PIXMAP:
327 case IMAGE_COLOR_PIXMAP:
329 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
330 write_c_string (buf, printcharfun);
331 if (IMAGE_INSTANCE_X_MASK (p))
333 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
334 write_c_string (buf, printcharfun);
336 write_c_string (")", printcharfun);
344 x_finalize_image_instance (struct Lisp_Image_Instance *p)
349 if (DEVICE_LIVE_P (XDEVICE (p->device)))
351 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
353 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
355 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
357 XtUnmanageChild (IMAGE_INSTANCE_X_WIDGET_ID (p));
358 XtDestroyWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
359 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
362 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
364 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
365 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
366 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
370 if (IMAGE_INSTANCE_X_PIXMAP (p))
371 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p));
372 if (IMAGE_INSTANCE_X_MASK (p) &&
373 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
374 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
375 IMAGE_INSTANCE_X_PIXMAP (p) = 0;
376 IMAGE_INSTANCE_X_MASK (p) = 0;
378 if (IMAGE_INSTANCE_X_CURSOR (p))
380 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
381 IMAGE_INSTANCE_X_CURSOR (p) = 0;
384 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
387 IMAGE_INSTANCE_X_COLORMAP (p),
388 IMAGE_INSTANCE_X_PIXELS (p),
389 IMAGE_INSTANCE_X_NPIXELS (p), 0);
390 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
394 if (IMAGE_INSTANCE_X_PIXELS (p))
396 xfree (IMAGE_INSTANCE_X_PIXELS (p));
397 IMAGE_INSTANCE_X_PIXELS (p) = 0;
405 x_image_instance_equal (struct Lisp_Image_Instance *p1,
406 struct Lisp_Image_Instance *p2, int depth)
408 switch (IMAGE_INSTANCE_TYPE (p1))
410 case IMAGE_MONO_PIXMAP:
411 case IMAGE_COLOR_PIXMAP:
413 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
414 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
425 x_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
427 switch (IMAGE_INSTANCE_TYPE (p))
429 case IMAGE_MONO_PIXMAP:
430 case IMAGE_COLOR_PIXMAP:
432 return IMAGE_INSTANCE_X_NPIXELS (p);
438 /* Set all the slots in an image instance structure to reasonable
439 default values. This is used somewhere within an instantiate
440 method. It is assumed that the device slot within the image
441 instance is already set -- this is the case when instantiate
442 methods are called. */
445 x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
446 enum image_instance_type type)
448 ii->data = xnew_and_zero (struct x_image_instance_data);
449 IMAGE_INSTANCE_TYPE (ii) = type;
450 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
451 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
452 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
453 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
454 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
455 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
459 /************************************************************************/
460 /* pixmap file functions */
461 /************************************************************************/
463 /* Where bitmaps are; initialized from resource database */
464 Lisp_Object Vx_bitmap_file_path;
467 #define BITMAPDIR "/usr/include/X11/bitmaps"
470 #define USE_XBMLANGPATH
472 /* Given a pixmap filename, look through all of the "standard" places
473 where the file might be located. Return a full pathname if found;
474 otherwise, return Qnil. */
477 x_locate_pixmap_file (Lisp_Object name)
479 /* This function can GC if IN_REDISPLAY is false */
482 /* Check non-absolute pathnames with a directory component relative to
483 the search path; that's the way Xt does it. */
484 /* #### Unix-specific */
485 if (XSTRING_BYTE (name, 0) == '/' ||
486 (XSTRING_BYTE (name, 0) == '.' &&
487 (XSTRING_BYTE (name, 1) == '/' ||
488 (XSTRING_BYTE (name, 1) == '.' &&
489 (XSTRING_BYTE (name, 2) == '/')))))
491 if (!NILP (Ffile_readable_p (name)))
497 if (NILP (Vdefault_x_device))
498 /* This may occur during initialization. */
501 /* We only check the bitmapFilePath resource on the original X device. */
502 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
504 #ifdef USE_XBMLANGPATH
506 char *path = egetenv ("XBMLANGPATH");
507 SubstitutionRec subs[1];
509 subs[0].substitution = (char *) XSTRING_DATA (name);
510 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
511 We don't. If you want it used, set it. */
513 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
514 subs, XtNumber (subs), 0)))
516 name = build_string (path);
523 if (NILP (Vx_bitmap_file_path))
527 if (XrmGetResource (XtDatabase (display),
528 "bitmapFilePath", "BitmapFilePath", &type, &value)
529 && !strcmp (type, "String"))
530 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
531 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
532 (decode_path (BITMAPDIR)));
537 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
539 Lisp_Object temp = list1 (Vdata_directory);
543 locate_file (temp, name, Qnil, &found, R_OK);
552 locate_pixmap_file (Lisp_Object name)
554 return x_locate_pixmap_file (name);
559 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
561 Lisp_Object instream, outstream;
562 Lstream *istr, *ostr;
563 char tempbuf[1024]; /* some random amount */
566 static Extbyte_dynarr *conversion_out_dynarr;
567 Bytecount bstart, bend;
568 struct gcpro gcpro1, gcpro2;
570 Lisp_Object conv_out_stream;
575 /* This function can GC */
576 if (!conversion_out_dynarr)
577 conversion_out_dynarr = Dynarr_new (Extbyte);
579 Dynarr_reset (conversion_out_dynarr);
581 /* Create the temporary file ... */
582 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
583 mktemp (filename_out);
584 tmpfil = fopen (filename_out, "w");
589 int old_errno = errno;
591 unlink (filename_out);
594 report_file_error ("Creating temp file",
595 list1 (build_string (filename_out)));
598 CHECK_STRING (string);
599 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
600 GB_HISTORICAL_STRING_BEHAVIOR);
601 instream = make_lisp_string_input_stream (string, bstart, bend);
602 istr = XLSTREAM (instream);
603 /* setup the out stream */
604 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
605 ostr = XLSTREAM (outstream);
607 /* setup the conversion stream */
608 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
609 costr = XLSTREAM (conv_out_stream);
610 GCPRO3 (instream, outstream, conv_out_stream);
612 GCPRO2 (instream, outstream);
615 /* Get the data while doing the conversion */
618 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
621 /* It does seem the flushes are necessary... */
623 Lstream_write (costr, tempbuf, size_in_bytes);
624 Lstream_flush (costr);
626 Lstream_write (ostr, tempbuf, size_in_bytes);
628 Lstream_flush (ostr);
629 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
630 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
635 /* reset the dynarr */
636 Lstream_rewind(ostr);
639 if (fclose (tmpfil) != 0)
641 Lstream_close (istr);
643 Lstream_close (costr);
645 Lstream_close (ostr);
648 Lstream_delete (istr);
649 Lstream_delete (ostr);
651 Lstream_delete (costr);
655 report_file_error ("Writing temp file",
656 list1 (build_string (filename_out)));
661 /************************************************************************/
662 /* cursor functions */
663 /************************************************************************/
665 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
666 not, signal an error. INSTANTIATOR is only used in the error
670 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
671 Lisp_Object instantiator)
673 unsigned int best_width, best_height;
674 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
675 width, height, &best_width, &best_height))
676 /* this means that an X error of some sort occurred (we trap
677 these so they're not fatal). */
678 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
680 if (width > best_width || height > best_height)
681 error_with_frob (instantiator,
682 "pointer too large (%dx%d): "
683 "server requires %dx%d or smaller",
684 width, height, best_width, best_height);
689 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
690 Lisp_Object *background, XColor *xfg, XColor *xbg)
692 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
694 Fmake_color_instance (*foreground, device,
695 encode_error_behavior_flag (ERROR_ME));
696 if (COLOR_INSTANCEP (*foreground))
697 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
701 xfg->red = xfg->green = xfg->blue = 0;
704 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
706 Fmake_color_instance (*background, device,
707 encode_error_behavior_flag (ERROR_ME));
708 if (COLOR_INSTANCEP (*background))
709 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
713 xbg->red = xbg->green = xbg->blue = ~0;
718 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
719 Lisp_Object background)
721 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
724 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
725 if (!NILP (foreground) || !NILP (background))
727 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
728 XIMAGE_INSTANCE_X_CURSOR (image_instance),
730 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
731 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
736 /************************************************************************/
737 /* color pixmap functions */
738 /************************************************************************/
740 /* Initialize an image instance from an XImage.
742 DEST_MASK specifies the mask of allowed image types.
744 PIXELS and NPIXELS specify an array of pixels that are used in
745 the image. These need to be kept around for the duration of the
746 image. When the image instance is freed, XFreeColors() will
747 automatically be called on all the pixels specified here; thus,
748 you should have allocated the pixels yourself using XAllocColor()
749 or the like. The array passed in is used directly without
750 being copied, so it should be heap data created with xmalloc().
751 It will be freed using xfree() when the image instance is
754 If this fails, signal an error. INSTANTIATOR is only used
755 in the error message.
757 #### This should be able to handle conversion into `pointer'.
758 Use the same code as for `xpm'. */
761 init_image_instance_from_x_image (struct Lisp_Image_Instance *ii,
765 unsigned long *pixels,
767 Lisp_Object instantiator)
769 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
775 if (!DEVICE_X_P (XDEVICE (device)))
776 signal_simple_error ("Not an X device", device);
778 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
779 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
781 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
782 incompatible_image_types (instantiator, dest_mask,
783 IMAGE_COLOR_PIXMAP_MASK);
785 pixmap = XCreatePixmap (dpy, d, ximage->width,
786 ximage->height, ximage->depth);
788 signal_simple_error ("Unable to create pixmap", instantiator);
790 gc = XCreateGC (dpy, pixmap, 0, NULL);
793 XFreePixmap (dpy, pixmap);
794 signal_simple_error ("Unable to create GC", instantiator);
797 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
798 ximage->width, ximage->height);
802 x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
804 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
805 find_keyword_in_vector (instantiator, Q_file);
807 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
808 IMAGE_INSTANCE_X_MASK (ii) = 0;
809 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
810 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
811 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
812 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
813 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
814 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
818 x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
819 int width, int height,
820 unsigned char *eimage,
822 Lisp_Object instantiator,
825 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
826 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
827 unsigned long *pixtbl = NULL;
831 ximage = convert_EImage_to_XImage (device, width, height, eimage,
835 if (pixtbl) xfree (pixtbl);
836 signal_image_error("EImage to XImage conversion failed", instantiator);
839 /* Now create the pixmap and set up the image instance */
840 init_image_instance_from_x_image (ii, ximage, dest_mask,
841 cmap, pixtbl, npixels,
848 xfree (ximage->data);
851 XDestroyImage (ximage);
855 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width,
856 unsigned int *height, unsigned char **datap,
857 int *x_hot, int *y_hot)
859 return XmuReadBitmapDataFromFile (filename, width, height,
860 datap, x_hot, y_hot);
863 /* Given inline data for a mono pixmap, create and return the
864 corresponding X object. */
867 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
868 /* Note that data is in ext-format! */
871 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
872 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
873 (char *) bits, width, height,
877 /* Given inline data for a mono pixmap, initialize the given
878 image instance accordingly. */
881 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
882 int width, int height,
883 /* Note that data is in ext-format! */
885 Lisp_Object instantiator,
886 Lisp_Object pointer_fg,
887 Lisp_Object pointer_bg,
890 Lisp_Object mask_filename)
892 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
893 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
894 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
898 enum image_instance_type type;
900 if (!DEVICE_X_P (XDEVICE (device)))
901 signal_simple_error ("Not an X device", device);
903 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
904 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
905 scr = DefaultScreenOfDisplay (dpy);
907 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
908 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
910 if (!NILP (foreground) || !NILP (background))
911 type = IMAGE_COLOR_PIXMAP;
913 type = IMAGE_MONO_PIXMAP;
915 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
916 type = IMAGE_MONO_PIXMAP;
917 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
918 type = IMAGE_COLOR_PIXMAP;
919 else if (dest_mask & IMAGE_POINTER_MASK)
920 type = IMAGE_POINTER;
922 incompatible_image_types (instantiator, dest_mask,
923 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
924 | IMAGE_POINTER_MASK);
926 x_initialize_pixmap_image_instance (ii, type);
927 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
928 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
929 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
930 find_keyword_in_vector (instantiator, Q_file);
934 case IMAGE_MONO_PIXMAP:
936 IMAGE_INSTANCE_X_PIXMAP (ii) =
937 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
941 case IMAGE_COLOR_PIXMAP:
943 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
944 unsigned long fg = BlackPixelOfScreen (scr);
945 unsigned long bg = WhitePixelOfScreen (scr);
947 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
949 Fmake_color_instance (foreground, device,
950 encode_error_behavior_flag (ERROR_ME));
952 if (COLOR_INSTANCEP (foreground))
953 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
955 if (!NILP (background) && !COLOR_INSTANCEP (background))
957 Fmake_color_instance (background, device,
958 encode_error_behavior_flag (ERROR_ME));
960 if (COLOR_INSTANCEP (background))
961 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
963 /* We used to duplicate the pixels using XAllocColor(), to protect
964 against their getting freed. Just as easy to just store the
965 color instances here and GC-protect them, so this doesn't
967 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
968 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
969 IMAGE_INSTANCE_X_PIXMAP (ii) =
970 XCreatePixmapFromBitmapData (dpy, draw,
971 (char *) bits, width, height,
973 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
979 XColor fg_color, bg_color;
982 check_pointer_sizes (scr, width, height, instantiator);
985 XCreatePixmapFromBitmapData (dpy, draw,
986 (char *) bits, width, height,
989 if (NILP (foreground))
990 foreground = pointer_fg;
991 if (NILP (background))
992 background = pointer_bg;
993 generate_cursor_fg_bg (device, &foreground, &background,
994 &fg_color, &bg_color);
996 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
997 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
998 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
999 find_keyword_in_vector (instantiator, Q_hotspot_x);
1000 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1001 find_keyword_in_vector (instantiator, Q_hotspot_y);
1002 IMAGE_INSTANCE_X_CURSOR (ii) =
1004 (dpy, source, mask, &fg_color, &bg_color,
1005 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1006 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1007 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1008 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1018 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1019 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1020 int dest_mask, int width, int height,
1021 /* Note that data is in ext-format! */
1024 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1025 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1026 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1028 CONST char *gcc_may_you_rot_in_hell;
1030 if (!NILP (mask_data))
1032 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1033 gcc_may_you_rot_in_hell);
1035 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1036 XINT (XCAR (mask_data)),
1037 XINT (XCAR (XCDR (mask_data))),
1038 (CONST unsigned char *)
1039 gcc_may_you_rot_in_hell);
1042 init_image_instance_from_xbm_inline (ii, width, height, bits,
1043 instantiator, pointer_fg, pointer_bg,
1044 dest_mask, mask, mask_file);
1047 /* Instantiate method for XBM's. */
1050 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1051 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1052 int dest_mask, Lisp_Object domain)
1054 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1055 CONST char *gcc_go_home;
1057 assert (!NILP (data));
1059 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1062 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1063 pointer_bg, dest_mask, XINT (XCAR (data)),
1064 XINT (XCAR (XCDR (data))), gcc_go_home);
1070 /**********************************************************************
1072 **********************************************************************/
1073 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1074 There was no version number in xpm.h before 3.3, but this should do.
1076 #if (XpmVersion >= 3) || defined(XpmExactColors)
1077 # define XPM_DOES_BUFFERS
1080 #ifndef XPM_DOES_BUFFERS
1081 Your version of XPM is too old. You cannot compile with it.
1082 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1083 #endif /* !XPM_DOES_BUFFERS */
1085 static XpmColorSymbol *
1086 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1088 Lisp_Object color_symbol_alist)
1090 /* This function can GC */
1091 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1092 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1095 Lisp_Object results = Qnil;
1097 XpmColorSymbol *symbols;
1098 struct gcpro gcpro1, gcpro2;
1100 GCPRO2 (results, device);
1102 /* We built up results to be (("name" . #<color>) ...) so that if an
1103 error happens we don't lose any malloc()ed data, or more importantly,
1104 leave any pixels allocated in the server. */
1106 LIST_LOOP (rest, color_symbol_alist)
1108 Lisp_Object cons = XCAR (rest);
1109 Lisp_Object name = XCAR (cons);
1110 Lisp_Object value = XCDR (cons);
1113 if (STRINGP (value))
1115 Fmake_color_instance
1116 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1119 assert (COLOR_SPECIFIERP (value));
1120 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1124 results = noseeum_cons (noseeum_cons (name, value), results);
1127 UNGCPRO; /* no more evaluation */
1129 if (i == 0) return 0;
1131 symbols = xnew_array (XpmColorSymbol, i);
1132 xpmattrs->valuemask |= XpmColorSymbols;
1133 xpmattrs->colorsymbols = symbols;
1134 xpmattrs->numsymbols = i;
1138 Lisp_Object cons = XCAR (results);
1139 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1140 /* Duplicate the pixel value so that we still have a lock on it if
1141 the pixel we were passed is later freed. */
1142 if (! XAllocColor (dpy, cmap, &color))
1143 abort (); /* it must be allocable since we're just duplicating it */
1145 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1146 symbols [i].pixel = color.pixel;
1147 symbols [i].value = 0;
1148 free_cons (XCONS (cons));
1150 results = XCDR (results);
1151 free_cons (XCONS (cons));
1157 xpm_free (XpmAttributes *xpmattrs)
1159 /* Could conceivably lose if XpmXXX returned an error without first
1160 initializing this structure, if we didn't know that initializing it
1161 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1162 multiple times, since it zeros slots as it frees them...) */
1163 XpmFreeAttributes (xpmattrs);
1167 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1168 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1169 int dest_mask, Lisp_Object domain)
1171 /* This function can GC */
1172 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1173 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1174 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1182 XpmAttributes xpmattrs;
1184 XpmColorSymbol *color_symbols;
1185 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1187 enum image_instance_type type;
1191 if (!DEVICE_X_P (XDEVICE (device)))
1192 signal_simple_error ("Not an X device", device);
1194 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1195 xs = DefaultScreenOfDisplay (dpy);
1197 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1198 type = IMAGE_COLOR_PIXMAP;
1199 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1200 type = IMAGE_MONO_PIXMAP;
1201 else if (dest_mask & IMAGE_POINTER_MASK)
1202 type = IMAGE_POINTER;
1204 incompatible_image_types (instantiator, dest_mask,
1205 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1206 | IMAGE_POINTER_MASK);
1207 force_mono = (type != IMAGE_COLOR_PIXMAP);
1210 /* Although I haven't found it documented yet, it appears that pointers are
1211 always colored via the default window colormap... Sigh. */
1212 if (type == IMAGE_POINTER)
1214 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1215 depth = DefaultDepthOfScreen (xs);
1216 visual = DefaultVisualOfScreen (xs);
1220 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1221 depth = DEVICE_X_DEPTH (XDEVICE(device));
1222 visual = DEVICE_X_VISUAL (XDEVICE(device));
1225 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1226 depth = DEVICE_X_DEPTH (XDEVICE(device));
1227 visual = DEVICE_X_VISUAL (XDEVICE(device));
1230 x_initialize_pixmap_image_instance (ii, type);
1232 assert (!NILP (data));
1236 xzero (xpmattrs); /* want XpmInitAttributes() */
1237 xpmattrs.valuemask = XpmReturnPixels;
1240 /* Without this, we get a 1-bit version of the color image, which
1241 isn't quite right. With this, we get the mono image, which might
1242 be very different looking. */
1243 xpmattrs.valuemask |= XpmColorKey;
1244 xpmattrs.color_key = XPM_MONO;
1246 xpmattrs.valuemask |= XpmDepth;
1250 xpmattrs.closeness = 65535;
1251 xpmattrs.valuemask |= XpmCloseness;
1252 xpmattrs.depth = depth;
1253 xpmattrs.valuemask |= XpmDepth;
1254 xpmattrs.visual = visual;
1255 xpmattrs.valuemask |= XpmVisual;
1256 xpmattrs.colormap = cmap;
1257 xpmattrs.valuemask |= XpmColormap;
1260 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1261 color_symbol_alist);
1263 result = XpmCreatePixmapFromBuffer (dpy,
1264 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1265 (char *) XSTRING_DATA (data),
1266 &pixmap, &mask, &xpmattrs);
1270 xfree (color_symbols);
1271 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1272 xpmattrs.numsymbols = 0;
1279 case XpmFileInvalid:
1281 xpm_free (&xpmattrs);
1282 signal_image_error ("invalid XPM data", data);
1284 case XpmColorFailed:
1287 xpm_free (&xpmattrs);
1290 /* second time; blow out. */
1291 signal_double_file_error ("Reading pixmap data",
1292 "color allocation failed",
1297 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1299 /* second time; blow out. */
1300 signal_double_file_error ("Reading pixmap data",
1301 "color allocation failed",
1305 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1311 xpm_free (&xpmattrs);
1312 signal_double_file_error ("Parsing pixmap data",
1313 "out of memory", data);
1317 xpm_free (&xpmattrs);
1318 signal_double_file_error_2 ("Parsing pixmap data",
1319 "unknown error code",
1320 make_int (result), data);
1325 h = xpmattrs.height;
1328 int npixels = xpmattrs.npixels;
1333 pixels = xnew_array (Pixel, npixels);
1334 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1339 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1340 IMAGE_INSTANCE_X_MASK (ii) = mask;
1341 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1342 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1343 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1344 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1345 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1346 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1347 find_keyword_in_vector (instantiator, Q_file);
1352 case IMAGE_MONO_PIXMAP:
1355 case IMAGE_COLOR_PIXMAP:
1357 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1363 int npixels = xpmattrs.npixels;
1364 Pixel *pixels = xpmattrs.pixels;
1367 int xhot = 0, yhot = 0;
1369 if (xpmattrs.valuemask & XpmHotspot)
1371 xhot = xpmattrs.x_hotspot;
1372 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1374 if (xpmattrs.valuemask & XpmHotspot)
1376 yhot = xpmattrs.y_hotspot;
1377 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1379 check_pointer_sizes (xs, w, h, instantiator);
1381 /* If the loaded pixmap has colors allocated (meaning it came from an
1382 XPM file), then use those as the default colors for the cursor we
1383 create. Otherwise, default to pointer_fg and pointer_bg.
1387 /* With an XBM file, it's obvious which bit is foreground
1388 and which is background, or rather, it's implicit: in
1389 an XBM file, a 1 bit is foreground, and a 0 bit is
1392 XCreatePixmapCursor() assumes this property of the
1393 pixmap it is called with as well; the `foreground'
1394 color argument is used for the 1 bits.
1396 With an XPM file, it's tricker, since the elements of
1397 the pixmap don't represent FG and BG, but are actual
1398 pixel values. So we need to figure out which of those
1399 pixels is the foreground color and which is the
1400 background. We do it by comparing RGB and assuming
1401 that the darker color is the foreground. This works
1402 with the result of xbmtopbm|ppmtoxpm, at least.
1404 It might be nice if there was some way to tag the
1405 colors in the XPM file with whether they are the
1406 foreground - perhaps with logical color names somehow?
1408 Once we have decided which color is the foreground, we
1409 need to ensure that that color corresponds to a `1' bit
1410 in the Pixmap. The XPM library wrote into the (1-bit)
1411 pixmap with XPutPixel, which will ignore all but the
1412 least significant bit.
1414 This means that a 1 bit in the image corresponds to
1415 `fg' only if `fg.pixel' is odd.
1417 (This also means that the image will be all the same
1418 color if both `fg' and `bg' are odd or even, but we can
1419 safely assume that that won't happen if the XPM file is
1422 The desired result is that the image use `1' to
1423 represent the foreground color, and `0' to represent
1424 the background color. So, we may need to invert the
1425 image to accomplish this; we invert if fg is
1426 odd. (Remember that WhitePixel and BlackPixel are not
1427 necessarily 1 and 0 respectively, though I think it
1428 might be safe to assume that one of them is always 1
1429 and the other is always 0. We also pretty much need to
1430 assume that one is even and the other is odd.)
1433 fg.pixel = pixels[0]; /* pick a pixel at random. */
1434 bg.pixel = fg.pixel;
1435 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1437 bg.pixel = pixels[i];
1438 if (fg.pixel != bg.pixel)
1442 /* If (fg.pixel == bg.pixel) then probably something has
1443 gone wrong, but I don't think signalling an error would
1446 XQueryColor (dpy, cmap, &fg);
1447 XQueryColor (dpy, cmap, &bg);
1449 /* If the foreground is lighter than the background, swap them.
1450 (This occurs semi-randomly, depending on the ordering of the
1451 color list in the XPM file.)
1454 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1456 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1458 if (fg_total > bg_total)
1467 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1468 (This occurs (only?) on servers with Black=0, White=1.)
1470 if ((fg.pixel & 1) == 0)
1474 gcv.function = GXxor;
1476 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1478 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1484 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1486 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1487 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1490 IMAGE_INSTANCE_X_CURSOR (ii) =
1492 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1501 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1504 #endif /* HAVE_XPM */
1509 /**********************************************************************
1511 **********************************************************************/
1513 /* This is about to get redefined! */
1516 /* We have to define SYSV32 so that compface.h includes string.h
1517 instead of strings.h. */
1522 #include <compface.h>
1526 /* JMP_BUF cannot be used here because if it doesn't get defined
1527 to jmp_buf we end up with a conflicting type error with the
1528 definition in compface.h */
1529 extern jmp_buf comp_env;
1533 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1534 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1535 int dest_mask, Lisp_Object domain)
1537 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1539 char *p, *bits, *bp;
1540 CONST char * volatile emsg = 0;
1541 CONST char * volatile dstring;
1543 assert (!NILP (data));
1545 GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
1547 if ((p = strchr (dstring, ':')))
1552 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1553 if (!(stattis = setjmp (comp_env)))
1555 UnCompAll ((char *) dstring);
1562 emsg = "uncompface: internal error";
1565 emsg = "uncompface: insufficient or invalid data";
1568 emsg = "uncompface: excess data ignored";
1573 signal_simple_error_2 (emsg, data, Qimage);
1575 bp = bits = (char *) alloca (PIXELS / 8);
1577 /* the compface library exports char F[], which uses a single byte per
1578 pixel to represent a 48x48 bitmap. Yuck. */
1579 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1582 /* reverse the bit order of each byte... */
1583 for (b = n = 0; b < 8; ++b)
1590 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1591 pointer_bg, dest_mask, 48, 48, bits);
1594 #endif /* HAVE_XFACE */
1597 /**********************************************************************
1599 **********************************************************************/
1602 autodetect_validate (Lisp_Object instantiator)
1604 data_must_be_present (instantiator);
1608 autodetect_normalize (Lisp_Object instantiator,
1609 Lisp_Object console_type)
1611 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1612 Lisp_Object filename = Qnil;
1613 Lisp_Object data = Qnil;
1614 struct gcpro gcpro1, gcpro2, gcpro3;
1615 Lisp_Object alist = Qnil;
1617 GCPRO3 (filename, data, alist);
1619 if (NILP (file)) /* no conversion necessary */
1620 RETURN_UNGCPRO (instantiator);
1622 alist = tagged_vector_to_alist (instantiator);
1624 filename = locate_pixmap_file (file);
1625 if (!NILP (filename))
1628 /* #### Apparently some versions of XpmReadFileToData, which is
1629 called by pixmap_to_lisp_data, don't return an error value
1630 if the given file is not a valid XPM file. Instead, they
1631 just seg fault. It is definitely caused by passing a
1632 bitmap. To try and avoid this we check for bitmaps first. */
1634 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1638 alist = remassq_no_quit (Q_data, alist);
1639 alist = Fcons (Fcons (Q_file, filename),
1640 Fcons (Fcons (Q_data, data), alist));
1642 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1645 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1648 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1651 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1653 RETURN_UNGCPRO (result);
1658 data = pixmap_to_lisp_data (filename, 1);
1662 alist = remassq_no_quit (Q_data, alist);
1663 alist = Fcons (Fcons (Q_file, filename),
1664 Fcons (Fcons (Q_data, data), alist));
1665 alist = Fcons (Fcons (Q_color_symbols,
1666 evaluate_xpm_color_symbols ()),
1669 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1671 RETURN_UNGCPRO (result);
1677 /* If we couldn't convert it, just put it back as it is.
1678 We might try to further frob it later as a cursor-font
1679 specification. (We can't do that now because we don't know
1680 what dest-types it's going to be instantiated into.) */
1682 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1684 RETURN_UNGCPRO (result);
1689 autodetect_possible_dest_types (void)
1692 IMAGE_MONO_PIXMAP_MASK |
1693 IMAGE_COLOR_PIXMAP_MASK |
1694 IMAGE_POINTER_MASK |
1699 autodetect_instantiate (Lisp_Object image_instance,
1700 Lisp_Object instantiator,
1701 Lisp_Object pointer_fg,
1702 Lisp_Object pointer_bg,
1703 int dest_mask, Lisp_Object domain)
1705 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1706 struct gcpro gcpro1, gcpro2, gcpro3;
1707 Lisp_Object alist = Qnil;
1708 Lisp_Object result = Qnil;
1709 int is_cursor_font = 0;
1711 GCPRO3 (data, alist, result);
1713 alist = tagged_vector_to_alist (instantiator);
1714 if (dest_mask & IMAGE_POINTER_MASK)
1716 CONST char *name_ext;
1717 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1718 if (XmuCursorNameToIndex (name_ext) != -1)
1720 result = alist_to_tagged_vector (Qcursor_font, alist);
1725 if (!is_cursor_font)
1726 result = alist_to_tagged_vector (Qstring, alist);
1730 cursor_font_instantiate (image_instance, result, pointer_fg,
1731 pointer_bg, dest_mask, domain);
1733 string_instantiate (image_instance, result, pointer_fg,
1734 pointer_bg, dest_mask, domain);
1740 /**********************************************************************
1742 **********************************************************************/
1745 font_validate (Lisp_Object instantiator)
1747 data_must_be_present (instantiator);
1750 /* XmuCvtStringToCursor is bogus in the following ways:
1752 - When it can't convert the given string to a real cursor, it will
1753 sometimes return a "success" value, after triggering a BadPixmap
1754 error. It then gives you a cursor that will itself generate BadCursor
1755 errors. So we install this error handler to catch/notice the X error
1756 and take that as meaning "couldn't convert."
1758 - When you tell it to find a cursor file that doesn't exist, it prints
1759 an error message on stderr. You can't make it not do that.
1761 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1762 objects, or XPM files, or $XBMLANGPATH.
1765 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1767 static int XLoadFont_got_error;
1770 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1772 XLoadFont_got_error = 1;
1777 safe_XLoadFont (Display *dpy, char *name)
1780 int (*old_handler) (Display *, XErrorEvent *);
1781 XLoadFont_got_error = 0;
1783 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1784 font = XLoadFont (dpy, name);
1786 XSetErrorHandler (old_handler);
1787 if (XLoadFont_got_error) return 0;
1792 font_possible_dest_types (void)
1794 return IMAGE_POINTER_MASK;
1798 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1799 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1800 int dest_mask, Lisp_Object domain)
1802 /* This function can GC */
1803 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1804 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1805 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1809 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1810 int source_char, mask_char;
1812 Lisp_Object foreground, background;
1814 if (!DEVICE_X_P (XDEVICE (device)))
1815 signal_simple_error ("Not an X device", device);
1817 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1819 if (!STRINGP (data) ||
1820 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1821 signal_simple_error ("Invalid font-glyph instantiator",
1824 if (!(dest_mask & IMAGE_POINTER_MASK))
1825 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1827 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1828 if (NILP (foreground))
1829 foreground = pointer_fg;
1830 background = find_keyword_in_vector (instantiator, Q_background);
1831 if (NILP (background))
1832 background = pointer_bg;
1834 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1836 count = sscanf ((char *) XSTRING_DATA (data),
1837 "FONT %s %d %s %d %c",
1838 source_name, &source_char,
1839 mask_name, &mask_char, &dummy);
1840 /* Allow "%s %d %d" as well... */
1841 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1842 count = 4, mask_name[0] = 0;
1844 if (count != 2 && count != 4)
1845 signal_simple_error ("invalid cursor specification", data);
1846 source = safe_XLoadFont (dpy, source_name);
1848 signal_simple_error_2 ("couldn't load font",
1849 build_string (source_name),
1853 else if (!mask_name[0])
1857 mask = safe_XLoadFont (dpy, mask_name);
1860 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1861 build_string (mask_name), data));
1866 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1868 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1869 IMAGE_INSTANCE_X_CURSOR (ii) =
1870 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1872 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1873 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1874 XUnloadFont (dpy, source);
1875 if (mask && mask != source) XUnloadFont (dpy, mask);
1879 /**********************************************************************
1881 **********************************************************************/
1884 cursor_font_validate (Lisp_Object instantiator)
1886 data_must_be_present (instantiator);
1890 cursor_font_possible_dest_types (void)
1892 return IMAGE_POINTER_MASK;
1896 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1897 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1898 int dest_mask, Lisp_Object domain)
1900 /* This function can GC */
1901 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1902 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1903 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1906 CONST char *name_ext;
1907 Lisp_Object foreground, background;
1909 if (!DEVICE_X_P (XDEVICE (device)))
1910 signal_simple_error ("Not an X device", device);
1912 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1914 if (!(dest_mask & IMAGE_POINTER_MASK))
1915 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1917 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1918 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
1919 signal_simple_error ("Unrecognized cursor-font name", data);
1921 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1922 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
1923 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1924 if (NILP (foreground))
1925 foreground = pointer_fg;
1926 background = find_keyword_in_vector (instantiator, Q_background);
1927 if (NILP (background))
1928 background = pointer_bg;
1929 maybe_recolor_cursor (image_instance, foreground, background);
1933 x_colorize_image_instance (Lisp_Object image_instance,
1934 Lisp_Object foreground, Lisp_Object background)
1936 struct Lisp_Image_Instance *p;
1938 p = XIMAGE_INSTANCE (image_instance);
1940 switch (IMAGE_INSTANCE_TYPE (p))
1942 case IMAGE_MONO_PIXMAP:
1943 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
1944 /* Make sure there aren't two pointers to the same mask, causing
1945 it to get freed twice. */
1946 IMAGE_INSTANCE_X_MASK (p) = 0;
1954 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1955 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
1956 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1957 Pixmap new = XCreatePixmap (dpy, draw,
1958 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
1959 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
1963 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
1964 gcv.foreground = color.pixel;
1965 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
1966 gcv.background = color.pixel;
1967 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
1968 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
1969 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
1970 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
1973 IMAGE_INSTANCE_X_PIXMAP (p) = new;
1974 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
1975 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
1976 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
1982 /************************************************************************/
1983 /* subwindow and widget support */
1984 /************************************************************************/
1986 /* unmap the image if it is a widget. This is used by redisplay via
1987 redisplay_unmap_subwindows */
1989 x_unmap_subwindow (struct Lisp_Image_Instance *p)
1991 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
1994 (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)),
1995 IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
1997 else /* must be a widget */
1999 XtUnmapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
2003 /* map the subwindow. This is used by redisplay via
2004 redisplay_output_subwindow */
2006 x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y)
2008 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2010 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2011 Screen* screen = IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p);
2012 XMapWindow (DisplayOfScreen (screen), subwindow);
2013 XMoveWindow (DisplayOfScreen (screen), subwindow, x, y);
2015 else /* must be a widget */
2017 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2018 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2019 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2020 XtMapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
2024 /* when you click on a widget you may activate another widget this
2025 needs to be checked and all appropriate widgets updated */
2027 x_update_subwindow (struct Lisp_Image_Instance *p)
2029 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
2031 widget_value* wv = xmalloc_widget_value ();
2032 button_item_to_widget_value (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p),
2034 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2039 /* instantiate and x type subwindow */
2041 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2042 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2043 int dest_mask, Lisp_Object domain)
2045 /* This function can GC */
2046 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2047 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2048 Lisp_Object frame = FW_FRAME (domain);
2049 struct frame* f = XFRAME (frame);
2053 XSetWindowAttributes xswa;
2055 unsigned int w = IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii),
2056 h = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii);
2058 if (!DEVICE_X_P (XDEVICE (device)))
2059 signal_simple_error ("Not an X device", device);
2061 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2062 xs = DefaultScreenOfDisplay (dpy);
2064 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2066 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2068 ii->data = xnew_and_zero (struct x_subwindow_data);
2070 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2071 IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii) = xs;
2073 xswa.backing_store = Always;
2074 valueMask |= CWBackingStore;
2075 xswa.colormap = DefaultColormapOfScreen (xs);
2076 valueMask |= CWColormap;
2078 win = XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2079 InputOutput, CopyFromParent, valueMask,
2082 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2086 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2087 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2088 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2089 Subwindows are not currently implemented.
2091 (subwindow, property, data))
2094 struct Lisp_Subwindow *sw;
2097 CHECK_SUBWINDOW (subwindow);
2098 CHECK_STRING (property);
2099 CHECK_STRING (data);
2101 sw = XSUBWINDOW (subwindow);
2102 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2103 (FRAME_DEVICE (XFRAME (sw->frame))));
2105 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2106 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2108 XSTRING_DATA (data),
2109 XSTRING_LENGTH (data));
2116 x_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h)
2118 XResizeWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii)),
2119 IMAGE_INSTANCE_X_SUBWINDOW_ID (ii),
2123 /************************************************************************/
2125 /************************************************************************/
2128 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2129 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2130 int dest_mask, Lisp_Object domain,
2131 CONST char* type, widget_value* wv)
2133 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2134 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2135 struct device* d = XDEVICE (device);
2136 Lisp_Object frame = FW_FRAME (domain);
2137 struct frame* f = XFRAME (frame);
2138 XColor fcolor, bcolor;
2143 int id = new_lwlib_id ();
2145 if (!DEVICE_X_P (d))
2146 signal_simple_error ("Not an mswindows device", device);
2148 /* have to set the type this late in case there is no device
2149 instantiation for a widget. But we can go ahead and do it without
2150 checking because there is always a generic instantiator. */
2151 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2153 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2154 GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm);
2156 ii->data = xnew_and_zero (struct x_subwindow_data);
2158 /* copy any args we were given */
2160 lw_add_value_args_to_args (wv, al, &ac);
2162 /* add our own arguments */
2163 pixel = FACE_FOREGROUND
2164 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2165 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
2166 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2167 pixel = FACE_BACKGROUND
2168 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2169 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
2170 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2172 XtSetArg (al [ac], XtNbackground, bcolor.pixel); ac++;
2173 XtSetArg (al [ac], XtNforeground, fcolor.pixel); ac++;
2174 XtSetArg (al [ac], XtNfont, (void*)FONT_INSTANCE_X_FONT
2175 (XFONT_INSTANCE (widget_face_font_info
2177 IMAGE_INSTANCE_WIDGET_FACE (ii),
2183 wid = lw_create_widget (type, wv->name, id, wv, FRAME_X_CONTAINER_WIDGET (f),
2184 False, 0, popup_selection_callback, 0);
2186 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2188 /* because the EmacsManager is the widgets parent we have to
2189 offset the redisplay of the widget by the amount the text
2190 widget is inside the manager. */
2192 XtSetArg (al [ac], XtNwidth,
2193 (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++;
2194 XtSetArg (al [ac], XtNheight,
2195 (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++;
2196 XtSetValues (wid, al, ac);
2197 /* finally get offsets in the frame */
2199 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2200 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2201 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2203 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2205 free_widget_value (wv);
2209 x_widget_set_property (Lisp_Object image_instance, Lisp_Object prop,
2212 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2214 if (EQ (prop, Q_text))
2217 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2219 GET_C_STRING_OS_DATA_ALLOCA (val, str);
2221 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False);
2227 /* get properties of a control */
2229 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2231 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2232 /* get the text from a control */
2233 if (EQ (prop, Q_text))
2235 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2236 return build_ext_string (wv->value, FORMAT_OS);
2241 /* Instantiate a button widget. Unfortunately instantiated widgets are
2242 particular to a frame since they need to have a parent. It's not
2243 like images where you just select the image into the context you
2244 want to display it in and BitBlt it. So images instances can have a
2245 many-to-one relationship with things you see, whereas widgets can
2246 only be one-to-one (i.e. per frame) */
2248 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2249 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2250 int dest_mask, Lisp_Object domain)
2252 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2253 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2254 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2255 widget_value* wv = xmalloc_widget_value ();
2257 button_item_to_widget_value (gui, wv, 1, 1);
2261 if (!IMAGE_INSTANCEP (glyph))
2262 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2265 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2266 pointer_bg, dest_mask, domain, "button", wv);
2268 /* add the image if one was given */
2269 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph))
2273 #ifdef LWLIB_USES_MOTIF
2274 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2275 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2277 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2279 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2283 /* get properties of a button */
2285 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2287 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2288 /* check the state of a button */
2289 if (EQ (prop, Q_selected))
2291 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2301 /* instantiate a progress gauge */
2303 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2304 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2305 int dest_mask, Lisp_Object domain)
2307 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2308 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2309 widget_value* wv = xmalloc_widget_value ();
2311 button_item_to_widget_value (gui, wv, 1, 1);
2313 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2314 pointer_bg, dest_mask, domain, "progress", wv);
2317 /* set the properties of a progres guage */
2319 x_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop,
2322 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2324 if (EQ (prop, Q_percent))
2328 XtSetArg (al[0], XtNvalue, XINT (val));
2329 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2335 /* instantiate an edit control */
2337 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2338 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2339 int dest_mask, Lisp_Object domain)
2341 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2342 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2343 widget_value* wv = xmalloc_widget_value ();
2345 button_item_to_widget_value (gui, wv, 1, 1);
2347 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2348 pointer_bg, dest_mask, domain, "text-field", wv);
2351 /* instantiate a combo control */
2353 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2354 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2355 int dest_mask, Lisp_Object domain)
2357 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2359 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2360 widget_value* wv = xmalloc_widget_value ();
2362 button_item_to_widget_value (gui, wv, 1, 1);
2364 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2365 pointer_bg, dest_mask, domain, "combo-box", wv);
2366 /* add items to the combo box */
2367 LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
2372 GET_C_STRING_OS_DATA_ALLOCA (XCAR (rest), str);
2373 xmstr = XmStringCreate (str, XmSTRING_DEFAULT_CHARSET);
2374 XmListAddItem (IMAGE_INSTANCE_X_WIDGET_ID (ii), xmstr, 0);
2375 XmStringFree (xmstr);
2381 /************************************************************************/
2382 /* initialization */
2383 /************************************************************************/
2386 syms_of_glyphs_x (void)
2389 DEFSUBR (Fchange_subwindow_property);
2394 console_type_create_glyphs_x (void)
2398 CONSOLE_HAS_METHOD (x, print_image_instance);
2399 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2400 CONSOLE_HAS_METHOD (x, image_instance_equal);
2401 CONSOLE_HAS_METHOD (x, image_instance_hash);
2402 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2403 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2404 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2405 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2406 CONSOLE_HAS_METHOD (x, map_subwindow);
2407 CONSOLE_HAS_METHOD (x, resize_subwindow);
2408 CONSOLE_HAS_METHOD (x, update_subwindow);
2412 image_instantiator_format_create_glyphs_x (void)
2415 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2416 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2418 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2419 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2421 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2422 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2425 INITIALIZE_DEVICE_IIFORMAT (x, button);
2426 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2427 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2429 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2430 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2431 IIFORMAT_HAS_DEVMETHOD (x, widget, set_property);
2432 /* progress gauge */
2433 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2434 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, set_property);
2435 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2437 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2438 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2440 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2441 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2443 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2445 IIFORMAT_HAS_METHOD (cursor_font, validate);
2446 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2447 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2449 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2450 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2451 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2453 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2455 IIFORMAT_HAS_METHOD (font, validate);
2456 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2457 IIFORMAT_HAS_METHOD (font, instantiate);
2459 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2460 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2461 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2464 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2465 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2468 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2471 IIFORMAT_HAS_METHOD (autodetect, validate);
2472 IIFORMAT_HAS_METHOD (autodetect, normalize);
2473 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2474 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2476 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2480 vars_of_glyphs_x (void)
2482 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2483 A list of the directories in which X bitmap files may be found.
2484 If nil, this is initialized from the "*bitmapFilePath" resource.
2485 This is used by the `make-image-instance' function (however, note that if
2486 the environment variable XBMLANGPATH is set, it is consulted first).
2488 Vx_bitmap_file_path = Qnil;
2492 complex_vars_of_glyphs_x (void)
2494 #define BUILD_GLYPH_INST(variable, name) \
2495 Fadd_spec_to_specifier \
2496 (GLYPH_IMAGE (XGLYPH (variable)), \
2497 vector3 (Qxbm, Q_data, \
2498 list3 (make_int (name##_width), \
2499 make_int (name##_height), \
2500 make_ext_string (name##_bits, \
2501 sizeof (name##_bits), \
2505 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2506 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2507 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2508 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2510 #undef BUILD_GLYPH_INST
2511 Fprovide_on_console (Qbutton, Qx);
2512 Fprovide_on_console (Qedit_field, Qx);
2513 Fprovide_on_console (Qprogress_gauge, Qx);
2514 /* Fprovide (Qcombo_box);*/