the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Image support (XBM, XPM, PBM, JPEG, TIFF, GIF, PNG, GS). tooltips,
- tool-bars, busy-cursor, file selection dialog added by Gerd
- Moellmann <gerd@gnu.org>. */
-
-/* Completely rewritten by Richard Stallman. */
-
-/* Rewritten for X11 by Joseph Arceneaux */
-
-#include <signal.h>
#include <config.h>
+#include <signal.h>
#include <stdio.h>
#include <math.h>
#include "frame.h"
#include "window.h"
#include "buffer.h"
+#include "intervals.h"
#include "dispextern.h"
#include "keyboard.h"
#include "blockinput.h"
#include "fontset.h"
#include "systime.h"
#include "termhooks.h"
+#include "atimer.h"
#ifdef HAVE_X_WINDOWS
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#else
-extern void abort ();
-#endif
#include <ctype.h>
-
-/* On some systems, the character-composition stuff is broken in X11R5. */
-
-#if defined (HAVE_X11R5) && ! defined (HAVE_X11R6)
-#ifdef X11R5_INHIBIT_I18N
-#define X_I18N_INHIBITED
-#endif
-#endif
+#include <sys/types.h>
+#include <sys/stat.h>
#ifndef VMS
#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work. */
Lisp_Object Qx_resource_name;
Lisp_Object Quser_position;
Lisp_Object Quser_size;
-Lisp_Object Qdisplay;
+extern Lisp_Object Qdisplay;
Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
Lisp_Object Qscreen_gamma;
if (!GC_FRAMEP (frame))
continue;
f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+ if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
+ if (f->output_data.x->busy_window == wdesc)
+ return f;
#ifdef USE_X_TOOLKIT
if ((f->output_data.x->edit_widget
&& XtWindow (f->output_data.x->edit_widget) == wdesc)
int wdesc;
{
Lisp_Object tail, frame;
- struct frame *f;
+ struct frame *f, *found;
struct x_output *x;
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+ found = NULL;
+ for (tail = Vframe_list; GC_CONSP (tail) && !found; tail = XCDR (tail))
{
frame = XCAR (tail);
if (!GC_FRAMEP (frame))
continue;
+
f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
- continue;
- x = f->output_data.x;
- /* This frame matches if the window is any of its widgets. */
- if (x->widget)
+ if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
- if (wdesc == XtWindow (x->widget)
- || wdesc == XtWindow (x->column_widget)
- || wdesc == XtWindow (x->edit_widget))
- return f;
- /* Match if the window is this frame's menubar. */
- if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
- return f;
+ /* This frame matches if the window is any of its widgets. */
+ x = f->output_data.x;
+ if (x->busy_window == wdesc)
+ found = f;
+ else if (x->widget)
+ {
+ if (wdesc == XtWindow (x->widget)
+ || wdesc == XtWindow (x->column_widget)
+ || wdesc == XtWindow (x->edit_widget))
+ found = f;
+ /* Match if the window is this frame's menubar. */
+ else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
+ found = f;
+ }
+ else if (FRAME_X_WINDOW (f) == wdesc)
+ /* A tooltip frame. */
+ found = f;
}
- else if (FRAME_X_WINDOW (f) == wdesc)
- /* A tooltip frame. */
- return f;
}
- return 0;
+
+ return found;
}
/* Likewise, but exclude the menu bar widget. */
if (!GC_FRAMEP (frame))
continue;
f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+ if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
x = f->output_data.x;
/* This frame matches if the window is any of its widgets. */
- if (x->widget)
+ if (x->busy_window == wdesc)
+ return f;
+ else if (x->widget)
{
if (wdesc == XtWindow (x->widget)
|| wdesc == XtWindow (x->column_widget)
if (!GC_FRAMEP (frame))
continue;
f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+ if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
x = f->output_data.x;
/* Match if the window is this frame's menubar. */
if (!GC_FRAMEP (frame))
continue;
f = XFRAME (frame);
- if (f->output_data.nothing == 1 || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
+ if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
continue;
x = f->output_data.x;
/* XReadBitmapFile won't handle magic file names. */
if (fd == 0)
return -1;
- close (fd);
+ emacs_close (fd);
filename = (char *) XSTRING (found)->data;
void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
};
+static void x_create_im P_ ((struct frame *));
void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
}
-/* Decide if color named COLOR is valid for the display associated with
- the selected frame; if so, return the rgb values in COLOR_DEF.
- If ALLOC is nonzero, allocate a new colormap cell. */
+/* Decide if color named COLOR_NAME is valid for use on frame F. If
+ so, return the RGB values in COLOR. If ALLOC_P is non-zero,
+ allocate the color. Value is zero if COLOR_NAME is invalid, or
+ no color could be allocated. */
int
-defined_color (f, color, color_def, alloc)
- FRAME_PTR f;
- char *color;
- XColor *color_def;
- int alloc;
+x_defined_color (f, color_name, color, alloc_p)
+ struct frame *f;
+ char *color_name;
+ XColor *color;
+ int alloc_p;
{
- register int status;
- Colormap screen_colormap;
- Display *display = FRAME_X_DISPLAY (f);
+ int success_p;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Colormap cmap = FRAME_X_COLORMAP (f);
BLOCK_INPUT;
- screen_colormap = DefaultColormap (display, XDefaultScreen (display));
-
- status = XParseColor (display, screen_colormap, color, color_def);
- if (status && alloc)
- {
- /* Apply gamma correction. */
- gamma_correct (f, color_def);
-
- status = XAllocColor (display, screen_colormap, color_def);
- if (!status)
- {
- /* If we got to this point, the colormap is full, so we're
- going to try and get the next closest color.
- The algorithm used is a least-squares matching, which is
- what X uses for closest color matching with StaticColor visuals. */
-
- XColor *cells;
- int no_cells;
- int nearest;
- long nearest_delta, trial_delta;
- int x;
-
- no_cells = XDisplayCells (display, XDefaultScreen (display));
- cells = (XColor *) alloca (sizeof (XColor) * no_cells);
-
- for (x = 0; x < no_cells; x++)
- cells[x].pixel = x;
-
- XQueryColors (display, screen_colormap, cells, no_cells);
- nearest = 0;
- /* I'm assuming CSE so I'm not going to condense this. */
- nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8))
- * ((color_def->red >> 8) - (cells[0].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[0].green >> 8))
- * ((color_def->green >> 8) - (cells[0].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[0].blue >> 8))
- * ((color_def->blue >> 8) - (cells[0].blue >> 8))));
- for (x = 1; x < no_cells; x++)
- {
- trial_delta = ((((color_def->red >> 8) - (cells[x].red >> 8))
- * ((color_def->red >> 8) - (cells[x].red >> 8)))
- +
- (((color_def->green >> 8) - (cells[x].green >> 8))
- * ((color_def->green >> 8) - (cells[x].green >> 8)))
- +
- (((color_def->blue >> 8) - (cells[x].blue >> 8))
- * ((color_def->blue >> 8) - (cells[x].blue >> 8))));
- if (trial_delta < nearest_delta)
- {
- XColor temp;
- temp.red = cells[x].red;
- temp.green = cells[x].green;
- temp.blue = cells[x].blue;
- status = XAllocColor (display, screen_colormap, &temp);
- if (status)
- {
- nearest = x;
- nearest_delta = trial_delta;
- }
- }
- }
- color_def->red = cells[nearest].red;
- color_def->green = cells[nearest].green;
- color_def->blue = cells[nearest].blue;
- status = XAllocColor (display, screen_colormap, color_def);
- }
- }
+ success_p = XParseColor (dpy, cmap, color_name, color);
+ if (success_p && alloc_p)
+ success_p = x_alloc_nearest_color (f, cmap, color);
UNBLOCK_INPUT;
- if (status)
- return 1;
- else
- return 0;
+ return success_p;
}
-/* Given a string ARG naming a color, compute a pixel value from it
- suitable for screen F.
- If F is not a color screen, return DEF (default) regardless of what
- ARG says. */
+
+/* Return the pixel color value for color COLOR_NAME on frame F. If F
+ is a monochrome frame, return MONO_COLOR regardless of what ARG says.
+ Signal an error if color can't be allocated. */
int
-x_decode_color (f, arg, def)
+x_decode_color (f, color_name, mono_color)
FRAME_PTR f;
- Lisp_Object arg;
- int def;
+ Lisp_Object color_name;
+ int mono_color;
{
XColor cdef;
- CHECK_STRING (arg, 0);
+ CHECK_STRING (color_name, 0);
- if (strcmp (XSTRING (arg)->data, "black") == 0)
+#if 0 /* Don't do this. It's wrong when we're not using the default
+ colormap, it makes freeing difficult, and it's probably not
+ an important optimization. */
+ if (strcmp (XSTRING (color_name)->data, "black") == 0)
return BLACK_PIX_DEFAULT (f);
- else if (strcmp (XSTRING (arg)->data, "white") == 0)
+ else if (strcmp (XSTRING (color_name)->data, "white") == 0)
return WHITE_PIX_DEFAULT (f);
+#endif
+ /* Return MONO_COLOR for monochrome frames. */
if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
- return def;
+ return mono_color;
- /* defined_color is responsible for coping with failures
+ /* x_defined_color is responsible for coping with failures
by looking for a near-miss. */
- if (defined_color (f, XSTRING (arg)->data, &cdef, 1))
+ if (x_defined_color (f, XSTRING (color_name)->data, &cdef, 1))
return cdef.pixel;
Fsignal (Qerror, Fcons (build_string ("undefined color"),
- Fcons (arg, Qnil)));
+ Fcons (color_name, Qnil)));
}
+
+
\f
/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
the previous value of that parameter, NEW_VALUE is the new value. */
fore_color.pixel = f->output_data.x->mouse_pixel;
back_color.pixel = mask_color;
- XQueryColor (FRAME_X_DISPLAY (f),
- DefaultColormap (FRAME_X_DISPLAY (f),
- DefaultScreen (FRAME_X_DISPLAY (f))),
+ XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
&fore_color);
- XQueryColor (FRAME_X_DISPLAY (f),
- DefaultColormap (FRAME_X_DISPLAY (f),
- DefaultScreen (FRAME_X_DISPLAY (f))),
+ XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
&back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
&fore_color, &back_color);
FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
f->output_data.x->cursor_width = 2;
}
- else if (CONSP (arg) && EQ (XCAR (arg), Qbar)
- && INTEGERP (XCDR (arg)))
+ else if (CONSP (arg)
+ && EQ (XCAR (arg), Qbar)
+ && INTEGERP (XCDR (arg))
+ && XINT (XCDR (arg)) >= 0)
{
FRAME_DESIRED_CURSOR (f) = BAR_CURSOR;
f->output_data.x->cursor_width = XINT (XCDR (arg));
}
+ else if (NILP (arg))
+ FRAME_DESIRED_CURSOR (f) = NO_CURSOR;
else
/* Treat anything unknown as "box cursor".
It was bad to signal an error; people have trouble fixing
XSETFASTINT (w->top, XFASTINT (w->top) + n);
XSETFASTINT (w->height, XFASTINT (w->height) - n);
+ if (INTEGERP (w->orig_top))
+ XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
+ if (INTEGERP (w->orig_height))
+ XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
+
/* Handle just the top child in a vertical split. */
if (!NILP (w->vchild))
x_set_menu_bar_lines_1 (w->vchild, n);
char *name_key;
char *class_key;
- check_x ();
-
CHECK_STRING (attribute, 0);
CHECK_STRING (class, 0);
UNBLOCK_INPUT;
}
#endif
+
+
+\f
+/* Support routines for XIC (X Input Context). */
+
+#ifdef HAVE_X_I18N
+
+static XFontSet xic_create_xfontset P_ ((struct frame *, char *));
+static XIMStyle best_xim_style P_ ((XIMStyles *, XIMStyles *));
+
+
+/* Supported XIM styles, ordered by preferenc. */
+
+static XIMStyle supported_xim_styles[] =
+{
+ XIMPreeditPosition | XIMStatusArea,
+ XIMPreeditPosition | XIMStatusNothing,
+ XIMPreeditPosition | XIMStatusNone,
+ XIMPreeditNothing | XIMStatusArea,
+ XIMPreeditNothing | XIMStatusNothing,
+ XIMPreeditNothing | XIMStatusNone,
+ XIMPreeditNone | XIMStatusArea,
+ XIMPreeditNone | XIMStatusNothing,
+ XIMPreeditNone | XIMStatusNone,
+ 0,
+};
+
+
+/* Create an X fontset on frame F with base font name
+ BASE_FONTNAME.. */
+
+static XFontSet
+xic_create_xfontset (f, base_fontname)
+ struct frame *f;
+ char *base_fontname;
+{
+ XFontSet xfs;
+ char **missing_list;
+ int missing_count;
+ char *def_string;
+
+ xfs = XCreateFontSet (FRAME_X_DISPLAY (f),
+ base_fontname, &missing_list,
+ &missing_count, &def_string);
+ if (missing_list)
+ XFreeStringList (missing_list);
+
+ /* No need to free def_string. */
+ return xfs;
+}
+
+
+/* Value is the best input style, given user preferences USER (already
+ checked to be supported by Emacs), and styles supported by the
+ input method XIM. */
+
+static XIMStyle
+best_xim_style (user, xim)
+ XIMStyles *user;
+ XIMStyles *xim;
+{
+ int i, j;
+
+ for (i = 0; i < user->count_styles; ++i)
+ for (j = 0; j < xim->count_styles; ++j)
+ if (user->supported_styles[i] == xim->supported_styles[j])
+ return user->supported_styles[i];
+
+ /* Return the default style. */
+ return XIMPreeditNothing | XIMStatusNothing;
+}
+
+/* Create XIC for frame F. */
+
+void
+create_frame_xic (f)
+ struct frame *f;
+{
+ XIM xim;
+ XIC xic = NULL;
+ XFontSet xfs = NULL;
+ static XIMStyle xic_style;
+
+ if (FRAME_XIC (f))
+ return;
+
+ xim = FRAME_X_XIM (f);
+ if (xim)
+ {
+ XRectangle s_area;
+ XPoint spot;
+ XVaNestedList preedit_attr;
+ XVaNestedList status_attr;
+ char *base_fontname;
+ int fontset;
+
+ s_area.x = 0; s_area.y = 0; s_area.width = 1; s_area.height = 1;
+ spot.x = 0; spot.y = 1;
+ /* Create X fontset. */
+ fontset = FRAME_FONTSET (f);
+ if (fontset < 0)
+ base_fontname = "-*-*-*-r-normal--14-*-*-*-*-*-*-*";
+ else
+ {
+ struct fontset_info *fontsetp;
+ int len = 0;
+ int i;
+
+ fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
+ for (i = 0; i <= MAX_CHARSET; i++)
+ if (fontsetp->fontname[i])
+ len += strlen (fontsetp->fontname[i]) + 1;
+ base_fontname = alloca (len);
+ strcpy (base_fontname, fontsetp->fontname[CHARSET_ASCII]);
+ for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
+ if (fontsetp->fontname[i])
+ {
+ strcat (base_fontname, ",");
+ strcat (base_fontname, fontsetp->fontname[i]);
+ }
+ }
+ xfs = xic_create_xfontset (f, base_fontname);
+
+ /* Determine XIC style. */
+ if (xic_style == 0)
+ {
+ XIMStyles supported_list;
+ supported_list.count_styles = (sizeof supported_xim_styles
+ / sizeof supported_xim_styles[0]);
+ supported_list.supported_styles = supported_xim_styles;
+ xic_style = best_xim_style (&supported_list,
+ FRAME_X_XIM_STYLES (f));
+ }
+
+ preedit_attr = XVaCreateNestedList (0,
+ XNFontSet, xfs,
+ XNForeground,
+ FRAME_FOREGROUND_PIXEL (f),
+ XNBackground,
+ FRAME_BACKGROUND_PIXEL (f),
+ (xic_style & XIMPreeditPosition
+ ? XNSpotLocation
+ : NULL),
+ &spot,
+ NULL);
+ status_attr = XVaCreateNestedList (0,
+ XNArea,
+ &s_area,
+ XNFontSet,
+ xfs,
+ XNForeground,
+ FRAME_FOREGROUND_PIXEL (f),
+ XNBackground,
+ FRAME_BACKGROUND_PIXEL (f),
+ NULL);
+
+ xic = XCreateIC (xim,
+ XNInputStyle, xic_style,
+ XNClientWindow, FRAME_X_WINDOW(f),
+ XNFocusWindow, FRAME_X_WINDOW(f),
+ XNStatusAttributes, status_attr,
+ XNPreeditAttributes, preedit_attr,
+ NULL);
+ XFree (preedit_attr);
+ XFree (status_attr);
+ }
+
+ FRAME_XIC (f) = xic;
+ FRAME_XIC_STYLE (f) = xic_style;
+ FRAME_XIC_FONTSET (f) = xfs;
+}
+
+
+/* Destroy XIC and free XIC fontset of frame F, if any. */
+
+void
+free_frame_xic (f)
+ struct frame *f;
+{
+ if (FRAME_XIC (f) == NULL)
+ return;
+
+ XDestroyIC (FRAME_XIC (f));
+ if (FRAME_XIC_FONTSET (f))
+ XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+
+ FRAME_XIC (f) = NULL;
+ FRAME_XIC_FONTSET (f) = NULL;
+}
+
+
+/* Place preedit area for XIC of window W's frame to specified
+ pixel position X/Y. X and Y are relative to window W. */
+
+void
+xic_set_preeditarea (w, x, y)
+ struct window *w;
+ int x, y;
+{
+ struct frame *f = XFRAME (w->frame);
+ XVaNestedList attr;
+ XPoint spot;
+
+ spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x);
+ spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
+ attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
+ XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
+ XFree (attr);
+}
+
+
+/* Place status area for XIC in bottom right corner of frame F.. */
+
+void
+xic_set_statusarea (f)
+ struct frame *f;
+{
+ XIC xic = FRAME_XIC (f);
+ XVaNestedList attr;
+ XRectangle area;
+ XRectangle *needed;
+
+ /* Negotiate geometry of status area. If input method has existing
+ status area, use its current size. */
+ area.x = area.y = area.width = area.height = 0;
+ attr = XVaCreateNestedList (0, XNAreaNeeded, &area, NULL);
+ XSetICValues (xic, XNStatusAttributes, attr, NULL);
+ XFree (attr);
+
+ attr = XVaCreateNestedList (0, XNAreaNeeded, &needed, NULL);
+ XGetICValues (xic, XNStatusAttributes, attr, NULL);
+ XFree (attr);
+
+ if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
+ {
+ attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
+ XGetICValues (xic, XNStatusAttributes, attr, NULL);
+ XFree (attr);
+ }
+
+ area.width = needed->width;
+ area.height = needed->height;
+ area.x = PIXEL_WIDTH (f) - area.width - FRAME_INTERNAL_BORDER_WIDTH (f);
+ area.y = (PIXEL_HEIGHT (f) - area.height
+ - FRAME_MENUBAR_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f));
+ XFree (needed);
+
+ attr = XVaCreateNestedList (0, XNArea, &area, NULL);
+ XSetICValues(xic, XNStatusAttributes, attr, NULL);
+ XFree (attr);
+}
+
+
+/* Set X fontset for XIC of frame F, using base font name
+ BASE_FONTNAME. Called when a new Emacs fontset is chosen. */
+
+void
+xic_set_xfontset (f, base_fontname)
+ struct frame *f;
+ char *base_fontname;
+{
+ XVaNestedList attr;
+ XFontSet xfs;
+
+ xfs = xic_create_xfontset (f, base_fontname);
+
+ attr = XVaCreateNestedList (0, XNFontSet, xfs, NULL);
+ if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
+ XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
+ if (FRAME_XIC_STYLE (f) & XIMStatusArea)
+ XSetICValues (FRAME_XIC (f), XNStatusAttributes, attr, NULL);
+ XFree (attr);
+
+ if (FRAME_XIC_FONTSET (f))
+ XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
+ FRAME_XIC_FONTSET (f) = xfs;
+}
+
+#endif /* HAVE_X_I18N */
+
+
\f
#ifdef USE_X_TOOLKIT
XClassHint class_hints;
XSetWindowAttributes attributes;
unsigned long attribute_mask;
-
Widget shell_widget;
Widget pane_widget;
Widget frame_widget;
XtSetArg (al[ac], XtNinput, 1); ac++;
XtSetArg (al[ac], XtNmappedWhenManaged, 0); ac++;
XtSetArg (al[ac], XtNborderWidth, f->output_data.x->border_width); ac++;
+ XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+ XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+ XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
shell_widget = XtAppCreateShell (f->namebuf, EMACS_CLASS,
applicationShellWidgetClass,
FRAME_X_DISPLAY (f), al, ac);
shell_widget, False,
(lw_callback) NULL,
(lw_callback) NULL,
+ (lw_callback) NULL,
(lw_callback) NULL);
+ ac = 0;
+ XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+ XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+ XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
+ XtSetValues (pane_widget, al, ac);
f->output_data.x->column_widget = pane_widget;
/* mappedWhenManaged to false tells to the paned window to not map/unmap
XtSetArg (al[ac], XtNallowResize, 1); ac++;
XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
XtSetArg (al[ac], XtNemacsFrame, f); ac++;
- frame_widget = XtCreateWidget (f->namebuf,
- emacsFrameClass,
- pane_widget, al, ac);
+ XtSetArg (al[ac], XtNvisual, FRAME_X_VISUAL (f)); ac++;
+ XtSetArg (al[ac], XtNdepth, FRAME_X_DISPLAY_INFO (f)->n_planes); ac++;
+ XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
+ frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget,
+ al, ac);
f->output_data.x->edit_widget = frame_widget;
XSetClassHint (FRAME_X_DISPLAY (f), XtWindow (shell_widget), &class_hints);
#ifdef HAVE_X_I18N
-#ifndef X_I18N_INHIBITED
- {
- XIM xim;
- XIC xic = NULL;
-
- xim = XOpenIM (FRAME_X_DISPLAY (f), NULL, NULL, NULL);
-
- if (xim)
- {
- xic = XCreateIC (xim,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, FRAME_X_WINDOW(f),
- XNFocusWindow, FRAME_X_WINDOW(f),
- NULL);
-
- if (xic == 0)
- {
- XCloseIM (xim);
- xim = NULL;
- }
- }
- FRAME_XIM (f) = xim;
- FRAME_XIC (f) = xic;
- }
-#else /* X_I18N_INHIBITED */
- FRAME_XIM (f) = 0;
- FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
-#endif /* HAVE_X_I18N */
+ FRAME_XIC (f) = NULL;
+ create_frame_xic (f);
+#endif
f->output_data.x->wm_hints.input = True;
f->output_data.x->wm_hints.flags |= InputHint;
XA_ATOM, 32, PropModeAppend,
(unsigned char*) NULL, 0);
- /* Make all the standard events reach the Emacs frame. */
+ /* Make all the standard events reach the Emacs frame. */
attributes.event_mask = STANDARD_EVENT_SET;
+
+#ifdef HAVE_X_I18N
+ if (FRAME_XIC (f))
+ {
+ /* XIM server might require some X events. */
+ unsigned long fevent = NoEventMask;
+ XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+ attributes.event_mask |= fevent;
+ }
+#endif /* HAVE_X_I18N */
+
attribute_mask = CWEventMask;
XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
attribute_mask, &attributes);
attributes.backing_store = NotUseful;
attributes.save_under = True;
attributes.event_mask = STANDARD_EVENT_SET;
- attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity
-#if 0
- | CWBackingStore | CWSaveUnder
-#endif
- | CWEventMask);
+ attributes.colormap = FRAME_X_COLORMAP (f);
+ attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
+ | CWColormap);
BLOCK_INPUT;
FRAME_X_WINDOW (f)
f->output_data.x->border_width,
CopyFromParent, /* depth */
InputOutput, /* class */
- FRAME_X_DISPLAY_INFO (f)->visual,
+ FRAME_X_VISUAL (f),
attribute_mask, &attributes);
-#ifdef HAVE_X_I18N
-#ifndef X_I18N_INHIBITED
- {
- XIM xim;
- XIC xic = NULL;
- xim = XOpenIM (FRAME_X_DISPLAY(f), NULL, NULL, NULL);
-
- if (xim)
- {
- xic = XCreateIC (xim,
- XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, FRAME_X_WINDOW(f),
- XNFocusWindow, FRAME_X_WINDOW(f),
- NULL);
-
- if (!xic)
- {
- XCloseIM (xim);
- xim = NULL;
- }
- }
-
- FRAME_XIM (f) = xim;
- FRAME_XIC (f) = xic;
- }
-#else /* X_I18N_INHIBITED */
- FRAME_XIM (f) = 0;
- FRAME_XIC (f) = 0;
-#endif /* X_I18N_INHIBITED */
+#ifdef HAVE_X_I18N
+ create_frame_xic (f);
+ if (FRAME_XIC (f))
+ {
+ /* XIM server might require some X events. */
+ unsigned long fevent = NoEventMask;
+ XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+ attributes.event_mask |= fevent;
+ attribute_mask = CWEventMask;
+ XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ attribute_mask, &attributes);
+ }
#endif /* HAVE_X_I18N */
-
+
validate_x_resource_name ();
class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
FRAME_KBOARD (f) = kb;
#endif
+ /* 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;
+ }
+
/* Specify the parent under which to make this X window. */
if (!NILP (parent))
x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
"foreground", "Foreground", RES_TYPE_STRING);
x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
- "background", "Background", RES_TYPE_STRING);
+ "background", "Background", RES_TYPE_STRING);
x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
"pointerColor", "Foreground", RES_TYPE_STRING);
x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
"menuBar", "MenuBar", RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
"toolBar", "ToolBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth",
- RES_TYPE_NUMBER);
x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
"bufferPredicate", "BufferPredicate",
RES_TYPE_SYMBOL);
"autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
x_default_parameter (f, parms, Qcursor_type, Qbox,
"cursorType", "CursorType", RES_TYPE_SYMBOL);
+ x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+ "scrollBarWidth", "ScrollBarWidth",
+ RES_TYPE_NUMBER);
/* Dimensions, especially f->height, must be done via change_frame_size.
Change will not be effected unless different from the current
return xfocus;
}
+
+/* In certain situations, when the window manager follows a
+ click-to-focus policy, there seems to be no way around calling
+ XSetInputFocus to give another frame the input focus .
+
+ In an ideal world, XSetInputFocus should generally be avoided so
+ that applications don't interfere with the window manager's focus
+ policy. But I think it's okay to use when it's clearly done
+ following a user-command. */
+
+DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
+ "Set the input focus to FRAME.\n\
+FRAME nil means use the selected frame.")
+ (frame)
+ Lisp_Object frame;
+{
+ struct frame *f = check_x_frame (frame);
+ Display *dpy = FRAME_X_DISPLAY (f);
+ int count;
+
+ BLOCK_INPUT;
+ count = x_catch_errors (dpy);
+ XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ RevertToParent, CurrentTime);
+ x_uncatch_errors (dpy, count);
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+
\f
-DEFUN ("x-color-defined-p", Fx_color_defined_p, Sx_color_defined_p, 1, 2, 0,
- "Return non-nil if color COLOR is supported on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.")
+DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
+ "Internal function called by `color-defined-p', which see.")
(color, frame)
Lisp_Object color, frame;
{
CHECK_STRING (color, 1);
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
+ if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
return Qt;
else
return Qnil;
}
-DEFUN ("x-color-values", Fx_color_values, Sx_color_values, 1, 2, 0,
- "Return a description of the color named COLOR on frame FRAME.\n\
-The value is a list of integer RGB values--(RED GREEN BLUE).\n\
-These values appear to range from 0 to 65280 or 65535, depending\n\
-on the system; white is (65280 65280 65280) or (65535 65535 65535).\n\
-If FRAME is omitted or nil, use the selected frame.")
+DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
+ "Internal function called by `color-values', which see.")
(color, frame)
Lisp_Object color, frame;
{
CHECK_STRING (color, 1);
- if (defined_color (f, XSTRING (color)->data, &foo, 0))
+ if (x_defined_color (f, XSTRING (color)->data, &foo, 0))
{
Lisp_Object rgb[3];
return Qnil;
}
-DEFUN ("x-display-color-p", Fx_display_color_p, Sx_display_color_p, 0, 1, 0,
- "Return t if the X display supports color.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
+DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
+ "Internal function called by `display-color-p', which see.")
(display)
Lisp_Object display;
{
{
return FRAME_X_DISPLAY_INFO (f)->n_planes;
}
-\f
-#if 0 /* These no longer seem like the right way to do things. */
-/* Draw a rectangle on the frame with left top corner including
- the character specified by LEFT_CHAR and TOP_CHAR. The rectangle is
- CHARS by LINES wide and long and is the color of the cursor. */
-void
-x_rectangle (f, gc, left_char, top_char, chars, lines)
- register struct frame *f;
- GC gc;
- register int top_char, left_char, chars, lines;
-{
- int width;
- int height;
- int left = (left_char * FONT_WIDTH (f->output_data.x->font)
- + f->output_data.x->internal_border_width);
- int top = (top_char * f->output_data.x->line_height
- + f->output_data.x->internal_border_width);
-
- if (chars < 0)
- width = FONT_WIDTH (f->output_data.x->font) / 2;
- else
- width = FONT_WIDTH (f->output_data.x->font) * chars;
- if (lines < 0)
- height = f->output_data.x->line_height / 2;
- else
- height = f->output_data.x->line_height * lines;
+\f
+/************************************************************************
+ X Displays
+ ************************************************************************/
- XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- gc, left, top, width, height);
-}
+\f
+/* Mapping visual names to visuals. */
-DEFUN ("x-draw-rectangle", Fx_draw_rectangle, Sx_draw_rectangle, 5, 5, 0,
- "Draw a rectangle on FRAME between coordinates specified by\n\
-numbers X0, Y0, X1, Y1 in the cursor pixel.")
- (frame, X0, Y0, X1, Y1)
- register Lisp_Object frame, X0, X1, Y0, Y1;
+static struct visual_class
+{
+ char *name;
+ int class;
+}
+visual_classes[] =
{
- register int x0, y0, x1, y1, top, left, n_chars, n_lines;
+ {"StaticGray", StaticGray},
+ {"GrayScale", GrayScale},
+ {"StaticColor", StaticColor},
+ {"PseudoColor", PseudoColor},
+ {"TrueColor", TrueColor},
+ {"DirectColor", DirectColor},
+ NULL
+};
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (X0, 0);
- CHECK_NUMBER (Y0, 1);
- CHECK_NUMBER (X1, 2);
- CHECK_NUMBER (Y1, 3);
- x0 = XINT (X0);
- x1 = XINT (X1);
- y0 = XINT (Y0);
- y1 = XINT (Y1);
+#ifndef HAVE_XSCREENNUMBEROFSCREEN
- if (y1 > y0)
- {
- top = y0;
- n_lines = y1 - y0 + 1;
- }
- else
- {
- top = y1;
- n_lines = y0 - y1 + 1;
- }
+/* Value is the screen number of screen SCR. This is a substitute for
+ the X function with the same name when that doesn't exist. */
- if (x1 > x0)
- {
- left = x0;
- n_chars = x1 - x0 + 1;
- }
- else
- {
- left = x1;
- n_chars = x0 - x1 + 1;
- }
+int
+XScreenNumberOfScreen (scr)
+ register Screen *scr;
+{
+ Display *dpy = scr->display;
+ int i;
- BLOCK_INPUT;
- x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->cursor_gc,
- left, top, n_chars, n_lines);
- UNBLOCK_INPUT;
+ for (i = 0; i < dpy->nscreens; ++i)
+ if (scr == dpy->screens[i])
+ break;
- return Qt;
+ return i;
}
-DEFUN ("x-erase-rectangle", Fx_erase_rectangle, Sx_erase_rectangle, 5, 5, 0,
- "Draw a rectangle drawn on FRAME between coordinates\n\
-X0, Y0, X1, Y1 in the regular background-pixel.")
- (frame, X0, Y0, X1, Y1)
- register Lisp_Object frame, X0, Y0, X1, Y1;
-{
- register int x0, y0, x1, y1, top, left, n_chars, n_lines;
+#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
- CHECK_LIVE_FRAME (frame, 0);
- CHECK_NUMBER (X0, 0);
- CHECK_NUMBER (Y0, 1);
- CHECK_NUMBER (X1, 2);
- CHECK_NUMBER (Y1, 3);
- x0 = XINT (X0);
- x1 = XINT (X1);
- y0 = XINT (Y0);
- y1 = XINT (Y1);
+/* Select the visual that should be used on display DPYINFO. Set
+ members of DPYINFO appropriately. Called from x_term_init. */
- if (y1 > y0)
- {
- top = y0;
- n_lines = y1 - y0 + 1;
- }
- else
- {
- top = y1;
- n_lines = y0 - y1 + 1;
- }
-
- if (x1 > x0)
- {
- left = x0;
- n_chars = x1 - x0 + 1;
- }
- else
- {
- left = x1;
- n_chars = x0 - x1 + 1;
- }
-
- BLOCK_INPUT;
- x_rectangle (XFRAME (frame), XFRAME (frame)->output_data.x->reverse_gc,
- left, top, n_chars, n_lines);
- UNBLOCK_INPUT;
-
- return Qt;
-}
-
-/* Draw lines around the text region beginning at the character position
- TOP_X, TOP_Y and ending at BOTTOM_X and BOTTOM_Y. GC specifies the
- pixel and line characteristics. */
-
-#define line_len(line) (FRAME_CURRENT_GLYPHS (f)->used[(line)])
-
-static void
-outline_region (f, gc, top_x, top_y, bottom_x, bottom_y)
- register struct frame *f;
- GC gc;
- int top_x, top_y, bottom_x, bottom_y;
-{
- register int ibw = f->output_data.x->internal_border_width;
- register int font_w = FONT_WIDTH (f->output_data.x->font);
- register int font_h = f->output_data.x->line_height;
- int y = top_y;
- int x = line_len (y);
- XPoint *pixel_points
- = (XPoint *) alloca (((bottom_y - top_y + 2) * 4) * sizeof (XPoint));
- register XPoint *this_point = pixel_points;
-
- /* Do the horizontal top line/lines */
- if (top_x == 0)
- {
- this_point->x = ibw;
- this_point->y = ibw + (font_h * top_y);
- this_point++;
- if (x == 0)
- this_point->x = ibw + (font_w / 2); /* Half-size for newline chars. */
- else
- this_point->x = ibw + (font_w * x);
- this_point->y = (this_point - 1)->y;
- }
- else
- {
- this_point->x = ibw;
- this_point->y = ibw + (font_h * (top_y + 1));
- this_point++;
- this_point->x = ibw + (font_w * top_x);
- this_point->y = (this_point - 1)->y;
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * top_y);
- this_point++;
- this_point->x = ibw + (font_w * x);
- this_point->y = (this_point - 1)->y;
- }
-
- /* Now do the right side. */
- while (y < bottom_y)
- { /* Right vertical edge */
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * (y + 1));
- this_point++;
-
- y++; /* Horizontal connection to next line */
- x = line_len (y);
- if (x == 0)
- this_point->x = ibw + (font_w / 2);
- else
- this_point->x = ibw + (font_w * x);
-
- this_point->y = (this_point - 1)->y;
- }
-
- /* Now do the bottom and connect to the top left point. */
- this_point->x = ibw + (font_w * (bottom_x + 1));
-
- this_point++;
- this_point->x = (this_point - 1)->x;
- this_point->y = ibw + (font_h * (bottom_y + 1));
- this_point++;
- this_point->x = ibw;
- this_point->y = (this_point - 1)->y;
- this_point++;
- this_point->x = pixel_points->x;
- this_point->y = pixel_points->y;
-
- XDrawLines (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- gc, pixel_points,
- (this_point - pixel_points + 1), CoordModeOrigin);
-}
-
-DEFUN ("x-contour-region", Fx_contour_region, Sx_contour_region, 1, 1, 0,
- "Highlight the region between point and the character under the mouse\n\
-selected frame.")
- (event)
- register Lisp_Object event;
-{
- register int x0, y0, x1, y1;
- register struct frame *f = selected_frame;
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
- register int p1, p2;
-
- CHECK_CONS (event, 0);
-
- BLOCK_INPUT;
- x0 = XINT (Fcar (Fcar (event)));
- y0 = XINT (Fcar (Fcdr (Fcar (event))));
-
- /* If the mouse is past the end of the line, don't that area. */
- /* ReWrite this... */
-
- /* Where the cursor is. */
- x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
- y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
-
- if (y1 > y0) /* point below mouse */
- outline_region (f, f->output_data.x->cursor_gc,
- x0, y0, x1, y1);
- else if (y1 < y0) /* point above mouse */
- outline_region (f, f->output_data.x->cursor_gc,
- x1, y1, x0, y0);
- else /* same line: draw horizontal rectangle */
- {
- if (x1 > x0)
- x_rectangle (f, f->output_data.x->cursor_gc,
- x0, y0, (x1 - x0 + 1), 1);
- else if (x1 < x0)
- x_rectangle (f, f->output_data.x->cursor_gc,
- x1, y1, (x0 - x1 + 1), 1);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-DEFUN ("x-uncontour-region", Fx_uncontour_region, Sx_uncontour_region, 1, 1, 0,
- "Erase any highlighting of the region between point and the character\n\
-at X, Y on the selected frame.")
- (event)
- register Lisp_Object event;
-{
- register int x0, y0, x1, y1;
- register struct frame *f = selected_frame;
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-
- BLOCK_INPUT;
- x0 = XINT (Fcar (Fcar (event)));
- y0 = XINT (Fcar (Fcdr (Fcar (event))));
- x1 = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
- y1 = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
-
- if (y1 > y0) /* point below mouse */
- outline_region (f, f->output_data.x->reverse_gc,
- x0, y0, x1, y1);
- else if (y1 < y0) /* point above mouse */
- outline_region (f, f->output_data.x->reverse_gc,
- x1, y1, x0, y0);
- else /* same line: draw horizontal rectangle */
- {
- if (x1 > x0)
- x_rectangle (f, f->output_data.x->reverse_gc,
- x0, y0, (x1 - x0 + 1), 1);
- else if (x1 < x0)
- x_rectangle (f, f->output_data.x->reverse_gc,
- x1, y1, (x0 - x1 + 1), 1);
- }
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-
-#if 0
-int contour_begin_x, contour_begin_y;
-int contour_end_x, contour_end_y;
-int contour_npoints;
-
-/* Clip the top part of the contour lines down (and including) line Y_POS.
- If X_POS is in the middle (rather than at the end) of the line, drop
- down a line at that character. */
-
-static void
-clip_contour_top (y_pos, x_pos)
-{
- register XPoint *begin = contour_lines[y_pos].top_left;
- register XPoint *end;
- register int npoints;
- register struct display_line *line = selected_frame->phys_lines[y_pos + 1];
-
- if (x_pos >= line->len - 1) /* Draw one, straight horizontal line. */
- {
- end = contour_lines[y_pos].top_right;
- npoints = (end - begin + 1);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
-
- bcopy (end, begin + 1, contour_last_point - end + 1);
- contour_last_point -= (npoints - 2);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin, 2, CoordModeOrigin);
- XFlush (x_current_display);
-
- /* Now, update contour_lines structure. */
- }
- /* ______. */
- else /* |________*/
- {
- register XPoint *p = begin + 1;
- end = contour_lines[y_pos].bottom_right;
- npoints = (end - begin + 1);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin_erase, npoints, CoordModeOrigin);
-
- p->y = begin->y;
- p->x = ibw + (font_w * (x_pos + 1));
- p++;
- p->y = begin->y + font_h;
- p->x = (p - 1)->x;
- bcopy (end, begin + 3, contour_last_point - end + 1);
- contour_last_point -= (npoints - 5);
- XDrawLines (x_current_display, contour_window,
- contour_erase_gc, begin, 4, CoordModeOrigin);
- XFlush (x_current_display);
-
- /* Now, update contour_lines structure. */
- }
-}
-
-/* Erase the top horizontal lines of the contour, and then extend
- the contour upwards. */
-
-static void
-extend_contour_top (line)
-{
-}
-
-static void
-clip_contour_bottom (x_pos, y_pos)
- int x_pos, y_pos;
-{
-}
-
-static void
-extend_contour_bottom (x_pos, y_pos)
-{
-}
-
-DEFUN ("x-select-region", Fx_select_region, Sx_select_region, 1, 1, "e",
- "")
- (event)
- Lisp_Object event;
-{
- register struct frame *f = selected_frame;
- struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
- register int point_x = WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x);
- register int point_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y);
- register int mouse_below_point;
- register Lisp_Object obj;
- register int x_contour_x, x_contour_y;
-
- x_contour_x = x_mouse_x;
- x_contour_y = x_mouse_y;
- if (x_contour_y > point_y || (x_contour_y == point_y
- && x_contour_x > point_x))
- {
- mouse_below_point = 1;
- outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
- x_contour_x, x_contour_y);
- }
- else
- {
- mouse_below_point = 0;
- outline_region (f, f->output_data.x->cursor_gc, x_contour_x, x_contour_y,
- point_x, point_y);
- }
-
- while (1)
- {
- obj = read_char (-1, 0, 0, Qnil, 0);
- if (!CONSP (obj))
- break;
-
- if (mouse_below_point)
- {
- if (x_mouse_y <= point_y) /* Flipped. */
- {
- mouse_below_point = 0;
-
- outline_region (f, f->output_data.x->reverse_gc, point_x, point_y,
- x_contour_x, x_contour_y);
- outline_region (f, f->output_data.x->cursor_gc, x_mouse_x, x_mouse_y,
- point_x, point_y);
- }
- else if (x_mouse_y < x_contour_y) /* Bottom clipped. */
- {
- clip_contour_bottom (x_mouse_y);
- }
- else if (x_mouse_y > x_contour_y) /* Bottom extended. */
- {
- extend_bottom_contour (x_mouse_y);
- }
-
- x_contour_x = x_mouse_x;
- x_contour_y = x_mouse_y;
- }
- else /* mouse above or same line as point */
- {
- if (x_mouse_y >= point_y) /* Flipped. */
- {
- mouse_below_point = 1;
-
- outline_region (f, f->output_data.x->reverse_gc,
- x_contour_x, x_contour_y, point_x, point_y);
- outline_region (f, f->output_data.x->cursor_gc, point_x, point_y,
- x_mouse_x, x_mouse_y);
- }
- else if (x_mouse_y > x_contour_y) /* Top clipped. */
- {
- clip_contour_top (x_mouse_y);
- }
- else if (x_mouse_y < x_contour_y) /* Top extended. */
- {
- extend_contour_top (x_mouse_y);
- }
- }
- }
-
- unread_command_event = obj;
- if (mouse_below_point)
- {
- contour_begin_x = point_x;
- contour_begin_y = point_y;
- contour_end_x = x_contour_x;
- contour_end_y = x_contour_y;
- }
- else
- {
- contour_begin_x = x_contour_x;
- contour_begin_y = x_contour_y;
- contour_end_x = point_x;
- contour_end_y = point_y;
- }
-}
-#endif
-
-DEFUN ("x-horizontal-line", Fx_horizontal_line, Sx_horizontal_line, 1, 1, "e",
- "")
- (event)
- Lisp_Object event;
+void
+select_visual (dpyinfo)
+ struct x_display_info *dpyinfo;
{
- register Lisp_Object obj;
- struct frame *f = selected_frame;
- register struct window *w = XWINDOW (selected_window);
- register GC line_gc = f->output_data.x->cursor_gc;
- register GC erase_gc = f->output_data.x->reverse_gc;
-#if 0
- char dash_list[] = {6, 4, 6, 4};
- int dashes = 4;
- XGCValues gc_values;
-#endif
- register int previous_y;
- register int line = (x_mouse_y + 1) * f->output_data.x->line_height
- + f->output_data.x->internal_border_width;
- register int left = f->output_data.x->internal_border_width
- + (WINDOW_LEFT_MARGIN (w)
- * FONT_WIDTH (f->output_data.x->font));
- register int right = left + (w->width
- * FONT_WIDTH (f->output_data.x->font))
- - f->output_data.x->internal_border_width;
-
-#if 0
- BLOCK_INPUT;
- gc_values.foreground = f->output_data.x->cursor_pixel;
- gc_values.background = f->output_data.x->background_pixel;
- gc_values.line_width = 1;
- gc_values.line_style = LineOnOffDash;
- gc_values.cap_style = CapRound;
- gc_values.join_style = JoinRound;
-
- line_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- GCLineStyle | GCJoinStyle | GCCapStyle
- | GCLineWidth | GCForeground | GCBackground,
- &gc_values);
- XSetDashes (FRAME_X_DISPLAY (f), line_gc, 0, dash_list, dashes);
- gc_values.foreground = f->output_data.x->background_pixel;
- gc_values.background = f->output_data.x->foreground_pixel;
- erase_gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- GCLineStyle | GCJoinStyle | GCCapStyle
- | GCLineWidth | GCForeground | GCBackground,
- &gc_values);
- XSetDashes (FRAME_X_DISPLAY (f), erase_gc, 0, dash_list, dashes);
- UNBLOCK_INPUT;
-#endif
+ Display *dpy = dpyinfo->display;
+ Screen *screen = dpyinfo->screen;
+ Lisp_Object value;
- while (1)
+ /* See if a visual is specified. */
+ value = display_x_get_resource (dpyinfo,
+ build_string ("visualClass"),
+ build_string ("VisualClass"),
+ Qnil, Qnil);
+ if (STRINGP (value))
{
- BLOCK_INPUT;
- if (x_mouse_y >= XINT (w->top)
- && x_mouse_y < XINT (w->top) + XINT (w->height) - 1)
+ /* VALUE should be of the form CLASS-DEPTH, where CLASS is one
+ of `PseudoColor', `TrueColor' etc. and DEPTH is the color
+ depth, a decimal number. NAME is compared with case ignored. */
+ char *s = (char *) alloca (STRING_BYTES (XSTRING (value)) + 1);
+ char *dash;
+ int i, class = -1;
+ XVisualInfo vinfo;
+
+ strcpy (s, XSTRING (value)->data);
+ dash = index (s, '-');
+ if (dash)
{
- previous_y = x_mouse_y;
- line = (x_mouse_y + 1) * f->output_data.x->line_height
- + f->output_data.x->internal_border_width;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- line_gc, left, line, right, line);
- }
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- do
- {
- obj = read_char (-1, 0, 0, Qnil, 0);
- if (!CONSP (obj)
- || (! EQ (Fcar (Fcdr (Fcdr (obj))),
- Qvertical_scroll_bar))
- || x_mouse_grabbed)
- {
- BLOCK_INPUT;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- erase_gc, left, line, right, line);
- unread_command_event = obj;
-#if 0
- XFreeGC (FRAME_X_DISPLAY (f), line_gc);
- XFreeGC (FRAME_X_DISPLAY (f), erase_gc);
-#endif
- UNBLOCK_INPUT;
- return Qnil;
- }
+ dpyinfo->n_planes = atoi (dash + 1);
+ *dash = '\0';
}
- while (x_mouse_y == previous_y);
-
- BLOCK_INPUT;
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- erase_gc, left, line, right, line);
- UNBLOCK_INPUT;
- }
-}
-#endif
-\f
-#if 0
-/* These keep track of the rectangle following the pointer. */
-int mouse_track_top, mouse_track_left, mouse_track_width;
-
-/* Offset in buffer of character under the pointer, or 0. */
-int mouse_buffer_offset;
-
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 0, 0, 0,
- "Track the pointer.")
- ()
-{
- static Cursor current_pointer_shape;
- FRAME_PTR f = x_mouse_frame;
-
- BLOCK_INPUT;
- if (EQ (Vmouse_frame_part, Qtext_part)
- && (current_pointer_shape != f->output_data.x->nontext_cursor))
- {
- unsigned char c;
- struct buffer *buf;
-
- current_pointer_shape = f->output_data.x->nontext_cursor;
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- current_pointer_shape);
-
- buf = XBUFFER (XWINDOW (Vmouse_window)->buffer);
- c = *(BUF_CHAR_ADDRESS (buf, mouse_buffer_offset));
- }
- else if (EQ (Vmouse_frame_part, Qmodeline_part)
- && (current_pointer_shape != f->output_data.x->modeline_cursor))
- {
- current_pointer_shape = f->output_data.x->modeline_cursor;
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- current_pointer_shape);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-#endif
-
-#if 0
-DEFUN ("x-track-pointer", Fx_track_pointer, Sx_track_pointer, 1, 1, "e",
- "Draw rectangle around character under mouse pointer, if there is one.")
- (event)
- Lisp_Object event;
-{
- struct window *w = XWINDOW (Vmouse_window);
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct buffer *b = XBUFFER (w->buffer);
- Lisp_Object obj;
-
- if (! EQ (Vmouse_window, selected_window))
- return Qnil;
-
- if (EQ (event, Qnil))
- {
- int x, y;
-
- x_read_mouse_position (selected_frame, &x, &y);
- }
-
- BLOCK_INPUT;
- mouse_track_width = 0;
- mouse_track_left = mouse_track_top = -1;
+ else
+ /* We won't find a matching visual with depth 0, so that
+ an error will be printed below. */
+ dpyinfo->n_planes = 0;
- do
- {
- if ((x_mouse_x != mouse_track_left
- && (x_mouse_x < mouse_track_left
- || x_mouse_x > (mouse_track_left + mouse_track_width)))
- || x_mouse_y != mouse_track_top)
- {
- int hp = 0; /* Horizontal position */
- int len = FRAME_CURRENT_GLYPHS (f)->used[x_mouse_y];
- int p = FRAME_CURRENT_GLYPHS (f)->bufp[x_mouse_y];
- int tab_width = XINT (b->tab_width);
- int ctl_arrow_p = !NILP (b->ctl_arrow);
- unsigned char c;
- int mode_line_vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
- int in_mode_line = 0;
-
- if (! FRAME_CURRENT_GLYPHS (f)->enable[x_mouse_y])
+ /* Determine the visual class. */
+ for (i = 0; visual_classes[i].name; ++i)
+ if (xstricmp (s, visual_classes[i].name) == 0)
+ {
+ class = visual_classes[i].class;
break;
+ }
- /* Erase previous rectangle. */
- if (mouse_track_width)
- {
- x_rectangle (f, f->output_data.x->reverse_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
-
- if ((mouse_track_left == f->phys_cursor_x
- || mouse_track_left == f->phys_cursor_x - 1)
- && mouse_track_top == f->phys_cursor_y)
- {
- x_display_cursor (f, 1);
- }
- }
-
- mouse_track_left = x_mouse_x;
- mouse_track_top = x_mouse_y;
- mouse_track_width = 0;
-
- if (mouse_track_left > len) /* Past the end of line. */
- goto draw_or_not;
-
- if (mouse_track_top == mode_line_vpos)
- {
- in_mode_line = 1;
- goto draw_or_not;
- }
-
- if (tab_width <= 0 || tab_width > 20) tab_width = 8;
- do
- {
- c = FETCH_BYTE (p);
- if (len == f->width && hp == len - 1 && c != '\n')
- goto draw_or_not;
-
- switch (c)
- {
- case '\t':
- mouse_track_width = tab_width - (hp % tab_width);
- p++;
- hp += mouse_track_width;
- if (hp > x_mouse_x)
- {
- mouse_track_left = hp - mouse_track_width;
- goto draw_or_not;
- }
- continue;
-
- case '\n':
- mouse_track_width = -1;
- goto draw_or_not;
-
- default:
- if (ctl_arrow_p && (c < 040 || c == 0177))
- {
- if (p > ZV)
- goto draw_or_not;
-
- mouse_track_width = 2;
- p++;
- hp +=2;
- if (hp > x_mouse_x)
- {
- mouse_track_left = hp - mouse_track_width;
- goto draw_or_not;
- }
- }
- else
- {
- mouse_track_width = 1;
- p++;
- hp++;
- }
- continue;
- }
- }
- while (hp <= x_mouse_x);
-
- draw_or_not:
- if (mouse_track_width) /* Over text; use text pointer shape. */
- {
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
- x_rectangle (f, f->output_data.x->cursor_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
- }
- else if (in_mode_line)
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->modeline_cursor);
- else
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->nontext_cursor);
- }
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- obj = read_char (-1, 0, 0, Qnil, 0);
- BLOCK_INPUT;
- }
- while (CONSP (obj) /* Mouse event */
- && EQ (Fcar (Fcdr (Fcdr (obj))), Qnil) /* Not scroll bar */
- && EQ (Vmouse_depressed, Qnil) /* Only motion events */
- && EQ (Vmouse_window, selected_window) /* In this window */
- && x_mouse_frame);
-
- unread_command_event = obj;
-
- if (mouse_track_width)
- {
- x_rectangle (f, f->output_data.x->reverse_gc,
- mouse_track_left, mouse_track_top,
- mouse_track_width, 1);
- mouse_track_width = 0;
- if ((mouse_track_left == f->phys_cursor_x
- || mouse_track_left - 1 == f->phys_cursor_x)
- && mouse_track_top == f->phys_cursor_y)
- {
- x_display_cursor (f, 1);
- }
+ /* Look up a matching visual for the specified class. */
+ if (class == -1
+ || !XMatchVisualInfo (dpy, XScreenNumberOfScreen (screen),
+ dpyinfo->n_planes, class, &vinfo))
+ fatal ("Invalid visual specification `%s'", XSTRING (value)->data);
+
+ dpyinfo->visual = vinfo.visual;
}
- XDefineCursor (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- f->output_data.x->nontext_cursor);
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-#endif
-\f
-#if 0
-#include "glyphs.h"
-
-/* Draw a pixmap specified by IMAGE_DATA of dimensions WIDTH and HEIGHT
- on the frame F at position X, Y. */
-
-x_draw_pixmap (f, x, y, image_data, width, height)
- struct frame *f;
- int x, y, width, height;
- char *image_data;
-{
- Pixmap image;
-
- image = XCreateBitmapFromData (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f), image_data,
- width, height);
- XCopyPlane (FRAME_X_DISPLAY (f), image, FRAME_X_WINDOW (f),
- f->output_data.x->normal_gc, 0, 0, width, height, x, y);
-}
-#endif
-\f
-#if 0 /* I'm told these functions are superfluous
- given the ability to bind function keys. */
-
-#ifdef HAVE_X11
-DEFUN ("x-rebind-key", Fx_rebind_key, Sx_rebind_key, 3, 3, 0,
-"Rebind X keysym KEYSYM, with MODIFIERS, to generate NEWSTRING.\n\
-KEYSYM is a string which conforms to the X keysym definitions found\n\
-in X11/keysymdef.h, sans the initial XK_. MODIFIERS is nil or a\n\
-list of strings specifying modifier keys such as Control_L, which must\n\
-also be depressed for NEWSTRING to appear.")
- (x_keysym, modifiers, newstring)
- register Lisp_Object x_keysym;
- register Lisp_Object modifiers;
- register Lisp_Object newstring;
-{
- char *rawstring;
- register KeySym keysym;
- KeySym modifier_list[16];
-
- check_x ();
- CHECK_STRING (x_keysym, 1);
- CHECK_STRING (newstring, 3);
-
- keysym = XStringToKeysym ((char *) XSTRING (x_keysym)->data);
- if (keysym == NoSymbol)
- error ("Keysym does not exist");
-
- if (NILP (modifiers))
- XRebindKeysym (x_current_display, keysym, modifier_list, 0,
- XSTRING (newstring)->data,
- STRING_BYTES (XSTRING (newstring)));
else
{
- register Lisp_Object rest, mod;
- register int i = 0;
-
- for (rest = modifiers; !NILP (rest); rest = Fcdr (rest))
- {
- if (i == 16)
- error ("Can't have more than 16 modifiers");
-
- mod = Fcar (rest);
- CHECK_STRING (mod, 3);
- modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
-#ifndef HAVE_X11R5
- if (modifier_list[i] == NoSymbol
- || !(IsModifierKey (modifier_list[i])
- || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
- || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
-#else
- if (modifier_list[i] == NoSymbol
- || !IsModifierKey (modifier_list[i]))
-#endif
- error ("Element is not a modifier keysym");
- i++;
- }
-
- XRebindKeysym (x_current_display, keysym, modifier_list, i,
- XSTRING (newstring)->data,
- STRING_BYTES (XSTRING (newstring)));
- }
-
- return Qnil;
-}
-
-DEFUN ("x-rebind-keys", Fx_rebind_keys, Sx_rebind_keys, 2, 2, 0,
- "Rebind KEYCODE to list of strings STRINGS.\n\
-STRINGS should be a list of 16 elements, one for each shift combination.\n\
-nil as element means don't change.\n\
-See the documentation of `x-rebind-key' for more information.")
- (keycode, strings)
- register Lisp_Object keycode;
- register Lisp_Object strings;
-{
- register Lisp_Object item;
- register unsigned char *rawstring;
- KeySym rawkey, modifier[1];
- int strsize;
- register unsigned i;
-
- check_x ();
- CHECK_NUMBER (keycode, 1);
- CHECK_CONS (strings, 2);
- rawkey = (KeySym) ((unsigned) (XINT (keycode))) & 255;
- for (i = 0; i <= 15; strings = Fcdr (strings), i++)
- {
- item = Fcar (strings);
- if (!NILP (item))
- {
- CHECK_STRING (item, 2);
- strsize = STRING_BYTES (XSTRING (item));
- rawstring = (unsigned char *) xmalloc (strsize);
- bcopy (XSTRING (item)->data, rawstring, strsize);
- modifier[1] = 1 << i;
- XRebindKeysym (x_current_display, rawkey, modifier, 1,
- rawstring, strsize);
- }
- }
- return Qnil;
-}
-#endif /* HAVE_X11 */
-#endif /* 0 */
-\f
-#ifndef HAVE_XSCREENNUMBEROFSCREEN
-int
-XScreenNumberOfScreen (scr)
- register Screen *scr;
-{
- register Display *dpy;
- register Screen *dpyscr;
- register int i;
-
- dpy = scr->display;
- dpyscr = dpy->screens;
-
- for (i = 0; i < dpy->nscreens; i++, dpyscr++)
- if (scr == dpyscr)
- return i;
-
- return -1;
-}
-#endif /* not HAVE_XSCREENNUMBEROFSCREEN */
-
-Visual *
-select_visual (dpy, screen, depth)
- Display *dpy;
- Screen *screen;
- unsigned int *depth;
-{
- Visual *v;
- XVisualInfo *vinfo, vinfo_template;
- int n_visuals;
-
- v = DefaultVisualOfScreen (screen);
+ int n_visuals;
+ XVisualInfo *vinfo, vinfo_template;
+
+ dpyinfo->visual = DefaultVisualOfScreen (screen);
#ifdef HAVE_X11R4
- vinfo_template.visualid = XVisualIDFromVisual (v);
+ vinfo_template.visualid = XVisualIDFromVisual (dpyinfo->visual);
#else
- vinfo_template.visualid = v->visualid;
+ vinfo_template.visualid = dpyinfo->visual->visualid;
#endif
-
- vinfo_template.screen = XScreenNumberOfScreen (screen);
-
- vinfo = XGetVisualInfo (dpy,
- VisualIDMask | VisualScreenMask, &vinfo_template,
- &n_visuals);
- if (n_visuals != 1)
- fatal ("Can't get proper X visual info");
-
- if ((1 << vinfo->depth) == vinfo->colormap_size)
- *depth = vinfo->depth;
- else
- {
- int i = 0;
- int n = vinfo->colormap_size - 1;
- while (n)
+ vinfo_template.screen = XScreenNumberOfScreen (screen);
+ vinfo = XGetVisualInfo (dpy, VisualIDMask | VisualScreenMask,
+ &vinfo_template, &n_visuals);
+ if (n_visuals != 1)
+ fatal ("Can't get proper X visual info");
+
+ if ((1 << vinfo->depth) == vinfo->colormap_size)
+ dpyinfo->n_planes = vinfo->depth;
+ else
{
- n = n >> 1;
- i++;
+ int i = 0;
+ int n = vinfo->colormap_size - 1;
+ while (n)
+ {
+ n = n >> 1;
+ i++;
+ }
+ dpyinfo->n_planes = i;
}
- *depth = i;
- }
- XFree ((char *) vinfo);
- return v;
+ XFree ((char *) vinfo);
+ }
}
+
/* Return the X display structure for the display named NAME.
Open a new connection if necessary. */
return dpyinfo;
}
+
DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1, 3, 0, "Open a connection to an X server.\n\
DISPLAY is the name of the display to connect to.\n\
/* Keywords. */
-Lisp_Object QCtype, QCdata, QCascent, QCmargin, QCrelief;
extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
+extern Lisp_Object QCdata;
+Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
Lisp_Object QCindex;
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 int x_build_heuristic_mask P_ ((struct frame *, Lisp_Object,
- struct image *, Lisp_Object));
+static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
+ Lisp_Object));
/* Define a new image type from TYPE. This adds a copy of TYPE to
};
-static int parse_image_spec P_ ((Lisp_Object spec,
- struct image_keyword *keywords,
- int nkeywords, Lisp_Object type,
- int allow_other_keys_p));
+static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
+ int, Lisp_Object));
static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
has the format (image KEYWORD VALUE ...). One of the keyword/
value pairs must be `:type TYPE'. KEYWORDS is a vector of
image_keywords structures of size NKEYWORDS describing other
- allowed keyword/value pairs. ALLOW_OTHER_KEYS_P non-zero means
- allow KEYWORD/VALUE pairs other than those described by KEYWORDS
- without checking them. Value is non-zero if SPEC is valid. */
+ allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
static int
-parse_image_spec (spec, keywords, nkeywords, type, allow_other_keys_p)
+parse_image_spec (spec, keywords, nkeywords, type)
Lisp_Object spec;
struct image_keyword *keywords;
int nkeywords;
Lisp_Object type;
- int allow_other_keys_p;
{
int i;
Lisp_Object plist;
break;
if (i == nkeywords)
- {
- if (!allow_other_keys_p)
- return 0;
- continue;
- }
+ continue;
/* Record that we recognized the keyword. If a keywords
was found more than once, it's an error. */
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
- if (img->pixmap == 0)
- img->type->load (f, img);
+ if (img->pixmap == 0 && !img->load_failed_p)
+ img->load_failed_p = img->type->load (f, img) == 0;
}
if (img->ncolors)
{
- int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-
- /* If display has an immutable color map, freeing colors is not
- necessary and some servers don't allow it. So don't do it. */
- if (class != StaticColor
- && class != StaticGray
- && class != TrueColor)
- {
- Colormap cmap;
- BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_X_DISPLAY_INFO (f)->screen);
- XFreeColors (FRAME_X_DISPLAY (f), cmap, img->colors,
- img->ncolors, 0);
- UNBLOCK_INPUT;
- }
+ BLOCK_INPUT;
+ x_free_colors (f, img->colors, img->ncolors);
+ UNBLOCK_INPUT;
xfree (img->colors);
img->colors = NULL;
xassert (STRINGP (color_name));
- if (defined_color (f, XSTRING (color_name)->data, &color, 1))
+ if (x_defined_color (f, XSTRING (color_name)->data, &color, 1))
{
/* This isn't called frequently so we get away with simply
reallocating the color vector to the needed size, here. */
/* If not found, create a new image and cache it. */
if (img == NULL)
{
- int loading_failed_p;
-
img = make_image (spec, hash);
cache_image (f, img);
- loading_failed_p = img->type->load (f, img) == 0;
+ 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
draw a rectangle for it. */
- if (loading_failed_p)
+ if (img->load_failed_p)
{
Lisp_Object value;
/* Should we built a mask heuristically? */
heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
if (img->pixmap && !img->mask && !NILP (heuristic_mask))
- {
- file = image_spec_value (spec, QCfile, NULL);
- x_build_heuristic_mask (f, file, img, heuristic_mask);
- }
+ x_build_heuristic_mask (f, img, heuristic_mask);
}
}
X support code
***********************************************************************/
-static int x_create_x_image_and_pixmap P_ ((struct frame *, Lisp_Object,
- int, int, int, XImage **,
- Pixmap *));
+static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
+ XImage **, Pixmap *));
static void x_destroy_x_image P_ ((XImage *));
static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
via xmalloc. Print error messages via image_error if an error
- occurs. FILE is the name of an image file being processed, for
- error messages. Value is non-zero if successful. */
+ occurs. Value is non-zero if successful. */
static int
-x_create_x_image_and_pixmap (f, file, width, height, depth, ximg, pixmap)
+x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
struct frame *f;
- Lisp_Object file;
int width, height, depth;
XImage **ximg;
Pixmap *pixmap;
depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
if (*ximg == NULL)
{
- image_error ("Unable to allocate X image for %s", file, Qnil);
+ image_error ("Unable to allocate X image", Qnil, Qnil);
return 0;
}
{
x_destroy_x_image (*ximg);
*ximg = NULL;
- image_error ("Unable to create pixmap for `%s'", file, Qnil);
+ image_error ("Unable to create X pixmap", Qnil, Qnil);
return 0;
}
struct image_keyword kw[XBM_LAST];
bcopy (xbm_format, kw, sizeof kw);
- if (!parse_image_spec (object, kw, XBM_LAST, Qxbm, 0))
+ if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
return 0;
xassert (EQ (kw[XBM_TYPE].value, Qxbm));
file = x_find_image_file (specified_file);
if (!STRINGP (file))
{
- image_error ("Cannot find image file %s", specified_file, Qnil);
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
UNGCPRO;
return 0;
}
UNBLOCK_INPUT;
}
else
- image_error ("Error loading XBM image %s", img->spec, Qnil);
+ image_error ("Error loading XBM image `%s'", img->spec, Qnil);
UNGCPRO;
return success_p;
/* Parse the list specification. */
bcopy (xbm_format, fmt, sizeof fmt);
- parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm, 0);
+ parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
xassert (parsed_p);
/* Get specified width, and height. */
success_p = 1;
else
{
- image_error ("Unable to create pixmap for XBM image", Qnil, Qnil);
+ image_error ("Unable to create pixmap for XBM image `%s'",
+ img->spec, Qnil);
x_clear_image (f, img);
}
{
struct image_keyword fmt[XPM_LAST];
bcopy (xpm_format, fmt, sizeof fmt);
- return (parse_image_spec (object, fmt, XPM_LAST, Qxpm, 0)
+ return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
/* Either `:file' or `:data' must be present. */
&& fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
/* Either no `:color-symbols' or it's a list of conses
/* Configure the XPM lib. Use the visual of frame F. Allocate
close colors. Return colors allocated. */
bzero (&attrs, sizeof attrs);
- attrs.visual = FRAME_X_DISPLAY_INFO (f)->visual;
+ attrs.visual = FRAME_X_VISUAL (f);
+ attrs.colormap = FRAME_X_COLORMAP (f);
attrs.valuemask |= XpmVisual;
+ attrs.valuemask |= XpmColormap;
attrs.valuemask |= XpmReturnAllocPixels;
#ifdef XpmAllocCloseColors
attrs.alloc_close_colors = 1;
Lisp_Object file = x_find_image_file (specified_file);
if (!STRINGP (file))
{
- image_error ("Cannot find image file %s", specified_file, Qnil);
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNBLOCK_INPUT;
return 0;
}
color.blue = b;
BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ cmap = FRAME_X_COLORMAP (f);
rc = x_alloc_nearest_color (f, cmap, &color);
UNBLOCK_INPUT;
BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ cmap = FRAME_X_COLORMAP (f);
color.pixel = pixel;
XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
struct frame *f;
struct image *img;
{
- Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ Colormap cmap = FRAME_X_COLORMAP (f);
XImage *ximg, *oimg;
XColor *in[3];
long *out;
out = (long *) alloca (img->width * sizeof (long));
/* Create an X image for output. */
- rc = x_create_x_image_and_pixmap (f, Qnil, img->width, img->height, 0,
+ rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
&oimg, &pixmap);
/* Fill first two rows. */
heuristically. Value is non-zero if successful. */
static int
-x_build_heuristic_mask (f, file, img, how)
+x_build_heuristic_mask (f, img, how)
struct frame *f;
- Lisp_Object file;
struct image *img;
Lisp_Object how;
{
BLOCK_INPUT;
/* Create an image and pixmap serving as mask. */
- rc = x_create_x_image_and_pixmap (f, file, img->width, img->height, 1,
+ rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
&mask_img, &img->mask);
if (!rc)
{
sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ cmap = FRAME_X_COLORMAP (f);
if (XLookupColor (dpy, cmap, color_name, &exact, &color))
{
bg = color.pixel;
static int pbm_image_p P_ ((Lisp_Object object));
static int pbm_load P_ ((struct frame *f, struct image *img));
-static int pbm_scan_number P_ ((FILE *fp));
+static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
/* The symbol `pbm' identifying images of this type. */
{
PBM_TYPE,
PBM_FILE,
+ PBM_DATA,
PBM_ASCENT,
PBM_MARGIN,
PBM_RELIEF,
static struct image_keyword pbm_format[PBM_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":data", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
bcopy (pbm_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm, 0)
+ if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
|| (fmt[PBM_ASCENT].count
&& XFASTINT (fmt[PBM_ASCENT].value) > 100))
return 0;
- return 1;
+
+ /* Must specify either :data or :file. */
+ return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
}
-/* Scan a decimal number from PBM input file FP and return it. Value
- is -1 at end of file or if an error occurs. */
+/* Scan a decimal number from *S and return it. Advance *S while
+ reading the number. END is the end of the string. Value is -1 at
+ end of input. */
static int
-pbm_scan_number (fp)
- FILE *fp;
+pbm_scan_number (s, end)
+ unsigned char **s, *end;
{
int c, val = -1;
- while (!feof (fp))
+ while (*s < end)
{
/* Skip white-space. */
- while ((c = fgetc (fp)) != EOF && isspace (c))
+ while (*s < end && (c = *(*s)++, isspace (c)))
;
if (c == '#')
{
/* Skip comment to end of line. */
- while ((c = fgetc (fp)) != EOF && c != '\n')
+ while (*s < end && (c = *(*s)++, c != '\n'))
;
}
else if (isdigit (c))
{
/* Read decimal number. */
val = c - '0';
- while ((c = fgetc (fp)) != EOF && isdigit (c))
+ while (*s < end && (c = *(*s)++, isdigit (c)))
val = 10 * val + c - '0';
break;
}
}
+/* 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
struct frame *f;
struct image *img;
{
- FILE *fp;
- char magic[2];
int raw_p, x, y;
int width, height, max_color_idx = 0;
XImage *ximg;
Lisp_Object file, specified_file;
enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
struct gcpro gcpro1;
+ unsigned char *contents = NULL;
+ unsigned char *end, *p;
+ int size;
specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = x_find_image_file (specified_file);
+ file = Qnil;
GCPRO1 (file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file %s", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
- fp = fopen (XSTRING (file)->data, "r");
- if (fp == NULL)
+ if (STRINGP (specified_file))
{
- UNGCPRO;
- return 0;
- }
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
- /* Read first two characters. */
- if (fread (magic, sizeof *magic, 2, fp) != 2)
+ contents = pbm_read_file (file, &size);
+ if (contents == NULL)
+ {
+ image_error ("Error reading `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ p = contents;
+ end = contents + size;
+ }
+ else
{
- fclose (fp);
- image_error ("Not a PBM image file: %s", file, Qnil);
- UNGCPRO;
- return 0;
+ Lisp_Object data;
+ data = image_spec_value (img->spec, QCdata, NULL);
+ p = XSTRING (data)->data;
+ end = p + STRING_BYTES (XSTRING (data));
}
- if (*magic != 'P')
+ /* Check magic number. */
+ if (end - p < 2 || *p++ != 'P')
{
- fclose (fp);
- image_error ("Not a PBM image file: %s", file, Qnil);
+ image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+ error:
+ xfree (contents);
UNGCPRO;
return 0;
}
- switch (magic[1])
+ switch (*p++)
{
case '1':
raw_p = 0, type = PBM_MONO;
break;
default:
- fclose (fp);
- image_error ("Not a PBM image file: %s", file, Qnil);
- UNGCPRO;
- return 0;
+ image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+ goto error;
}
/* Read width, height, maximum color-component. Characters
starting with `#' up to the end of a line are ignored. */
- width = pbm_scan_number (fp);
- height = pbm_scan_number (fp);
+ width = pbm_scan_number (&p, end);
+ height = pbm_scan_number (&p, end);
if (type != PBM_MONO)
{
- max_color_idx = pbm_scan_number (fp);
+ max_color_idx = pbm_scan_number (&p, end);
if (raw_p && max_color_idx > 255)
max_color_idx = 255;
}
- if (width < 0 || height < 0
+ if (width < 0
+ || height < 0
|| (type != PBM_MONO && max_color_idx < 0))
- {
- fclose (fp);
- UNGCPRO;
- return 0;
- }
+ goto error;
BLOCK_INPUT;
- if (!x_create_x_image_and_pixmap (f, file, width, height, 0,
+ if (!x_create_x_image_and_pixmap (f, width, height, 0,
&ximg, &img->pixmap))
{
- fclose (fp);
UNBLOCK_INPUT;
- UNGCPRO;
- return 0;
+ goto error;
}
/* Initialize the color hash table. */
if (raw_p)
{
if ((x & 7) == 0)
- c = fgetc (fp);
+ c = *p++;
g = c & 0x80;
c <<= 1;
}
else
- g = pbm_scan_number (fp);
+ g = pbm_scan_number (&p, end);
XPutPixel (ximg, x, y, (g
? FRAME_FOREGROUND_PIXEL (f)
int r, g, b;
if (type == PBM_GRAY)
- r = g = b = raw_p ? fgetc (fp) : pbm_scan_number (fp);
+ r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
else if (raw_p)
{
- r = fgetc (fp);
- g = fgetc (fp);
- b = fgetc (fp);
+ r = *p++;
+ g = *p++;
+ b = *p++;
}
else
{
- r = pbm_scan_number (fp);
- g = pbm_scan_number (fp);
- b = pbm_scan_number (fp);
+ r = pbm_scan_number (&p, end);
+ g = pbm_scan_number (&p, end);
+ b = pbm_scan_number (&p, end);
}
if (r < 0 || g < 0 || b < 0)
{
- fclose (fp);
xfree (ximg->data);
ximg->data = NULL;
XDestroyImage (ximg);
UNBLOCK_INPUT;
- image_error ("Invalid pixel value in file `%s'",
- file, Qnil);
- UNGCPRO;
- return 0;
+ image_error ("Invalid pixel value in image `%s'",
+ img->spec, Qnil);
+ goto error;
}
/* RGB values are now in the range 0..max_color_idx.
}
}
- fclose (fp);
-
/* Store in IMG->colors the colors allocated for the image, and
free the color table. */
img->colors = colors_in_color_table (&img->ncolors);
img->height = height;
UNGCPRO;
+ xfree (contents);
return 1;
}
enum png_keyword_index
{
PNG_TYPE,
+ PNG_DATA,
PNG_FILE,
PNG_ASCENT,
PNG_MARGIN,
static struct image_keyword png_format[PNG_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
};
-/* Structure describing the image type `gif'. */
+/* Structure describing the image type `png'. */
static struct image_type png_type =
{
struct image_keyword fmt[PNG_LAST];
bcopy (png_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, PNG_LAST, Qpng, 1)
+ if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
|| (fmt[PNG_ASCENT].count
&& XFASTINT (fmt[PNG_ASCENT].value) > 100))
return 0;
- return 1;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
}
image_error ("PNG warning: %s", build_string (msg), Qnil);
}
+/* Memory source for PNG decoding. */
+
+struct png_memory_storage
+{
+ unsigned char *bytes; /* The data */
+ size_t len; /* How big is it? */
+ int index; /* Where are we? */
+};
+
+
+/* Function set as reader function when reading PNG image from memory.
+ PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
+ bytes from the input to DATA. */
+
+static void
+png_read_from_memory (png_ptr, data, length)
+ png_structp png_ptr;
+ png_bytep data;
+ png_size_t length;
+{
+ struct png_memory_storage *tbr
+ = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
+
+ if (length > tbr->len - tbr->index)
+ png_error (png_ptr, "Read error");
+
+ bcopy (tbr->bytes + tbr->index, data, length);
+ tbr->index = tbr->index + length;
+}
/* Load PNG image IMG for use on frame F. Value is non-zero if
successful. */
struct image *img;
{
Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
int x, y, i;
XImage *ximg, *mask_img = NULL;
struct gcpro gcpro1;
png_struct *png_ptr = NULL;
png_info *info_ptr = NULL, *end_info = NULL;
- FILE *fp;
+ FILE *fp = NULL;
png_byte sig[8];
png_byte *pixels = NULL;
png_byte **rows = NULL;
char *gamma_str;
double screen_gamma, image_gamma;
int intent;
+ struct png_memory_storage tbr; /* Data to be read */
/* Find out what file to load. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = x_find_image_file (specified_file);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
GCPRO1 (file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file %s", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
- /* Open the image file. */
- fp = fopen (XSTRING (file)->data, "rb");
- if (!fp)
+ if (NILP (specified_data))
{
- image_error ("Cannot open image file %s", file, Qnil);
- UNGCPRO;
- fclose (fp);
- return 0;
- }
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Open the image file. */
+ fp = fopen (XSTRING (file)->data, "rb");
+ if (!fp)
+ {
+ image_error ("Cannot open image file `%s'", file, Qnil);
+ UNGCPRO;
+ fclose (fp);
+ return 0;
+ }
- /* Check PNG signature. */
- if (fread (sig, 1, sizeof sig, fp) != sizeof sig
- || !png_check_sig (sig, sizeof sig))
+ /* Check PNG signature. */
+ if (fread (sig, 1, sizeof sig, fp) != sizeof sig
+ || !png_check_sig (sig, sizeof sig))
+ {
+ image_error ("Not a PNG file: `%s'", file, Qnil);
+ UNGCPRO;
+ fclose (fp);
+ return 0;
+ }
+ }
+ else
{
- image_error ("Not a PNG file: %s", file, Qnil);
- UNGCPRO;
- fclose (fp);
- return 0;
+ /* Read from memory. */
+ tbr.bytes = XSTRING (specified_data)->data;
+ tbr.len = STRING_BYTES (XSTRING (specified_data));
+ tbr.index = 0;
+
+ /* Check PNG signature. */
+ if (tbr.len < sizeof sig
+ || !png_check_sig (tbr.bytes, sizeof sig))
+ {
+ image_error ("Not a PNG image: `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Need to skip past the signature. */
+ tbr.bytes += sizeof (sig);
}
/* Initialize read and info structs for PNG lib. */
my_png_error, my_png_warning);
if (!png_ptr)
{
- fclose (fp);
+ if (fp) fclose (fp);
UNGCPRO;
return 0;
}
if (!info_ptr)
{
png_destroy_read_struct (&png_ptr, NULL, NULL);
- fclose (fp);
+ if (fp) fclose (fp);
UNGCPRO;
return 0;
}
if (!end_info)
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
- fclose (fp);
+ if (fp) fclose (fp);
UNGCPRO;
return 0;
}
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
xfree (pixels);
xfree (rows);
- if (fp)
- fclose (fp);
+ if (fp) fclose (fp);
UNGCPRO;
return 0;
}
/* Read image info. */
- png_init_io (png_ptr, fp);
+ if (!NILP (specified_data))
+ png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+ else
+ png_init_io (png_ptr, fp);
+
png_set_sig_bytes (png_ptr, sizeof sig);
png_read_info (png_ptr, info_ptr);
png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
/* Tell the PNG lib to handle gamma correction for us. */
+#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
if (png_get_sRGB (png_ptr, info_ptr, &intent))
/* There is a special chunk in the image specifying the gamma. */
png_set_sRGB (png_ptr, info_ptr, intent);
- else if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
+ else
+#endif
+ if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
/* Image contains gamma information. */
png_set_gamma (png_ptr, screen_gamma, image_gamma);
else
png_color_16 frame_background;
BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ cmap = FRAME_X_COLORMAP (f);
color.pixel = FRAME_BACKGROUND_PIXEL (f);
XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
UNBLOCK_INPUT;
/* Read the entire image. */
png_read_image (png_ptr, rows);
png_read_end (png_ptr, info_ptr);
- fclose (fp);
- fp = NULL;
+ if (fp)
+ {
+ fclose (fp);
+ fp = NULL;
+ }
BLOCK_INPUT;
/* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
&img->pixmap))
{
UNBLOCK_INPUT;
contains an alpha channel. */
if (channels == 4
&& !transparent_p
- && !x_create_x_image_and_pixmap (f, file, width, height, 1,
+ && !x_create_x_image_and_pixmap (f, width, height, 1,
&mask_img, &img->mask))
{
x_destroy_x_image (ximg);
enum jpeg_keyword_index
{
JPEG_TYPE,
+ JPEG_DATA,
JPEG_FILE,
JPEG_ASCENT,
JPEG_MARGIN,
static struct image_keyword jpeg_format[JPEG_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
bcopy (jpeg_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg, 0)
+ if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
|| (fmt[JPEG_ASCENT].count
&& XFASTINT (fmt[JPEG_ASCENT].value) > 100))
return 0;
- return 1;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
+}
+
+
+struct my_jpeg_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+static void
+my_error_exit (cinfo)
+ j_common_ptr cinfo;
+{
+ struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
+ longjmp (mgr->setjmp_buffer, 1);
+}
+
+/* Init source method for JPEG data source manager. Called by
+ jpeg_read_header() before any data is actually read. See
+ libjpeg.doc from the JPEG lib distribution. */
+
+static void
+our_init_source (cinfo)
+ j_decompress_ptr cinfo;
+{
+}
+
+
+/* Fill input buffer method for JPEG data source manager. Called
+ whenever more data is needed. We read the whole image in one step,
+ so this only adds a fake end of input marker at the end. */
+
+static boolean
+our_fill_input_buffer (cinfo)
+ j_decompress_ptr cinfo;
+{
+ /* Insert a fake EOI marker. */
+ struct jpeg_source_mgr *src = cinfo->src;
+ static JOCTET buffer[2];
+
+ buffer[0] = (JOCTET) 0xFF;
+ buffer[1] = (JOCTET) JPEG_EOI;
+
+ src->next_input_byte = buffer;
+ src->bytes_in_buffer = 2;
+ return TRUE;
+}
+
+
+/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
+ is the JPEG data source manager. */
+
+static void
+our_skip_input_data (cinfo, num_bytes)
+ j_decompress_ptr cinfo;
+ long num_bytes;
+{
+ struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
+
+ if (src)
+ {
+ if (num_bytes > src->bytes_in_buffer)
+ ERREXIT (cinfo, JERR_INPUT_EOF);
+
+ src->bytes_in_buffer -= num_bytes;
+ src->next_input_byte += num_bytes;
+ }
}
-struct my_jpeg_error_mgr
+
+/* Method to terminate data source. Called by
+ jpeg_finish_decompress() after all data has been processed. */
+
+static void
+our_term_source (cinfo)
+ j_decompress_ptr cinfo;
{
- struct jpeg_error_mgr pub;
- jmp_buf setjmp_buffer;
-};
+}
+
+
+/* Set up the JPEG lib for reading an image from DATA which contains
+ LEN bytes. CINFO is the decompression info structure created for
+ reading the image. */
static void
-my_error_exit (cinfo)
- j_common_ptr cinfo;
+jpeg_memory_src (cinfo, data, len)
+ j_decompress_ptr cinfo;
+ JOCTET *data;
+ unsigned int len;
{
- struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
- longjmp (mgr->setjmp_buffer, 1);
+ struct jpeg_source_mgr *src;
+
+ if (cinfo->src == NULL)
+ {
+ /* First time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof (struct jpeg_source_mgr));
+ src = (struct jpeg_source_mgr *) cinfo->src;
+ src->next_input_byte = data;
+ }
+
+ src = (struct jpeg_source_mgr *) cinfo->src;
+ src->init_source = our_init_source;
+ src->fill_input_buffer = our_fill_input_buffer;
+ src->skip_input_data = our_skip_input_data;
+ src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
+ src->term_source = our_term_source;
+ src->bytes_in_buffer = len;
+ src->next_input_byte = data;
}
+
/* Load image IMG for use on frame F. Patterned after example.c
from the JPEG lib. */
struct jpeg_decompress_struct cinfo;
struct my_jpeg_error_mgr mgr;
Lisp_Object file, specified_file;
- FILE *fp;
+ Lisp_Object specified_data;
+ FILE *fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
XImage *ximg = NULL;
/* Open the JPEG file. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = x_find_image_file (specified_file);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
GCPRO1 (file);
- if (!STRINGP (file))
+
+ if (NILP (specified_data))
{
- image_error ("Cannot find image file %s", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
- fp = fopen (XSTRING (file)->data, "r");
- if (fp == NULL)
- {
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
+ fp = fopen (XSTRING (file)->data, "r");
+ if (fp == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
}
- /* Customize libjpeg's error handling to call my_error_exit
- when an error is detected. This function will perform
- a longjmp. */
+ /* 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);
/* Called from my_error_exit. Display a JPEG error. */
char buffer[JMSG_LENGTH_MAX];
cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
- image_error ("Error reading JPEG file `%s': %s", file,
+ image_error ("Error reading JPEG image `%s': %s", img->spec,
build_string (buffer));
}
/* Close the input file and destroy the JPEG object. */
- fclose (fp);
+ if (fp)
+ fclose (fp);
jpeg_destroy_decompress (&cinfo);
BLOCK_INPUT;
}
/* Create the JPEG decompression object. Let it read from fp.
- Read the JPEG image header. */
+ Read the JPEG image header. */
jpeg_create_decompress (&cinfo);
- jpeg_stdio_src (&cinfo, fp);
+
+ if (NILP (specified_data))
+ jpeg_stdio_src (&cinfo, fp);
+ else
+ jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
+ STRING_BYTES (XSTRING (specified_data)));
+
jpeg_read_header (&cinfo, TRUE);
/* Customize decompression so that color quantization will be used.
- Start decompression. */
+ Start decompression. */
cinfo.quantize_colors = TRUE;
jpeg_start_decompress (&cinfo);
width = img->width = cinfo.output_width;
BLOCK_INPUT;
/* Create X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
- &img->pixmap))
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
UNBLOCK_INPUT;
longjmp (mgr.setjmp_buffer, 2);
/* Clean up. */
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
- fclose (fp);
+ if (fp)
+ fclose (fp);
/* Put the image into the pixmap. */
x_put_x_image (f, ximg, img->pixmap, width, height);
enum tiff_keyword_index
{
TIFF_TYPE,
+ TIFF_DATA,
TIFF_FILE,
TIFF_ASCENT,
TIFF_MARGIN,
static struct image_keyword tiff_format[TIFF_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
struct image_keyword fmt[TIFF_LAST];
bcopy (tiff_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff, 1)
+ if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
|| (fmt[TIFF_ASCENT].count
&& XFASTINT (fmt[TIFF_ASCENT].value) > 100))
return 0;
- return 1;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
+}
+
+
+/* Reading from a memory buffer for TIFF images Based on the PNG
+ memory source, but we have to provide a lot of extra functions.
+ Blah.
+
+ We really only need to implement read and seek, but I am not
+ convinced that the TIFF library is smart enough not to destroy
+ itself if we only hand it the function pointers we need to
+ override. */
+
+typedef struct
+{
+ unsigned char *bytes;
+ size_t len;
+ int index;
+}
+tiff_memory_source;
+
+static size_t
+tiff_read_from_memory (data, buf, size)
+ thandle_t data;
+ tdata_t buf;
+ tsize_t size;
+{
+ tiff_memory_source *src = (tiff_memory_source *) data;
+
+ if (size > src->len - src->index)
+ return (size_t) -1;
+ bcopy (src->bytes + src->index, buf, size);
+ src->index += size;
+ return size;
+}
+
+static size_t
+tiff_write_from_memory (data, buf, size)
+ thandle_t data;
+ tdata_t buf;
+ tsize_t size;
+{
+ return (size_t) -1;
+}
+
+static toff_t
+tiff_seek_in_memory (data, off, whence)
+ thandle_t data;
+ toff_t off;
+ int whence;
+{
+ tiff_memory_source *src = (tiff_memory_source *) data;
+ int idx;
+
+ switch (whence)
+ {
+ case SEEK_SET: /* Go from beginning of source. */
+ idx = off;
+ break;
+
+ case SEEK_END: /* Go from end of source. */
+ idx = src->len + off;
+ break;
+
+ case SEEK_CUR: /* Go from current position. */
+ idx = src->index + off;
+ break;
+
+ default: /* Invalid `whence'. */
+ return -1;
+ }
+
+ if (idx > src->len || idx < 0)
+ return -1;
+
+ src->index = idx;
+ return src->index;
+}
+
+static int
+tiff_close_memory (data)
+ thandle_t data;
+{
+ /* NOOP */
+ return 0;
+}
+
+static int
+tiff_mmap_memory (data, pbase, psize)
+ thandle_t data;
+ tdata_t *pbase;
+ toff_t *psize;
+{
+ /* It is already _IN_ memory. */
+ return 0;
+}
+
+static void
+tiff_unmap_memory (data, base, size)
+ thandle_t data;
+ tdata_t base;
+ toff_t size;
+{
+ /* We don't need to do this. */
}
+static toff_t
+tiff_size_of_memory (data)
+ thandle_t data;
+{
+ return ((tiff_memory_source *) data)->len;
+}
/* Load TIFF image IMG for use on frame F. Value is non-zero if
successful. */
struct image *img;
{
Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
TIFF *tiff;
int width, height, x, y;
uint32 *buf;
int rc;
XImage *ximg;
struct gcpro gcpro1;
+ tiff_memory_source memsrc;
specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = x_find_image_file (specified_file);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
GCPRO1 (file);
- if (!STRINGP (file))
+
+ if (NILP (specified_data))
{
- image_error ("Cannot find image file %s", file, Qnil);
- UNGCPRO;
- return 0;
+ /* Read from a file */
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Try to open the image file. */
+ tiff = TIFFOpen (XSTRING (file)->data, "r");
+ if (tiff == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
}
-
- /* Try to open the image file. */
- tiff = TIFFOpen (XSTRING (file)->data, "r");
- if (tiff == NULL)
+ else
{
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
+ /* Memory source! */
+ memsrc.bytes = XSTRING (specified_data)->data;
+ memsrc.len = STRING_BYTES (XSTRING (specified_data));
+ memsrc.index = 0;
+
+ tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
+ (TIFFReadWriteProc) tiff_read_from_memory,
+ (TIFFReadWriteProc) tiff_write_from_memory,
+ tiff_seek_in_memory,
+ tiff_close_memory,
+ tiff_size_of_memory,
+ tiff_mmap_memory,
+ tiff_unmap_memory);
+
+ if (!tiff)
+ {
+ image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
}
/* Get width and height of the image, and allocate a raster buffer
TIFFClose (tiff);
if (!rc)
{
- image_error ("Error reading `%s'", file, Qnil);
+ image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
xfree (buf);
UNGCPRO;
return 0;
BLOCK_INPUT;
/* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
- &img->pixmap))
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
UNBLOCK_INPUT;
xfree (buf);
enum gif_keyword_index
{
GIF_TYPE,
+ GIF_DATA,
GIF_FILE,
GIF_ASCENT,
GIF_MARGIN,
static struct image_keyword gif_format[GIF_LAST] =
{
{":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
{":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
NULL
};
-
/* Return non-zero if OBJECT is a valid GIF image specification. */
static int
struct image_keyword fmt[GIF_LAST];
bcopy (gif_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, GIF_LAST, Qgif, 1)
+ if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
|| (fmt[GIF_ASCENT].count
&& XFASTINT (fmt[GIF_ASCENT].value) > 100))
return 0;
- return 1;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
+}
+
+/* Reading a GIF image from memory
+ Based on the PNG memory stuff to a certain extent. */
+
+typedef struct
+{
+ unsigned char *bytes;
+ size_t len;
+ int index;
+}
+gif_memory_source;
+
+/* Make the current memory source available to gif_read_from_memory.
+ It's done this way because not all versions of libungif support
+ a UserData field in the GifFileType structure. */
+static gif_memory_source *current_gif_memory_src;
+
+static int
+gif_read_from_memory (file, buf, len)
+ GifFileType *file;
+ GifByteType *buf;
+ int len;
+{
+ gif_memory_source *src = current_gif_memory_src;
+
+ if (len > src->len - src->index)
+ return -1;
+
+ bcopy (src->bytes + src->index, buf, len);
+ src->index += len;
+ return len;
}
struct image *img;
{
Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
int rc, width, height, x, y, i;
XImage *ximg;
ColorMapObject *gif_color_map;
struct gcpro gcpro1;
Lisp_Object image;
int ino, image_left, image_top, image_width, image_height;
+ gif_memory_source memsrc;
+ unsigned char *raster;
specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = x_find_image_file (specified_file);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
GCPRO1 (file);
- if (!STRINGP (file))
+
+ if (NILP (specified_data))
{
- image_error ("Cannot find image file %s", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
- /* Open the GIF file. */
- gif = DGifOpenFileName (XSTRING (file)->data);
- if (gif == NULL)
+ /* Open the GIF file. */
+ gif = DGifOpenFileName (XSTRING (file)->data);
+ if (gif == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+ else
{
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
+ /* Read from memory! */
+ current_gif_memory_src = &memsrc;
+ memsrc.bytes = XSTRING (specified_data)->data;
+ memsrc.len = STRING_BYTES (XSTRING (specified_data));
+ memsrc.index = 0;
+
+ gif = DGifOpen(&memsrc, gif_read_from_memory);
+ if (!gif)
+ {
+ image_error ("Cannot open memory source `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
}
/* Read entire contents. */
rc = DGifSlurp (gif);
if (rc == GIF_ERROR)
{
- image_error ("Error reading `%s'", file, Qnil);
+ image_error ("Error reading `%s'", img->spec, Qnil);
DGifCloseFile (gif);
UNGCPRO;
return 0;
ino = INTEGERP (image) ? XFASTINT (image) : 0;
if (ino >= gif->ImageCount)
{
- image_error ("Invalid image number `%s'", image, Qnil);
+ image_error ("Invalid image number `%s' in image `%s'",
+ image, img->spec);
DGifCloseFile (gif);
UNGCPRO;
return 0;
BLOCK_INPUT;
/* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
- &img->pixmap))
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
UNBLOCK_INPUT;
DGifCloseFile (gif);
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
- /* Read the GIF image into the X image. */
+ /* Read the GIF image into the X image. We use a local variable
+ `raster' here because RasterBits below is a char *, and invites
+ problems with bytes >= 0x80. */
+ raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+
if (gif->SavedImages[ino].ImageDesc.Interlace)
{
static int interlace_start[] = {0, 4, 2, 1};
static int interlace_increment[] = {8, 8, 4, 2};
int pass, inc;
+ int row = interlace_start[0];
+
+ pass = 0;
- for (pass = 0; pass < 4; ++pass)
+ for (y = 0; y < image_height; y++)
{
- inc = interlace_increment[pass];
- for (y = interlace_start[pass]; y < image_height; y += inc)
- for (x = 0; x < image_width; ++x)
- {
- unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
- XPutPixel (ximg, x + image_left, y + image_top,
- pixel_colors[i]);
- }
+ if (row >= image_height)
+ {
+ row = interlace_start[++pass];
+ while (row >= image_height)
+ row = interlace_start[++pass];
+ }
+
+ for (x = 0; x < image_width; x++)
+ {
+ int i = raster[(y * image_width) + x];
+ XPutPixel (ximg, x + image_left, row + image_top,
+ pixel_colors[i]);
+ }
+
+ row += interlace_increment[pass];
}
}
else
for (y = 0; y < image_height; ++y)
for (x = 0; x < image_width; ++x)
{
- unsigned i = gif->SavedImages[ino].RasterBits[y * image_width + x];
+ int i = raster[y * image_width + x];
XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
}
}
bcopy (gs_format, fmt, sizeof fmt);
- if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript, 1)
+ if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
|| (fmt[GS_ASCENT].count
&& XFASTINT (fmt[GS_ASCENT].value) > 100))
return 0;
if (!img->pixmap)
{
- image_error ("Unable to create pixmap for `%s'",
- image_spec_value (img->spec, QCfile, NULL), Qnil);
+ image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
return 0;
}
/* On displays with a mutable colormap, figure out the colors
allocated for the image by looking at the pixels of an XImage for
img->pixmap. */
- class = FRAME_X_DISPLAY_INFO (f)->visual->class;
+ class = FRAME_X_VISUAL (f)->class;
if (class != StaticColor && class != StaticGray && class != TrueColor)
{
XImage *ximg;
allocated colors on behalf of us. So, to get the
reference counts right, free them once. */
if (img->ncolors)
- {
- Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- XFreeColors (FRAME_X_DISPLAY (f), cmap,
- img->colors, img->ncolors, 0);
- }
+ x_free_colors (f, img->colors, img->ncolors);
#endif
}
else
image_error ("Cannot get X image of `%s'; colors will not be freed",
- image_spec_value (img->spec, QCfile, NULL), Qnil);
+ img->spec, Qnil);
UNBLOCK_INPUT;
}
Busy cursor
***********************************************************************/
-/* The implementation partly follows a patch from
- F.Pierresteguy@frcl.bull.fr dated 1994. */
+/* If non-null, an asynchronous timer that, when it expires, displays
+ a busy cursor on all frames. */
-/* Setting inhibit_busy_cursor to 2 inhibits busy-cursor display until
- the next X event is read and we enter XTread_socket again. Setting
- it to 1 inhibits busy-cursor display for direct commands. */
+static struct atimer *busy_cursor_atimer;
-int inhibit_busy_cursor;
+/* Non-zero means a busy cursor is currently shown. */
-/* Incremented with each call to x-display-busy-cursor.
- Decremented in x-undisplay-busy-cursor. */
+static int busy_cursor_shown_p;
-static int busy_count;
+/* Number of seconds to wait before displaying a busy cursor. */
+static Lisp_Object Vbusy_cursor_delay;
-DEFUN ("x-show-busy-cursor", Fx_show_busy_cursor,
- Sx_show_busy_cursor, 0, 0, 0,
- "Show a busy cursor, if not already shown.\n\
-Each call to this function must be matched by a call to\n\
-x-undisplay-busy-cursor to make the busy pointer disappear again.")
- ()
+/* Default number of seconds to wait before displaying a busy
+ cursor. */
+
+#define DEFAULT_BUSY_CURSOR_DELAY 1
+
+/* Function prototypes. */
+
+static void show_busy_cursor P_ ((struct atimer *));
+static void hide_busy_cursor P_ ((void));
+
+
+/* Cancel a currently active busy-cursor timer, and start a new one. */
+
+void
+start_busy_cursor ()
{
- ++busy_count;
- if (busy_count == 1)
+ EMACS_TIME delay;
+ int secs, usecs = 0;
+
+ cancel_busy_cursor ();
+
+ if (INTEGERP (Vbusy_cursor_delay)
+ && XINT (Vbusy_cursor_delay) > 0)
+ secs = XFASTINT (Vbusy_cursor_delay);
+ else if (FLOATP (Vbusy_cursor_delay)
+ && XFLOAT_DATA (Vbusy_cursor_delay) > 0)
{
- Lisp_Object rest, frame;
+ Lisp_Object tem;
+ tem = Ftruncate (Vbusy_cursor_delay, Qnil);
+ secs = XFASTINT (tem);
+ usecs = (XFLOAT_DATA (Vbusy_cursor_delay) - secs) * 1000000;
+ }
+ else
+ secs = DEFAULT_BUSY_CURSOR_DELAY;
+
+ EMACS_SET_SECS_USECS (delay, secs, usecs);
+ busy_cursor_atimer = start_atimer (ATIMER_RELATIVE, delay,
+ show_busy_cursor, NULL);
+}
+
+
+/* Cancel the busy cursor timer if active, hide a busy cursor if
+ shown. */
+
+void
+cancel_busy_cursor ()
+{
+ if (busy_cursor_atimer)
+ {
+ cancel_atimer (busy_cursor_atimer);
+ busy_cursor_atimer = NULL;
+ }
+
+ if (busy_cursor_shown_p)
+ hide_busy_cursor ();
+}
+
+
+/* Timer function of busy_cursor_atimer. TIMER is equal to
+ busy_cursor_atimer.
+ Display a busy cursor on all frames by mapping the frames'
+ busy_window. Set the busy_p flag in the frames' output_data.x
+ structure to indicate that a busy cursor is shown on the
+ frames. */
+
+static void
+show_busy_cursor (timer)
+ struct atimer *timer;
+{
+ /* The timer implementation will cancel this timer automatically
+ after this function has run. Set busy_cursor_atimer to null
+ so that we know the timer doesn't have to be canceled. */
+ busy_cursor_atimer = NULL;
+
+ if (!busy_cursor_shown_p)
+ {
+ Lisp_Object rest, frame;
+
+ BLOCK_INPUT;
+
FOR_EACH_FRAME (rest, frame)
if (FRAME_X_P (XFRAME (frame)))
{
struct frame *f = XFRAME (frame);
-
- BLOCK_INPUT;
+
f->output_data.x->busy_p = 1;
-
+
if (!f->output_data.x->busy_window)
{
unsigned long mask = CWCursor;
XSetWindowAttributes attrs;
-
+
attrs.cursor = f->output_data.x->busy_cursor;
+
f->output_data.x->busy_window
= XCreateWindow (FRAME_X_DISPLAY (f),
FRAME_OUTER_WINDOW (f),
0, 0, 32000, 32000, 0, 0,
- InputOnly, CopyFromParent,
+ InputOnly,
+ CopyFromParent,
mask, &attrs);
}
-
+
XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
- UNBLOCK_INPUT;
+ XFlush (FRAME_X_DISPLAY (f));
}
- }
- return Qnil;
+ busy_cursor_shown_p = 1;
+ UNBLOCK_INPUT;
+ }
}
-DEFUN ("x-hide-busy-cursor", Fx_hide_busy_cursor,
- Sx_hide_busy_cursor, 0, 1, 0,
- "Hide a busy-cursor.\n\
-A busy-cursor will actually be undisplayed when a matching\n\
-`x-undisplay-busy-cursor' is called for each `x-display-busy-cursor'\n\
-issued. FORCE non-nil means undisplay the busy-cursor forcibly,\n\
-not counting calls.")
- (force)
- Lisp_Object force;
-{
- Lisp_Object rest, frame;
-
- if (busy_count == 0)
- return Qnil;
-
- if (!NILP (force) && busy_count != 0)
- busy_count = 1;
-
- --busy_count;
- if (busy_count != 0)
- return Qnil;
+/* Hide the busy cursor on all frames, if it is currently shown. */
- FOR_EACH_FRAME (rest, frame)
+static void
+hide_busy_cursor ()
+{
+ if (busy_cursor_shown_p)
{
- struct frame *f = XFRAME (frame);
-
- if (FRAME_X_P (f)
- /* Watch out for newly created frames. */
- && f->output_data.x->busy_window)
+ Lisp_Object rest, frame;
+
+ BLOCK_INPUT;
+ FOR_EACH_FRAME (rest, frame)
{
-
- BLOCK_INPUT;
- XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
- /* Sync here because XTread_socket looks at the busy_p flag
- that is reset to zero below. */
- XSync (FRAME_X_DISPLAY (f), False);
- UNBLOCK_INPUT;
- f->output_data.x->busy_p = 0;
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_X_P (f)
+ /* Watch out for newly created frames. */
+ && f->output_data.x->busy_window)
+ {
+ XUnmapWindow (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
+ /* Sync here because XTread_socket looks at the busy_p flag
+ that is reset to zero below. */
+ XSync (FRAME_X_DISPLAY (f), False);
+ f->output_data.x->busy_p = 0;
+ }
}
- }
- return Qnil;
+ busy_cursor_shown_p = 0;
+ UNBLOCK_INPUT;
+ }
}
BLOCK_INPUT;
mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
- /* Window managers looks at the override-redirect flag to
- determine whether or net to give windows a decoration (Xlib
+ /* Window managers look at the override-redirect flag to determine
+ whether or net to give windows a decoration (Xlib spec, chapter
3.2.8). */
attrs.override_redirect = True;
attrs.save_under = True;
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;
+ Lisp_Object string, frame, parms, timeout;
{
struct frame *f;
struct window *w;
int i, width, height;
int root_x, root_y, win_x, win_y;
unsigned pmask;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
int count = specpdl_ptr - specpdl;
specbind (Qinhibit_redisplay, Qt);
- GCPRO3 (string, parms, frame);
+ GCPRO4 (string, parms, frame, timeout);
CHECK_STRING (string, 0);
f = check_x_frame (frame);
/* Let the tip disappear after timeout seconds. */
tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
intern ("x-hide-tip"));
-
+
+ UNGCPRO;
return unbind_to (count, Qnil);
}
staticpro (&Quser_position);
Quser_size = intern ("user-size");
staticpro (&Quser_size);
- Qdisplay = intern ("display");
- staticpro (&Qdisplay);
Qscroll_bar_foreground = intern ("scroll-bar-foreground");
staticpro (&Qscroll_bar_foreground);
Qscroll_bar_background = intern ("scroll-bar-background");
staticpro (&Qscreen_gamma);
/* This is the end of symbol initialization. */
+ /* Text property `display' should be nonsticky by default. */
+ Vtext_property_default_nonsticky
+ = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
+
+
Qlaplace = intern ("laplace");
staticpro (&Qlaplace);
"Non-zero means Emacs displays a busy cursor on window systems.");
display_busy_cursor_p = 1;
+ DEFVAR_LISP ("busy-cursor-delay", &Vbusy_cursor_delay,
+ "*Seconds to wait before displaying a busy-cursor.\n\
+Value must be an integer or float.");
+ Vbusy_cursor_delay = make_number (DEFAULT_BUSY_CURSOR_DELAY);
+
#if 0 /* This doesn't really do anything. */
DEFVAR_LISP ("x-mode-pointer-shape", &Vx_mode_pointer_shape,
"The shape of the pointer when over the mode line.\n\
defsubr (&Sx_delete_window_property);
defsubr (&Sx_window_property);
-#if 0
- defsubr (&Sx_draw_rectangle);
- defsubr (&Sx_erase_rectangle);
- defsubr (&Sx_contour_region);
- defsubr (&Sx_uncontour_region);
-#endif
- defsubr (&Sx_display_color_p);
+ defsubr (&Sxw_display_color_p);
defsubr (&Sx_display_grayscale_p);
- defsubr (&Sx_color_defined_p);
- defsubr (&Sx_color_values);
+ defsubr (&Sxw_color_defined_p);
+ defsubr (&Sxw_color_values);
defsubr (&Sx_server_max_request_size);
defsubr (&Sx_server_vendor);
defsubr (&Sx_server_version);
defsubr (&Sx_display_visual_class);
defsubr (&Sx_display_backing_store);
defsubr (&Sx_display_save_under);
-#if 0
- defsubr (&Sx_rebind_key);
- defsubr (&Sx_rebind_keys);
- defsubr (&Sx_track_pointer);
- defsubr (&Sx_grab_pointer);
- defsubr (&Sx_ungrab_pointer);
-#endif
defsubr (&Sx_parse_geometry);
defsubr (&Sx_create_frame);
-#if 0
- defsubr (&Sx_horizontal_line);
-#endif
defsubr (&Sx_open_connection);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
+ defsubr (&Sx_focus_frame);
/* Setting callback functions for fontset handler. */
get_font_info_func = x_get_font_info;
staticpro (&QCheuristic_mask);
QCcolor_symbols = intern (":color-symbols");
staticpro (&QCcolor_symbols);
- QCdata = intern (":data");
- staticpro (&QCdata);
QCascent = intern (":ascent");
staticpro (&QCascent);
QCmargin = intern (":margin");
defsubr (&Slookup_image);
#endif
- /* Busy-cursor. */
- defsubr (&Sx_show_busy_cursor);
- defsubr (&Sx_hide_busy_cursor);
- busy_count = 0;
- inhibit_busy_cursor = 0;
+ busy_cursor_atimer = NULL;
+ busy_cursor_shown_p = 0;
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);