/* Functions for the X window system.
- Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999
+ Copyright (C) 1989, 92, 93, 94, 95, 96, 1997, 1998, 1999, 2000
Free Software Foundation.
This file is part of GNU Emacs.
#include "blockinput.h"
#include <epaths.h>
#include "charset.h"
+#include "coding.h"
#include "fontset.h"
#include "systime.h"
#include "termhooks.h"
Lisp_Object Quser_size;
extern Lisp_Object Qdisplay;
Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-Lisp_Object Qscreen_gamma, Qline_spacing;
+Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
+Lisp_Object Qcompound_text;
/* The below are defined in frame.c. */
check_x_display_info (frame)
Lisp_Object frame;
{
+ struct x_display_info *dpyinfo = NULL;
+
if (NILP (frame))
{
struct frame *sf = XFRAME (selected_frame);
if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
- return FRAME_X_DISPLAY_INFO (sf);
+ dpyinfo = FRAME_X_DISPLAY_INFO (sf);
else if (x_display_list != 0)
- return x_display_list;
+ dpyinfo = x_display_list;
else
error ("X windows are not in use or not initialized");
}
else if (STRINGP (frame))
- return x_display_info_for_name (frame);
+ dpyinfo = x_display_info_for_name (frame);
else
{
FRAME_PTR f;
f = XFRAME (frame);
if (! FRAME_X_P (f))
error ("Non-X frame used");
- return FRAME_X_DISPLAY_INFO (f);
+ dpyinfo = FRAME_X_DISPLAY_INFO (f);
}
+
+ return dpyinfo;
}
\f
fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
if (fd < 0)
return -1;
- /* XReadBitmapFile won't handle magic file names. */
- if (fd == 0)
- return -1;
emacs_close (fd);
filename = (char *) XSTRING (found)->data;
void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
};
+static void x_change_window_heights P_ ((Lisp_Object, int));
+static void x_disable_image P_ ((struct frame *, struct image *));
static void x_create_im P_ ((struct frame *));
void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
char *, char *,
int));
static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
+ Lisp_Object));
+static void init_color_table P_ ((void));
+static void free_color_table P_ ((void));
+static unsigned long *colors_in_color_table P_ ((int *n));
+static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
+static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
+
+
static struct x_frame_parm_table x_frame_parms[] =
{
}
\f
/* Change the parameters of frame F as specified by ALIST.
- If a parameter is not specially recognized, do nothing;
- otherwise call the `x_set_...' function for that parameter. */
+ If a parameter is not specially recognized, do nothing special;
+ otherwise call the `x_set_...' function for that parameter.
+ Except for certain geometry properties, always call store_frame_param
+ to store the new value in the parameter alist. */
void
x_set_frame_parameters (f, alist)
#endif
Window tmp_root_window;
Window *tmp_children;
- int tmp_nchildren;
+ unsigned int tmp_nchildren;
while (1)
{
if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
return cdef.pixel;
- Fsignal (Qerror, Fcons (build_string ("undefined color"),
+ Fsignal (Qerror, Fcons (build_string ("Undefined color"),
Fcons (color_name, Qnil)));
+ return 0;
}
else if (NATNUMP (new_value))
f->extra_line_spacing = XFASTINT (new_value);
else
- Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
+ Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
Fcons (new_value, Qnil)));
if (FRAME_VISIBLE_P (f))
redraw_frame (f);
/* The value 0.4545 is the normal viewing gamma. */
f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
else
- Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
+ Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
Fcons (new_value, Qnil)));
clear_face_cache (0);
XColor fore_color, back_color;
fore_color.pixel = f->output_data.x->mouse_pixel;
+ x_query_color (f, &fore_color);
back_color.pixel = mask_color;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &fore_color);
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &back_color);
+ x_query_color (f, &back_color);
+
XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
- &fore_color, &back_color);
+ &fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
&fore_color, &back_color);
}
else
Fmake_frame_visible (frame);
}
+
\f
+/* Change window heights in windows rooted in WINDOW by N lines. */
+
static void
-x_set_menu_bar_lines_1 (window, n)
+x_change_window_heights (window, n)
Lisp_Object window;
int n;
{
/* Handle just the top child in a vertical split. */
if (!NILP (w->vchild))
- x_set_menu_bar_lines_1 (w->vchild, n);
+ x_change_window_heights (w->vchild, n);
/* Adjust all children in a horizontal split. */
for (window = w->hchild; !NILP (window); window = w->next)
{
w = XWINDOW (window);
- x_set_menu_bar_lines_1 (window, n);
+ x_change_window_heights (window, n);
}
}
}
#else /* not USE_X_TOOLKIT */
FRAME_MENU_BAR_LINES (f) = nlines;
- x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
+ x_change_window_heights (f->root_window, nlines - olines);
#endif /* not USE_X_TOOLKIT */
adjust_glyphs (f);
}
struct frame *f;
Lisp_Object value, oldval;
{
- int delta, nlines;
+ int delta, nlines, root_height;
+ Lisp_Object root_window;
/* Use VALUE only if an integer >= 0. */
if (INTEGERP (value) && XINT (value) >= 0)
++windows_or_buffers_changed;
delta = nlines - FRAME_TOOL_BAR_LINES (f);
+
+ /* Don't resize the tool-bar to more than we have room for. */
+ root_window = FRAME_ROOT_WINDOW (f);
+ root_height = XINT (XWINDOW (root_window)->height);
+ if (root_height - delta < 1)
+ {
+ delta = root_height - 1;
+ nlines = FRAME_TOOL_BAR_LINES (f) + delta;
+ }
+
FRAME_TOOL_BAR_LINES (f) = nlines;
- x_set_menu_bar_lines_1 (FRAME_ROOT_WINDOW (f), delta);
+ x_change_window_heights (root_window, delta);
adjust_glyphs (f);
+
+ /* We also have to make sure that the internal border at the top of
+ the frame, below the menu bar or tool bar, is redrawn when the
+ tool bar disappears. This is so because the internal border is
+ below the tool bar if one is displayed, but is below the menu bar
+ if there isn't a tool bar. The tool bar draws into the area
+ below the menu bar. */
+ if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
+ {
+ updating_frame = f;
+ clear_frame ();
+ clear_current_matrices (f);
+ updating_frame = NULL;
+ }
}
}
\f
+/* Encode Lisp string STRING as a text in a format appropriate for
+ XICCC (X Inter Client Communication Conventions).
+
+ If STRING contains only ASCII characters, do no conversion and
+ return the string data of STRING. Otherwise, encode the text by
+ CODING_SYSTEM, and return a newly allocated memory area which
+ should be freed by `xfree' by a caller.
+
+ Store the byte length of resulting text in *TEXT_BYTES.
+
+ If the text contains only ASCII and Latin-1, store 1 in *STRING_P,
+ which means that the `encoding' of the result can be `STRING'.
+ Otherwise store 0 in *STRINGP, which means that the `encoding' of
+ the result should be `COMPOUND_TEXT'. */
+
+unsigned char *
+x_encode_text (string, coding_system, text_bytes, stringp)
+ Lisp_Object string, coding_system;
+ int *text_bytes, *stringp;
+{
+ unsigned char *str = XSTRING (string)->data;
+ int chars = XSTRING (string)->size;
+ int bytes = STRING_BYTES (XSTRING (string));
+ int charset_info;
+ int bufsize;
+ unsigned char *buf;
+ struct coding_system coding;
+
+ charset_info = find_charset_in_text (str, chars, bytes, NULL, Qnil);
+ if (charset_info == 0)
+ {
+ /* No multibyte character in OBJ. We need not encode it. */
+ *text_bytes = bytes;
+ *stringp = 1;
+ return str;
+ }
+
+ setup_coding_system (coding_system, &coding);
+ coding.src_multibyte = 1;
+ coding.dst_multibyte = 0;
+ coding.mode |= CODING_MODE_LAST_BLOCK;
+ if (coding.type == coding_type_iso2022)
+ coding.flags |= CODING_FLAG_ISO_SAFE;
+ /* We suppress producing escape sequences for composition. */
+ coding.composing = COMPOSITION_DISABLED;
+ bufsize = encoding_buffer_size (&coding, bytes);
+ buf = (unsigned char *) xmalloc (bufsize);
+ encode_coding (&coding, str, buf, bytes, bufsize);
+ *text_bytes = coding.produced;
+ *stringp = (charset_info == 1 || !EQ (coding_system, Qcompound_text));
+ return buf;
+}
+
+\f
/* Change the name of frame F to NAME. If NAME is nil, set F's name to
x_id_name.
#ifdef HAVE_X11R4
{
XTextProperty text, icon;
- Lisp_Object icon_name;
-
- text.value = XSTRING (name)->data;
- text.encoding = XA_STRING;
+ int bytes, stringp;
+ Lisp_Object coding_system;
+
+ coding_system = Vlocale_coding_system;
+ if (NILP (coding_system))
+ coding_system = Qcompound_text;
+ text.value = x_encode_text (name, coding_system, &bytes, &stringp);
+ text.encoding = (stringp ? XA_STRING
+ : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
text.format = 8;
- text.nitems = STRING_BYTES (XSTRING (name));
+ text.nitems = bytes;
- icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
-
- icon.value = XSTRING (icon_name)->data;
- icon.encoding = XA_STRING;
- icon.format = 8;
- icon.nitems = STRING_BYTES (XSTRING (icon_name));
+ if (NILP (f->icon_name))
+ {
+ icon = text;
+ }
+ else
+ {
+ icon.value = x_encode_text (f->icon_name, coding_system,
+ &bytes, &stringp);
+ icon.encoding = (stringp ? XA_STRING
+ : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
+ icon.format = 8;
+ icon.nitems = bytes;
+ }
#ifdef USE_X_TOOLKIT
XSetWMName (FRAME_X_DISPLAY (f),
XtWindow (f->output_data.x->widget), &text);
XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
#endif /* not USE_X_TOOLKIT */
+ if (!NILP (f->icon_name)
+ && icon.value != XSTRING (f->icon_name)->data)
+ xfree (icon.value);
+ if (text.value != XSTRING (name)->data)
+ xfree (text.value);
}
#else /* not HAVE_X11R4 */
XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
#ifdef HAVE_X11R4
{
XTextProperty text, icon;
- Lisp_Object icon_name;
-
- text.value = XSTRING (name)->data;
- text.encoding = XA_STRING;
+ int bytes, stringp;
+ Lisp_Object coding_system;
+
+ coding_system = Vlocale_coding_system;
+ if (NILP (coding_system))
+ coding_system = Qcompound_text;
+ text.value = x_encode_text (name, coding_system, &bytes, &stringp);
+ text.encoding = (stringp ? XA_STRING
+ : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
text.format = 8;
- text.nitems = STRING_BYTES (XSTRING (name));
-
- icon_name = (!NILP (f->icon_name) ? f->icon_name : name);
+ text.nitems = bytes;
- icon.value = XSTRING (icon_name)->data;
- icon.encoding = XA_STRING;
- icon.format = 8;
- icon.nitems = STRING_BYTES (XSTRING (icon_name));
+ if (NILP (f->icon_name))
+ {
+ icon = text;
+ }
+ else
+ {
+ icon.value = x_encode_text (f->icon_name, coding_system,
+ &bytes, &stringp);
+ icon.encoding = (stringp ? XA_STRING
+ : FRAME_X_DISPLAY_INFO (f)->Xatom_COMPOUND_TEXT);
+ icon.format = 8;
+ icon.nitems = bytes;
+ }
#ifdef USE_X_TOOLKIT
XSetWMName (FRAME_X_DISPLAY (f),
XtWindow (f->output_data.x->widget), &text);
XSetWMName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &icon);
#endif /* not USE_X_TOOLKIT */
+ if (!NILP (f->icon_name)
+ && icon.value != XSTRING (f->icon_name)->data)
+ xfree (icon.value);
+ if (text.value != XSTRING (name)->data)
+ xfree (text.value);
}
#else /* not HAVE_X11R4 */
XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
else
{
int len = strlen (ascii_font) + 1;
- char *p1;
+ char *p1 = NULL;
for (i = 0, p = ascii_font; i < 8; p++)
{
#ifdef HAVE_X_I18N
FRAME_XIC (f) = NULL;
+#ifdef USE_XIM
create_frame_xic (f);
+#endif
#endif
f->output_data.x->wm_hints.input = True;
attribute_mask, &attributes);
#ifdef HAVE_X_I18N
+#ifdef USE_XIM
create_frame_xic (f);
if (FRAME_XIC (f))
{
XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
attribute_mask, &attributes);
}
+#endif
#endif /* HAVE_X_I18N */
validate_x_resource_name ();
UNBLOCK_INPUT;
}
-/* Make the GC's needed for this window, setting the
+/* Make the GCs needed for this window, setting the
background, border and mouse colors; also create the
mouse cursor and the gray border tile. */
BLOCK_INPUT;
- /* Create the GC's of this frame.
+ /* Create the GCs of this frame.
Note that many default values are used. */
/* Normal video */
x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
"menuBar", "MenuBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
+ x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
"toolBar", "ToolBar", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate",
SET_FRAME_WIDTH (f, 0);
change_frame_size (f, height, width, 1, 0, 0);
- /* Set up faces after all frame parameters are known. */
- call1 (Qface_set_after_frame_default, frame);
-
#ifdef USE_X_TOOLKIT
/* Create the menu bar. */
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
Lisp_Object display;
{
struct x_display_info *dpyinfo = check_x_display_info (display);
+ Lisp_Object result;
switch (DoesBackingStore (dpyinfo->screen))
{
case Always:
- return intern ("always");
+ result = intern ("always");
+ break;
case WhenMapped:
- return intern ("when-mapped");
+ result = intern ("when-mapped");
+ break;
case NotUseful:
- return intern ("not-useful");
+ result = intern ("not-useful");
+ break;
default:
error ("Strange value for BackingStore parameter of screen");
+ result = Qnil;
}
+
+ return result;
}
DEFUN ("x-display-visual-class", Fx_display_visual_class,
Lisp_Object display;
{
struct x_display_info *dpyinfo = check_x_display_info (display);
+ Lisp_Object result;
switch (dpyinfo->visual->class)
{
- case StaticGray: return (intern ("static-gray"));
- case GrayScale: return (intern ("gray-scale"));
- case StaticColor: return (intern ("static-color"));
- case PseudoColor: return (intern ("pseudo-color"));
- case TrueColor: return (intern ("true-color"));
- case DirectColor: return (intern ("direct-color"));
+ case StaticGray:
+ result = intern ("static-gray");
+ break;
+ case GrayScale:
+ result = intern ("gray-scale");
+ break;
+ case StaticColor:
+ result = intern ("static-color");
+ break;
+ case PseudoColor:
+ result = intern ("pseudo-color");
+ break;
+ case TrueColor:
+ result = intern ("true-color");
+ break;
+ case DirectColor:
+ result = intern ("direct-color");
+ break;
default:
error ("Display has an unknown visual class");
+ result = Qnil;
}
+
+ return result;
}
DEFUN ("x-display-save-under", Fx_display_save_under,
static struct image_type *image_types;
-/* A list of symbols, one for each supported image type. */
-
-Lisp_Object Vimage_types;
-
/* The symbol `image' which is the car of the lists used to represent
images in Lisp. */
extern Lisp_Object QCdata;
Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
/* Other symbols. */
-Lisp_Object Qlaplace;
+Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
/* Time in seconds after which images should be removed from the cache
if not displayed. */
static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
static void x_laplace P_ ((struct frame *, struct image *));
+static void x_emboss P_ ((struct frame *, struct image *));
static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
Lisp_Object));
IMAGE_SYMBOL_VALUE,
IMAGE_POSITIVE_INTEGER_VALUE,
IMAGE_NON_NEGATIVE_INTEGER_VALUE,
+ IMAGE_ASCENT_VALUE,
IMAGE_INTEGER_VALUE,
IMAGE_FUNCTION_VALUE,
IMAGE_NUMBER_VALUE,
return 0;
break;
+ case IMAGE_ASCENT_VALUE:
+ if (SYMBOLP (value) && EQ (value, Qcenter))
+ break;
+ else if (INTEGERP (value)
+ && XINT (value) >= 0
+ && XINT (value) <= 100)
+ break;
+ return 0;
+
case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
if (!INTEGERP (value) || XINT (value) < 0)
return 0;
}
+DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
+ "Return the size of image SPEC as pair (WIDTH . HEIGHT).\n\
+PIXELS non-nil means return the size in pixels, otherwise return the\n\
+size in canonical character units.\n\
+FRAME is the frame on which the image will be displayed. FRAME nil\n\
+or omitted means use the selected frame.")
+ (spec, pixels, frame)
+ Lisp_Object spec, pixels, frame;
+{
+ Lisp_Object size;
+
+ size = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ int width = img->width + 2 * img->margin;
+ int height = img->height + 2 * img->margin;
+
+ if (NILP (pixels))
+ size = Fcons (make_float ((double) width / CANON_X_UNIT (f)),
+ make_float ((double) height / CANON_Y_UNIT (f)));
+ else
+ size = Fcons (make_number (width), make_number (height));
+ }
+ else
+ error ("Invalid image specification");
+
+ return size;
+}
+
+
+DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
+ "Return t if image SPEC has a mask bitmap.\n\
+FRAME is the frame on which the image will be displayed. FRAME nil\n\
+or omitted means use the selected frame.")
+ (spec, frame)
+ Lisp_Object spec, frame;
+{
+ Lisp_Object mask;
+
+ mask = Qnil;
+ if (valid_image_p (spec))
+ {
+ struct frame *f = check_x_frame (frame);
+ int id = lookup_image (f, spec);
+ struct image *img = IMAGE_FROM_ID (f, id);
+ if (img->mask)
+ mask = Qt;
+ }
+ else
+ error ("Invalid image specification");
+
+ return mask;
+}
+
\f
/***********************************************************************
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
- if (img->pixmap == 0 && !img->load_failed_p)
+ if (img->pixmap == None && !img->load_failed_p)
img->load_failed_p = img->type->load (f, img) == 0;
}
+/* Value is the number of pixels for the ascent of image IMG when
+ drawn in face FACE. */
+
+int
+image_ascent (img, face)
+ struct image *img;
+ struct face *face;
+{
+ int height = img->height + img->margin;
+ int ascent;
+
+ if (img->ascent == CENTERED_IMAGE_ASCENT)
+ {
+ if (face->font)
+ /* This expression is arranged so that if the image can't be
+ exactly centered, it will be moved slightly up. This is
+ because a typical font is `top-heavy' (due to the presence
+ uppercase letters), so the image placement should err towards
+ being top-heavy too. It also just generally looks better. */
+ ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
+ else
+ ascent = height / 2;
+ }
+ else
+ ascent = height * img->ascent / 100.0;
+
+ return ascent;
+}
+
+
\f
/***********************************************************************
Helper functions for X image types
***********************************************************************/
+static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
+ int, int));
static void x_clear_image P_ ((struct frame *f, struct image *img));
static unsigned long x_alloc_image_color P_ ((struct frame *f,
struct image *img,
Lisp_Object color_name,
unsigned long dflt));
-/* Free X resources of image IMG which is used on frame F. */
+
+/* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
+ free the pixmap if any. MASK_P non-zero means clear the mask
+ pixmap if any. COLORS_P non-zero means free colors allocated for
+ the image, if any. */
static void
-x_clear_image (f, img)
+x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
struct frame *f;
struct image *img;
+ int pixmap_p, mask_p, colors_p;
{
- if (img->pixmap)
+ if (pixmap_p && img->pixmap)
{
- BLOCK_INPUT;
XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
- img->pixmap = 0;
- UNBLOCK_INPUT;
+ img->pixmap = None;
+ }
+
+ if (mask_p && img->mask)
+ {
+ XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+ img->mask = None;
}
- if (img->ncolors)
+ if (colors_p && img->ncolors)
{
- BLOCK_INPUT;
x_free_colors (f, img->colors, img->ncolors);
- UNBLOCK_INPUT;
-
xfree (img->colors);
img->colors = NULL;
img->ncolors = 0;
}
}
+/* Free X resources of image IMG which is used on frame F. */
+
+static void
+x_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ BLOCK_INPUT;
+ x_clear_image_1 (f, img, 1, 1, 1);
+ UNBLOCK_INPUT;
+}
+
/* Allocate color COLOR_NAME for image IMG on frame F. If color
cannot be allocated, use DFLT. Add a newly allocated color to
{
EMACS_TIME t;
unsigned long old;
- int i, any_freed_p = 0;
+ int i, nfreed;
EMACS_GET_TIME (t);
old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
+
+ /* Block input so that we won't be interrupted by a SIGIO
+ while being in an inconsistent state. */
+ BLOCK_INPUT;
- for (i = 0; i < c->used; ++i)
+ for (i = nfreed = 0; i < c->used; ++i)
{
struct image *img = c->images[i];
if (img != NULL
- && (force_p
- || (img->timestamp > old)))
+ && (force_p || img->timestamp < old))
{
free_image (f, img);
- any_freed_p = 1;
+ ++nfreed;
}
}
Emacs was iconified for a longer period of time. In that
case, current matrices may still contain references to
images freed above. So, clear these matrices. */
- if (any_freed_p)
+ if (nfreed)
{
- clear_current_matrices (f);
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *f = XFRAME (frame);
+ if (FRAME_X_P (f)
+ && FRAME_X_IMAGE_CACHE (f) == c)
+ clear_current_matrices (f);
+ }
+
++windows_or_buffers_changed;
}
+
+ UNBLOCK_INPUT;
}
}
/* If not found, create a new image and cache it. */
if (img == NULL)
{
+ BLOCK_INPUT;
img = make_image (spec, hash);
cache_image (f, img);
img->load_failed_p = img->type->load (f, img) == 0;
- xassert (!interrupt_input_blocked);
/* If we can't load the image, and we don't have a width and
height, use some arbitrary width and height so that we can
else
{
/* Handle image type independent image attributes
- `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
- Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
+ `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
+ Lisp_Object ascent, margin, relief;
Lisp_Object file;
ascent = image_spec_value (spec, QCascent, NULL);
if (INTEGERP (ascent))
img->ascent = XFASTINT (ascent);
+ else if (EQ (ascent, Qcenter))
+ img->ascent = CENTERED_IMAGE_ASCENT;
margin = image_spec_value (spec, QCmargin, NULL);
if (INTEGERP (margin) && XINT (margin) >= 0)
img->margin += abs (img->relief);
}
- /* Should we apply a Laplace edge-detection algorithm? */
- algorithm = image_spec_value (spec, QCalgorithm, NULL);
- if (img->pixmap && EQ (algorithm, Qlaplace))
- x_laplace (f, img);
-
- /* Should we built a mask heuristically? */
- heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
- if (img->pixmap && !img->mask && !NILP (heuristic_mask))
- x_build_heuristic_mask (f, img, heuristic_mask);
+ /* Manipulation of the image's mask. */
+ if (img->pixmap)
+ {
+ /* `:heuristic-mask t'
+ `:mask heuristic'
+ means build a mask heuristically.
+ `:heuristic-mask (R G B)'
+ `:mask (heuristic (R G B))'
+ means build a mask from color (R G B) in the
+ image.
+ `:mask nil'
+ means remove a mask, if any. */
+
+ Lisp_Object mask;
+
+ mask = image_spec_value (spec, QCheuristic_mask, NULL);
+ if (!NILP (mask))
+ x_build_heuristic_mask (f, img, mask);
+ else
+ {
+ int found_p;
+
+ mask = image_spec_value (spec, QCmask, &found_p);
+
+ if (EQ (mask, Qheuristic))
+ x_build_heuristic_mask (f, img, Qt);
+ else if (CONSP (mask)
+ && EQ (XCAR (mask), Qheuristic))
+ {
+ if (CONSP (XCDR (mask)))
+ x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
+ else
+ x_build_heuristic_mask (f, img, XCDR (mask));
+ }
+ else if (NILP (mask) && found_p && img->mask)
+ {
+ XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+ img->mask = None;
+ }
+ }
+ }
+
+ /* Should we apply an image transformation algorithm? */
+ if (img->pixmap)
+ {
+ Lisp_Object algorithm;
+
+ algorithm = image_spec_value (spec, QCalgorithm, NULL);
+ if (EQ (algorithm, Qdisabled))
+ x_disable_image (f, img);
+ else if (EQ (algorithm, Qlaplace))
+ x_laplace (f, img);
+ else if (EQ (algorithm, Qemboss))
+ x_emboss (f, img);
+ else if (CONSP (algorithm)
+ && EQ (XCAR (algorithm), Qedge_detection))
+ {
+ Lisp_Object tem;
+ tem = XCDR (algorithm);
+ if (CONSP (tem))
+ x_edge_detection (f, img,
+ Fplist_get (tem, QCmatrix),
+ Fplist_get (tem, QCcolor_adjustment));
+ }
+ }
}
+
+ UNBLOCK_INPUT;
+ xassert (!interrupt_input_blocked);
}
/* We're using IMG, so set its timestamp to `now'. */
/* Allocate a pixmap of the same size. */
*pixmap = XCreatePixmap (display, window, width, height, depth);
- if (*pixmap == 0)
+ if (*pixmap == None)
{
x_destroy_x_image (*ximg);
*ximg = NULL;
\f
/***********************************************************************
- Searching files
+ File Handling
***********************************************************************/
static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+static char *slurp_file P_ ((char *, int *));
+
/* Find image file FILE. Look in data-directory, then
x-bitmap-file-path. Value is the full name of the file found, or
/* Try to find FILE in data-directory, then x-bitmap-file-path. */
fd = openp (search_path, file, "", &file_found, 0);
- if (fd < 0)
+ if (fd == -1)
file_found = Qnil;
else
close (fd);
}
+/* Read FILE into memory. Value is a pointer to a buffer allocated
+ with xmalloc holding FILE's contents. Value is null if an error
+ occurred. *SIZE is set to the size of the file. */
+
+static char *
+slurp_file (file, size)
+ char *file;
+ int *size;
+{
+ FILE *fp = NULL;
+ char *buf = NULL;
+ struct stat st;
+
+ if (stat (file, &st) == 0
+ && (fp = fopen (file, "r")) != NULL
+ && (buf = (char *) xmalloc (st.st_size),
+ fread (buf, 1, st.st_size, fp) == st.st_size))
+ {
+ *size = st.st_size;
+ fclose (fp);
+ }
+ else
+ {
+ if (fp)
+ fclose (fp);
+ if (buf)
+ {
+ xfree (buf);
+ buf = NULL;
+ }
+ }
+
+ return buf;
+}
+
+
\f
/***********************************************************************
XBM images
***********************************************************************/
+static int xbm_scan P_ ((char **, char *, char *, int *));
static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
- Lisp_Object file));
+static int xbm_load_image P_ ((struct frame *f, struct image *img,
+ char *, char *));
static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
- unsigned char **));
+static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
+ unsigned char **));
+static int xbm_file_p P_ ((Lisp_Object));
/* Indices of image specification fields in xbm_format, below. */
XBM_RELIEF,
XBM_ALGORITHM,
XBM_HEURISTIC_MASK,
+ XBM_MASK,
XBM_LAST
};
{":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":foreground", IMAGE_STRING_VALUE, 0},
{":background", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
/* Structure describing the image type XBM. */
3. a vector of strings or bool-vectors, one for each line of the
bitmap.
+ 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
+ may not be specified in this case because they are defined in the
+ XBM file.
+
Both the file and data forms may contain the additional entries
`:background COLOR' and `:foreground COLOR'. If not present,
foreground and background of the frame on which the image is
if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
return 0;
}
+ else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
+ {
+ /* In-memory XBM file. */
+ if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+ return 0;
+ }
else
{
Lisp_Object data;
return 0;
}
- /* Baseline must be a value between 0 and 100 (a percentage). */
- if (kw[XBM_ASCENT].count
- && XFASTINT (kw[XBM_ASCENT].value) > 100)
- return 0;
-
return 1;
}
scanning a number, store its value in *IVAL. */
static int
-xbm_scan (fp, sval, ival)
- FILE *fp;
+xbm_scan (s, end, sval, ival)
+ char **s, *end;
char *sval;
int *ival;
{
int c;
+
+ loop:
/* Skip white space. */
- while ((c = fgetc (fp)) != EOF && isspace (c))
+ while (*s < end && (c = *(*s)++, isspace (c)))
;
- if (c == EOF)
+ if (*s >= end)
c = 0;
else if (isdigit (c))
{
int value = 0, digit;
- if (c == '0')
+ if (c == '0' && *s < end)
{
- c = fgetc (fp);
+ c = *(*s)++;
if (c == 'x' || c == 'X')
{
- while ((c = fgetc (fp)) != EOF)
+ while (*s < end)
{
+ c = *(*s)++;
if (isdigit (c))
digit = c - '0';
else if (c >= 'a' && c <= 'f')
else if (isdigit (c))
{
value = c - '0';
- while ((c = fgetc (fp)) != EOF
- && isdigit (c))
+ while (*s < end
+ && (c = *(*s)++, isdigit (c)))
value = 8 * value + c - '0';
}
}
else
{
value = c - '0';
- while ((c = fgetc (fp)) != EOF
- && isdigit (c))
+ while (*s < end
+ && (c = *(*s)++, isdigit (c)))
value = 10 * value + c - '0';
}
- if (c != EOF)
- ungetc (c, fp);
+ if (*s < end)
+ *s = *s - 1;
*ival = value;
c = XBM_TK_NUMBER;
}
else if (isalpha (c) || c == '_')
{
*sval++ = c;
- while ((c = fgetc (fp)) != EOF
- && (isalnum (c) || c == '_'))
+ while (*s < end
+ && (c = *(*s)++, (isalnum (c) || c == '_')))
*sval++ = c;
*sval = 0;
- if (c != EOF)
- ungetc (c, fp);
+ if (*s < end)
+ *s = *s - 1;
c = XBM_TK_IDENT;
}
+ else if (c == '/' && **s == '*')
+ {
+ /* C-style comment. */
+ ++*s;
+ while (**s && (**s != '*' || *(*s + 1) != '/'))
+ ++*s;
+ if (**s)
+ {
+ *s += 2;
+ goto loop;
+ }
+ }
return c;
}
/* Replacement for XReadBitmapFileData which isn't available under old
- X versions. FILE is the name of the bitmap file to read. Set
- *WIDTH and *HEIGHT to the width and height of the image. Return in
- *DATA the bitmap data allocated with xmalloc. Value is non-zero if
- successful. */
+ X versions. CONTENTS is a pointer to a buffer to parse; END is the
+ buffer's end. Set *WIDTH and *HEIGHT to the width and height of
+ the image. Return in *DATA the bitmap data allocated with xmalloc.
+ Value is non-zero if successful. DATA null means just test if
+ CONTENTS looks like an in-memory XBM file. */
static int
-xbm_read_bitmap_file_data (file, width, height, data)
- char *file;
+xbm_read_bitmap_data (contents, end, width, height, data)
+ char *contents, *end;
int *width, *height;
unsigned char **data;
{
- FILE *fp;
+ char *s = contents;
char buffer[BUFSIZ];
int padding_p = 0;
int v10 = 0;
int LA1;
#define match() \
- LA1 = xbm_scan (fp, buffer, &value)
+ LA1 = xbm_scan (&s, end, buffer, &value)
#define expect(TOKEN) \
if (LA1 != (TOKEN)) \
else \
goto failure
- fp = fopen (file, "r");
- if (fp == NULL)
- return 0;
-
*width = *height = -1;
- *data = NULL;
- LA1 = xbm_scan (fp, buffer, &value);
+ if (data)
+ *data = NULL;
+ LA1 = xbm_scan (&s, end, buffer, &value);
/* Parse defines for width, height and hot-spots. */
while (LA1 == '#')
if (*width < 0 || *height < 0)
goto failure;
+ else if (data == NULL)
+ goto success;
/* Parse bits. Must start with `static'. */
expect_ident ("static");
}
}
- fclose (fp);
+ success:
return 1;
failure:
- fclose (fp);
- if (*data)
+ if (data && *data)
{
xfree (*data);
*data = NULL;
}
-/* Load XBM image IMG which will be displayed on frame F from file
- SPECIFIED_FILE. Value is non-zero if successful. */
+/* Load XBM image IMG which will be displayed on frame F from buffer
+ CONTENTS. END is the end of the buffer. Value is non-zero if
+ successful. */
static int
-xbm_load_image_from_file (f, img, specified_file)
+xbm_load_image (f, img, contents, end)
struct frame *f;
struct image *img;
- Lisp_Object specified_file;
+ char *contents, *end;
{
int rc;
unsigned char *data;
int success_p = 0;
- Lisp_Object file;
- struct gcpro gcpro1;
- xassert (STRINGP (specified_file));
- file = Qnil;
- GCPRO1 (file);
-
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
- &img->height, &data);
+ rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
if (rc)
{
int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
if (!NILP (value))
background = x_alloc_image_color (f, img, value, background);
- BLOCK_INPUT;
img->pixmap
= XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
FRAME_X_WINDOW (f),
depth);
xfree (data);
- if (img->pixmap == 0)
+ if (img->pixmap == None)
{
x_clear_image (f, img);
- image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+ image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
}
else
success_p = 1;
-
- UNBLOCK_INPUT;
}
else
image_error ("Error loading XBM image `%s'", img->spec, Qnil);
- UNGCPRO;
return success_p;
}
+/* Value is non-zero if DATA looks like an in-memory XBM file. */
+
+static int
+xbm_file_p (data)
+ Lisp_Object data;
+{
+ int w, h;
+ return (STRINGP (data)
+ && xbm_read_bitmap_data (XSTRING (data)->data,
+ (XSTRING (data)->data
+ + STRING_BYTES (XSTRING (data))),
+ &w, &h, NULL));
+}
+
+
/* Fill image IMG which is used on frame F with pixmap data. Value is
non-zero if successful. */
/* If IMG->spec specifies a file name, create a non-file spec from it. */
file_name = image_spec_value (img->spec, QCfile, NULL);
if (STRINGP (file_name))
- success_p = xbm_load_image_from_file (f, img, file_name);
+ {
+ Lisp_Object file;
+ char *contents;
+ int size;
+ struct gcpro gcpro1;
+
+ file = x_find_image_file (file_name);
+ GCPRO1 (file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", file_name, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ contents = slurp_file (XSTRING (file)->data, &size);
+ if (contents == NULL)
+ {
+ image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ success_p = xbm_load_image (f, img, contents, contents + size);
+ UNGCPRO;
+ }
else
{
struct image_keyword fmt[XBM_LAST];
Lisp_Object data;
+ unsigned char *bitmap_data;
int depth;
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
char *bits;
- int parsed_p;
+ int parsed_p, height, width;
+ int in_memory_file_p = 0;
+
+ /* See if data looks like an in-memory XBM file. */
+ data = image_spec_value (img->spec, QCdata, NULL);
+ in_memory_file_p = xbm_file_p (data);
- /* Parse the list specification. */
+ /* Parse the image specification. */
bcopy (xbm_format, fmt, sizeof fmt);
parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
xassert (parsed_p);
/* Get specified width, and height. */
- img->width = XFASTINT (fmt[XBM_WIDTH].value);
- img->height = XFASTINT (fmt[XBM_HEIGHT].value);
- xassert (img->width > 0 && img->height > 0);
-
- BLOCK_INPUT;
-
- if (fmt[XBM_ASCENT].count)
- img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
+ if (!in_memory_file_p)
+ {
+ img->width = XFASTINT (fmt[XBM_WIDTH].value);
+ img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+ xassert (img->width > 0 && img->height > 0);
+ }
/* Get foreground and background colors, maybe allocate colors. */
if (fmt[XBM_FOREGROUND].count)
background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
background);
- /* Set bits to the bitmap image data. */
- data = fmt[XBM_DATA].value;
- if (VECTORP (data))
+ if (in_memory_file_p)
+ success_p = xbm_load_image (f, img, XSTRING (data)->data,
+ (XSTRING (data)->data
+ + STRING_BYTES (XSTRING (data))));
+ else
{
- int i;
- char *p;
- int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
-
- p = bits = (char *) alloca (nbytes * img->height);
- for (i = 0; i < img->height; ++i, p += nbytes)
+ if (VECTORP (data))
{
- Lisp_Object line = XVECTOR (data)->contents[i];
- if (STRINGP (line))
- bcopy (XSTRING (line)->data, p, nbytes);
- else
- bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+ int i;
+ char *p;
+ int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+
+ p = bits = (char *) alloca (nbytes * img->height);
+ for (i = 0; i < img->height; ++i, p += nbytes)
+ {
+ Lisp_Object line = XVECTOR (data)->contents[i];
+ if (STRINGP (line))
+ bcopy (XSTRING (line)->data, p, nbytes);
+ else
+ bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+ }
+ }
+ else if (STRINGP (data))
+ bits = XSTRING (data)->data;
+ else
+ bits = XBOOL_VECTOR (data)->data;
+
+ /* Create the pixmap. */
+ depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+ img->pixmap
+ = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ bits,
+ img->width, img->height,
+ foreground, background,
+ depth);
+ if (img->pixmap)
+ success_p = 1;
+ else
+ {
+ image_error ("Unable to create pixmap for XBM image `%s'",
+ img->spec, Qnil);
+ x_clear_image (f, img);
}
}
- else if (STRINGP (data))
- bits = XSTRING (data)->data;
- else
- bits = XBOOL_VECTOR (data)->data;
-
- /* Create the pixmap. */
- depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
- img->pixmap
- = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- bits,
- img->width, img->height,
- foreground, background,
- depth);
- if (img->pixmap)
- success_p = 1;
- else
- {
- image_error ("Unable to create pixmap for XBM image `%s'",
- img->spec, Qnil);
- x_clear_image (f, img);
- }
-
- UNBLOCK_INPUT;
}
return success_p;
XPM_RELIEF,
XPM_ALGORITHM,
XPM_HEURISTIC_MASK,
+ XPM_MASK,
XPM_COLOR_SYMBOLS,
XPM_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
};
+/* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
+ functions for allocating image colors. Our own functions handle
+ color allocation failures more gracefully than the ones on the XPM
+ lib. */
+
+#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
+#define ALLOC_XPM_COLORS
+#endif
+
+#ifdef ALLOC_XPM_COLORS
+
+static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
+static void xpm_free_color_cache P_ ((void));
+static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
+static int xpm_color_bucket P_ ((char *));
+static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
+ XColor *, int));
+
+/* An entry in a hash table used to cache color definitions of named
+ colors. This cache is necessary to speed up XPM image loading in
+ case we do color allocations ourselves. Without it, we would need
+ a call to XParseColor per pixel in the image. */
+
+struct xpm_cached_color
+{
+ /* Next in collision chain. */
+ struct xpm_cached_color *next;
+
+ /* Color definition (RGB and pixel color). */
+ XColor color;
+
+ /* Color name. */
+ char name[1];
+};
+
+/* The hash table used for the color cache, and its bucket vector
+ size. */
+
+#define XPM_COLOR_CACHE_BUCKETS 1001
+struct xpm_cached_color **xpm_color_cache;
+
+/* Initialize the color cache. */
+
+static void
+xpm_init_color_cache (f, attrs)
+ struct frame *f;
+ XpmAttributes *attrs;
+{
+ size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
+ xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
+ memset (xpm_color_cache, 0, nbytes);
+ init_color_table ();
+
+ if (attrs->valuemask & XpmColorSymbols)
+ {
+ int i;
+ XColor color;
+
+ for (i = 0; i < attrs->numsymbols; ++i)
+ if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ attrs->colorsymbols[i].value, &color))
+ {
+ color.pixel = lookup_rgb_color (f, color.red, color.green,
+ color.blue);
+ xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
+ }
+ }
+}
+
+
+/* Free the color cache. */
+
+static void
+xpm_free_color_cache ()
+{
+ struct xpm_cached_color *p, *next;
+ int i;
+
+ for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
+ for (p = xpm_color_cache[i]; p; p = next)
+ {
+ next = p->next;
+ xfree (p);
+ }
+
+ xfree (xpm_color_cache);
+ xpm_color_cache = NULL;
+ free_color_table ();
+}
+
+
+/* Return the bucket index for color named COLOR_NAME in the color
+ cache. */
+
+static int
+xpm_color_bucket (color_name)
+ char *color_name;
+{
+ unsigned h = 0;
+ char *s;
+
+ for (s = color_name; *s; ++s)
+ h = (h << 2) ^ *s;
+ return h %= XPM_COLOR_CACHE_BUCKETS;
+}
+
+
+/* On frame F, cache values COLOR for color with name COLOR_NAME.
+ BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
+ entry added. */
+
+static struct xpm_cached_color *
+xpm_cache_color (f, color_name, color, bucket)
+ struct frame *f;
+ char *color_name;
+ XColor *color;
+ int bucket;
+{
+ size_t nbytes;
+ struct xpm_cached_color *p;
+
+ if (bucket < 0)
+ bucket = xpm_color_bucket (color_name);
+
+ nbytes = sizeof *p + strlen (color_name);
+ p = (struct xpm_cached_color *) xmalloc (nbytes);
+ strcpy (p->name, color_name);
+ p->color = *color;
+ p->next = xpm_color_cache[bucket];
+ xpm_color_cache[bucket] = p;
+ return p;
+}
+
+
+/* Look up color COLOR_NAME for frame F in the color cache. If found,
+ return the cached definition in *COLOR. Otherwise, make a new
+ entry in the cache and allocate the color. Value is zero if color
+ allocation failed. */
+
+static int
+xpm_lookup_color (f, color_name, color)
+ struct frame *f;
+ char *color_name;
+ XColor *color;
+{
+ struct xpm_cached_color *p;
+ int h = xpm_color_bucket (color_name);
+
+ for (p = xpm_color_cache[h]; p; p = p->next)
+ if (strcmp (p->name, color_name) == 0)
+ break;
+
+ if (p != NULL)
+ *color = p->color;
+ else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ color_name, color))
+ {
+ color->pixel = lookup_rgb_color (f, color->red, color->green,
+ color->blue);
+ p = xpm_cache_color (f, color_name, color, h);
+ }
+
+ return p != NULL;
+}
+
+
+/* Callback for allocating color COLOR_NAME. Called from the XPM lib.
+ CLOSURE is a pointer to the frame on which we allocate the
+ color. Return in *COLOR the allocated color. Value is non-zero
+ if successful. */
+
+static int
+xpm_alloc_color (dpy, cmap, color_name, color, closure)
+ Display *dpy;
+ Colormap cmap;
+ char *color_name;
+ XColor *color;
+ void *closure;
+{
+ return xpm_lookup_color ((struct frame *) closure, color_name, color);
+}
+
+
+/* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
+ is a pointer to the frame on which we allocate the color. Value is
+ non-zero if successful. */
+
+static int
+xpm_free_colors (dpy, cmap, pixels, npixels, closure)
+ Display *dpy;
+ Colormap cmap;
+ Pixel *pixels;
+ int npixels;
+ void *closure;
+{
+ return 1;
+}
+
+#endif /* ALLOC_XPM_COLORS */
+
+
/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
for XPM images. Such a list must consist of conses whose car and
cdr are strings. */
/* Either no `:color-symbols' or it's a list of conses
whose car and cdr are strings. */
&& (fmt[XPM_COLOR_SYMBOLS].count == 0
- || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
- && (fmt[XPM_ASCENT].count == 0
- || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+ || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
}
attrs.colormap = FRAME_X_COLORMAP (f);
attrs.valuemask |= XpmVisual;
attrs.valuemask |= XpmColormap;
+
+#ifdef ALLOC_XPM_COLORS
+ /* Allocate colors with our own functions which handle
+ failing color allocation more gracefully. */
+ attrs.color_closure = f;
+ attrs.alloc_color = xpm_alloc_color;
+ attrs.free_colors = xpm_free_colors;
+ attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
+#else /* not ALLOC_XPM_COLORS */
+ /* Let the XPM lib allocate colors. */
attrs.valuemask |= XpmReturnAllocPixels;
#ifdef XpmAllocCloseColors
attrs.alloc_close_colors = 1;
attrs.valuemask |= XpmAllocCloseColors;
-#else
+#else /* not XpmAllocCloseColors */
attrs.closeness = 600;
attrs.valuemask |= XpmCloseness;
-#endif
+#endif /* not XpmAllocCloseColors */
+#endif /* ALLOC_XPM_COLORS */
/* If image specification contains symbolic color definitions, add
these to `attrs'. */
/* Create a pixmap for the image, either from a file, or from a
string buffer containing data in the same format as an XPM file. */
- BLOCK_INPUT;
+#ifdef ALLOC_XPM_COLORS
+ xpm_init_color_cache (f, &attrs);
+#endif
+
specified_file = image_spec_value (img->spec, QCfile, NULL);
if (STRINGP (specified_file))
{
if (!STRINGP (file))
{
image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNBLOCK_INPUT;
return 0;
}
&img->pixmap, &img->mask,
&attrs);
}
- UNBLOCK_INPUT;
if (rc == XpmSuccess)
{
- /* Remember allocated colors. */
+#ifdef ALLOC_XPM_COLORS
+ img->colors = colors_in_color_table (&img->ncolors);
+#else /* not ALLOC_XPM_COLORS */
img->ncolors = attrs.nalloc_pixels;
img->colors = (unsigned long *) xmalloc (img->ncolors
* sizeof *img->colors);
register_color (img->colors[i]);
#endif
}
+#endif /* not ALLOC_XPM_COLORS */
img->width = attrs.width;
img->height = attrs.height;
xassert (img->width > 0 && img->height > 0);
/* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
- BLOCK_INPUT;
XpmFreeAttributes (&attrs);
- UNBLOCK_INPUT;
}
else
{
}
}
+#ifdef ALLOC_XPM_COLORS
+ xpm_free_color_cache ();
+#endif
return rc == XpmSuccess;
}
int ct_colors_allocated;
-/* Function prototypes. */
-
-static void init_color_table P_ ((void));
-static void free_color_table P_ ((void));
-static unsigned long *colors_in_color_table P_ ((int *n));
-static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
-static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
-
-
/* Initialize the color table. */
static void
color.green = g;
color.blue = b;
- BLOCK_INPUT;
cmap = FRAME_X_COLORMAP (f);
rc = x_alloc_nearest_color (f, cmap, &color);
- UNBLOCK_INPUT;
if (rc)
{
Colormap cmap;
int rc;
- BLOCK_INPUT;
-
cmap = FRAME_X_COLORMAP (f);
color.pixel = pixel;
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+ x_query_color (f, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
- UNBLOCK_INPUT;
if (rc)
{
int, XImage *, int));
static void x_laplace_read_row P_ ((struct frame *, Colormap,
XColor *, int, XImage *, int));
+static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
+static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
+static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+
+/* Non-zero means draw a cross on images having `:algorithm
+ disabled'. */
+
+int cross_disabled_images;
+
+/* Edge detection matrices for different edge-detection
+ strategies. */
+
+static int emboss_matrix[9] = {
+ /* x - 1 x x + 1 */
+ 2, -1, 0, /* y - 1 */
+ -1, 0, 1, /* y */
+ 0, 1, -2 /* y + 1 */
+};
+static int laplace_matrix[9] = {
+ /* x - 1 x x + 1 */
+ 1, 0, 0, /* y - 1 */
+ 0, 0, 0, /* y */
+ 0, 0, -1 /* y + 1 */
+};
+
+/* Value is the intensity of the color whose red/green/blue values
+ are R, G, and B. */
+
+#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
+
+
+/* On frame F, return an array of XColor structures describing image
+ IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
+ non-zero means also fill the red/green/blue members of the XColor
+ structures. Value is a pointer to the array of XColors structures,
+ allocated with xmalloc; it must be freed by the caller. */
+
+static XColor *
+x_to_xcolors (f, img, rgb_p)
+ struct frame *f;
+ struct image *img;
+ int rgb_p;
+{
+ int x, y;
+ XColor *colors, *p;
+ XImage *ximg;
+
+ colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
-/* Fill COLORS with RGB colors from row Y of image XIMG. F is the
- frame we operate on, CMAP is the color-map in effect, and WIDTH is
- the width of one row in the image. */
+ /* Get the X image IMG->pixmap. */
+ ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+ 0, 0, img->width, img->height, ~0, ZPixmap);
+
+ /* Fill the `pixel' members of the XColor array. I wished there
+ were an easy and portable way to circumvent XGetPixel. */
+ p = colors;
+ for (y = 0; y < img->height; ++y)
+ {
+ XColor *row = p;
+
+ for (x = 0; x < img->width; ++x, ++p)
+ p->pixel = XGetPixel (ximg, x, y);
+
+ if (rgb_p)
+ x_query_colors (f, row, img->width);
+ }
+
+ XDestroyImage (ximg);
+ return colors;
+}
+
+
+/* Create IMG->pixmap from an array COLORS of XColor structures, whose
+ RGB members are set. F is the frame on which this all happens.
+ COLORS will be freed; an existing IMG->pixmap will be freed, too. */
static void
-x_laplace_read_row (f, cmap, colors, width, ximg, y)
+x_from_xcolors (f, img, colors)
struct frame *f;
- Colormap cmap;
+ struct image *img;
XColor *colors;
- int width;
- XImage *ximg;
- int y;
{
- int x;
+ int x, y;
+ XImage *oimg;
+ Pixmap pixmap;
+ XColor *p;
+
+ init_color_table ();
+
+ x_create_x_image_and_pixmap (f, img->width, img->height, 0,
+ &oimg, &pixmap);
+ p = colors;
+ for (y = 0; y < img->height; ++y)
+ for (x = 0; x < img->width; ++x, ++p)
+ {
+ unsigned long pixel;
+ pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+ XPutPixel (oimg, x, y, pixel);
+ }
- for (x = 0; x < width; ++x)
- colors[x].pixel = XGetPixel (ximg, x, y);
+ xfree (colors);
+ x_clear_image_1 (f, img, 1, 0, 1);
- XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
+ x_put_x_image (f, oimg, pixmap, img->width, img->height);
+ x_destroy_x_image (oimg);
+ img->pixmap = pixmap;
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
}
-/* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
- containing the pixel colors to write. F is the frame we are
- working on. */
+/* On frame F, perform edge-detection on image IMG.
+
+ MATRIX is a nine-element array specifying the transformation
+ matrix. See emboss_matrix for an example.
+
+ COLOR_ADJUST is a color adjustment added to each pixel of the
+ outgoing image. */
static void
-x_laplace_write_row (f, pixels, width, ximg, y)
+x_detect_edges (f, img, matrix, color_adjust)
struct frame *f;
- long *pixels;
- int width;
- XImage *ximg;
- int y;
+ struct image *img;
+ int matrix[9], color_adjust;
{
- int x;
+ XColor *colors = x_to_xcolors (f, img, 1);
+ XColor *new, *p;
+ int x, y, i, sum;
+
+ for (i = sum = 0; i < 9; ++i)
+ sum += abs (matrix[i]);
+
+#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
+
+ new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+
+ for (y = 0; y < img->height; ++y)
+ {
+ p = COLOR (new, 0, y);
+ p->red = p->green = p->blue = 0xffff/2;
+ p = COLOR (new, img->width - 1, y);
+ p->red = p->green = p->blue = 0xffff/2;
+ }
- for (x = 0; x < width; ++x)
- XPutPixel (ximg, x, y, pixels[x]);
+ for (x = 1; x < img->width - 1; ++x)
+ {
+ p = COLOR (new, x, 0);
+ p->red = p->green = p->blue = 0xffff/2;
+ p = COLOR (new, x, img->height - 1);
+ p->red = p->green = p->blue = 0xffff/2;
+ }
+
+ for (y = 1; y < img->height - 1; ++y)
+ {
+ p = COLOR (new, 1, y);
+
+ for (x = 1; x < img->width - 1; ++x, ++p)
+ {
+ int r, g, b, y1, x1;
+
+ r = g = b = i = 0;
+ for (y1 = y - 1; y1 < y + 2; ++y1)
+ for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+ if (matrix[i])
+ {
+ XColor *t = COLOR (colors, x1, y1);
+ r += matrix[i] * t->red;
+ g += matrix[i] * t->green;
+ b += matrix[i] * t->blue;
+ }
+
+ r = (r / sum + color_adjust) & 0xffff;
+ g = (g / sum + color_adjust) & 0xffff;
+ b = (b / sum + color_adjust) & 0xffff;
+ p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
+ }
+ }
+
+ xfree (colors);
+ x_from_xcolors (f, img, new);
+
+#undef COLOR
}
-/* Transform image IMG which is used on frame F with a Laplace
- edge-detection algorithm. The result is an image that can be used
- to draw disabled buttons, for example. */
+/* Perform the pre-defined `emboss' edge-detection on image IMG
+ on frame F. */
static void
-x_laplace (f, img)
+x_emboss (f, img)
struct frame *f;
struct image *img;
{
- Colormap cmap = FRAME_X_COLORMAP (f);
- XImage *ximg, *oimg;
- XColor *in[3];
- long *out;
- Pixmap pixmap;
- int x, y, i;
- long pixel;
- int in_y, out_y, rc;
- int mv2 = 45000;
+ x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
+}
- BLOCK_INPUT;
- /* Get the X image IMG->pixmap. */
- ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
- 0, 0, img->width, img->height, ~0, ZPixmap);
+/* Perform the pre-defined `laplace' edge-detection on image IMG
+ on frame F. */
+
+static void
+x_laplace (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ x_detect_edges (f, img, laplace_matrix, 45000);
+}
- /* Allocate 3 input rows, and one output row of colors. */
- for (i = 0; i < 3; ++i)
- in[i] = (XColor *) alloca (img->width * sizeof (XColor));
- out = (long *) alloca (img->width * sizeof (long));
- /* Create an X image for output. */
- rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
- &oimg, &pixmap);
+/* Perform edge-detection on image IMG on frame F, with specified
+ transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
- /* Fill first two rows. */
- x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
- x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
- in_y = 2;
+ MATRIX must be either
- /* Write first row, all zeros. */
- init_color_table ();
- pixel = lookup_rgb_color (f, 0, 0, 0);
- for (x = 0; x < img->width; ++x)
- out[x] = pixel;
- x_laplace_write_row (f, out, img->width, oimg, 0);
- out_y = 1;
+ - a list of at least 9 numbers in row-major form
+ - a vector of at least 9 numbers
- for (y = 2; y < img->height; ++y)
+ COLOR_ADJUST nil means use a default; otherwise it must be a
+ number. */
+
+static void
+x_edge_detection (f, img, matrix, color_adjust)
+ struct frame *f;
+ struct image *img;
+ Lisp_Object matrix, color_adjust;
+{
+ int i = 0;
+ int trans[9];
+
+ if (CONSP (matrix))
{
- int rowa = y % 3;
- int rowb = (y + 2) % 3;
+ for (i = 0;
+ i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
+ ++i, matrix = XCDR (matrix))
+ trans[i] = XFLOATINT (XCAR (matrix));
+ }
+ else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
+ {
+ for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
+ trans[i] = XFLOATINT (AREF (matrix, i));
+ }
+
+ if (NILP (color_adjust))
+ color_adjust = make_number (0xffff / 2);
+
+ if (i == 9 && NUMBERP (color_adjust))
+ x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
+}
+
+
+/* Transform image IMG on frame F so that it looks disabled. */
+
+static void
+x_disable_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
+ if (dpyinfo->n_planes >= 2)
+ {
+ /* Color (or grayscale). Convert to gray, and equalize. Just
+ drawing such images with a stipple can look very odd, so
+ we're using this method instead. */
+ XColor *colors = x_to_xcolors (f, img, 1);
+ XColor *p, *end;
+ const int h = 15000;
+ const int l = 30000;
- for (x = 0; x < img->width - 2; ++x)
+ for (p = colors, end = colors + img->width * img->height;
+ p < end;
+ ++p)
{
- int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
- int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
- int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
-
- out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
- b & 0xffff);
+ int i = COLOR_INTENSITY (p->red, p->green, p->blue);
+ int i2 = (0xffff - h - l) * i / 0xffff + l;
+ p->red = p->green = p->blue = i2;
}
- x_laplace_write_row (f, out, img->width, oimg, out_y++);
+ x_from_xcolors (f, img, colors);
}
- /* Write last line, all zeros. */
- for (x = 0; x < img->width; ++x)
- out[x] = pixel;
- x_laplace_write_row (f, out, img->width, oimg, out_y);
-
- /* Free the input image, and free resources of IMG. */
- XDestroyImage (ximg);
- x_clear_image (f, img);
-
- /* Put the output image into pixmap, and destroy it. */
- x_put_x_image (f, oimg, pixmap, img->width, img->height);
- x_destroy_x_image (oimg);
+ /* Draw a cross over the disabled image, if we must or if we
+ should. */
+ if (dpyinfo->n_planes < 2 || cross_disabled_images)
+ {
+ Display *dpy = FRAME_X_DISPLAY (f);
+ GC gc;
- /* Remember new pixmap and colors in IMG. */
- img->pixmap = pixmap;
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
+ gc = XCreateGC (dpy, img->pixmap, 0, NULL);
+ XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
+ XDrawLine (dpy, img->pixmap, gc, 0, 0,
+ img->width - 1, img->height - 1);
+ XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
+ img->width - 1, 0);
+ XFreeGC (dpy, gc);
- UNBLOCK_INPUT;
+ if (img->mask)
+ {
+ gc = XCreateGC (dpy, img->mask, 0, NULL);
+ XSetForeground (dpy, gc, WHITE_PIX_DEFAULT (f));
+ XDrawLine (dpy, img->mask, gc, 0, 0,
+ img->width - 1, img->height - 1);
+ XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
+ img->width - 1, 0);
+ XFreeGC (dpy, gc);
+ }
+ }
}
Display *dpy = FRAME_X_DISPLAY (f);
XImage *ximg, *mask_img;
int x, y, rc, look_at_corners_p;
- unsigned long bg;
+ unsigned long bg = 0;
+
+ if (img->mask)
+ {
+ XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+ img->mask = None;
+ }
- BLOCK_INPUT;
-
/* Create an image and pixmap serving as mask. */
rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
&mask_img, &img->mask);
if (!rc)
- {
- UNBLOCK_INPUT;
- return 0;
- }
+ return 0;
/* Get the X image of IMG->pixmap. */
ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
x_destroy_x_image (mask_img);
XDestroyImage (ximg);
- UNBLOCK_INPUT;
return 1;
}
PBM_RELIEF,
PBM_ALGORITHM,
PBM_HEURISTIC_MASK,
+ PBM_MASK,
+ PBM_FOREGROUND,
+ PBM_BACKGROUND,
PBM_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":file", IMAGE_STRING_VALUE, 0},
{":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_VALUE, 0},
+ {":background", IMAGE_STRING_VALUE, 0}
};
/* Structure describing the image type `pbm'. */
bcopy (pbm_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
- || (fmt[PBM_ASCENT].count
- && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
return 0;
/* Must specify either :data or :file. */
pbm_scan_number (s, end)
unsigned char **s, *end;
{
- int c, val = -1;
+ int c = 0, val = -1;
while (*s < end)
{
}
-/* Read FILE into memory. Value is a pointer to a buffer allocated
- with xmalloc holding FILE's contents. Value is null if an error
- occured. *SIZE is set to the size of the file. */
-
-static char *
-pbm_read_file (file, size)
- Lisp_Object file;
- int *size;
-{
- FILE *fp = NULL;
- char *buf = NULL;
- struct stat st;
-
- if (stat (XSTRING (file)->data, &st) == 0
- && (fp = fopen (XSTRING (file)->data, "r")) != NULL
- && (buf = (char *) xmalloc (st.st_size),
- fread (buf, 1, st.st_size, fp) == st.st_size))
- {
- *size = st.st_size;
- fclose (fp);
- }
- else
- {
- if (fp)
- fclose (fp);
- if (buf)
- {
- xfree (buf);
- buf = NULL;
- }
- }
-
- return buf;
-}
-
-
/* Load PBM image IMG for use on frame F. */
static int
return 0;
}
- contents = pbm_read_file (file, &size);
+ contents = slurp_file (XSTRING (file)->data, &size);
if (contents == NULL)
{
image_error ("Error reading `%s'", file, Qnil);
|| (type != PBM_MONO && max_color_idx < 0))
goto error;
- BLOCK_INPUT;
if (!x_create_x_image_and_pixmap (f, width, height, 0,
&ximg, &img->pixmap))
- {
- UNBLOCK_INPUT;
- goto error;
- }
+ goto error;
/* Initialize the color hash table. */
init_color_table ();
if (type == PBM_MONO)
{
int c = 0, g;
+ struct image_keyword fmt[PBM_LAST];
+ unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+ unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+
+ /* Parse the image specification. */
+ bcopy (pbm_format, fmt, sizeof fmt);
+ parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
+
+ /* Get foreground and background colors, maybe allocate colors. */
+ if (fmt[PBM_FOREGROUND].count)
+ fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
+ if (fmt[PBM_BACKGROUND].count)
+ bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
else
g = pbm_scan_number (&p, end);
- XPutPixel (ximg, x, y, (g
- ? FRAME_FOREGROUND_PIXEL (f)
- : FRAME_BACKGROUND_PIXEL (f)));
+ XPutPixel (ximg, x, y, g ? fg : bg);
}
}
else
xfree (ximg->data);
ximg->data = NULL;
XDestroyImage (ximg);
- UNBLOCK_INPUT;
image_error ("Invalid pixel value in image `%s'",
img->spec, Qnil);
goto error;
/* Put the image into a pixmap. */
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
img->width = width;
img->height = height;
PNG_RELIEF,
PNG_ALGORITHM,
PNG_HEURISTIC_MASK,
+ PNG_MASK,
PNG_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
/* Structure describing the image type `png'. */
struct image_keyword fmt[PNG_LAST];
bcopy (png_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
- || (fmt[PNG_ASCENT].count
- && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
return 0;
/* Must specify either the :data or :file keyword. */
struct gcpro gcpro1;
png_struct *png_ptr = NULL;
png_info *info_ptr = NULL, *end_info = NULL;
- FILE *fp = NULL;
+ FILE *volatile fp = NULL;
png_byte sig[8];
- png_byte *pixels = NULL;
- png_byte **rows = NULL;
+ png_byte * volatile pixels = NULL;
+ png_byte ** volatile rows = NULL;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
png_byte channels;
Colormap cmap;
png_color_16 frame_background;
- BLOCK_INPUT;
cmap = FRAME_X_COLORMAP (f);
color.pixel = FRAME_BACKGROUND_PIXEL (f);
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
- UNBLOCK_INPUT;
+ x_query_color (f, &color);
bzero (&frame_background, sizeof frame_background);
frame_background.red = color.red;
fp = NULL;
}
- BLOCK_INPUT;
-
/* Create the X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
&img->pixmap))
- {
- UNBLOCK_INPUT;
- goto error;
- }
+ goto error;
/* Create an image and pixmap serving as mask if the PNG image
contains an alpha channel. */
{
x_destroy_x_image (ximg);
XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap);
- img->pixmap = 0;
- UNBLOCK_INPUT;
+ img->pixmap = None;
goto error;
}
x_destroy_x_image (mask_img);
}
- UNBLOCK_INPUT;
UNGCPRO;
return 1;
}
JPEG_RELIEF,
JPEG_ALGORITHM,
JPEG_HEURISTIC_MASK,
+ JPEG_MASK,
JPEG_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
/* Structure describing the image type `jpeg'. */
bcopy (jpeg_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
- || (fmt[JPEG_ASCENT].count
- && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
return 0;
/* Must specify either the :data or :file keyword. */
struct my_jpeg_error_mgr mgr;
Lisp_Object file, specified_file;
Lisp_Object specified_data;
- FILE *fp = NULL;
+ FILE * volatile fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
XImage *ximg = NULL;
/* Customize libjpeg's error handling to call my_error_exit when an
error is detected. This function will perform a longjmp. */
- mgr.pub.error_exit = my_error_exit;
cinfo.err = jpeg_std_error (&mgr.pub);
+ mgr.pub.error_exit = my_error_exit;
if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
{
/* Close the input file and destroy the JPEG object. */
if (fp)
- fclose (fp);
+ fclose ((FILE *) fp);
jpeg_destroy_decompress (&cinfo);
- BLOCK_INPUT;
-
/* If we already have an XImage, free that. */
x_destroy_x_image (ximg);
/* Free pixmap and colors. */
x_clear_image (f, img);
- UNBLOCK_INPUT;
UNGCPRO;
return 0;
}
jpeg_create_decompress (&cinfo);
if (NILP (specified_data))
- jpeg_stdio_src (&cinfo, fp);
+ jpeg_stdio_src (&cinfo, (FILE *) fp);
else
jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
STRING_BYTES (XSTRING (specified_data)));
width = img->width = cinfo.output_width;
height = img->height = cinfo.output_height;
- BLOCK_INPUT;
-
/* Create X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
- {
- UNBLOCK_INPUT;
- longjmp (mgr.setjmp_buffer, 2);
- }
+ longjmp (mgr.setjmp_buffer, 2);
/* Allocate colors. When color quantization is used,
cinfo.actual_number_of_colors has been set with the number of
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
if (fp)
- fclose (fp);
+ fclose ((FILE *) fp);
/* Put the image into the pixmap. */
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
UNGCPRO;
return 1;
}
TIFF_RELIEF,
TIFF_ALGORITHM,
TIFF_HEURISTIC_MASK,
+ TIFF_MASK,
TIFF_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
/* Structure describing the image type `tiff'. */
struct image_keyword fmt[TIFF_LAST];
bcopy (tiff_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
- || (fmt[TIFF_ASCENT].count
- && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
return 0;
/* Must specify either the :data or :file keyword. */
return 0;
}
- BLOCK_INPUT;
-
/* Create the X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
- UNBLOCK_INPUT;
xfree (buf);
UNGCPRO;
return 0;
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
xfree (buf);
- UNBLOCK_INPUT;
img->width = width;
img->height = height;
GIF_RELIEF,
GIF_ALGORITHM,
GIF_HEURISTIC_MASK,
+ GIF_MASK,
GIF_IMAGE,
GIF_LAST
};
{":type", IMAGE_SYMBOL_VALUE, 1},
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
};
struct image_keyword fmt[GIF_LAST];
bcopy (gif_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
- || (fmt[GIF_ASCENT].count
- && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
return 0;
/* Must specify either the :data or :file keyword. */
width = img->width = gif->SWidth;
height = img->height = gif->SHeight;
- BLOCK_INPUT;
-
/* Create the X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
- UNBLOCK_INPUT;
DGifCloseFile (gif);
UNGCPRO;
return 0;
/* Put the image into the pixmap, then free the X image and its buffer. */
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
UNGCPRO;
return 1;
GS_RELIEF,
GS_ALGORITHM,
GS_HEURISTIC_MASK,
+ GS_MASK,
GS_LAST
};
{":file", IMAGE_STRING_VALUE, 1},
{":loader", IMAGE_FUNCTION_VALUE, 0},
{":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
/* Structure describing the image type `ghostscript'. */
bcopy (gs_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
- || (fmt[GS_ASCENT].count
- && XFASTINT (fmt[GS_ASCENT].value) > 100))
+ if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
return 0;
/* Bounding box must be a list or vector containing 4 integers. */
img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
/* Create the pixmap. */
- BLOCK_INPUT;
- xassert (img->pixmap == 0);
+ xassert (img->pixmap == None);
img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
img->width, img->height,
DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
- UNBLOCK_INPUT;
if (!img->pixmap)
{
bzero (f->output_data.x, sizeof (struct x_output));
f->output_data.x->icon_bitmap = -1;
f->output_data.x->fontset = -1;
+ f->output_data.x->scroll_bar_foreground_pixel = -1;
+ f->output_data.x->scroll_bar_background_pixel = -1;
f->icon_name = Qnil;
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
#ifdef MULTI_KBOARD
f->output_data.x->parent_desc = FRAME_X_DISPLAY_INFO (f)->root_window;
f->output_data.x->explicit_parent = 0;
+ /* These colors will be set anyway later, but it's important
+ to get the color reference counts right, so initialize them! */
+ {
+ Lisp_Object black;
+ struct gcpro gcpro1;
+
+ black = build_string ("black");
+ GCPRO1 (black);
+ f->output_data.x->foreground_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.x->background_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.x->cursor_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.x->cursor_foreground_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.x->border_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.x->mouse_pixel
+ = x_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ UNGCPRO;
+ }
+
/* Set the name; the functions to which we pass f expect the name to
be set. */
if (EQ (name, Qunbound) || NILP (name))
unsigned long mask;
BLOCK_INPUT;
- mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
+ mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
+ if (DoesSaveUnders (dpyinfo->screen))
+ mask |= CWSaveUnder;
+
/* Window managers look at the override-redirect flag to determine
whether or net to give windows a decoration (Xlib spec, chapter
3.2.8). */
}
-DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 4, 0,
+DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
"Show STRING in a \"tooltip\" window on frame FRAME.\n\
-A tooltip window is a small X window displaying STRING at\n\
-the current mouse position.\n\
+A tooltip window is a small X window displaying a string.\n\
+\n\
FRAME nil or omitted means use the selected frame.\n\
+\n\
PARMS is an optional list of frame parameters which can be\n\
used to change the tooltip's appearance.\n\
+\n\
Automatically hide the tooltip after TIMEOUT seconds.\n\
-TIMEOUT nil means use the default timeout of 5 seconds.")
- (string, frame, parms, timeout)
- Lisp_Object string, frame, parms, timeout;
+TIMEOUT nil means use the default timeout of 5 seconds.\n\
+\n\
+If the list of frame parameters PARAMS contains a `left' parameters,\n\
+the tooltip is displayed at that x-position. Otherwise it is\n\
+displayed at the mouse position, with offset DX added (default is 5 if\n\
+DX isn't specified). Likewise for the y-position; if a `top' frame\n\
+parameter is specified, it determines the y-position of the tooltip\n\
+window, otherwise it is displayed at the mouse position, with offset\n\
+DY added (default is -10).")
+ (string, frame, parms, timeout, dx, dy)
+ Lisp_Object string, frame, parms, timeout, dx, dy;
{
struct frame *f;
struct window *w;
Window root, child;
- Lisp_Object buffer;
+ Lisp_Object buffer, top, left;
struct buffer *old_buffer;
struct text_pos pos;
int i, width, height;
timeout = make_number (5);
else
CHECK_NATNUM (timeout, 2);
+
+ if (NILP (dx))
+ dx = make_number (5);
+ else
+ CHECK_NUMBER (dx, 5);
+
+ if (NILP (dy))
+ dy = make_number (-10);
+ else
+ CHECK_NUMBER (dy, 6);
/* Hide a previous tip, if any. */
Fx_hide_tip ();
height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+ /* User-specified position? */
+ left = Fcdr (Fassq (Qleft, parms));
+ top = Fcdr (Fassq (Qtop, parms));
+
/* Move the tooltip window where the mouse pointer is. Resize and
show it. */
BLOCK_INPUT;
XQueryPointer (FRAME_X_DISPLAY (f), FRAME_X_DISPLAY_INFO (f)->root_window,
&root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
+ UNBLOCK_INPUT;
+
+ root_x += XINT (dx);
+ root_y += XINT (dy);
+
+ if (INTEGERP (left))
+ root_x = XINT (left);
+ if (INTEGERP (top))
+ root_y = XINT (top);
+
+ BLOCK_INPUT;
XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- root_x + 5, root_y - height - 5, width, height);
+ root_x, root_y - height, width, height);
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
UNBLOCK_INPUT;
if (tip_frame)
{
Lisp_Object frame;
-
+
XSETFRAME (frame, tip_frame);
Fdelete_frame (frame, Qt);
tip_frame = NULL;
deleted_p = 1;
+
+#ifdef USE_LUCID
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over menu
+ items is unmapped. Redisplay the menu manually... */
+ {
+ struct frame *f = SELECTED_FRAME ();
+ Widget w = f->output_data.x->menubar_widget;
+ extern void xlwmenu_redisplay P_ ((Widget));
+
+ if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
+ && w != None)
+ {
+ BLOCK_INPUT;
+ xlwmenu_redisplay (w);
+ UNBLOCK_INPUT;
+ }
+ }
+#endif /* USE_LUCID */
}
return unbind_to (count, deleted_p ? Qt : Qnil);
XmListSetPos (list, item_pos);
}
+#ifdef HAVE_MOTIF_2_1
+
+ /* Process events until the user presses Cancel or OK. */
+ result = 0;
+ while (result == 0 || XtAppPending (Xt_app_con))
+ XtAppProcessEvent (Xt_app_con, XtIMAll);
+
+#else /* not HAVE_MOTIF_2_1 */
+
/* Process all events until the user presses Cancel or OK. */
for (result = 0; result == 0;)
{
parent = widget;
while (parent && parent != dialog)
parent = XtParent (parent);
-
+
if (parent == dialog
|| (event.type == Expose
&& !process_expose_from_menu (event)))
XtDispatchEvent (&event);
}
+#endif /* not HAVE_MOTIF_2_1 */
+
/* Get the result. */
if (result == XmCR_OK)
{
XmString text;
String data;
- XtVaGetValues (dialog, XmNtextString, &text, 0);
+ XtVaGetValues (dialog, XmNtextString, &text, NULL);
XmStringGetLtoR (text, XmFONTLIST_DEFAULT_TAG, &data);
XmStringFree (text);
file = build_string (data);
#endif /* USE_MOTIF */
-\f
-/***********************************************************************
- Tests
- ***********************************************************************/
-
-#if GLYPH_DEBUG
-
-DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
- "Value is non-nil if SPEC is a valid image specification.")
- (spec)
- Lisp_Object spec;
-{
- return valid_image_p (spec) ? Qt : Qnil;
-}
-
-
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
- (spec)
- Lisp_Object spec;
-{
- int id = -1;
-
- if (valid_image_p (spec))
- id = lookup_image (SELECTED_FRAME (), spec);
-
- debug_print (spec);
- return make_number (id);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
\f
/***********************************************************************
staticpro (&Qscreen_gamma);
Qline_spacing = intern ("line-spacing");
staticpro (&Qline_spacing);
+ Qcenter = intern ("center");
+ staticpro (&Qcenter);
+ Qcompound_text = intern ("compound-text");
+ staticpro (&Qcompound_text);
/* This is the end of symbol initialization. */
/* Text property `display' should be nonsticky by default. */
Qlaplace = intern ("laplace");
staticpro (&Qlaplace);
-
+ Qemboss = intern ("emboss");
+ staticpro (&Qemboss);
+ Qedge_detection = intern ("edge-detection");
+ staticpro (&Qedge_detection);
+ Qheuristic = intern ("heuristic");
+ staticpro (&Qheuristic);
+ QCmatrix = intern (":matrix");
+ staticpro (&QCmatrix);
+ QCcolor_adjustment = intern (":color-adjustment");
+ staticpro (&QCcolor_adjustment);
+ QCmask = intern (":mask");
+ staticpro (&QCmask);
+
Qface_set_after_frame_default = intern ("face-set-after-frame-default");
staticpro (&Qface_set_after_frame_default);
init_x_parm_symbols ();
+ DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
+ "Non-nil means always draw a cross over disabled images.\n\
+Disabled images are those having an `:algorithm disabled' property.\n\
+A cross is always drawn on black & white displays.");
+ cross_disabled_images = 0;
+
DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
"List of directories to search for bitmap files for X.");
Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
meaning don't clear the cache.");
Vimage_cache_eviction_delay = make_number (30 * 60);
- DEFVAR_LISP ("image-types", &Vimage_types,
- "List of supported image types.\n\
-Each element of the list is a symbol for a supported image type.");
- Vimage_types = Qnil;
-
#ifdef USE_X_TOOLKIT
Fprovide (intern ("x-toolkit"));
#endif
#endif
defsubr (&Sclear_image_cache);
-
-#if GLYPH_DEBUG
- defsubr (&Simagep);
- defsubr (&Slookup_image);
-#endif
+ defsubr (&Simage_size);
+ defsubr (&Simage_mask_p);
busy_cursor_atimer = NULL;
busy_cursor_shown_p = 0;