#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
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 *));
unsigned));
static int fast_find_position P_ ((struct window *, int, int *, int *,
int *, int *));
+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));
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 *,
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;
}
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);
}
};
-#if 0
+#if 1
static void
x_dump_glyph_string (s)
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. */
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;
/* 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. */
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_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_box (s);
+ relief_drawn_p = 1;
+ }
+
switch (s->first_glyph->type)
{
case IMAGE_GLYPH:
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];
}
if (start == s->row->used[s->area]
&& s->hl == DRAW_NORMAL_TEXT
- && ((s->area == TEXT_AREA && s->row->fill_line_p)
+ && 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;
}
x += FRAME_INTERNAL_BORDER_WIDTH (f);
- last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+ last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
}
else
{
- 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,
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);
}
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);
- }
+ 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;
-
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
+ expose_window (XWINDOW (f->menu_bar_window), &r);
#endif /* not USE_X_TOOLKIT */
}
expose_window_tree (XWINDOW (w->hchild), r);
else if (!NILP (w->vchild))
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);
+ else if (expose_window (w, r) == 0)
+ break;
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
}
}
}
-/* 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. */
-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;
/* 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;
-
- 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);
+ if (w->current_matrix == NULL)
+ return 1;
- /* 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))
+ expose_line (w, row, &r);
+
+ 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)
+ 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;
}
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);
+ 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))
- {
- /* 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);
+ &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;
+ }
+ }
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- }
+ check_help_echo:
- /* Look for a `help-echo' property. */
- {
- Lisp_Object help, overlay;
+ /* 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);
- }
+ /* 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
- {
- /* 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))
+ {
+ 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);
- if (!NILP (help))
- {
- help_echo = help;
- help_echo_window = window;
- help_echo_object = glyph->object;
- help_echo_pos = glyph->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
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);
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])
}
+/* 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;
+ row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
x_draw_glyphs (w, start_x, row, TEXT_AREA,
start_hpos, end_hpos, draw, NULL, NULL, 0);
}
}
/* 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;
}
dpyinfo->mouse_face_window = Qnil;
}
}
+
\f
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
+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 = window_from_coordinates (f, x, y, &part, 0);
+ if (!NILP (window))
+ {
+ 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;
+}
+
/* 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_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
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;
#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
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 */
{
/* 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 handle itself. */
XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
-
/* x, y, width, height */
VERTICAL_SCROLL_BAR_LEFT_BORDER,
VERTICAL_SCROLL_BAR_TOP_BORDER + start,
if (NILP (w->vertical_scroll_bar))
{
BLOCK_INPUT;
- x_clear_area (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. */
- x_clear_area (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. */
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
height, False);
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)
&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);
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))
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.
- On the other hand, Motif seems to not have this
- problem.
-
- (gerd, LessTif 0.92). */
-
- 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)
{
- int from_menu_bar_p = 0;
-
if (f == dpyinfo->mouse_face_mouse_frame)
{
/* If we move outside the frame, then we're
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
{
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 != None)
+ if (f->output_data.x->widget != NULL)
{
/* The x and y position of the widget is clobbered by the
call to XtSetValues within EmacsFrameSetCharSize.
#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
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;
#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\