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 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_ ((struct frame *, 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 *));
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 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 *,
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);
}
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);
}
#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. */
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);
+ left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
if (raised_p)
/* Bottom. */
for (i = 0; i < width; ++i)
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- left_x + i * left_p, bottom_y - i,
+ left_x + i * left_p + 1, bottom_y - i,
right_x + 1 - i * right_p, bottom_y - i);
/* Right. */
/* 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);
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;
/* 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];
}
}
x += FRAME_INTERNAL_BORDER_WIDTH (f);
- last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+ last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
}
else
{
expose_window_tree (XWINDOW (w->hchild), r);
else if (!NILP (w->vchild))
expose_window_tree (XWINDOW (w->vchild), r);
- else
- expose_window (w, r);
+ else if (expose_window (w, r) == 0)
+ break;
w = NILP (w->next) ? NULL : XWINDOW (w->next);
}
}
coordinates in FR are frame-relative. Call this function with
input blocked. */
-static void
+static int
expose_window (w, fr)
struct window *w;
XRectangle *fr;
{
struct frame *f = XFRAME (w->frame);
- struct glyph_row *row;
- int y, yb, cursor_cleared_p;
XRectangle wr, r;
/* 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 || w == updated_window)
- return;
+ if (w->current_matrix == NULL)
+ return 1;
+
+ /* 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)
+ {
+ SET_FRAME_GARBAGED (f);
+ return 0;
+ }
- /* Frame-relative pixel rectangle of W. */
+ /* 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))
- return;
-
- yb = window_text_bottom_y (w);
+ if (x_intersect_rectangles (fr, &wr, &r))
+ {
+ 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));
+ 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);
+ /* Convert to window coordinates. */
+ r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
+ r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
- /* 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;
+ /* 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. */
- 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)
- {
- expose_line (w, row, &r);
- y += row->height;
- ++row;
- }
+ /* 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))
+ expose_line (w, row, &r);
- /* 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);
+ if (y1 >= yb)
+ break;
+ }
- if (!w->pseudo_window_p)
- {
- /* Draw border between windows. */
- x_draw_vertical_border (w);
+ /* 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);
+
+ 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 1;
}
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, 0);
|| 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;
object = glyph->object;
if (!STRINGP (object) && !BUFFERP (object))
- return;
+ goto set_cursor;
- {
- Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
- Lisp_Object *overlay_vec = NULL;
- int len, noverlays;
- struct buffer *obuf;
- int obegv, ozv;
-
- /* If we get an out-of-range value, return now; avoid an error. */
- if (BUFFERP (object) && 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? */
- 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);
- }
+ /* If we get an out-of-range value, return now; avoid an error. */
+ if (BUFFERP (object) && pos > BUF_Z (b))
+ goto set_cursor;
- /* Sort overlays into increasing priority order. */
- noverlays = sort_overlays (overlay_vec, noverlays, w);
- }
- else
- noverlays = 0;
-
- /* 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))
- /* 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)))
-
- {
- /* Clear the display of the old active region, if any. */
- clear_mouse_face (dpyinfo);
+ /* 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;
- /* 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];
- }
- dpyinfo->mouse_face_overlay = overlay;
+ /* 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);
+ }
+ 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;
- /* If no overlay applies, get a text property. */
- if (NILP (overlay))
- mouse_face = Fget_text_property (position, Qmouse_face, object);
+ dpyinfo->mouse_face_overlay = overlay;
- /* 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;
+ /* 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, 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;
+ 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);
+ 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;
+
+ 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) && 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);
+ /* 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;
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
+ 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;
-
- 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);
- }
- 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, 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);
- }
- }
+ &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;
+ }
+ }
- /* Look for a `help-echo' property. */
- {
- Lisp_Object help, overlay;
+ check_help_echo:
- /* 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);
- }
+ /* Look for a `help-echo' property. */
+ {
+ Lisp_Object help, overlay;
- 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;
+ /* 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_text_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);
+ /* 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_text_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;
+ 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
}
/* 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 0 /* This prevents redrawing tool bar items when changing from one
- to another while a tooltip is open, so don't do it. */
- if (!NILP (tip_frame))
- return;
-#endif
+ 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;
}
}
+#if defined USE_X_TOOLKIT && 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_X_TOOLKIT && USE_LUCID */
+
\f
/************************************************************************
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_X_TOOLKIT && 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_X_TOOLKIT && 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);
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);
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
x,
}
+/* 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. */
#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_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 */
}
}
}
+
if (!try_XLoadQueryFont)
- XFreeFontNames (names);
+ {
+ BLOCK_INPUT;
+ XFreeFontNames (names);
+ UNBLOCK_INPUT;
+ }
}
/* Now store the result in the cache. */
= (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
#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
wide as that tab on the display.");
x_stretch_cursor_p = 0;
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ &x_use_underline_position_properties,
+ "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
+Nil means ignore them. If you encounter fonts with bogus\n\
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
+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.\n\
A value of nil means Emacs doesn't use X toolkit scroll bars.\n\