/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+ Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef HAVE_X_WINDOWS
+#define DOC_STRINGS_IN_COMMENTS
#include "lisp.h"
#include "blockinput.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
-#if 0
-#include "sink.h"
-#include "sinkmask.h"
-#endif /* ! 0 */
#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "intervals.h"
#include "process.h"
#include "atimer.h"
+#include "keymap.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
#include <unistd.h>
#endif
+#ifdef USE_LUCID
+extern int xlwmenu_window_p (Widget w, Window window);
+extern void xlwmenu_redisplay P_ ((Widget));
+#endif
+
#ifdef USE_X_TOOLKIT
extern void free_frame_menubar P_ ((struct frame *));
#if defined USE_MOTIF
#include <Xm/Xm.h> /* for LESSTIF_VERSION */
#include <Xm/ScrollBar.h>
-#include <Xm/ScrollBarP.h>
#else /* !USE_MOTIF i.e. use Xaw */
#ifdef HAVE_XAW3D
#endif
#endif
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
#define abs(x) ((x) < 0 ? -(x) : (x))
#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
extern Lisp_Object Qhelp_echo;
\f
-/* Non-zero means Emacs uses toolkit scroll bars. */
+/* Non-nil means Emacs uses toolkit scroll bars. */
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
int x_stretch_cursor_p;
+/* Non-zero means make use of UNDERLINE_POSITION font properties. */
+
+int x_use_underline_position_properties;
+
/* This is a chain of structures for all the X displays currently in
use. */
DRAW_IMAGE_SUNKEN
};
-static const XColor *x_color_cells P_ ((struct frame *, int *));
+static int cursor_in_mouse_face_p P_ ((struct window *));
+static int clear_mouse_face P_ ((struct x_display_info *));
+static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
+static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
+static const XColor *x_color_cells P_ ((Display *, int *));
static void x_update_window_end P_ ((struct window *, int, int));
static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
void x_delete_display P_ ((struct x_display_info *));
static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
unsigned));
static int fast_find_position P_ ((struct window *, int, int *, int *,
- int *, int *));
+ int *, int *, Lisp_Object));
+static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
+ int *, int *, int *, int *, int));
static void set_output_cursor P_ ((struct cursor_pos *));
static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
- int *, int *, int *));
+ int *, int *, int *, int));
static void note_mode_line_highlight P_ ((struct window *, int, int));
static void note_mouse_highlight P_ ((struct frame *, int, int));
static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
XRectangle *));
static void expose_frame P_ ((struct frame *, int, int, int, int));
-static void expose_window_tree P_ ((struct window *, XRectangle *));
-static void expose_window P_ ((struct window *, XRectangle *));
+static int expose_window_tree P_ ((struct window *, XRectangle *));
+static int expose_window P_ ((struct window *, XRectangle *));
static void expose_area P_ ((struct window *, struct glyph_row *,
XRectangle *, enum glyph_row_area));
-static void expose_line P_ ((struct window *, struct glyph_row *,
+static int expose_line P_ ((struct window *, struct glyph_row *,
XRectangle *));
static void x_update_cursor_in_window_tree P_ ((struct window *, int));
static void x_update_window_cursor P_ ((struct window *, int));
GC, int));
static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
-static void note_overwritten_text_cursor P_ ((struct window *, int, int));
+static void notice_overwritten_cursor P_ ((struct window *, int, int));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
static void x_after_update_window_line P_ ((struct glyph_row *));
static INLINE void take_vertical_position_into_account P_ ((struct it *));
static void x_produce_stretch_glyph P_ ((struct it *));
-
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
+ enum scroll_bar_part *,
+ Lisp_Object *, Lisp_Object *,
+ unsigned long *));
/* Flush display of frame F, or of all frames if F is null. */
struct window *w;
int cursor_on_p, mouse_face_overwritten_p;
{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+
if (!w->pseudo_window_p)
{
- struct x_display_info *dpyinfo
- = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
-
BLOCK_INPUT;
- /* If a row with mouse-face was overwritten, arrange for
- XTframe_up_to_date to redisplay the mouse highlight. */
- if (mouse_face_overwritten_p)
- {
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-
if (cursor_on_p)
x_display_and_set_cursor (w, 1, output_cursor.hpos,
output_cursor.vpos,
UNBLOCK_INPUT;
}
+ /* If a row with mouse-face was overwritten, arrange for
+ XTframe_up_to_date to redisplay the mouse highlight. */
+ if (mouse_face_overwritten_p)
+ {
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ }
+
updated_window = NULL;
}
if (!desired_row->mode_line_p && !w->pseudo_window_p)
{
+ struct frame *f;
+ int width;
+
BLOCK_INPUT;
x_draw_row_bitmaps (w, desired_row);
/* When a window has disappeared, make sure that no rest of
full-width rows stays visible in the internal border. */
- if (windows_or_buffers_changed)
+ if (windows_or_buffers_changed
+ && (f = XFRAME (w->frame),
+ width = FRAME_INTERNAL_BORDER_WIDTH (f),
+ width != 0))
{
- struct frame *f = XFRAME (w->frame);
- int width = FRAME_INTERNAL_BORDER_WIDTH (f);
int height = desired_row->visible_height;
int x = (window_box_right (w, -1)
+ FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- x, y, width, height, False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ x, y, width, height, False);
}
UNBLOCK_INPUT;
prepare_image_for_display (it->f, img);
it->ascent = it->phys_ascent = image_ascent (img, face);
- it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
- it->pixel_width = img->width + 2 * img->margin;
+ it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+ it->pixel_width = img->width + 2 * img->hmargin;
it->nglyphs = 1;
if (face->box != FACE_NO_BOX)
{
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
+ if (face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
if (it->start_of_box_run_p)
- it->pixel_width += face->box_line_width;
+ it->pixel_width += abs (face->box_line_width);
if (it->end_of_box_run_p)
- it->pixel_width += face->box_line_width;
+ it->pixel_width += abs (face->box_line_width);
}
take_vertical_position_into_account (it);
if (face->box != FACE_NO_BOX)
{
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
+ if (face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
if (it->start_of_box_run_p)
- it->pixel_width += face->box_line_width;
+ it->pixel_width += abs (face->box_line_width);
if (it->end_of_box_run_p)
- it->pixel_width += face->box_line_width;
+ it->pixel_width += abs (face->box_line_width);
}
take_vertical_position_into_account (it);
struct glyph because the character code itself tells if or
not the character is multibyte. Thus, in the future, we must
consider eliminating the field `multibyte_p' in the struct
- glyph.
- */
+ glyph. */
int saved_multibyte_p = it->multibyte_p;
/* Maybe translate single-byte characters to multibyte, or the
else if (!SINGLE_BYTE_CHAR_P (it->c)
&& !it->multibyte_p)
{
- it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
- it->multibyte_p = 0;
+ it->multibyte_p = 1;
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
{
int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
-
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = -thick;
+
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->ascent = it->phys_ascent = font->ascent + boff;
it->descent = it->phys_descent = font->descent - boff;
- if (face->box != FACE_NO_BOX)
+ if (face->box != FACE_NO_BOX
+ && face->box_line_width > 0)
{
- int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
}
}
else if (it->char_to_display == '\t')
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
+
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = - thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
+
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = - thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
{
if (face->font)
height = FONT_HEIGHT (face->font);
- height += 2 * face->box_line_width;
+ if (face->box_line_width > 0)
+ height += 2 * face->box_line_width;
}
}
};
-#if 0
+#if GLYPH_DEBUG
static void
x_dump_glyph_string (s)
int face_id;
struct face *face;
- /* What face has to be used for the mouse face? */
+ /* What face has to be used last for the mouse face? */
face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
face = FACE_FROM_ID (s->f, face_id);
+ if (face == NULL)
+ face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+
if (s->first_glyph->type == CHAR_GLYPH)
face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
else
r->height = s->row->visible_height;
}
- /* Don't use S->y for clipping because it doesn't take partially
- visible lines into account. For example, it can be negative for
- partially visible lines at the top of a window. */
- if (!s->row->full_width_p
- && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
- r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
- else
- r->y = max (0, s->row->y);
-
- /* If drawing a tool-bar window, draw it over the internal border
- at the top of the window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
- r->y -= s->f->output_data.x->internal_border_width;
-
/* If S draws overlapping rows, it's sufficient to use the top and
bottom of the window for clipping because this glyph string
intentionally draws over other lines. */
r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
r->height = window_text_bottom_y (s->w) - r->y;
}
-
+ else
+ {
+ /* Don't use S->y for clipping because it doesn't take partially
+ visible lines into account. For example, it can be negative for
+ partially visible lines at the top of a window. */
+ if (!s->row->full_width_p
+ && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
+ r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+ else
+ r->y = max (0, s->row->y);
+
+ /* If drawing a tool-bar window, draw it over the internal border
+ at the top of the window. */
+ if (s->w == XWINDOW (s->f->tool_bar_window))
+ r->y -= s->f->output_data.x->internal_border_width;
+ }
+
r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
}
shouldn't be drawn in the first place. */
if (!s->background_filled_p)
{
+ int box_line_width = max (s->face->box_line_width, 0);
+
if (s->stippled_p)
{
/* Fill background with a stipple pattern. */
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, s->gc, s->x,
- s->y + s->face->box_line_width,
+ s->y + box_line_width,
s->background_width,
- s->height - 2 * s->face->box_line_width);
+ s->height - 2 * box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
s->background_filled_p = 1;
}
- else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
+ else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| force_p)
{
- x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
+ x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
- s->height - 2 * s->face->box_line_width);
+ s->height - 2 * box_line_width);
s->background_filled_p = 1;
}
}
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
+ x = s->x + abs (s->face->box_line_width);
else
x = s->x;
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
+ x = s->x + abs (s->face->box_line_width);
else
x = s->x;
#ifdef USE_X_TOOLKIT
static struct frame *x_frame_of_widget P_ ((Widget));
+static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
+ XrmValue *, XrmValue *, XtPointer *));
+static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
+ XrmValue *, Cardinal *));
/* Return the frame on which widget WIDGET is used.. Abort if frame
}
+/* Structure specifying which arguments should be passed by Xt to
+ cvt_string_to_pixel. We want the widget's screen and colormap. */
+
+static XtConvertArgRec cvt_string_to_pixel_args[] =
+ {
+ {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
+ sizeof (Screen *)},
+ {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
+ sizeof (Colormap)}
+ };
+
+
+/* The address of this variable is returned by
+ cvt_string_to_pixel. */
+
+static Pixel cvt_string_to_pixel_value;
+
+
+/* Convert a color name to a pixel color.
+
+ DPY is the display we are working on.
+
+ ARGS is an array of *NARGS XrmValue structures holding additional
+ information about the widget for which the conversion takes place.
+ The contents of this array are determined by the specification
+ in cvt_string_to_pixel_args.
+
+ FROM is a pointer to an XrmValue which points to the color name to
+ convert. TO is an XrmValue in which to return the pixel color.
+
+ CLOSURE_RET is a pointer to user-data, in which we record if
+ we allocated the color or not.
+
+ Value is True if successful, False otherwise. */
+
+static Boolean
+cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
+ Display *dpy;
+ XrmValue *args;
+ Cardinal *nargs;
+ XrmValue *from, *to;
+ XtPointer *closure_ret;
+{
+ Screen *screen;
+ Colormap cmap;
+ Pixel pixel;
+ String color_name;
+ XColor color;
+
+ if (*nargs != 2)
+ {
+ XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+ "wrongParameters", "cvt_string_to_pixel",
+ "XtToolkitError",
+ "Screen and colormap args required", NULL, NULL);
+ return False;
+ }
+
+ screen = *(Screen **) args[0].addr;
+ cmap = *(Colormap *) args[1].addr;
+ color_name = (String) from->addr;
+
+ if (strcmp (color_name, XtDefaultBackground) == 0)
+ {
+ *closure_ret = (XtPointer) False;
+ pixel = WhitePixelOfScreen (screen);
+ }
+ else if (strcmp (color_name, XtDefaultForeground) == 0)
+ {
+ *closure_ret = (XtPointer) False;
+ pixel = BlackPixelOfScreen (screen);
+ }
+ else if (XParseColor (dpy, cmap, color_name, &color)
+ && x_alloc_nearest_color_1 (dpy, cmap, &color))
+ {
+ pixel = color.pixel;
+ *closure_ret = (XtPointer) True;
+ }
+ else
+ {
+ String params[1];
+ Cardinal nparams = 1;
+
+ params[0] = color_name;
+ XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
+ "badValue", "cvt_string_to_pixel",
+ "XtToolkitError", "Invalid color `%s'",
+ params, &nparams);
+ return False;
+ }
+
+ if (to->addr != NULL)
+ {
+ if (to->size < sizeof (Pixel))
+ {
+ to->size = sizeof (Pixel);
+ return False;
+ }
+
+ *(Pixel *) to->addr = pixel;
+ }
+ else
+ {
+ cvt_string_to_pixel_value = pixel;
+ to->addr = (XtPointer) &cvt_string_to_pixel_value;
+ }
+
+ to->size = sizeof (Pixel);
+ return True;
+}
+
+
+/* Free a pixel color which was previously allocated via
+ cvt_string_to_pixel. This is registered as the destructor
+ for this type of resource via XtSetTypeConverter.
+
+ APP is the application context in which we work.
+
+ TO is a pointer to an XrmValue holding the color to free.
+ CLOSURE is the value we stored in CLOSURE_RET for this color
+ in cvt_string_to_pixel.
+
+ ARGS and NARGS are like for cvt_string_to_pixel. */
+
+static void
+cvt_pixel_dtor (app, to, closure, args, nargs)
+ XtAppContext app;
+ XrmValuePtr to;
+ XtPointer closure;
+ XrmValuePtr args;
+ Cardinal *nargs;
+{
+ if (*nargs != 2)
+ {
+ XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
+ "XtToolkitError",
+ "Screen and colormap arguments required",
+ NULL, NULL);
+ }
+ else if (closure != NULL)
+ {
+ /* We did allocate the pixel, so free it. */
+ Screen *screen = *(Screen **) args[0].addr;
+ Colormap cmap = *(Colormap *) args[1].addr;
+ x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
+ (Pixel *) to->addr, 1);
+ }
+}
+
+
#endif /* USE_X_TOOLKIT */
/* Value is an array of XColor structures for the contents of the
- color map of frame F. Set *NCELLS to the size of the array.
+ color map of display DPY. Set *NCELLS to the size of the array.
Note that this probably shouldn't be called for large color maps,
say a 24-bit TrueColor map. */
static const XColor *
-x_color_cells (f, ncells)
- struct frame *f;
+x_color_cells (dpy, ncells)
+ Display *dpy;
int *ncells;
{
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
if (dpyinfo->color_cells == NULL)
{
- Display *display = FRAME_X_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
+ Screen *screen = dpyinfo->screen;
int i;
dpyinfo->ncolor_cells
- = XDisplayCells (display, XScreenNumberOfScreen (screen));
+ = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
dpyinfo->color_cells
= (XColor *) xmalloc (dpyinfo->ncolor_cells
* sizeof *dpyinfo->color_cells);
for (i = 0; i < dpyinfo->ncolor_cells; ++i)
dpyinfo->color_cells[i].pixel = i;
- XQueryColors (display, FRAME_X_COLORMAP (f),
+ XQueryColors (dpy, dpyinfo->cmap,
dpyinfo->color_cells, dpyinfo->ncolor_cells);
}
}
-/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
- CMAP. If an exact match can't be allocated, try the nearest color
- available. Value is non-zero if successful. Set *COLOR to the
- color allocated. */
+/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
+ exact match can't be allocated, try the nearest color available.
+ Value is non-zero if successful. Set *COLOR to the color
+ allocated. */
-int
-x_alloc_nearest_color (f, cmap, color)
- struct frame *f;
+static int
+x_alloc_nearest_color_1 (dpy, cmap, color)
+ Display *dpy;
Colormap cmap;
XColor *color;
{
- Display *display = FRAME_X_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
int rc;
- gamma_correct (f, color);
- rc = XAllocColor (display, cmap, color);
+ rc = XAllocColor (dpy, cmap, color);
if (rc == 0)
{
/* If we got to this point, the colormap is full, so we're going
int nearest, i;
unsigned long nearest_delta = ~0;
int ncells;
- const XColor *cells = x_color_cells (f, &ncells);
+ const XColor *cells = x_color_cells (dpy, &ncells);
for (nearest = i = 0; i < ncells; ++i)
{
color->red = cells[nearest].red;
color->green = cells[nearest].green;
color->blue = cells[nearest].blue;
- rc = XAllocColor (display, cmap, color);
+ rc = XAllocColor (dpy, cmap, color);
}
else
{
/* If allocation succeeded, and the allocated pixel color is not
equal to a cached pixel color recorded earlier, there was a
change in the colormap, so clear the color cache. */
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
XColor *cached_color;
if (dpyinfo->color_cells
}
+/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
+ exact match can't be allocated, try the nearest color available.
+ Value is non-zero if successful. Set *COLOR to the color
+ allocated. */
+
+int
+x_alloc_nearest_color (f, cmap, color)
+ struct frame *f;
+ Colormap cmap;
+ XColor *color;
+{
+ gamma_correct (f, color);
+ return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
+}
+
+
/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
It's necessary to do this instead of just using PIXEL directly to
get color reference counts right. */
int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
XRectangle *clip_rect;
{
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
int i;
GC gc;
gc = f->output_data.x->white_relief.gc;
else
gc = f->output_data.x->black_relief.gc;
- XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+ XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Top. */
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
left_x + i * left_p, top_y + i,
right_x + 1 - i * right_p, top_y + i);
/* Left. */
if (left_p)
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i);
+ XDrawLine (dpy, window, gc,
+ left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
- XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+ XSetClipMask (dpy, gc, None);
if (raised_p)
gc = f->output_data.x->black_relief.gc;
else
gc = f->output_data.x->white_relief.gc;
- XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+ XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Bottom. */
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
left_x + i * left_p, bottom_y - i,
- right_x + 1 - i * right_p, bottom_y - i);
+ right_x + 2 - i * right_p, bottom_y - i);
/* Right. */
if (right_p)
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
- XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+ XSetClipMask (dpy, gc, None);
}
? s->first_glyph
: s->first_glyph + s->nchars - 1);
- width = s->face->box_line_width;
+ width = abs (s->face->box_line_width);
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
- right_x = ((s->row->full_width_p
- ? last_x - 1
- : min (last_x, s->x + s->background_width) - 1));
+ right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
+ ? last_x - 1
+ : min (last_x, s->x + s->background_width) - 1);
top_y = s->y;
bottom_y = top_y + s->height - 1;
right of that line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
+ x = s->x + abs (s->face->box_line_width);
else
x = s->x;
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->img->pixmap)
{
right of that line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
+ x = s->x + abs (s->face->box_line_width);
else
x = s->x;
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
right of that line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->face->box_line_width;
+ x = abs (s->face->box_line_width);
else
x = 0;
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
- if (s->img->margin)
- {
- x += s->img->margin;
- y += s->img->margin;
- }
+ x += s->img->hmargin;
+ y += s->img->vmargin;
if (s->img->pixmap)
{
struct glyph_string *s;
{
int x, y;
- int box_line_width = s->face->box_line_width;
- int margin = s->img->margin;
+ int box_line_hwidth = abs (s->face->box_line_width);
+ int box_line_vwidth = max (s->face->box_line_width, 0);
int height;
Pixmap pixmap = None;
- height = s->height - 2 * box_line_width;
+ height = s->height - 2 * box_line_vwidth;
/* Fill background with face under the image. Do it only if row is
taller than image or if image has a clip mask to reduce
flickering. */
s->stippled_p = s->face->stipple != 0;
if (height > s->img->height
- || margin
+ || s->img->hmargin
+ || s->img->vmargin
|| s->img->mask
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
- if (box_line_width && s->first_glyph->left_box_line_p)
- x = s->x + box_line_width;
+ if (box_line_hwidth && s->first_glyph->left_box_line_p)
+ x = s->x + box_line_hwidth;
else
x = s->x;
- y = s->y + box_line_width;
+ y = s->y + box_line_vwidth;
if (s->img->mask)
{
/* Clear rest using the GC of the original non-cursor face. */
if (width < s->background_width)
{
- GC gc = s->face->gc;
int x = s->x + width, y = s->y;
int w = s->background_width - width, h = s->height;
XRectangle r;
+ GC gc;
+ if (s->row->mouse_face_p
+ && cursor_in_mouse_face_p (s->w))
+ {
+ x_set_mouse_face_gc (s);
+ gc = s->gc;
+ }
+ else
+ gc = s->face->gc;
+
x_get_glyph_string_clip_rect (s, &r);
XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
-
+
if (s->face->stipple)
{
/* Fill background with a stipple pattern. */
}
}
}
- else
+ else if (!s->background_filled_p)
x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
s->height);
x_draw_glyph_string (s)
struct glyph_string *s;
{
+ int relief_drawn_p = 0;
+
/* If S draws into the background of its successor, draw the
background of the successor first so that S can draw into it.
This makes S->next use XDrawString instead of XDrawImageString. */
/* Set up S->gc, set clipping and draw S. */
x_set_glyph_string_gc (s);
- x_set_glyph_string_clipping (s);
+
+ /* Draw relief (if any) in advance for char/composition so that the
+ glyph string can be drawn over it. */
+ if (!s->for_overlaps_p
+ && s->face->box != FACE_NO_BOX
+ && (s->first_glyph->type == CHAR_GLYPH
+ || s->first_glyph->type == COMPOSITE_GLYPH))
+
+ {
+ x_set_glyph_string_clipping (s);
+ x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_box (s);
+ x_set_glyph_string_clipping (s);
+ relief_drawn_p = 1;
+ }
+ else
+ x_set_glyph_string_clipping (s);
switch (s->first_glyph->type)
{
ROUND ((maximum descent) / 2), with
ROUND(x) = floor (x + 0.5) */
- if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+ if (x_use_underline_position_properties
+ && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
y = s->ybase + (long) tem;
else if (s->face->font)
y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
else
- y = s->height - h;
+ y = s->y + s->height - h;
if (s->face->underline_defaulted_p)
XFillRectangle (s->display, s->window, s->gc,
}
}
- /* Draw relief. */
- if (s->face->box != FACE_NO_BOX)
+ /* Draw relief if not yet drawn. */
+ if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
}
/* Adjust base line for subscript/superscript text. */
s->ybase += voffset;
- xassert (s->face && s->face->gc);
+ /* The case that face->gc == 0 is handled when drawing the glyph
+ string by calling PREPARE_FACE_FOR_DISPLAY. */
+ xassert (s->face);
return glyph - s->row->glyphs[s->area];
}
struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
if (start == s->row->used[s->area]
- && s->hl == DRAW_NORMAL_TEXT
- && ((s->area == TEXT_AREA && s->row->fill_line_p)
- || s->face->background != default_face->background
- || s->face->stipple != default_face->stipple))
- s->extends_to_end_of_line_p = 1;
+ && s->area == TEXT_AREA
+ && ((s->hl == DRAW_NORMAL_TEXT
+ && (s->row->fill_line_p
+ || s->face->background != default_face->background
+ || s->face->stipple != default_face->stipple
+ || s->row->mouse_face_p))
+ || s->hl == DRAW_MOUSE_FACE))
+ s->extends_to_end_of_line_p = 1;
/* If S extends its face to the end of the line, set its
background_width to the distance to the right edge of the drawing
}
x += FRAME_INTERNAL_BORDER_WIDTH (f);
- last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+ last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
}
else
{
&real_start, &real_end, 0);
/* If we drew over the cursor, note that it is not visible any more. */
- note_overwritten_text_cursor (updated_window, real_start,
+ notice_overwritten_cursor (updated_window, real_start,
real_end - real_start);
UNBLOCK_INPUT;
- shift_by_width);
/* Shift right. */
- frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
+ frame_x = window_box_left (w, updated_area) + output_cursor.x;
frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc,
hpos = start - row->glyphs[updated_area];
x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
- note_overwritten_text_cursor (w, real_start, real_end - real_start);
+ notice_overwritten_cursor (w, real_start, real_end - real_start);
/* Advance the output cursor. */
output_cursor.hpos += len;
}
+/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
+ If they are <= 0, this is probably an error. */
+
+void
+x_clear_area (dpy, window, x, y, width, height, exposures)
+ Display *dpy;
+ Window window;
+ int x, y;
+ int width, height;
+ int exposures;
+{
+ xassert (width > 0 && height > 0);
+ XClearArea (dpy, window, x, y, width, height, exposures);
+}
+
+
/* Erase the current text line from the nominal cursor position
(inclusive) to pixel column TO_X (exclusive). The idea is that
everything from TO_X onward is already erased.
/* Notice if the cursor will be cleared by this operation. */
if (!updated_row->full_width_p)
- note_overwritten_text_cursor (w, output_cursor.hpos, -1);
+ notice_overwritten_cursor (w, output_cursor.hpos, -1);
from_x = output_cursor.x;
if (to_x > from_x && to_y > from_y)
{
BLOCK_INPUT;
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- from_x, from_y, to_x - from_x, to_y - from_y,
- False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ from_x, from_y, to_x - from_x, to_y - from_y,
+ False);
UNBLOCK_INPUT;
}
}
wakeup.tv_sec += (wakeup.tv_usec / 1000000);
wakeup.tv_usec %= 1000000;
- /* Keep waiting until past the time wakeup. */
- while (1)
+ /* Keep waiting until past the time wakeup or any input gets
+ available. */
+ while (! detect_input_pending ())
{
+ struct timeval current;
struct timeval timeout;
- EMACS_GET_TIME (timeout);
+ EMACS_GET_TIME (current);
- /* In effect, timeout = wakeup - timeout.
- Break if result would be negative. */
- if (timeval_subtract (&timeout, wakeup, timeout))
+ /* Break if result would be negative. */
+ if (timeval_subtract (¤t, wakeup, current))
break;
+ /* How long `select' should wait. */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 10000;
+
/* Try to wait that long--but we might wake up sooner. */
select (0, NULL, NULL, NULL, &timeout);
}
int x, y, w, h;
{
XRectangle r;
+ int mouse_face_overwritten_p = 0;
TRACE ((stderr, "expose_frame "));
}
TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
- expose_window_tree (XWINDOW (f->root_window), &r);
+ mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
if (WINDOWP (f->tool_bar_window))
- {
- struct window *w = XWINDOW (f->tool_bar_window);
- XRectangle window_rect;
- XRectangle intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.x = window_x;
- window_rect.y = window_y;
- window_rect.width = window_width;
- window_rect.height = window_height;
-
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
+ mouse_face_overwritten_p
+ |= expose_window (XWINDOW (f->tool_bar_window), &r);
#ifndef USE_X_TOOLKIT
if (WINDOWP (f->menu_bar_window))
- {
- struct window *w = XWINDOW (f->menu_bar_window);
- XRectangle window_rect;
- XRectangle intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.x = window_x;
- window_rect.y = window_y;
- window_rect.width = window_width;
- window_rect.height = window_height;
+ mouse_face_overwritten_p
+ |= expose_window (XWINDOW (f->menu_bar_window), &r);
+#endif /* not USE_X_TOOLKIT */
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
+ /* Some window managers support a focus-follows-mouse style with
+ delayed raising of frames. Imagine a partially obscured frame,
+ and moving the mouse into partially obscured mouse-face on that
+ frame. The visible part of the mouse-face will be highlighted,
+ then the WM raises the obscured frame. With at least one WM, KDE
+ 2.1, Emacs is not getting any event for the raising of the frame
+ (even tried with SubstructureRedirectMask), only Expose events.
+ These expose events will draw text normally, i.e. not
+ highlighted. Which means we must redo the highlight here.
+ Subsume it under ``we love X''. --gerd 2001-08-15 */
+ if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
+ {
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ if (f == dpyinfo->mouse_face_mouse_frame)
+ {
+ int x = dpyinfo->mouse_face_mouse_x;
+ int y = dpyinfo->mouse_face_mouse_y;
+ clear_mouse_face (dpyinfo);
+ note_mouse_highlight (f, x, y);
+ }
}
-#endif /* not USE_X_TOOLKIT */
}
/* Redraw (parts) of all windows in the window tree rooted at W that
- intersect R. R contains frame pixel coordinates. */
+ intersect R. R contains frame pixel coordinates. Value is
+ non-zero if the exposure overwrites mouse-face. */
-static void
+static int
expose_window_tree (w, r)
struct window *w;
XRectangle *r;
{
- while (w)
+ struct frame *f = XFRAME (w->frame);
+ int mouse_face_overwritten_p = 0;
+
+ while (w && !FRAME_GARBAGED_P (f))
{
if (!NILP (w->hchild))
- expose_window_tree (XWINDOW (w->hchild), r);
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->hchild), r);
else if (!NILP (w->vchild))
- expose_window_tree (XWINDOW (w->vchild), r);
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->vchild), r);
else
- {
- XRectangle window_rect;
- XRectangle intersection_rect;
- struct frame *f = XFRAME (w->frame);
- int window_x, window_y, window_width, window_height;
-
- /* Frame-relative pixel rectangle of W. */
- window_box (w, -1, &window_x, &window_y, &window_width,
- &window_height);
- window_rect.x
- = (window_x
- - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
- window_rect.y = window_y;
- window_rect.width
- = (window_width
- + FRAME_X_FLAGS_AREA_WIDTH (f)
- + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
- window_rect.height
- = window_height + CURRENT_MODE_LINE_HEIGHT (w);
-
- if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
-
- w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ mouse_face_overwritten_p |= expose_window (w, r);
+
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
}
+
+ return mouse_face_overwritten_p;
}
/* Redraw the parts of the glyph row ROW on window W intersecting
- rectangle R. R is in window-relative coordinates. */
+ rectangle R. R is in window-relative coordinates. Value is
+ non-zero if mouse-face was overwritten. */
-static void
+static int
expose_line (w, row, r)
struct window *w;
struct glyph_row *row;
expose_area (w, row, r, RIGHT_MARGIN_AREA);
x_draw_row_bitmaps (w, row);
}
+
+ return row->mouse_face_p;
}
}
-/* Redraw a rectangle of window W. R is a rectangle in window
- relative coordinates. Call this function with input blocked. */
+/* Redraw the part of window W intersection rectangle FR. Pixel
+ coordinates in FR are frame-relative. Call this function with
+ input blocked. Value is non-zero if the exposure overwrites
+ mouse-face. */
-static void
-expose_window (w, r)
+static int
+expose_window (w, fr)
struct window *w;
- XRectangle *r;
+ XRectangle *fr;
{
- struct glyph_row *row;
- int y;
- int yb = window_text_bottom_y (w);
- int cursor_cleared_p;
+ struct frame *f = XFRAME (w->frame);
+ XRectangle wr, r;
+ int mouse_face_overwritten_p = 0;
/* If window is not yet fully initialized, do nothing. This can
happen when toolkit scroll bars are used and a window is split.
Reconfiguring the scroll bar will generate an expose for a newly
created window. */
if (w->current_matrix == NULL)
- return;
-
- TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
- r->x, r->y, r->width, r->height));
-
- /* Convert to window coordinates. */
- r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
- r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
+ return 0;
- /* Turn off the cursor. */
- if (!w->pseudo_window_p
- && x_phys_cursor_in_rect_p (w, r))
+ /* When we're currently updating the window, display and current
+ matrix usually don't agree. Arrange for a thorough display
+ later. */
+ if (w == updated_window)
{
- x_clear_cursor (w);
- cursor_cleared_p = 1;
+ SET_FRAME_GARBAGED (f);
+ return 0;
}
- else
- cursor_cleared_p = 0;
- /* Find the first row intersecting the rectangle R. */
- row = w->current_matrix->rows;
- y = 0;
- while (row->enabled_p
- && y < yb
- && y + row->height < r->y)
- {
- y += row->height;
- ++row;
- }
-
- /* Display the text in the rectangle, one text line at a time. */
- while (row->enabled_p
- && y < yb
- && y < r->y + r->height)
+ /* Frame-relative pixel rectangle of W. */
+ wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
+ wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
+ wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
+ wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+
+ if (x_intersect_rectangles (fr, &wr, &r))
{
- expose_line (w, row, r);
- y += row->height;
- ++row;
- }
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *row;
+ int cursor_cleared_p;
+
+ TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
+ r.x, r.y, r.width, r.height));
- /* Display the mode line if there is one. */
- if (WINDOW_WANTS_MODELINE_P (w)
- && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
- row->enabled_p)
- && row->y < r->y + r->height)
- expose_line (w, row, r);
+ /* Convert to window coordinates. */
+ r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
+ r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
- if (!w->pseudo_window_p)
- {
- /* Draw border between windows. */
- x_draw_vertical_border (w);
+ /* Turn off the cursor. */
+ if (!w->pseudo_window_p
+ && x_phys_cursor_in_rect_p (w, &r))
+ {
+ x_clear_cursor (w);
+ cursor_cleared_p = 1;
+ }
+ else
+ cursor_cleared_p = 0;
+
+ /* Find the first row intersecting the rectangle R. */
+ for (row = w->current_matrix->rows;
+ row->enabled_p;
+ ++row)
+ {
+ int y0 = row->y;
+ int y1 = MATRIX_ROW_BOTTOM_Y (row);
+
+ if ((y0 >= r.y && y0 < r.y + r.height)
+ || (y1 > r.y && y1 < r.y + r.height)
+ || (r.y >= y0 && r.y < y1)
+ || (r.y + r.height > y0 && r.y + r.height < y1))
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (y1 >= yb)
+ break;
+ }
+
+ /* Display the mode line if there is one. */
+ if (WINDOW_WANTS_MODELINE_P (w)
+ && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
+ row->enabled_p)
+ && row->y < r.y + r.height)
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (!w->pseudo_window_p)
+ {
+ /* Draw border between windows. */
+ x_draw_vertical_border (w);
- /* Turn the cursor on again. */
- if (cursor_cleared_p)
- x_update_window_cursor (w, 1);
+ /* Turn the cursor on again. */
+ if (cursor_cleared_p)
+ x_update_window_cursor (w, 1);
+ }
}
+
+ return mouse_face_overwritten_p;
}
date. */
static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
+x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
struct window *w;
int x, y;
int *hpos, *vpos, *area;
+ int buffer_only_p;
{
struct glyph *glyph, *end;
struct glyph_row *row = NULL;
{
if (w->pseudo_window_p)
break;
- else if (BUFFERP (glyph->object))
+ else if (!buffer_only_p || BUFFERP (glyph->object))
break;
}
int portion;
Lisp_Object window;
struct window *w;
+ Cursor cursor = None;
+ struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
#ifdef USE_X_TOOLKIT
return;
}
+ /* Mouse is on the mode or header line? */
if (portion == 1 || portion == 3)
{
- /* Mouse is on the mode or top line. */
note_mode_line_highlight (w, x, portion == 1);
return;
}
- else if (portion == 2)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->horizontal_drag_cursor);
+
+ if (portion == 2)
+ cursor = f->output_data.x->horizontal_drag_cursor;
else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
+ cursor = f->output_data.x->text_cursor;
/* Are we in a window whose display is up to date?
And verify the buffer's text has not changed. */
+ b = XBUFFER (w->buffer);
if (/* Within text portion of the window. */
portion == 0
&& EQ (w->window_end_valid, w->buffer)
- && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
- && (XFASTINT (w->last_overlay_modified)
- == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
+ && XFASTINT (w->last_modified) == BUF_MODIFF (b)
+ && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
{
int hpos, vpos, pos, i, area;
struct glyph *glyph;
+ Lisp_Object object;
+ Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
+ Lisp_Object *overlay_vec = NULL;
+ int len, noverlays;
+ struct buffer *obuf;
+ int obegv, ozv, same_region;
/* Find the glyph under X/Y. */
- glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
+ glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
/* Clear mouse face if X/Y not over text. */
if (glyph == NULL
|| area != TEXT_AREA
|| !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
{
- clear_mouse_face (dpyinfo);
- return;
+ if (clear_mouse_face (dpyinfo))
+ cursor = None;
+ goto set_cursor;
}
pos = glyph->charpos;
- xassert (w->pseudo_window_p || BUFFERP (glyph->object));
-
- /* Check for mouse-face and help-echo. */
- {
- Lisp_Object mouse_face, overlay, position;
- Lisp_Object *overlay_vec;
- int len, noverlays;
- struct buffer *obuf;
- int obegv, ozv;
-
- /* If we get an out-of-range value, return now; avoid an error. */
- if (pos > BUF_Z (XBUFFER (w->buffer)))
- return;
-
- /* Make the window's buffer temporarily current for
- overlays_at and compute_char_face. */
- obuf = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- obegv = BEGV;
- ozv = ZV;
- BEGV = BEG;
- ZV = Z;
-
- /* Is this char mouse-active or does it have help-echo? */
- XSETINT (position, pos);
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. If there are more than 10, make
- enough space for all, and try again. */
- len = 10;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
- }
+ object = glyph->object;
+ if (!STRINGP (object) && !BUFFERP (object))
+ goto set_cursor;
+
+ /* If we get an out-of-range value, return now; avoid an error. */
+ if (BUFFERP (object) && pos > BUF_Z (b))
+ goto set_cursor;
+
+ /* Make the window's buffer temporarily current for
+ overlays_at and compute_char_face. */
+ obuf = current_buffer;
+ current_buffer = b;
+ obegv = BEGV;
+ ozv = ZV;
+ BEGV = BEG;
+ ZV = Z;
+
+ /* Is this char mouse-active or does it have help-echo? */
+ position = make_number (pos);
+
+ if (BUFFERP (object))
+ {
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len. If there are more than 10, make
+ enough space for all, and try again. */
+ len = 10;
+ overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+ noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
+ if (noverlays > len)
+ {
+ len = noverlays;
+ overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+ noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
+ }
- /* Sort overlays into increasing priority order. */
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Check mouse-face highlighting. */
- if (! (EQ (window, dpyinfo->mouse_face_window)
- && vpos >= dpyinfo->mouse_face_beg_row
- && vpos <= dpyinfo->mouse_face_end_row
- && (vpos > dpyinfo->mouse_face_beg_row
- || hpos >= dpyinfo->mouse_face_beg_col)
- && (vpos < dpyinfo->mouse_face_end_row
- || hpos < dpyinfo->mouse_face_end_col
- || dpyinfo->mouse_face_past_end)))
- {
- /* Clear the display of the old active region, if any. */
- clear_mouse_face (dpyinfo);
+ /* Sort overlays into increasing priority order. */
+ noverlays = sort_overlays (overlay_vec, noverlays, w);
+ }
+ else
+ noverlays = 0;
+
+ same_region = (EQ (window, dpyinfo->mouse_face_window)
+ && vpos >= dpyinfo->mouse_face_beg_row
+ && vpos <= dpyinfo->mouse_face_end_row
+ && (vpos > dpyinfo->mouse_face_beg_row
+ || hpos >= dpyinfo->mouse_face_beg_col)
+ && (vpos < dpyinfo->mouse_face_end_row
+ || hpos < dpyinfo->mouse_face_end_col
+ || dpyinfo->mouse_face_past_end));
+
+ if (same_region)
+ cursor = None;
+
+ /* Check mouse-face highlighting. */
+ if (! same_region
+ /* If there exists an overlay with mouse-face overlapping
+ the one we are currently highlighting, we have to
+ check if we enter the overlapping overlay, and then
+ highlight only that. */
+ || (OVERLAYP (dpyinfo->mouse_face_overlay)
+ && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
+ {
+ /* Find the highest priority overlay that has a mouse-face
+ property. */
+ overlay = Qnil;
+ for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
+ {
+ mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
+ if (!NILP (mouse_face))
+ overlay = overlay_vec[i];
+ }
+
+ /* If we're actually highlighting the same overlay as
+ before, there's no need to do that again. */
+ if (!NILP (overlay)
+ && EQ (overlay, dpyinfo->mouse_face_overlay))
+ goto check_help_echo;
+
+ dpyinfo->mouse_face_overlay = overlay;
- /* Find the highest priority overlay that has a mouse-face prop. */
- overlay = Qnil;
- for (i = noverlays - 1; i >= 0; --i)
- {
- mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
- if (!NILP (mouse_face))
- {
- overlay = overlay_vec[i];
- break;
- }
- }
+ /* Clear the display of the old active region, if any. */
+ if (clear_mouse_face (dpyinfo))
+ cursor = None;
- /* If no overlay applies, get a text property. */
- if (NILP (overlay))
- mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
+ /* If no overlay applies, get a text property. */
+ if (NILP (overlay))
+ mouse_face = Fget_text_property (position, Qmouse_face, object);
- /* Handle the overlay case. */
- if (! NILP (overlay))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after;
- int ignore;
-
- before = Foverlay_start (overlay);
- after = Foverlay_end (overlay);
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
- &dpyinfo->mouse_face_beg_col,
- &dpyinfo->mouse_face_beg_row,
- &dpyinfo->mouse_face_beg_x,
- &dpyinfo->mouse_face_beg_y);
- dpyinfo->mouse_face_past_end
- = !fast_find_position (w, XFASTINT (after),
- &dpyinfo->mouse_face_end_col,
- &dpyinfo->mouse_face_end_row,
- &dpyinfo->mouse_face_end_x,
- &dpyinfo->mouse_face_end_y);
- dpyinfo->mouse_face_window = window;
+ /* Handle the overlay case. */
+ if (!NILP (overlay))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after;
+ int ignore;
+
+ before = Foverlay_start (overlay);
+ after = Foverlay_end (overlay);
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
+ }
+ /* Handle the text property case. */
+ else if (!NILP (mouse_face) && BUFFERP (object))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after, beginning, end;
+ int ignore;
+
+ beginning = Fmarker_position (w->start);
+ end = make_number (BUF_Z (XBUFFER (object))
+ - XFASTINT (w->window_end_pos));
+ before
+ = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, beginning);
+ after
+ = Fnext_single_property_change (position, Qmouse_face,
+ object, end);
+
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+
+ if (BUFFERP (object))
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- /* Handle the text property case. */
- else if (! NILP (mouse_face))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after, beginning, end;
- int ignore;
-
- beginning = Fmarker_position (w->start);
- XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- - XFASTINT (w->window_end_pos)));
- before
- = Fprevious_single_property_change (make_number (pos + 1),
- Qmouse_face,
- w->buffer, beginning);
- after
- = Fnext_single_property_change (position, Qmouse_face,
- w->buffer, end);
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
+ }
+ else if (!NILP (mouse_face) && STRINGP (object))
+ {
+ Lisp_Object b, e;
+ int ignore;
+
+ b = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, Qnil);
+ e = Fnext_single_property_change (position, Qmouse_face,
+ object, Qnil);
+ if (NILP (b))
+ b = make_number (0);
+ if (NILP (e))
+ e = make_number (XSTRING (object)->size - 1);
+ fast_find_string_pos (w, XINT (b), object,
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row,
&dpyinfo->mouse_face_beg_x,
- &dpyinfo->mouse_face_beg_y);
- dpyinfo->mouse_face_past_end
- = !fast_find_position (w, XFASTINT (after),
- &dpyinfo->mouse_face_end_col,
- &dpyinfo->mouse_face_end_row,
- &dpyinfo->mouse_face_end_x,
- &dpyinfo->mouse_face_end_y);
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
- = face_at_buffer_position (w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- }
-
- /* Look for a `help-echo' property. */
- {
- Lisp_Object help, overlay;
-
- /* Check overlays first. */
- help = overlay = Qnil;
- for (i = noverlays - 1; i >= 0 && NILP (help); --i)
- {
- overlay = overlay_vec[i];
- help = Foverlay_get (overlay, Qhelp_echo);
+ &dpyinfo->mouse_face_beg_y, 0);
+ fast_find_string_pos (w, XINT (e), object,
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, 1);
+ dpyinfo->mouse_face_past_end = 0;
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
+ glyph->face_id, 1);
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
}
-
- if (!NILP (help))
+ else if (STRINGP (object) && NILP (mouse_face))
{
- help_echo = help;
- help_echo_window = window;
- help_echo_object = overlay;
- help_echo_pos = pos;
- }
- else
- {
- /* Try text properties. */
- if ((STRINGP (glyph->object)
- && glyph->charpos >= 0
- && glyph->charpos < XSTRING (glyph->object)->size)
- || (BUFFERP (glyph->object)
- && glyph->charpos >= BEGV
- && glyph->charpos < ZV))
- help = Fget_text_property (make_number (glyph->charpos),
- Qhelp_echo, glyph->object);
-
- if (!NILP (help))
+ /* A string which doesn't have mouse-face, but
+ the text ``under'' it might have. */
+ struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+
+ pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ mouse_face = get_char_property_and_overlay (make_number (pos),
+ Qmouse_face,
+ w->buffer,
+ &overlay);
+ if (!NILP (mouse_face) && !NILP (overlay))
{
- help_echo = help;
- help_echo_window = window;
- help_echo_object = glyph->object;
- help_echo_pos = glyph->charpos;
+ Lisp_Object before = Foverlay_start (overlay);
+ Lisp_Object after = Foverlay_end (overlay);
+ Lisp_Object ignore;
+
+ /* Note that we might not be able to find position
+ BEFORE in the glyph matrix if the overlay is
+ entirely covered by a `display' property. In
+ this case, we overshoot. So let's stop in
+ the glyph matrix before glyphs for OBJECT. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y,
+ object);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y,
+ Qnil);
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
}
}
}
-
- BEGV = obegv;
- ZV = ozv;
- current_buffer = obuf;
+
+ check_help_echo:
+
+ /* Look for a `help-echo' property. */
+ {
+ Lisp_Object help, overlay;
+
+ /* Check overlays first. */
+ help = overlay = Qnil;
+ for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+ {
+ overlay = overlay_vec[i];
+ help = Foverlay_get (overlay, Qhelp_echo);
+ }
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = overlay;
+ help_echo_pos = pos;
+ }
+ else
+ {
+ Lisp_Object object = glyph->object;
+ int charpos = glyph->charpos;
+
+ /* Try text properties. */
+ if (STRINGP (object)
+ && charpos >= 0
+ && charpos < XSTRING (object)->size)
+ {
+ help = Fget_text_property (make_number (charpos),
+ Qhelp_echo, object);
+ if (NILP (help))
+ {
+ /* If the string itself doesn't specify a help-echo,
+ see if the buffer text ``under'' it does. */
+ struct glyph_row *r
+ = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+ int pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ {
+ help = Fget_char_property (make_number (pos),
+ Qhelp_echo, w->buffer);
+ if (!NILP (help))
+ {
+ charpos = pos;
+ object = w->buffer;
+ }
+ }
+ }
+ }
+ else if (BUFFERP (object)
+ && charpos >= BEGV
+ && charpos < ZV)
+ help = Fget_text_property (make_number (charpos), Qhelp_echo,
+ object);
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = object;
+ help_echo_pos = charpos;
+ }
+ }
}
+
+ BEGV = obegv;
+ ZV = ozv;
+ current_buffer = obuf;
}
+
+ set_cursor:
+
+ if (cursor != None)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
}
static void
int area;
/* Find the glyph under X/Y. */
- *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
+ *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
if (*glyph == NULL)
return -1;
int i;
Lisp_Object enabled_p;
int prop_idx;
- enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
+ enum draw_glyphs_face draw;
int mouse_down_p, rc;
/* Function note_mouse_highlight is called with negative x(y
return;
}
else if (rc == 0)
- /* On same tool-bar item as before. */
goto set_help_echo;
clear_mouse_face (dpyinfo);
\f
-/* Find the glyph matrix position of buffer position POS in window W.
- *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
- current glyphs must be up to date. If POS is above window start
- return (0, 0, 0, 0). If POS is after end of W, return end of
- last line in W. */
+/* Find the glyph matrix position of buffer position CHARPOS in window
+ *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
+ current glyphs must be up to date. If CHARPOS is above window
+ start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
+ of last line in W. In the row containing CHARPOS, stop before glyphs
+ having STOP as object. */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+ in the presence of hscrolling, for example. I didn't install
+ it right away because the problem fixed is minor, it failed
+ in 20.x as well, and I think it's too risky to install
+ so near the release of 21.1. 2001-09-25 gerd. */
+
+static int
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
+ struct window *w;
+ int charpos;
+ int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
+{
+ struct glyph_row *row, *first;
+ struct glyph *glyph, *end;
+ int i, past_end = 0;
+
+ first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row = row_containing_pos (w, charpos, first, NULL);
+ if (row == NULL)
+ {
+ if (charpos < MATRIX_ROW_START_CHARPOS (first))
+ {
+ *x = *y = *hpos = *vpos = 0;
+ return 0;
+ }
+ else
+ {
+ row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ past_end = 1;
+ }
+ }
+
+ *x = row->x;
+ *y = row->y;
+ *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
+ glyph = row->glyphs[TEXT_AREA];
+ end = glyph + row->used[TEXT_AREA];
+
+ /* Skip over glyphs not having an object at the start of the row.
+ These are special glyphs like truncation marks on terminal
+ frames. */
+ if (row->displays_text_p)
+ while (glyph < end
+ && INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && glyph->charpos < 0)
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ while (glyph < end
+ && !INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < charpos))
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ *hpos = glyph - row->glyphs[TEXT_AREA];
+ return past_end;
+}
+
+#else /* not 0 */
static int
-fast_find_position (w, pos, hpos, vpos, x, y)
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
struct window *w;
int pos;
int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
{
int i;
int lastcol;
int maybe_next_line_p = 0;
int line_start_position;
int yb = window_text_bottom_y (w);
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
- struct glyph_row *best_row = row;
- int row_vpos = 0, best_row_vpos = 0;
+ struct glyph_row *row, *best_row;
+ int row_vpos, best_row_vpos;
int current_x;
+ row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
while (row->y < yb)
{
if (row->used[TEXT_AREA])
for (i = 0; i < best_row->used[TEXT_AREA]; i++)
{
struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
- int charpos;
+ int charpos = glyph->charpos;
- charpos = glyph->charpos;
- if (charpos == pos)
+ if (BUFFERP (glyph->object))
{
- *hpos = i;
- *vpos = best_row_vpos;
- *x = current_x;
- *y = best_row->y;
- return 1;
+ if (charpos == pos)
+ {
+ *hpos = i;
+ *vpos = best_row_vpos;
+ *x = current_x;
+ *y = best_row->y;
+ return 1;
+ }
+ else if (charpos > pos)
+ break;
}
- else if (charpos > pos)
+ else if (EQ (glyph->object, stop))
break;
- else if (charpos > 0)
- lastcol = i;
+ if (charpos > 0)
+ lastcol = i;
current_x += glyph->pixel_width;
}
return 0;
}
+#endif /* not 0 */
+
+
+/* Find the position of the the glyph for position POS in OBJECT in
+ window W's current matrix, and return in *X/*Y the pixel
+ coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+
+ RIGHT_P non-zero means return the position of the right edge of the
+ glyph, RIGHT_P zero means return the left edge position.
+
+ If no glyph for POS exists in the matrix, return the position of
+ the glyph with the next smaller position that is in the matrix, if
+ RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
+ exists in the matrix, return the position of the glyph with the
+ next larger position in OBJECT.
+
+ Value is non-zero if a glyph was found. */
+
+static int
+fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
+ struct window *w;
+ int pos;
+ Lisp_Object object;
+ int *hpos, *vpos, *x, *y;
+ int right_p;
+{
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *r;
+ struct glyph *best_glyph = NULL;
+ struct glyph_row *best_row = NULL;
+ int best_x = 0;
+
+ for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ r->enabled_p && r->y < yb;
+ ++r)
+ {
+ struct glyph *g = r->glyphs[TEXT_AREA];
+ struct glyph *e = g + r->used[TEXT_AREA];
+ int gx;
+
+ for (gx = r->x; g < e; gx += g->pixel_width, ++g)
+ if (EQ (g->object, object))
+ {
+ if (g->charpos == pos)
+ {
+ best_glyph = g;
+ best_x = gx;
+ best_row = r;
+ goto found;
+ }
+ else if (best_glyph == NULL
+ || ((abs (g->charpos - pos)
+ < abs (best_glyph->charpos - pos))
+ && (right_p
+ ? g->charpos < pos
+ : g->charpos > pos)))
+ {
+ best_glyph = g;
+ best_x = gx;
+ best_row = r;
+ }
+ }
+ }
+
+ found:
+
+ if (best_glyph)
+ {
+ *x = best_x;
+ *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
+
+ if (right_p)
+ {
+ *x += best_glyph->pixel_width;
+ ++*hpos;
+ }
+
+ *y = best_row->y;
+ *vpos = best_row - w->current_matrix->rows;
+ }
+
+ return best_glyph != NULL;
+}
+
/* Display the active region described by mouse_face_*
in its mouse-face if HL > 0, in its normal face if HL = 0. */
if (end_hpos > start_hpos)
{
- row->mouse_face_p = draw == DRAW_MOUSE_FACE;
x_draw_glyphs (w, start_x, row, TEXT_AREA,
start_hpos, end_hpos, draw, NULL, NULL, 0);
+ row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
}
}
}
/* Clear out the mouse-highlighted active region.
- Redraw it un-highlighted first. */
+ Redraw it un-highlighted first. Value is non-zero if mouse
+ face was actually drawn unhighlighted. */
-void
+static int
clear_mouse_face (dpyinfo)
struct x_display_info *dpyinfo;
{
- if (tip_frame)
- return;
+ int cleared = 0;
- if (! NILP (dpyinfo->mouse_face_window))
- show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+ if (!NILP (dpyinfo->mouse_face_window))
+ {
+ show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+ cleared = 1;
+ }
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
+ dpyinfo->mouse_face_overlay = Qnil;
+ return cleared;
}
FRAME_PTR f;
{
Lisp_Object window;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ window = dpyinfo->mouse_face_window;
+ if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+ {
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ }
+}
+
+\f
+static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
+
+
+/* Try to determine frame pixel position and size of the glyph under
+ frame pixel coordinates X/Y on frame F . Return the position and
+ size in *RECT. Value is non-zero if we could compute these
+ values. */
+
+static int
+glyph_rect (f, x, y, rect)
+ struct frame *f;
+ int x, y;
+ XRectangle *rect;
+{
+ Lisp_Object window;
+ int part, found = 0;
- window = dpyinfo->mouse_face_window;
- if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+ window = window_from_coordinates (f, x, y, &part, 0);
+ if (!NILP (window))
{
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
+ struct window *w = XWINDOW (window);
+ struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ struct glyph_row *end = r + w->current_matrix->nrows - 1;
+ int area;
+
+ frame_to_window_pixel_xy (w, &x, &y);
+
+ for (; !found && r < end && r->enabled_p; ++r)
+ if (r->y >= y)
+ {
+ struct glyph *g = r->glyphs[TEXT_AREA];
+ struct glyph *end = g + r->used[TEXT_AREA];
+ int gx;
+
+ for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
+ if (gx >= x)
+ {
+ rect->width = g->pixel_width;
+ rect->height = r->height;
+ rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+ rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+ found = 1;
+ }
+ }
}
+
+ return found;
}
-\f
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
+
/* Return the current position of the mouse.
- *fp should be a frame which indicates which display to ask about.
+ *FP should be a frame which indicates which display to ask about.
- If the mouse movement started in a scroll bar, set *fp, *bar_window,
- and *part to the frame, window, and scroll bar part that the mouse
- is over. Set *x and *y to the portion and whole of the mouse's
+ If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
+ and *PART to the frame, window, and scroll bar part that the mouse
+ is over. Set *X and *Y to the portion and whole of the mouse's
position on the scroll bar.
- If the mouse movement started elsewhere, set *fp to the frame the
- mouse is on, *bar_window to nil, and *x and *y to the character cell
+ If the mouse movement started elsewhere, set *FP to the frame the
+ mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
the mouse is over.
- Set *time to the server time-stamp for the time at which the mouse
+ Set *TIME to the server time-stamp for the time at which the mouse
was at this position.
Don't store anything if we don't have a valid set of values to report.
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
-#if OLD_REDISPLAY_CODE
- int ignore1, ignore2;
- pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
- &last_mouse_glyph,
- FRAME_X_DISPLAY_INFO (f1)->grabbed
- || insist);
-#else
- {
- int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
- int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
- int x = win_x;
- int y = win_y;
-
- /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
- round down even for negative values. */
- if (x < 0)
- x -= width - 1;
- if (y < 0)
- y -= height - 1;
+ int width, height, gx, gy;
+ XRectangle rect;
+
+ if (glyph_rect (f1, win_x, win_y, &rect))
+ last_mouse_glyph = rect;
+ else
+ {
+ width = FRAME_SMALLEST_CHAR_WIDTH (f1);
+ height = FRAME_SMALLEST_FONT_HEIGHT (f1);
+ gx = win_x;
+ gy = win_y;
- last_mouse_glyph.width = width;
- last_mouse_glyph.height = height;
- last_mouse_glyph.x = (x + width - 1) / width * width;
- last_mouse_glyph.y = (y + height - 1) / height * height;
- }
-#endif
+ /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+ round down even for negative values. */
+ if (gx < 0)
+ gx -= width - 1;
+ if (gy < 0)
+ gy -= height - 1;
+ gx = (gx + width - 1) / width * width;
+ gy = (gy + height - 1) / height * height;
+
+ last_mouse_glyph.width = width;
+ last_mouse_glyph.height = height;
+ last_mouse_glyph.x = gx;
+ last_mouse_glyph.y = gy;
+ }
*bar_window = Qnil;
*part = 0;
}
+#if defined USE_LUCID
+
+/* Return the Lucid menu bar WINDOW is part of. Return null
+ if WINDOW is not part of a menu bar. */
+
+static Widget
+x_window_to_menu_bar (window)
+ Window window;
+{
+ Lisp_Object tail;
+
+ for (tail = Vframe_list;
+ XGCTYPE (tail) == Lisp_Cons;
+ tail = XCDR (tail))
+ {
+ Lisp_Object frame = XCAR (tail);
+ Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+
+ if (menu_bar && xlwmenu_window_p (menu_bar, window))
+ return menu_bar;
+ }
+
+ return NULL;
+}
+
+#endif /* USE_LUCID */
+
\f
/************************************************************************
Toolkit scroll bars
{
struct scroll_bar *bar = (struct scroll_bar *) client_data;
XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
- double percent;
int part = -1, whole = 0, portion = 0;
switch (cs->reason)
UNBLOCK_INPUT;
/* At the max position of the scroll bar, do a line-wise
- movement. Without doing anything, the LessTif scroll bar
- calls us with the same cs->value again and again. If we
- want to make sure that we can reach the end of the buffer,
- we have to do something.
+ movement. Without doing anything, we would be called with
+ the same cs->value again and again. If we want to make
+ sure that we can reach the end of the buffer, we have to do
+ something.
Implementation note: setting bar->dragging always to
cs->value gives a smoother movement at the max position.
BLOCK_INPUT;
#ifdef USE_MOTIF
- /* LessTif 0.85, problems:
-
- 1. When the mouse if over the scroll bar, the scroll bar will
- get keyboard events. I didn't find a way to turn this off.
-
- 2. Do we have to explicitly set the cursor to get an arrow
- cursor (see below)? */
-
/* Set resources. Create the widget. */
XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
/* For smoother scrolling with Xaw3d -sm */
/* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
- /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
pixel = f->output_data.x->scroll_bar_foreground_pixel;
if (pixel != -1)
XtSetArg (av[ac], XtNbackground, pixel);
++ac;
}
-
+
+ /* Top/bottom shadow colors. */
+
+ /* Allocate them, if necessary. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ &pixel, 1.2, 0x8000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+ }
+ if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ &pixel, 0.6, 0x4000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+ }
+
+ /* Tell the toolkit about them. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
+ || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ /* We tried to allocate a color for the top/bottom shadow, and
+ failed, so tell Xaw3d to use dithering instead. */
+ {
+ XtSetArg (av[ac], XtNbeNiceToColormap, True);
+ ++ac;
+ }
+ else
+ /* Tell what colors Xaw3d should use for the top/bottom shadow, to
+ be more consistent with other emacs 3d colors, and since Xaw3d is
+ not good at dealing with allocation failure. */
+ {
+ /* This tells Xaw3d to use real colors instead of dithering for
+ the shadows. */
+ XtSetArg (av[ac], XtNbeNiceToColormap, False);
+ ++ac;
+
+ /* Specify the colors. */
+ pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], "topShadowPixel", pixel);
+ ++ac;
+ }
+ pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], "bottomShadowPixel", pixel);
+ ++ac;
+ }
+ }
+
widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
f->output_data.x->edit_widget, av, ac);
#ifdef USE_MOTIF
{
int size, value;
- Boolean arrow1_selected, arrow2_selected;
- unsigned char flags;
- XmScrollBarWidget sb;
/* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
is the scroll bar's maximum and MIN is the scroll bar's minimum
value = min (value, XM_SB_MAX - size);
value = max (value, XM_SB_MIN);
- /* LessTif: Calling XmScrollBarSetValues after an increment or
- decrement turns off auto-repeat LessTif-internally. This can
- be seen in ScrollBar.c which resets Arrow1Selected and
- Arrow2Selected. It also sets internal flags so that LessTif
- believes the mouse is in the slider. We either have to change
- our code, or work around that by accessing private data. */
-
- sb = (XmScrollBarWidget) widget;
- arrow1_selected = sb->scrollBar.arrow1_selected;
- arrow2_selected = sb->scrollBar.arrow2_selected;
- flags = sb->scrollBar.flags;
-
if (NILP (bar->dragging))
XmScrollBarSetValues (widget, value, size, 0, 0, False);
else if (last_scroll_bar_part == scroll_bar_down_arrow)
min (size, XM_SB_RANGE - old_value),
0, 0, False);
}
-
- sb->scrollBar.arrow1_selected = arrow1_selected;
- sb->scrollBar.arrow2_selected = arrow2_selected;
- sb->scrollBar.flags = flags;
}
#else /* !USE_MOTIF i.e. use Xaw */
{
/* Clear the area of W that will serve as a scroll bar. This is
for the case that a window has been split horizontally. In
this case, no clear_frame is generated to reduce flickering. */
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width,
- window_box_height (w), False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width,
+ window_box_height (w), False);
window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
/* Position and size of scroll bar. */
/* Map the window/widget. */
#ifdef USE_TOOLKIT_SCROLL_BARS
- {
- Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
- XtConfigureWidget (scroll_bar,
- left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- top,
- width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- height, 0);
- XtMapWidget (scroll_bar);
- }
+ {
+ Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
+ XtConfigureWidget (scroll_bar,
+ left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ top,
+ width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+ max (height, 1), 0);
+ XtMapWidget (scroll_bar);
+ }
#else /* not USE_TOOLKIT_SCROLL_BARS */
XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
#endif /* not USE_TOOLKIT_SCROLL_BARS */
/* Draw the empty space above the handle. Note that we can't clear
zero-height areas; that means "clear to end of window." */
if (0 < start)
- XClearArea (FRAME_X_DISPLAY (f), w,
-
- /* x, y, width, height, and exposures. */
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER,
- inside_width, start,
- False);
+ x_clear_area (FRAME_X_DISPLAY (f), w,
+ /* x, y, width, height, and exposures. */
+ VERTICAL_SCROLL_BAR_LEFT_BORDER,
+ VERTICAL_SCROLL_BAR_TOP_BORDER,
+ inside_width, start,
+ False);
/* Change to proper foreground color if one is specified. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
/* Draw the handle itself. */
XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
-
/* x, y, width, height */
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + start,
/* Draw the empty space below the handle. Note that we can't
clear zero-height areas; that means "clear to end of window." */
if (end < inside_height)
- XClearArea (FRAME_X_DISPLAY (f), w,
-
- /* x, y, width, height, and exposures. */
- VERTICAL_SCROLL_BAR_LEFT_BORDER,
- VERTICAL_SCROLL_BAR_TOP_BORDER + end,
- inside_width, inside_height - end,
- False);
+ x_clear_area (FRAME_X_DISPLAY (f), w,
+ /* x, y, width, height, and exposures. */
+ VERTICAL_SCROLL_BAR_LEFT_BORDER,
+ VERTICAL_SCROLL_BAR_TOP_BORDER + end,
+ inside_width, inside_height - end,
+ False);
}
if (NILP (w->vertical_scroll_bar))
{
BLOCK_INPUT;
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, False);
+ if (width && height)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height, False);
UNBLOCK_INPUT;
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
}
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, False);
+ if (width && height)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height, False);
/* Move/size the scroll bar widget. */
if (mask)
sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top,
sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- height, 0);
+ max (height, 1), 0);
#else /* not USE_TOOLKIT_SCROLL_BARS */
+ /* Clear areas not covered by the scroll bar because of
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
{
- /* Clear areas not covered by the scroll bar. This makes sure a
- previous mode line display is cleared after C-x 2 C-x 1, for
- example. Non-toolkit scroll bars are as wide as the area
- reserved for scroll bars - trim at both sides. */
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- height, False);
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- height, False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ height, False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ height, False);
}
+
+ /* Clear areas not covered by the scroll bar because it's not as
+ wide as the area reserved for it . This makes sure a
+ previous mode line display is cleared after C-x 2 C-x 1, for
+ example. */
+ {
+ int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+ int rest = area_width - sb_width;
+ if (rest > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left + area_width - rest, 0,
+ rest, max (height, 1), False);
+ }
/* Move/size the scroll bar window. */
if (mask)
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
- XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
+ XClearArea (FRAME_X_DISPLAY (f),
+ SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
0, 0, 0, 0, True);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
&event);
else
{
- XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
+ XSelectionRequestEvent *eventp
+ = (XSelectionRequestEvent *) &event;
if (numchars == 0)
abort ();
break;
case PropertyNotify:
-#ifdef USE_X_TOOLKIT
+#if 0 /* This is plain wrong. In the case that we are waiting for a
+ PropertyNotify used as an ACK in incremental selection
+ transfer, the property will be on the receiver's window. */
+#if defined USE_X_TOOLKIT
if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
goto OTHER;
-#endif /* not USE_X_TOOLKIT */
+#endif
+#endif
x_handle_property_notify (&event.xproperty);
- break;
+ goto OTHER;
case ReparentNotify:
f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
}
else
{
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ struct scroll_bar *bar;
+#endif
+#if defined USE_LUCID
+ /* Submenus of the Lucid menu bar aren't widgets
+ themselves, so there's no way to dispatch events
+ to them. Recognize this case separately. */
+ {
+ Widget widget
+ = x_window_to_menu_bar (event.xexpose.window);
+ if (widget)
+ xlwmenu_redisplay (widget);
+ }
+#endif /* USE_LUCID */
+
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Dispatch event to the widget. */
goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xexpose.window);
+ bar = x_window_to_scroll_bar (event.xexpose.window);
if (bar)
x_scroll_bar_expose (bar, &event);
break;
case GraphicsExpose: /* This occurs when an XCopyArea's
- source area was obscured or not
- available.*/
+ source area was obscured or not
+ available. */
f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
if (f)
{
case NoExpose: /* This occurs when an XCopyArea's
source area was completely
- available */
+ available. */
break;
case UnmapNotify:
f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
if (f) /* F may no longer exist if
- the frame was deleted. */
+ the frame was deleted. */
{
/* While a frame is unmapped, display generation is
disabled; you don't want to spend time updating a
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
- /* I couldn't find a way to prevent LessTif scroll bars
- from consuming key events. */
if (f == 0)
{
+ /* Scroll bars consume key events, but we want
+ the keys to go to the scroll bar's frame. */
Widget widget = XtWindowToWidget (dpyinfo->display,
event.xkey.window);
if (widget && XmIsScrollBar (widget))
|| IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
|| IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
/* Any "vendor-specific" key is ok. */
- || (orig_keysym & (1 << 28)))
+ || (orig_keysym & (1 << 28))
+ || (keysym != NoSymbol && nbytes == 0))
&& ! (IsModifierKey (orig_keysym)
#ifndef HAVE_X11R5
#ifdef XK_Mode_switch
{
register int i;
register int c;
- unsigned char *p, *pend;
int nchars, len;
for (i = 0; i < nbytes; i++)
case EnterNotify:
{
- int from_menu_bar_p = 0;
-
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
-#ifdef LESSTIF_VERSION
- /* When clicking outside of a menu bar popup to close
- it, we get a FocusIn/ EnterNotify sequence of
- events. The flag event.xcrossing.focus is not set
- in the EnterNotify event of that sequence because
- the focus is in the menu bar,
- event.xcrossing.window is the frame's X window.
- Unconditionally setting the focus frame to null in
- this case is not the right thing, because no event
- follows that could set the focus frame to the right
- value.
-
- This could be a LessTif bug, but I wasn't able to
- reproduce the behavior in a simple test program.
-
- (gerd, LessTif 0.88.1). */
-
- if (!event.xcrossing.focus
- && f
- && f->output_data.x->menubar_widget)
- {
- Window focus;
- int revert;
-
- XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
- if (focus == XtWindow (f->output_data.x->menubar_widget))
- from_menu_bar_p = 1;
- }
-#endif /* LESSTIF_VERSION */
-
- if (event.xcrossing.focus || from_menu_bar_p)
+ if (event.xcrossing.focus)
{
/* Avoid nasty pop/raise loops. */
if (f && (!(f->auto_raise)
/* EnterNotify counts as mouse movement,
so update things that depend on mouse position. */
- if (f && !f->output_data.x->busy_p)
+ if (f && !f->output_data.x->hourglass_p)
note_mouse_movement (f, &event.xmotion);
goto OTHER;
}
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
{
- Lisp_Object frame;
- int from_menu_bar_p = 0;
-
if (f == dpyinfo->mouse_face_mouse_frame)
{
/* If we move outside the frame, then we're
int n;
XSETFRAME (frame, f);
+ help_echo = Qnil;
n = gen_help_event (bufp, numchars,
Qnil, frame, Qnil, Qnil, 0);
bufp += n, count += n, numchars -= n;
}
-#ifdef LESSTIF_VERSION
- /* Please see the comment at the start of the
- EnterNotify case. */
- if (!event.xcrossing.focus
- && f->output_data.x->menubar_widget)
- {
- Window focus;
- int revert;
- XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
- if (focus == XtWindow (f->output_data.x->menubar_widget))
- from_menu_bar_p = 1;
- }
-#endif /* LESSTIF_VERSION */
-
- if (event.xcrossing.focus || from_menu_bar_p)
+ if (event.xcrossing.focus)
x_mouse_leave (dpyinfo);
else
{
Text Cursor
***********************************************************************/
-/* Note if the text cursor of window W has been overwritten by a
+/* Notice if the text cursor of window W has been overwritten by a
drawing operation that outputs N glyphs starting at HPOS in the
- line given by output_cursor.vpos. N < 0 means all the rest of the
- line after HPOS has been written. */
+ line given by output_cursor.vpos.
+
+ N < 0 means all the rest of the line after HPOS has been
+ written. */
static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, hpos, n)
struct window *w;
int hpos, n;
{
if (updated_area == TEXT_AREA
&& output_cursor.vpos == w->phys_cursor.vpos
- && hpos <= w->phys_cursor.hpos
- && (n < 0
- || hpos + n > w->phys_cursor.hpos))
- w->phys_cursor_on_p = 0;
+ && output_cursor.x <= w->phys_cursor.x
+ && w->phys_cursor_on_p)
+ {
+ if (n < 0)
+ w->phys_cursor_on_p = 0;
+ else
+ {
+ /* It depends on the width of the N glyphs written at HPOS
+ if the cursor has been overwritten or not. */
+ struct glyph *glyph = &updated_row->glyphs[TEXT_AREA][hpos];
+ struct glyph *end = glyph + n;
+ int width = 0;
+
+ for (; glyph < end; ++glyph)
+ width += glyph->pixel_width;
+
+ if (output_cursor.x + width > w->phys_cursor.x)
+ w->phys_cursor_on_p = 0;
+ }
+ }
}
if (cursor_glyph == NULL)
goto mark_cursor_off;
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- x,
- WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- cursor_row->y)),
- cursor_glyph->pixel_width,
- cursor_row->visible_height,
- False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ x,
+ WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+ cursor_row->y)),
+ cursor_glyph->pixel_width,
+ cursor_row->visible_height,
+ False);
}
/* Erase the cursor by redrawing the character underneath it. */
}
+/* Non-zero if physical cursor of window W is within mouse face. */
+
+static int
+cursor_in_mouse_face_p (w)
+ struct window *w;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
+ int in_mouse_face = 0;
+
+ if (WINDOWP (dpyinfo->mouse_face_window)
+ && XWINDOW (dpyinfo->mouse_face_window) == w)
+ {
+ int hpos = w->phys_cursor.hpos;
+ int vpos = w->phys_cursor.vpos;
+
+ if (vpos >= dpyinfo->mouse_face_beg_row
+ && vpos <= dpyinfo->mouse_face_end_row
+ && (vpos > dpyinfo->mouse_face_beg_row
+ || hpos >= dpyinfo->mouse_face_beg_col)
+ && (vpos < dpyinfo->mouse_face_end_row
+ || hpos < dpyinfo->mouse_face_end_col
+ || dpyinfo->mouse_face_past_end))
+ in_mouse_face = 1;
+ }
+
+ return in_mouse_face;
+}
+
+
/* Display or clear cursor of window W. If ON is zero, clear the
cursor. If it is non-zero, display the cursor. If ON is nonzero,
where to put the cursor is specified by HPOS, VPOS, X and Y. */
}
else
{
- if (w != XWINDOW (selected_window)
- || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
+ if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
+ || w != XWINDOW (f->selected_window))
{
extern int cursor_in_non_selected_windows;
\f
/* Icons. */
-/* Refresh bitmap kitchen sink icon for frame F
- when we get an expose event for it. */
-
-void
-refreshicon (f)
- struct frame *f;
-{
- /* Normally, the window manager handles this function. */
-}
-
/* Make the x-window of frame F use the gnu icon bitmap. */
int
signal (signalnum, x_connection_signal);
#endif /* USG */
}
+
\f
-/* Handling X errors. */
+/************************************************************************
+ Handling X errors
+ ************************************************************************/
+
+/* Error message passed to x_connection_closed. */
+
+static char *error_msg;
+
+/* Function installed as fatal_error_signal_hook.in
+ x_connection_closed. Print the X error message, and exit normally,
+ instead of dumping core when XtCloseDisplay fails. */
+
+static void
+x_fatal_error_signal ()
+{
+ fprintf (stderr, "%s\n", error_msg);
+ exit (70);
+}
-/* Handle the loss of connection to display DISPLAY. */
+/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
+ the text of an error message that lead to the connection loss. */
static SIGTYPE
-x_connection_closed (display, error_message)
- Display *display;
+x_connection_closed (dpy, error_message)
+ Display *dpy;
char *error_message;
{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
+ struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
+ int count;
+
+ error_msg = (char *) alloca (strlen (error_message) + 1);
+ strcpy (error_msg, error_message);
+ handling_signal = 0;
+
+ /* Prevent being called recursively because of an error condition
+ below. Otherwise, we might end up with printing ``can't find per
+ display information'' in the recursive call instead of printing
+ the original message here. */
+ count = x_catch_errors (dpy);
+
+ /* We have to close the display to inform Xt that it doesn't
+ exist anymore. If we don't, Xt will continue to wait for
+ events from the display. As a consequence, a sequence of
- /* Indicate that this display is dead. */
+ M-x make-frame-on-display RET :1 RET
+ ...kill the new frame, so that we get an IO error...
+ M-x make-frame-on-display RET :1 RET
-#if 0 /* Closing the display caused a bus error on OpenWindows. */
+ will indefinitely wait in Xt for events for display `:1', opened
+ in the first class to make-frame-on-display.
+
+ Closing the display is reported to lead to a bus error on
+ OpenWindows in certain situations. I suspect that is a bug
+ in OpenWindows. I don't know how to cicumvent it here. */
+
#ifdef USE_X_TOOLKIT
- XtCloseDisplay (display);
-#endif
+ /* If DPYINFO is null, this means we didn't open the display
+ in the first place, so don't try to close it. */
+ if (dpyinfo)
+ {
+ extern void (*fatal_error_signal_hook) P_ ((void));
+ fatal_error_signal_hook = x_fatal_error_signal;
+ XtCloseDisplay (dpy);
+ fatal_error_signal_hook = NULL;
+ }
#endif
+ /* Indicate that this display is dead. */
if (dpyinfo)
dpyinfo->display = 0;
if (dpyinfo)
x_delete_display (dpyinfo);
+ x_uncatch_errors (dpy, count);
+
if (x_display_list == 0)
{
- fprintf (stderr, "%s\n", error_message);
+ fprintf (stderr, "%s\n", error_msg);
shut_down_emacs (0, 0, Qnil);
exit (70);
}
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
- handling_signal = 0;
- error ("%s", error_message);
+ error ("%s", error_msg);
}
+
/* This is the usual handler for X protocol errors.
It kills all frames on the display that we got the error for.
If that was the only one, it prints an error message and kills Emacs. */
x_connection_closed (display, buf1);
}
+
/* This is the first-level handler for X protocol errors.
It calls x_error_quitter or x_error_catcher. */
f->output_data.x->font->fid);
frame_update_line_height (f);
- x_set_window_size (f, 0, f->width, f->height);
+
+ /* Don't change the size of a tip frame; there's no point in
+ doing it because it's done in Fx_show_tip, and it leads to
+ problems because the tip frame has no widget. */
+ if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+ x_set_window_size (f, 0, f->width, f->height);
}
else
/* If we are setting a new frame's font for the first time,
#ifdef HAVE_X11R6
destroy.callback = xim_destroy_callback;
destroy.client_data = (XPointer)dpyinfo;
- /* This isn't prptotyped in OSF 5.0. */
+ /* This isn't prototyped in OSF 5.0. */
XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
#endif
}
{
#ifdef USE_XIM
#ifdef HAVE_X11R6_XIM
- XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- NULL, EMACS_CLASS,
- xim_instantiate_callback, NULL);
+ if (dpyinfo->display)
+ XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
+ NULL, EMACS_CLASS,
+ xim_instantiate_callback, NULL);
#endif /* not HAVE_X11R6_XIM */
- XCloseIM (dpyinfo->xim);
+ if (dpyinfo->display)
+ XCloseIM (dpyinfo->xim);
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
#endif /* USE_XIM */
UNBLOCK_INPUT;
}
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-void
-x_set_window_size (f, change_gravity, cols, rows)
+/* Change the size of frame F's X window to COLS/ROWS in the case F
+ doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
+ top-left-corner window gravity for this size change and subsequent
+ size changes. Otherwise we leave the window gravity unchanged. */
+
+static void
+x_set_window_size_1 (f, change_gravity, cols, rows)
struct frame *f;
int change_gravity;
int cols, rows;
{
-#ifndef USE_X_TOOLKIT
int pixelwidth, pixelheight;
-#endif
-
- BLOCK_INPUT;
-
-#ifdef USE_X_TOOLKIT
- {
- /* The x and y position of the widget is clobbered by the
- call to XtSetValues within EmacsFrameSetCharSize.
- This is a real kludge, but I don't understand Xt so I can't
- figure out a correct fix. Can anyone else tell me? -- rms. */
- int xpos = f->output_data.x->widget->core.x;
- int ypos = f->output_data.x->widget->core.y;
- EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
- f->output_data.x->widget->core.x = xpos;
- f->output_data.x->widget->core.y = ypos;
- }
-
-#else /* not USE_X_TOOLKIT */
check_frame_size (f, &rows, &cols);
f->output_data.x->vertical_scroll_bar_extra
SET_FRAME_GARBAGED (f);
XFlush (FRAME_X_DISPLAY (f));
+}
+
+/* Call this to change the size of frame F's x-window.
+ If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ for this size change and subsequent size changes.
+ Otherwise we leave the window gravity unchanged. */
+
+void
+x_set_window_size (f, change_gravity, cols, rows)
+ struct frame *f;
+ int change_gravity;
+ int cols, rows;
+{
+ BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
+
+ if (f->output_data.x->widget != NULL)
+ {
+ /* The x and y position of the widget is clobbered by the
+ call to XtSetValues within EmacsFrameSetCharSize.
+ This is a real kludge, but I don't understand Xt so I can't
+ figure out a correct fix. Can anyone else tell me? -- rms. */
+ int xpos = f->output_data.x->widget->core.x;
+ int ypos = f->output_data.x->widget->core.y;
+ EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
+ f->output_data.x->widget->core.x = xpos;
+ f->output_data.x->widget->core.y = ypos;
+ }
+ else
+ x_set_window_size_1 (f, change_gravity, cols, rows);
+
+#else /* not USE_X_TOOLKIT */
+
+ x_set_window_size_1 (f, change_gravity, cols, rows);
+
#endif /* not USE_X_TOOLKIT */
/* If cursor was outside the new size, mark it as off. */
UNBLOCK_INPUT;
#endif /* not USE_X_TOOLKIT */
}
+
\f
-/* Destroy the X window of frame F. */
+/* Free X resources of frame F. */
void
-x_destroy_window (f)
+x_free_frame_resources (f)
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
/* If a display connection is dead, don't try sending more
commands to the X server. */
- if (dpyinfo->display != 0)
+ if (dpyinfo->display)
{
- if (f->output_data.x->icon_desc != 0)
+ if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
#endif
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+
+ if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
- XtDestroyWidget (f->output_data.x->widget);
+ {
+ XtDestroyWidget (f->output_data.x->widget);
+ f->output_data.x->widget = NULL;
+ }
free_frame_menubar (f);
#endif /* USE_X_TOOLKIT */
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
unload_color (f, f->output_data.x->mouse_pixel);
+
if (f->output_data.x->scroll_bar_background_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_background_pixel);
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ /* Scrollbar shadow colors. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
+ if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
+#endif /* USE_TOOLKIT_SCROLL_BARS */
if (f->output_data.x->white_relief.allocated_p)
unload_color (f, f->output_data.x->white_relief.pixel);
if (f->output_data.x->black_relief.allocated_p)
unload_color (f, f->output_data.x->black_relief.pixel);
+
+ if (FRAME_FACE_CACHE (f))
+ free_frame_faces (f);
- free_frame_faces (f);
+ x_free_gcs (f);
XFlush (FRAME_X_DISPLAY (f));
}
xfree (f->output_data.x->saved_menu_event);
xfree (f->output_data.x);
- f->output_data.x = 0;
+ f->output_data.x = NULL;
+
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
if (f == dpyinfo->x_focus_event_frame)
if (f == dpyinfo->x_highlight_frame)
dpyinfo->x_highlight_frame = 0;
- dpyinfo->reference_count--;
-
if (f == dpyinfo->mouse_face_mouse_frame)
{
dpyinfo->mouse_face_beg_row
UNBLOCK_INPUT;
}
+
+
+/* Destroy the X window of frame F. */
+
+void
+x_destroy_window (f)
+ struct frame *f;
+{
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ /* If a display connection is dead, don't try sending more
+ commands to the X server. */
+ if (dpyinfo->display != 0)
+ x_free_frame_resources (f);
+
+ dpyinfo->reference_count--;
+}
+
\f
/* Setting window manager hints. */
}
-/* Return a list of names of available fonts matching PATTERN on frame
- F. If SIZE is not 0, it is the size (maximum bound width) of fonts
- to be listed. Frame F NULL means we have not yet created any
- frame on X, and consult the first display in x_display_list.
- MAXNAMES sets a limit on how many fonts to match. */
+/* Return a list of names of available fonts matching PATTERN on frame F.
+
+ If SIZE is > 0, it is the size (maximum bounds width) of fonts
+ to be listed.
+
+ SIZE < 0 means include scalable fonts.
+
+ Frame F null means we have not yet created any frame on X, and
+ consult the first display in x_display_list. MAXNAMES sets a limit
+ on how many fonts to match. */
Lisp_Object
x_list_fonts (f, pattern, size, maxnames)
- FRAME_PTR f;
+ struct frame *f;
Lisp_Object pattern;
int size;
int maxnames;
{
Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
Lisp_Object tem, second_best;
- Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
+ struct x_display_info *dpyinfo
+ = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
+ Display *dpy = dpyinfo->display;
int try_XLoadQueryFont = 0;
int count;
+ int allow_scalable_fonts_p = 0;
+
+ if (size < 0)
+ {
+ allow_scalable_fonts_p = 1;
+ size = 0;
+ }
patterns = Fassoc (pattern, Valternate_fontname_alist);
if (NILP (patterns))
pattern = XCAR (patterns);
/* See if we cached the result for this particular query.
The cache is an alist of the form:
- (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
- */
- if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
- key = Fcons (pattern, make_number (maxnames)),
- !NILP (list = Fassoc (key, tem))))
+ ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
+ tem = XCDR (dpyinfo->name_list_element);
+ key = Fcons (Fcons (pattern, make_number (maxnames)),
+ allow_scalable_fonts_p ? Qt : Qnil);
+ list = Fassoc (key, tem);
+ if (!NILP (list))
{
list = Fcdr_safe (list);
/* We have a cashed list. Don't have to get the list again. */
int average_width = -1, dashes = 0;
/* Count the number of dashes in NAMES[I]. If there are
- 14 dashes, and the field value following 12th dash
- (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
- is usually too ugly to be used for editing. Let's
- ignore it. */
+ 14 dashes, and the field value following 12th dash
+ (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
+ is usually too ugly to be used for editing. Let's
+ ignore it. */
while (*p)
if (*p++ == '-')
{
else if (dashes == 12) /* AVERAGE_WIDTH field */
average_width = atoi (p);
}
- if (dashes < 14 || average_width != 0)
+
+ if (allow_scalable_fonts_p
+ || dashes < 14 || average_width != 0)
{
tem = build_string (names[i]);
if (NILP (Fassoc (tem, list)))
}
}
}
+
if (!try_XLoadQueryFont)
- XFreeFontNames (names);
+ {
+ BLOCK_INPUT;
+ XFreeFontNames (names);
+ UNBLOCK_INPUT;
+ }
}
/* Now store the result in the cache. */
- if (f != NULL)
- XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
- = Fcons (Fcons (key, list),
- XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
label_cached:
if (NILP (list)) continue; /* Try the remaining alternatives. */
if (!INTEGERP (XCDR (tem)))
{
/* Since we have not yet known the size of this font, we
- must try slow function call XLoadQueryFont. */
+ must try slow function call XLoadQueryFont. */
XFontStruct *thisinfo;
BLOCK_INPUT;
if (thisinfo)
{
- XCDR (tem)
- = (thisinfo->min_bounds.width == 0
- ? make_number (0)
- : make_number (thisinfo->max_bounds.width));
+ XSETCDR (tem,
+ (thisinfo->min_bounds.width == 0
+ ? make_number (0)
+ : make_number (thisinfo->max_bounds.width)));
+ BLOCK_INPUT;
XFreeFont (dpy, thisinfo);
+ UNBLOCK_INPUT;
}
else
/* For unknown reason, the previous call of XListFont had
returned a font which can't be opened. Record the size
as 0 not to try to open it again. */
- XCDR (tem) = make_number (0);
+ XSETCDR (tem, make_number (0));
}
found_size = XINT (XCDR (tem));
fontp->size = font->max_bounds.width;
fontp->height = FONT_HEIGHT (font);
- {
- /* For some font, ascent and descent in max_bounds field is
- larger than the above value. */
- int max_height = font->max_bounds.ascent + font->max_bounds.descent;
- if (max_height > fontp->height)
- fontp->height = max_height;
- }
if (NILP (font_names))
{
the cache for x_list_fonts. */
Lisp_Object lispy_name = build_string (fontname);
Lisp_Object lispy_full_name = build_string (fontp->full_name);
-
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
+ Qnil);
+
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
if (full_name)
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ {
+ key = Fcons (Fcons (lispy_full_name, make_number (256)),
+ Qnil);
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
+ }
}
/* The slot `encoding' specifies how to map a character
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
dpyinfo->mouse_face_window = Qnil;
+ dpyinfo->mouse_face_overlay = Qnil;
dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
dpyinfo->mouse_face_defer = 0;
dpyinfo->x_focus_frame = 0;
{
extern int gray_bitmap_width, gray_bitmap_height;
- extern unsigned char *gray_bitmap_bits;
+ extern char *gray_bitmap_bits;
dpyinfo->gray
= XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
gray_bitmap_bits,
{
if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
{
- XCDR (tail) = XCDR (XCDR (tail));
+ XSETCDR (tail, XCDR (XCDR (tail)));
break;
}
tail = XCDR (tail);
estimate_mode_line_height_hook = x_estimate_mode_line_height;
scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 0; /* just as fast to write the line */
+ char_ins_del_ok = 1;
line_ins_del_ok = 1; /* we'll just blt 'em */
fast_clear_end_of_line = 1; /* X does this well */
memory_below_frame = 0; /* we don't remember what scrolls
#ifdef USE_X_TOOLKIT
XtToolkitInitialize ();
+
Xt_app_con = XtCreateApplicationContext ();
+
+ /* Register a converter from strings to pixels, which uses
+ Emacs' color allocation infrastructure. */
+ XtAppSetTypeConverter (Xt_app_con,
+ XtRString, XtRPixel, cvt_string_to_pixel,
+ cvt_string_to_pixel_args,
+ XtNumber (cvt_string_to_pixel_args),
+ XtCacheByDisplay, cvt_pixel_dtor);
+
XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
/* Install an asynchronous timer that processes Xt timeout events
staticpro (&previous_help_echo);
help_echo_pos = -1;
- DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
- "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.");
+ DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p
+ /* *Non-nil means draw block cursor as wide as the glyph under it.
+For example, if a block cursor is over a tab, it will be drawn as
+wide as that tab on the display. */);
x_stretch_cursor_p = 0;
- DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
- "If not nil, Emacs uses toolkit scroll bars.");
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ &x_use_underline_position_properties
+ /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+Nil means ignore them. If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil. */);
+ x_use_underline_position_properties = 1;
+
+ DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
+ /* What X toolkit scroll bars Emacs uses.
+A value of nil means Emacs doesn't use X toolkit scroll bars.
+Otherwise, value is a symbol describing the X toolkit. */);
#ifdef USE_TOOLKIT_SCROLL_BARS
- x_toolkit_scroll_bars_p = 1;
+#ifdef USE_MOTIF
+ Vx_toolkit_scroll_bars = intern ("motif");
+#elif defined HAVE_XAW3D
+ Vx_toolkit_scroll_bars = intern ("xaw3d");
+#else
+ Vx_toolkit_scroll_bars = intern ("xaw");
+#endif
#else
- x_toolkit_scroll_bars_p = 0;
+ Vx_toolkit_scroll_bars = Qnil;
#endif
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
}
-#endif /* not HAVE_X_WINDOWS */
+#endif /* HAVE_X_WINDOWS */