#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
-#if 0
-#include "sink.h"
-#include "sinkmask.h"
-#endif /* ! 0 */
#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "intervals.h"
#include "process.h"
#include "atimer.h"
+#include "keymap.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
#include <unistd.h>
#endif
+#ifdef USE_LUCID
+extern int xlwmenu_window_p (Widget w, Window window);
+extern void xlwmenu_redisplay P_ ((Widget));
+#endif
+
#ifdef USE_X_TOOLKIT
extern void free_frame_menubar P_ ((struct frame *));
#if defined USE_MOTIF
#include <Xm/Xm.h> /* for LESSTIF_VERSION */
#include <Xm/ScrollBar.h>
-#include <Xm/ScrollBarP.h>
#else /* !USE_MOTIF i.e. use Xaw */
#ifdef HAVE_XAW3D
#endif
#endif
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
#define abs(x) ((x) < 0 ? -(x) : (x))
#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
\f
-/* Bitmaps for truncated lines. */
+/* Fringe bitmaps. */
-enum bitmap_type
+enum fringe_bitmap_type
{
- NO_BITMAP,
+ NO_FRINGE_BITMAP,
LEFT_TRUNCATION_BITMAP,
RIGHT_TRUNCATION_BITMAP,
OVERLAY_ARROW_BITMAP,
`indicate-empty-lines' is non-nil. */
#define zv_width 8
-#define zv_height 8
+#define zv_height 72
+#define zv_period 3
static unsigned char zv_bits[] = {
- 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
/* An arrow like this: `<-'. */
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. */
extern struct frame *updating_frame;
-extern int waiting_for_input;
-
/* This is a frame waiting to be auto-raised, within XTread_socket. */
struct frame *pending_autoraise_frame;
extern int extra_keyboard_modifiers;
+/* The keysyms to use for the various modifiers. */
+
+Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
+static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
+
static Lisp_Object Qvendor_specific_keysyms;
extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
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 *));
static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
unsigned));
static int fast_find_position P_ ((struct window *, int, int *, int *,
- int *, int *));
+ int *, int *, Lisp_Object));
+static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
+ int *, int *, int *, int *, int));
static void set_output_cursor P_ ((struct cursor_pos *));
static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
- int *, int *, int *));
+ int *, int *, int *, int));
static void note_mode_line_highlight P_ ((struct window *, int, int));
static void note_mouse_highlight P_ ((struct frame *, int, int));
static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
enum draw_glyphs_face));
static void x_update_end P_ ((struct frame *));
static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
static void XTset_terminal_modes P_ ((void));
static void XTreset_terminal_modes P_ ((void));
static void XTcursor_to P_ ((int, int, int, int));
static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
XRectangle *));
static void expose_frame P_ ((struct frame *, int, int, int, int));
-static void expose_window_tree P_ ((struct window *, XRectangle *));
-static void expose_window P_ ((struct window *, XRectangle *));
+static int expose_window_tree P_ ((struct window *, XRectangle *));
+static int expose_window P_ ((struct window *, XRectangle *));
static void expose_area P_ ((struct window *, struct glyph_row *,
XRectangle *, enum glyph_row_area));
-static void expose_line P_ ((struct window *, struct glyph_row *,
+static int expose_line P_ ((struct window *, struct glyph_row *,
XRectangle *));
static void x_update_cursor_in_window_tree P_ ((struct window *, int));
static void x_update_window_cursor P_ ((struct window *, int));
static void x_erase_phys_cursor P_ ((struct window *));
void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
- enum bitmap_type));
+static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
+ enum fringe_bitmap_type, int left_p));
static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
GC, int));
static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
-static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
-static void note_overwritten_text_cursor P_ ((struct window *, int, int));
+static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
+static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,
+ int, int, int, int));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
unsigned long *));
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
/* Flush display of frame F, or of all frames if F is null. */
int x0, x1, y0, y1;
window_box_edges (w, -1, &x0, &y0, &x1, &y1);
- x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
+ x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
y1 -= 1;
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
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;
}
/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
- arrow bitmaps, or clear the areas where they would be displayed
+ arrow bitmaps, or clear the fringes if no bitmaps are required
before DESIRED_ROW is made current. The window being updated is
found in updated_window. This function It is called from
update_window_line only if it is known that there are differences
struct glyph_row *desired_row;
{
struct window *w = updated_window;
+ struct frame *f;
+ int width, height;
xassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
{
- struct frame *f;
- int width;
-
BLOCK_INPUT;
- x_draw_row_bitmaps (w, desired_row);
-
- /* When a window has disappeared, make sure that no rest of
- full-width rows stays visible in the internal border. */
- if (windows_or_buffers_changed
- && (f = XFRAME (w->frame),
- width = FRAME_INTERNAL_BORDER_WIDTH (f),
- width != 0))
- {
- int height = desired_row->visible_height;
- int x = (window_box_right (w, -1)
- + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- x, y, width, height, False);
- }
+ x_draw_row_fringe_bitmaps (w, desired_row);
+ UNBLOCK_INPUT;
+ }
+ /* When a window has disappeared, make sure that no rest of
+ full-width rows stays visible in the internal border. Could
+ check here if updated_window is the leftmost/rightmost window,
+ but I guess it's not worth doing since vertically split windows
+ are almost never used, internal border is rarely set, and the
+ overhead is very small. */
+ if (windows_or_buffers_changed
+ && desired_row->full_width_p
+ && (f = XFRAME (w->frame),
+ width = FRAME_INTERNAL_BORDER_WIDTH (f),
+ width != 0)
+ && (height = desired_row->visible_height,
+ height > 0))
+ {
+ int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+
+ /* Internal border is drawn below the tool bar. */
+ if (WINDOWP (f->tool_bar_window)
+ && w == XWINDOW (f->tool_bar_window))
+ y -= width;
+
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->pixel_width - width,
+ y, width, height, False);
UNBLOCK_INPUT;
}
}
-/* Draw the bitmap WHICH in one of the areas to the left or right of
+/* Draw the bitmap WHICH in one of the left or right fringes of
window W. ROW is the glyph row for which to display the bitmap; it
determines the vertical position at which the bitmap has to be
drawn. */
static void
-x_draw_bitmap (w, row, which)
+x_draw_fringe_bitmap (w, row, which, left_p)
struct window *w;
struct glyph_row *row;
- enum bitmap_type which;
+ enum fringe_bitmap_type which;
+ int left_p;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_X_DISPLAY (f);
Window window = FRAME_X_WINDOW (f);
int x, y, wd, h, dy;
+ int b1, b2;
unsigned char *bits;
Pixmap pixmap;
GC gc = f->output_data.x->normal_gc;
/* Must clip because of partially visible lines. */
x_clip_to_row (w, row, gc, 1);
+ /* Convert row to frame coordinates. */
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
switch (which)
{
+ case NO_FRINGE_BITMAP:
+ wd = 0;
+ h = 0;
+ break;
+
case LEFT_TRUNCATION_BITMAP:
wd = left_width;
h = left_height;
bits = left_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case OVERLAY_ARROW_BITMAP:
- wd = left_width;
- h = left_height;
+ wd = ov_width;
+ h = ov_height;
bits = ov_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case RIGHT_TRUNCATION_BITMAP:
wd = right_width;
h = right_height;
bits = right_bits;
- x = window_box_right (w, -1);
- x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUED_LINE_BITMAP:
- wd = right_width;
- h = right_height;
+ wd = continued_width;
+ h = continued_height;
bits = continued_bits;
- x = window_box_right (w, -1);
- x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUATION_LINE_BITMAP:
wd = continuation_width;
h = continuation_height;
bits = continuation_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case ZV_LINE_BITMAP:
wd = zv_width;
- h = zv_height;
- bits = zv_bits;
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
+ h = zv_height - (y % zv_period);
+ bits = zv_bits + (y % zv_period);
break;
default:
abort ();
}
- /* Convert to frame coordinates. Set dy to the offset in the row to
- start drawing the bitmap. */
- y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
- dy = (row->height - h) / 2;
-
- /* Draw the bitmap. I believe these small pixmaps can be cached
- by the server. */
- face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
- pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
- face->foreground,
- face->background, depth);
- XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
- XFreePixmap (display, pixmap);
- XSetClipMask (display, gc, None);
-}
-
-
-/* Draw flags bitmaps for glyph row ROW on window W. Call this
- function with input blocked. */
-
-static void
-x_draw_row_bitmaps (w, row)
- struct window *w;
- struct glyph_row *row;
-{
- struct frame *f = XFRAME (w->frame);
- enum bitmap_type bitmap;
- struct face *face;
- int header_line_height = -1;
-
- xassert (interrupt_input_blocked);
+ /* Clip bitmap if too high. */
+ if (h > row->height)
+ h = row->height;
- /* If row is completely invisible, because of vscrolling, we
- don't have to draw anything. */
- if (row->visible_height <= 0)
- return;
+ /* Set dy to the offset in the row to start drawing the bitmap. */
+ dy = (row->height - h) / 2;
- face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
+ face = FACE_FROM_ID (f, FRINGE_FACE_ID);
PREPARE_FACE_FOR_DISPLAY (f, face);
- /* Decide which bitmap to draw at the left side. */
- if (row->overlay_arrow_p)
- bitmap = OVERLAY_ARROW_BITMAP;
- else if (row->truncated_on_left_p)
- bitmap = LEFT_TRUNCATION_BITMAP;
- else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
- bitmap = CONTINUATION_LINE_BITMAP;
- else if (row->indicate_empty_line_p)
- bitmap = ZV_LINE_BITMAP;
+ /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+ the fringe. */
+ b1 = b2 = -1;
+ if (left_p)
+ {
+ if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+ wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+ x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+ - wd
+ - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
+ if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ /* If W has a vertical border to its left, don't draw over it. */
+ int border = ((XFASTINT (w->left) > 0
+ && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ ? 1 : 0);
+ b1 = (window_box_left (w, -1)
+ - FRAME_X_LEFT_FRINGE_WIDTH (f)
+ + border);
+ b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+ }
+ }
else
- bitmap = NO_BITMAP;
-
- /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
- the flags area. */
- if (bitmap == NO_BITMAP
- || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
- {
- /* If W has a vertical border to its left, don't draw over it. */
- int border = ((XFASTINT (w->left) > 0
- && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- ? 1 : 0);
- int left = window_box_left (w, -1);
-
- if (header_line_height < 0)
- header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ {
+ if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+ wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ x = (window_box_right (w, -1)
+ + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
+ /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+ the fringe. */
+ if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ b1 = window_box_right (w, -1);
+ b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ }
+ }
+
+ if (b1 >= 0)
+ {
+ int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
- /* In case the same realized face is used for bitmap areas and
+ /* In case the same realized face is used for fringes and
for something displayed in the text (e.g. face `region' on
mono-displays, the fill style may have been changed to
FillSolid in x_draw_glyph_string_background. */
if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
+ XSetFillStyle (display, face->gc, FillOpaqueStippled);
else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
+ XSetForeground (display, face->gc, face->background);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- face->gc,
- (left
- - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- + border),
+ XFillRectangle (display, window, face->gc,
+ b1,
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
- FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
+ b2,
row->visible_height);
if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+ XSetForeground (display, face->gc, face->foreground);
}
- /* Draw the left bitmap. */
- if (bitmap != NO_BITMAP)
- x_draw_bitmap (w, row, bitmap);
-
- /* Decide which bitmap to draw at the right side. */
- if (row->truncated_on_right_p)
- bitmap = RIGHT_TRUNCATION_BITMAP;
- else if (row->continued_p)
- bitmap = CONTINUED_LINE_BITMAP;
- else
- bitmap = NO_BITMAP;
-
- /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
- the flags area. */
- if (bitmap == NO_BITMAP
- || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
- || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
+ if (which != NO_FRINGE_BITMAP)
{
- int right = window_box_right (w, -1);
-
- if (header_line_height < 0)
- header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
- /* In case the same realized face is used for bitmap areas and
- for something displayed in the text (e.g. face `region' on
- mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
- if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
- else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
- XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- face->gc,
- right,
- WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y)),
- FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
- row->visible_height);
- if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+ /* Draw the bitmap. I believe these small pixmaps can be cached
+ by the server. */
+ pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
+ face->foreground,
+ face->background, depth);
+ XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
+ XFreePixmap (display, pixmap);
}
-
- /* Draw the right bitmap. */
- if (bitmap != NO_BITMAP)
- x_draw_bitmap (w, row, bitmap);
+
+ XSetClipMask (display, gc, None);
}
-\f
-/***********************************************************************
- Line Highlighting
- ***********************************************************************/
-/* External interface to control of standout mode. Not used for X
- frames. Aborts when called. */
+/* Draw fringe bitmaps for glyph row ROW on window W. Call this
+ function with input blocked. */
static void
-XTreassert_line_highlight (new, vpos)
- int new, vpos;
+x_draw_row_fringe_bitmaps (w, row)
+ struct window *w;
+ struct glyph_row *row;
{
- abort ();
-}
+ struct frame *f = XFRAME (w->frame);
+ enum fringe_bitmap_type bitmap;
+ xassert (interrupt_input_blocked);
-/* Call this when about to modify line at position VPOS and change
- whether it is highlighted. Not used for X frames. Aborts when
- called. */
+ /* If row is completely invisible, because of vscrolling, we
+ don't have to draw anything. */
+ if (row->visible_height <= 0)
+ return;
-static void
-x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
- int new_highlight, vpos, y, first_unused_hpos;
-{
- abort ();
+ if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the left fringe. */
+ if (row->overlay_arrow_p)
+ bitmap = OVERLAY_ARROW_BITMAP;
+ else if (row->truncated_on_left_p)
+ bitmap = LEFT_TRUNCATION_BITMAP;
+ else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+ bitmap = CONTINUATION_LINE_BITMAP;
+ else if (row->indicate_empty_line_p)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
+
+ x_draw_fringe_bitmap (w, row, bitmap, 1);
+ }
+
+ if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the right fringe. */
+ if (row->truncated_on_right_p)
+ bitmap = RIGHT_TRUNCATION_BITMAP;
+ else if (row->continued_p)
+ bitmap = CONTINUED_LINE_BITMAP;
+ else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
+
+ x_draw_fringe_bitmap (w, row, bitmap, 0);
+ }
}
+\f
/* This is called when starting Emacs and when restarting after
suspend. When starting Emacs, no X window is mapped. And nothing
4. `:height HEIGHT' specifies that the height of the stretch produced
should be HEIGHT, measured in canonical character units.
- 5. `:relative-height FACTOR' specifies that the height of the the
+ 5. `:relative-height FACTOR' specifies that the height of the
stretch should be FACTOR times the height of the characters having
the glyph property.
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 GLYPH_DEBUG
static void
x_dump_glyph_string (s)
enum draw_glyphs_face));
static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
enum glyph_row_area, int, int,
- enum draw_glyphs_face, int *, int *, int));
+ enum draw_glyphs_face, int));
static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
static void x_set_glyph_string_gc P_ ((struct glyph_string *));
static void x_draw_glyph_string_background P_ ((struct glyph_string *,
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 (s->face->use_box_color_for_shadows_p)
color = s->face->box_color;
+ else if (s->first_glyph->type == IMAGE_GLYPH
+ && s->img->pixmap
+ && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+ color = IMAGE_BACKGROUND (s->img, s->f, 0);
else
{
XGCValues xgcv;
int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
XRectangle *clip_rect;
{
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
int i;
GC gc;
gc = f->output_data.x->white_relief.gc;
else
gc = f->output_data.x->black_relief.gc;
- XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+ XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Top. */
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
left_x + i * left_p, top_y + i,
right_x + 1 - i * right_p, top_y + i);
/* Left. */
if (left_p)
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i);
+ XDrawLine (dpy, window, gc,
+ left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
- XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+ XSetClipMask (dpy, gc, None);
if (raised_p)
gc = f->output_data.x->black_relief.gc;
else
gc = f->output_data.x->white_relief.gc;
- XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
+ XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
/* Bottom. */
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
left_x + i * left_p, bottom_y - i,
right_x + 1 - i * right_p, bottom_y - i);
/* Right. */
if (right_p)
for (i = 0; i < width; ++i)
- XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
+ XDrawLine (dpy, window, gc,
right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
- XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
+ XSetClipMask (dpy, gc, None);
}
if (s->row->full_width_p
&& !s->w->pseudo_window_p)
{
- last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
+ last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
}
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;
|| (s->hl == DRAW_MOUSE_FACE
&& (s->next == NULL
|| s->next->hl != s->hl)));
-
+
x_get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
}
else
{
- unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
- XGCValues xgcv;
XRectangle clip_rect, image_rect, r;
x_get_glyph_string_clip_rect (s, &clip_rect);
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
{
- thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+ thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
raised_p = s->hl == DRAW_IMAGE_RAISED;
}
else
/* Clear rest using the GC of the original non-cursor face. */
if (width < s->background_width)
{
- GC gc = s->face->gc;
int x = s->x + width, y = s->y;
int w = s->background_width - width, h = s->height;
XRectangle r;
+ GC gc;
+ if (s->row->mouse_face_p
+ && cursor_in_mouse_face_p (s->w))
+ {
+ x_set_mouse_face_gc (s);
+ gc = s->gc;
+ }
+ else
+ gc = s->face->gc;
+
x_get_glyph_string_clip_rect (s, &r);
XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
-
+
if (s->face->stipple)
{
/* Fill background with a stipple pattern. */
}
}
}
- else
+ else if (!s->background_filled_p)
x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
s->height);
x_draw_glyph_string (s)
struct glyph_string *s;
{
+ int relief_drawn_p = 0;
+
/* If S draws into the background of its successor, draw the
background of the successor first so that S can draw into it.
This makes S->next use XDrawString instead of XDrawImageString. */
/* Set up S->gc, set clipping and draw S. */
x_set_glyph_string_gc (s);
- x_set_glyph_string_clipping (s);
+
+ /* Draw relief (if any) in advance for char/composition so that the
+ glyph string can be drawn over it. */
+ if (!s->for_overlaps_p
+ && s->face->box != FACE_NO_BOX
+ && (s->first_glyph->type == CHAR_GLYPH
+ || s->first_glyph->type == COMPOSITE_GLYPH))
+
+ {
+ x_set_glyph_string_clipping (s);
+ x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_box (s);
+ x_set_glyph_string_clipping (s);
+ relief_drawn_p = 1;
+ }
+ else
+ x_set_glyph_string_clipping (s);
switch (s->first_glyph->type)
{
ROUND ((maximum descent) / 2), with
ROUND(x) = floor (x + 0.5) */
- if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
+ if (x_use_underline_position_properties
+ && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
y = s->ybase + (long) tem;
else if (s->face->font)
y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
else
- y = s->height - h;
+ y = s->y + s->height - h;
if (s->face->underline_defaulted_p)
XFillRectangle (s->display, s->window, s->gc,
}
}
- /* Draw relief. */
- if (s->face->box != FACE_NO_BOX)
+ /* Draw relief if not yet drawn. */
+ if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
}
/* Adjust base line for subscript/superscript text. */
s->ybase += voffset;
- xassert (s->face && s->face->gc);
+ /* The case that face->gc == 0 is handled when drawing the glyph
+ string by calling PREPARE_FACE_FOR_DISPLAY. */
+ xassert (s->face);
return glyph - s->row->glyphs[s->area];
}
struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
if (start == s->row->used[s->area]
- && s->hl == DRAW_NORMAL_TEXT
&& s->area == TEXT_AREA
- && (s->row->fill_line_p
- || s->face->background != default_face->background
- || s->face->stipple != default_face->stipple))
- s->extends_to_end_of_line_p = 1;
+ && ((s->hl == DRAW_NORMAL_TEXT
+ && (s->row->fill_line_p
+ || s->face->background != default_face->background
+ || s->face->stipple != default_face->stipple
+ || s->row->mouse_face_p))
+ || s->hl == DRAW_MOUSE_FACE
+ || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+ && s->row->fill_line_p)))
+ s->extends_to_end_of_line_p = 1;
/* If S extends its face to the end of the line, set its
background_width to the distance to the right edge of the drawing
DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
DRAW_IMAGE_RAISED draw an image with a raised relief around it
- If REAL_START is non-null, return in *REAL_START the real starting
- position for display. This can be different from START in case
- overlapping glyphs must be displayed. If REAL_END is non-null,
- return in *REAL_END the real end position for display. This can be
- different from END in case overlapping glyphs must be displayed.
-
If OVERLAPS_P is non-zero, draw only the foreground of characters
and clip to the physical height of ROW.
Value is the x-position reached, relative to AREA of W. */
static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
- overlaps_p)
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
struct window *w;
int x;
struct glyph_row *row;
enum glyph_row_area area;
int start, end;
enum draw_glyphs_face hl;
- int *real_start, *real_end;
int overlaps_p;
{
struct glyph_string *head, *tail;
end = min (end, row->used[area]);
start = max (0, start);
start = min (end, start);
- if (real_start)
- *real_start = start;
- if (real_end)
- *real_end = end;
/* Translate X to frame coordinates. Set last_x to the right
end of the drawing area. */
if (row->full_width_p)
{
/* X is relative to the left edge of W, without scroll bars
- or flag areas. */
+ or fringes. */
struct frame *f = XFRAME (w->frame);
- /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
x += window_left_x;
}
x += FRAME_INTERNAL_BORDER_WIDTH (f);
- last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+ last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
}
else
{
DRAW_NORMAL_TEXT, dummy_x, last_x,
overlaps_p);
start = i;
- if (real_start)
- *real_start = start;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
overlaps_p);
for (s = h; s; s = s->next)
s->background_filled_p = 1;
- if (real_start)
- *real_start = i;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
overlaps_p);
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
}
/* Append glyph strings for glyphs following the last glyph
s->background_filled_p = 1;
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
}
}
for (s = head; s; s = s->next)
x_draw_glyph_string (s);
+ if (area == TEXT_AREA
+ && !row->full_width_p
+ /* When drawing overlapping rows, only the glyph strings'
+ foreground is drawn, which doesn't erase a cursor
+ completely. */
+ && !overlaps_p)
+ {
+ int x0 = head ? head->x : x;
+ int x1 = tail ? tail->x + tail->background_width : x;
+
+ x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+ x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+
+ if (XFASTINT (w->left_margin_width) != 0)
+ {
+ int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+ x0 -= left_area_width;
+ x1 -= left_area_width;
+ }
+
+ notice_overwritten_cursor (w, area, x0, x1,
+ row->y, MATRIX_ROW_BOTTOM_Y (row));
+ }
+
/* Value is the x-position up to which drawn, relative to AREA of W.
This doesn't include parts drawn because of overhangs. */
x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
if (!row->full_width_p)
{
- if (area > LEFT_MARGIN_AREA)
+ if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
if (area > TEXT_AREA)
x_reached -= window_box_width (w, TEXT_AREA);
&& row->glyphs[area][i].overlaps_vertically_p);
x_draw_glyphs (w, start_x, row, area, start, i,
- (row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- NULL, NULL, 1);
+ DRAW_NORMAL_TEXT, 1);
}
else
{
struct glyph *start;
int len;
{
- int x, hpos, real_start, real_end;
+ int x, hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
x = x_draw_glyphs (updated_window, output_cursor.x,
updated_row, updated_area,
hpos, hpos + len,
- (updated_row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- &real_start, &real_end, 0);
-
- /* If we drew over the cursor, note that it is not visible any more. */
- note_overwritten_text_cursor (updated_window, real_start,
- real_end - real_start);
+ DRAW_NORMAL_TEXT, 0);
UNBLOCK_INPUT;
int line_height, shift_by_width, shifted_region_width;
struct glyph_row *row;
struct glyph *glyph;
- int frame_x, frame_y, hpos, real_start, real_end;
+ int frame_x, frame_y, hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
/* Write the glyphs. */
hpos = start - row->glyphs[updated_area];
x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
- DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
- note_overwritten_text_cursor (w, real_start, real_end - real_start);
+ DRAW_NORMAL_TEXT, 0);
/* Advance the output cursor. */
output_cursor.hpos += len;
/* Notice if the cursor will be cleared by this operation. */
if (!updated_row->full_width_p)
- note_overwritten_text_cursor (w, output_cursor.hpos, -1);
+ notice_overwritten_cursor (w, updated_area,
+ output_cursor.x, -1,
+ updated_row->y,
+ MATRIX_ROW_BOTTOM_Y (updated_row));
from_x = output_cursor.x;
int x, y, width, height, from_y, to_y, bottom_y;
/* Get frame-relative bounding box of the text display area of W,
- without mode lines. Include in this box the flags areas to the
- left and right of W. */
+ without mode lines. Include in this box the left and right
+ fringe of W. */
window_box (w, -1, &x, &y, &width, &height);
- width += FRAME_X_FLAGS_AREA_WIDTH (f);
- x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
+ width += FRAME_X_FRINGE_WIDTH (f);
+ x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
int x, y, w, h;
{
XRectangle r;
+ int mouse_face_overwritten_p = 0;
TRACE ((stderr, "expose_frame "));
}
TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
- expose_window_tree (XWINDOW (f->root_window), &r);
+ mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
if (WINDOWP (f->tool_bar_window))
- {
- struct window *w = XWINDOW (f->tool_bar_window);
- XRectangle window_rect;
- XRectangle intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.x = window_x;
- window_rect.y = window_y;
- window_rect.width = window_width;
- window_rect.height = window_height;
-
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
+ mouse_face_overwritten_p
+ |= expose_window (XWINDOW (f->tool_bar_window), &r);
#ifndef USE_X_TOOLKIT
if (WINDOWP (f->menu_bar_window))
- {
- struct window *w = XWINDOW (f->menu_bar_window);
- XRectangle window_rect;
- XRectangle intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.x = window_x;
- window_rect.y = window_y;
- window_rect.width = window_width;
- window_rect.height = window_height;
+ mouse_face_overwritten_p
+ |= expose_window (XWINDOW (f->menu_bar_window), &r);
+#endif /* not USE_X_TOOLKIT */
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
+ /* Some window managers support a focus-follows-mouse style with
+ delayed raising of frames. Imagine a partially obscured frame,
+ and moving the mouse into partially obscured mouse-face on that
+ frame. The visible part of the mouse-face will be highlighted,
+ then the WM raises the obscured frame. With at least one WM, KDE
+ 2.1, Emacs is not getting any event for the raising of the frame
+ (even tried with SubstructureRedirectMask), only Expose events.
+ These expose events will draw text normally, i.e. not
+ highlighted. Which means we must redo the highlight here.
+ Subsume it under ``we love X''. --gerd 2001-08-15 */
+ if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
+ {
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ if (f == dpyinfo->mouse_face_mouse_frame)
+ {
+ int x = dpyinfo->mouse_face_mouse_x;
+ int y = dpyinfo->mouse_face_mouse_y;
+ clear_mouse_face (dpyinfo);
+ note_mouse_highlight (f, x, y);
+ }
}
-#endif /* not USE_X_TOOLKIT */
}
/* Redraw (parts) of all windows in the window tree rooted at W that
- intersect R. R contains frame pixel coordinates. */
+ intersect R. R contains frame pixel coordinates. Value is
+ non-zero if the exposure overwrites mouse-face. */
-static void
+static int
expose_window_tree (w, r)
struct window *w;
XRectangle *r;
{
- while (w)
+ struct frame *f = XFRAME (w->frame);
+ int mouse_face_overwritten_p = 0;
+
+ while (w && !FRAME_GARBAGED_P (f))
{
if (!NILP (w->hchild))
- expose_window_tree (XWINDOW (w->hchild), r);
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->hchild), r);
else if (!NILP (w->vchild))
- expose_window_tree (XWINDOW (w->vchild), r);
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->vchild), r);
else
- {
- XRectangle window_rect;
- XRectangle intersection_rect;
- struct frame *f = XFRAME (w->frame);
- int window_x, window_y, window_width, window_height;
-
- /* Frame-relative pixel rectangle of W. */
- window_box (w, -1, &window_x, &window_y, &window_width,
- &window_height);
- window_rect.x
- = (window_x
- - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
- window_rect.y = window_y;
- window_rect.width
- = (window_width
- + FRAME_X_FLAGS_AREA_WIDTH (f)
- + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
- window_rect.height
- = window_height + CURRENT_MODE_LINE_HEIGHT (w);
-
- if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
-
- w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ mouse_face_overwritten_p |= expose_window (w, r);
+
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
}
+
+ return mouse_face_overwritten_p;
}
if (area == TEXT_AREA && row->fill_line_p)
/* If row extends face to end of line write the whole line. */
- x_draw_glyphs (w, 0, row, area,
- 0, row->used[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ x_draw_glyphs (w, 0, row, area, 0, row->used[area],
+ DRAW_NORMAL_TEXT, 0);
else
{
/* Set START_X to the window-relative start position for drawing glyphs of
x_draw_glyphs (w, first_x - start_x, row, area,
first - row->glyphs[area],
last - row->glyphs[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ DRAW_NORMAL_TEXT, 0);
}
}
/* Redraw the parts of the glyph row ROW on window W intersecting
- rectangle R. R is in window-relative coordinates. */
+ rectangle R. R is in window-relative coordinates. Value is
+ non-zero if mouse-face was overwritten. */
-static void
+static int
expose_line (w, row, r)
struct window *w;
struct glyph_row *row;
if (row->mode_line_p || w->pseudo_window_p)
x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
+ DRAW_NORMAL_TEXT, 0);
else
{
if (row->used[LEFT_MARGIN_AREA])
expose_area (w, row, r, TEXT_AREA);
if (row->used[RIGHT_MARGIN_AREA])
expose_area (w, row, r, RIGHT_MARGIN_AREA);
- x_draw_row_bitmaps (w, row);
+ x_draw_row_fringe_bitmaps (w, row);
}
+
+ return row->mouse_face_p;
}
}
-/* Redraw a rectangle of window W. R is a rectangle in window
- relative coordinates. Call this function with input blocked. */
+/* Redraw the part of window W intersection rectangle FR. Pixel
+ coordinates in FR are frame-relative. Call this function with
+ input blocked. Value is non-zero if the exposure overwrites
+ mouse-face. */
-static void
-expose_window (w, r)
+static int
+expose_window (w, fr)
struct window *w;
- XRectangle *r;
+ XRectangle *fr;
{
- struct glyph_row *row;
- int y;
- int yb = window_text_bottom_y (w);
- int cursor_cleared_p;
+ struct frame *f = XFRAME (w->frame);
+ XRectangle wr, r;
+ int mouse_face_overwritten_p = 0;
/* If window is not yet fully initialized, do nothing. This can
happen when toolkit scroll bars are used and a window is split.
Reconfiguring the scroll bar will generate an expose for a newly
created window. */
- if (w->current_matrix == NULL || 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 0;
- /* Turn off the cursor. */
- if (!w->pseudo_window_p
- && x_phys_cursor_in_rect_p (w, r))
+ /* When we're currently updating the window, display and current
+ matrix usually don't agree. Arrange for a thorough display
+ later. */
+ if (w == updated_window)
{
- x_clear_cursor (w);
- cursor_cleared_p = 1;
+ SET_FRAME_GARBAGED (f);
+ return 0;
}
- else
- cursor_cleared_p = 0;
- /* Find the first row intersecting the rectangle R. */
- row = w->current_matrix->rows;
- y = 0;
- while (row->enabled_p
- && y < yb
- && y + row->height < r->y)
- {
- y += row->height;
- ++row;
- }
-
- /* Display the text in the rectangle, one text line at a time. */
- while (row->enabled_p
- && y < yb
- && y < r->y + r->height)
+ /* Frame-relative pixel rectangle of W. */
+ wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
+ wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
+ wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
+ wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+
+ if (x_intersect_rectangles (fr, &wr, &r))
{
- expose_line (w, row, r);
- y += row->height;
- ++row;
- }
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *row;
+ int cursor_cleared_p;
+
+ TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
+ r.x, r.y, r.width, r.height));
- /* Display the mode line if there is one. */
- if (WINDOW_WANTS_MODELINE_P (w)
- && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
- row->enabled_p)
- && row->y < r->y + r->height)
- expose_line (w, row, r);
+ /* Convert to window coordinates. */
+ r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
+ r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
- if (!w->pseudo_window_p)
- {
- /* Draw border between windows. */
- x_draw_vertical_border (w);
+ /* Turn off the cursor. */
+ if (!w->pseudo_window_p
+ && x_phys_cursor_in_rect_p (w, &r))
+ {
+ x_clear_cursor (w);
+ cursor_cleared_p = 1;
+ }
+ else
+ cursor_cleared_p = 0;
+
+ /* Find the first row intersecting the rectangle R. */
+ for (row = w->current_matrix->rows;
+ row->enabled_p;
+ ++row)
+ {
+ int y0 = row->y;
+ int y1 = MATRIX_ROW_BOTTOM_Y (row);
+
+ if ((y0 >= r.y && y0 < r.y + r.height)
+ || (y1 > r.y && y1 < r.y + r.height)
+ || (r.y >= y0 && r.y < y1)
+ || (r.y + r.height > y0 && r.y + r.height < y1))
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (y1 >= yb)
+ break;
+ }
+
+ /* Display the mode line if there is one. */
+ if (WINDOW_WANTS_MODELINE_P (w)
+ && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
+ row->enabled_p)
+ && row->y < r.y + r.height)
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (!w->pseudo_window_p)
+ {
+ /* Draw border between windows. */
+ x_draw_vertical_border (w);
- /* Turn the cursor on again. */
- if (cursor_cleared_p)
- x_update_window_cursor (w, 1);
+ /* Turn the cursor on again. */
+ if (cursor_cleared_p)
+ x_update_window_cursor (w, 1);
+ }
}
+
+ return mouse_face_overwritten_p;
}
struct x_display_info *dpyinfo;
unsigned int state;
{
+ EMACS_UINT mod_meta = meta_modifier;
+ EMACS_UINT mod_alt = alt_modifier;
+ EMACS_UINT mod_hyper = hyper_modifier;
+ EMACS_UINT mod_super = super_modifier;
+ Lisp_Object tem;
+
+ tem = Fget (Vx_alt_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+ tem = Fget (Vx_meta_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+ tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+ tem = Fget (Vx_super_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+
+
return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
- | ((state & ControlMask) ? ctrl_modifier : 0)
- | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
- | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
- | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
- | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
+ | ((state & ControlMask) ? ctrl_modifier : 0)
+ | ((state & dpyinfo->meta_mod_mask) ? mod_meta : 0)
+ | ((state & dpyinfo->alt_mod_mask) ? mod_alt : 0)
+ | ((state & dpyinfo->super_mod_mask) ? mod_super : 0)
+ | ((state & dpyinfo->hyper_mod_mask) ? mod_hyper : 0));
}
static unsigned int
struct x_display_info *dpyinfo;
unsigned int state;
{
- return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
- | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
- | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
- | ((state & shift_modifier) ? ShiftMask : 0)
- | ((state & ctrl_modifier) ? ControlMask : 0)
- | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
+ EMACS_UINT mod_meta = meta_modifier;
+ EMACS_UINT mod_alt = alt_modifier;
+ EMACS_UINT mod_hyper = hyper_modifier;
+ EMACS_UINT mod_super = super_modifier;
+
+ Lisp_Object tem;
+
+ tem = Fget (Vx_alt_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+ tem = Fget (Vx_meta_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+ tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+ tem = Fget (Vx_super_keysym, Qmodifier_value);
+ if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+
+
+ return ( ((state & mod_alt) ? dpyinfo->alt_mod_mask : 0)
+ | ((state & mod_super) ? dpyinfo->super_mod_mask : 0)
+ | ((state & mod_hyper) ? dpyinfo->hyper_mod_mask : 0)
+ | ((state & shift_modifier) ? ShiftMask : 0)
+ | ((state & ctrl_modifier) ? ControlMask : 0)
+ | ((state & mod_meta) ? dpyinfo->meta_mod_mask : 0));
}
/* Convert a keysym to its name. */
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;
}
/* Take proper action when mouse has moved to the mode or header line of
window W, x-position X. MODE_LINE_P non-zero means mouse is on the
mode line. X is relative to the start of the text display area of
- W, so the width of bitmap areas and scroll bars must be subtracted
+ W, so the width of fringes and scroll bars must be subtracted
to get a position relative to the start of the mode line. */
static void
glyph = row->glyphs[TEXT_AREA];
end = glyph + row->used[TEXT_AREA];
x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
- + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+ + FRAME_X_LEFT_FRINGE_WIDTH (f));
while (glyph < end
&& x >= x0 + glyph->pixel_width)
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 = Qnil, 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))
- /* 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)))
+ /* 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];
+ }
- {
- /* Clear the display of the old active region, if any. */
- clear_mouse_face (dpyinfo);
+ /* 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);
- 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;
+ /* Handle the overlay case. */
+ if (!NILP (overlay))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after;
+ int ignore;
+
+ before = Foverlay_start (overlay);
+ after = Foverlay_end (overlay);
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
+ }
+ /* Handle the text property case. */
+ else if (!NILP (mouse_face) && BUFFERP (object))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after, beginning, end;
+ int ignore;
+
+ beginning = Fmarker_position (w->start);
+ end = make_number (BUF_Z (XBUFFER (object))
+ - XFASTINT (w->window_end_pos));
+ before
+ = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, beginning);
+ after
+ = Fnext_single_property_change (position, Qmouse_face,
+ object, end);
+
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+
+ if (BUFFERP (object))
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- /* Handle the text property case. */
- else if (! NILP (mouse_face))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after, beginning, end;
- int ignore;
-
- beginning = Fmarker_position (w->start);
- XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- - XFASTINT (w->window_end_pos)));
- before
- = Fprevious_single_property_change (make_number (pos + 1),
- Qmouse_face,
- w->buffer, beginning);
- after
- = Fnext_single_property_change (position, Qmouse_face,
- w->buffer, end);
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
+ }
+ else if (!NILP (mouse_face) && STRINGP (object))
+ {
+ Lisp_Object b, e;
+ int ignore;
+
+ b = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, Qnil);
+ e = Fnext_single_property_change (position, Qmouse_face,
+ object, Qnil);
+ if (NILP (b))
+ b = make_number (0);
+ if (NILP (e))
+ e = make_number (XSTRING (object)->size - 1);
+ fast_find_string_pos (w, XINT (b), object,
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row,
&dpyinfo->mouse_face_beg_x,
- &dpyinfo->mouse_face_beg_y);
- dpyinfo->mouse_face_past_end
- = !fast_find_position (w, XFASTINT (after),
- &dpyinfo->mouse_face_end_col,
- &dpyinfo->mouse_face_end_row,
- &dpyinfo->mouse_face_end_x,
- &dpyinfo->mouse_face_end_y);
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
- = face_at_buffer_position (w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- }
-
- /* Look for a `help-echo' property. */
- {
- Lisp_Object help, overlay;
-
- /* Check overlays first. */
- help = overlay = Qnil;
- for (i = noverlays - 1; i >= 0 && NILP (help); --i)
- {
- overlay = overlay_vec[i];
- help = Foverlay_get (overlay, Qhelp_echo);
- }
-
- if (!NILP (help))
- {
- help_echo = help;
- help_echo_window = window;
- help_echo_object = overlay;
- help_echo_pos = pos;
+ &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;
}
- else
+ else if (STRINGP (object) && NILP (mouse_face))
{
- /* Try text properties. */
- if ((STRINGP (glyph->object)
- && glyph->charpos >= 0
- && glyph->charpos < XSTRING (glyph->object)->size)
- || (BUFFERP (glyph->object)
- && glyph->charpos >= BEGV
- && glyph->charpos < ZV))
- help = Fget_text_property (make_number (glyph->charpos),
- Qhelp_echo, glyph->object);
-
- if (!NILP (help))
+ /* A string which doesn't have mouse-face, but
+ the text ``under'' it might have. */
+ struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+
+ pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ mouse_face = get_char_property_and_overlay (make_number (pos),
+ Qmouse_face,
+ w->buffer,
+ &overlay);
+ if (!NILP (mouse_face) && !NILP (overlay))
{
- help_echo = help;
- help_echo_window = window;
- help_echo_object = glyph->object;
- help_echo_pos = glyph->charpos;
+ Lisp_Object before = Foverlay_start (overlay);
+ Lisp_Object after = Foverlay_end (overlay);
+ int ignore;
+
+ /* Note that we might not be able to find position
+ BEFORE in the glyph matrix if the overlay is
+ entirely covered by a `display' property. In
+ this case, we overshoot. So let's stop in
+ the glyph matrix before glyphs for OBJECT. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y,
+ object);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y,
+ Qnil);
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ cursor = None;
}
}
}
-
- BEGV = obegv;
- ZV = ozv;
- current_buffer = obuf;
+
+ check_help_echo:
+
+ /* Look for a `help-echo' property. */
+ {
+ Lisp_Object help, overlay;
+
+ /* Check overlays first. */
+ help = overlay = Qnil;
+ for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+ {
+ overlay = overlay_vec[i];
+ help = Foverlay_get (overlay, Qhelp_echo);
+ }
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = overlay;
+ help_echo_pos = pos;
+ }
+ else
+ {
+ Lisp_Object object = glyph->object;
+ int charpos = glyph->charpos;
+
+ /* Try text properties. */
+ if (STRINGP (object)
+ && charpos >= 0
+ && charpos < XSTRING (object)->size)
+ {
+ help = Fget_text_property (make_number (charpos),
+ Qhelp_echo, object);
+ if (NILP (help))
+ {
+ /* If the string itself doesn't specify a help-echo,
+ see if the buffer text ``under'' it does. */
+ struct glyph_row *r
+ = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+ int pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ {
+ help = Fget_char_property (make_number (pos),
+ Qhelp_echo, w->buffer);
+ if (!NILP (help))
+ {
+ charpos = pos;
+ object = w->buffer;
+ }
+ }
+ }
+ }
+ else if (BUFFERP (object)
+ && charpos >= BEGV
+ && charpos < ZV)
+ help = Fget_text_property (make_number (charpos), Qhelp_echo,
+ object);
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = object;
+ help_echo_pos = charpos;
+ }
+ }
}
+
+ BEGV = obegv;
+ ZV = ozv;
+ current_buffer = obuf;
}
+
+ set_cursor:
+
+ if (cursor != None)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
}
static void
int area;
/* Find the glyph under X/Y. */
- *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
+ *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
if (*glyph == NULL)
return -1;
/* Handle mouse button event on the tool-bar of frame F, at
- frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
+ frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress
or ButtonRelase. */
static void
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);
set_help_echo:
- /* Set help_echo to a help string.to display for this tool-bar item.
+ /* Set help_echo to a help string to display for this tool-bar item.
XTread_socket does the rest. */
help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
\f
-/* Find the glyph matrix position of buffer position POS in window W.
- *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
- current glyphs must be up to date. If POS is above window start
- return (0, 0, 0, 0). If POS is after end of W, return end of
- last line in W. */
+/* Find the glyph matrix position of buffer position CHARPOS in window
+ *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
+ current glyphs must be up to date. If CHARPOS is above window
+ start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
+ of last line in W. In the row containing CHARPOS, stop before glyphs
+ having STOP as object. */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+ in the presence of hscrolling, for example. I didn't install
+ it right away because the problem fixed is minor, it failed
+ in 20.x as well, and I think it's too risky to install
+ so near the release of 21.1. 2001-09-25 gerd. */
static int
-fast_find_position (w, pos, hpos, vpos, x, y)
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
+ struct window *w;
+ int charpos;
+ int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
+{
+ struct glyph_row *row, *first;
+ struct glyph *glyph, *end;
+ int i, past_end = 0;
+
+ first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row = row_containing_pos (w, charpos, first, NULL, 0);
+ if (row == NULL)
+ {
+ if (charpos < MATRIX_ROW_START_CHARPOS (first))
+ {
+ *x = *y = *hpos = *vpos = 0;
+ return 0;
+ }
+ else
+ {
+ row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ past_end = 1;
+ }
+ }
+
+ *x = row->x;
+ *y = row->y;
+ *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
+ glyph = row->glyphs[TEXT_AREA];
+ end = glyph + row->used[TEXT_AREA];
+
+ /* Skip over glyphs not having an object at the start of the row.
+ These are special glyphs like truncation marks on terminal
+ frames. */
+ if (row->displays_text_p)
+ while (glyph < end
+ && INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && glyph->charpos < 0)
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ while (glyph < end
+ && !INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < charpos))
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ *hpos = glyph - row->glyphs[TEXT_AREA];
+ return past_end;
+}
+
+#else /* not 0 */
+
+static int
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
struct window *w;
int pos;
int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
{
int i;
int lastcol;
int maybe_next_line_p = 0;
int line_start_position;
int yb = window_text_bottom_y (w);
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
- struct glyph_row *best_row = row;
- int row_vpos = 0, best_row_vpos = 0;
+ struct glyph_row *row, *best_row;
+ int row_vpos, best_row_vpos;
int current_x;
+ row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
while (row->y < yb)
{
if (row->used[TEXT_AREA])
for (i = 0; i < best_row->used[TEXT_AREA]; i++)
{
struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
- int charpos;
+ int charpos = glyph->charpos;
- charpos = glyph->charpos;
- if (charpos == pos)
+ if (BUFFERP (glyph->object))
{
- *hpos = i;
- *vpos = best_row_vpos;
- *x = current_x;
- *y = best_row->y;
- return 1;
+ if (charpos == pos)
+ {
+ *hpos = i;
+ *vpos = best_row_vpos;
+ *x = current_x;
+ *y = best_row->y;
+ return 1;
+ }
+ else if (charpos > pos)
+ break;
}
- else if (charpos > pos)
+ else if (EQ (glyph->object, stop))
break;
- else if (charpos > 0)
- lastcol = i;
+ if (charpos > 0)
+ lastcol = i;
current_x += glyph->pixel_width;
}
return 0;
}
+#endif /* not 0 */
+
+
+/* Find the position of the 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. */
{
struct window *w = XWINDOW (dpyinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
- int i;
- int cursor_off_p = 0;
- struct cursor_pos saved_cursor;
-
- saved_cursor = output_cursor;
-
- /* If window is in the process of being destroyed, don't bother
- to do anything. */
- if (w->current_matrix == NULL)
- goto set_x_cursor;
-
- /* Recognize when we are called to operate on rows that don't exist
- anymore. This can happen when a window is split. */
- if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
- goto set_x_cursor;
- set_output_cursor (&w->phys_cursor);
-
- /* Note that mouse_face_beg_row etc. are window relative. */
- for (i = dpyinfo->mouse_face_beg_row;
- i <= dpyinfo->mouse_face_end_row;
- i++)
+ if (/* If window is in the process of being destroyed, don't bother
+ to do anything. */
+ w->current_matrix != NULL
+ /* Recognize when we are called to operate on rows that don't exist
+ anymore. This can happen when a window is split. */
+ && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
{
- int start_hpos, end_hpos, start_x;
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
-
- /* Don't do anything if row doesn't have valid contents. */
- if (!row->enabled_p)
- continue;
+ int phys_cursor_on_p = w->phys_cursor_on_p;
+ struct glyph_row *row, *first, *last;
- /* For all but the first row, the highlight starts at column 0. */
- if (i == dpyinfo->mouse_face_beg_row)
- {
- start_hpos = dpyinfo->mouse_face_beg_col;
- start_x = dpyinfo->mouse_face_beg_x;
- }
- else
+ first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+ last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+
+ for (row = first; row <= last && row->enabled_p; ++row)
{
- start_hpos = 0;
- start_x = 0;
- }
+ int start_hpos, end_hpos, start_x;
- if (i == dpyinfo->mouse_face_end_row)
- end_hpos = dpyinfo->mouse_face_end_col;
- else
- end_hpos = row->used[TEXT_AREA];
+ /* For all but the first row, the highlight starts at column 0. */
+ if (row == first)
+ {
+ start_hpos = dpyinfo->mouse_face_beg_col;
+ start_x = dpyinfo->mouse_face_beg_x;
+ }
+ else
+ {
+ start_hpos = 0;
+ start_x = 0;
+ }
- /* If the cursor's in the text we are about to rewrite, turn the
- cursor off. */
- if (!w->pseudo_window_p
- && i == output_cursor.vpos
- && output_cursor.hpos >= start_hpos - 1
- && output_cursor.hpos <= end_hpos)
- {
- x_update_window_cursor (w, 0);
- cursor_off_p = 1;
- }
+ if (row == last)
+ end_hpos = dpyinfo->mouse_face_end_col;
+ else
+ end_hpos = row->used[TEXT_AREA];
- if (end_hpos > start_hpos)
- {
- row->mouse_face_p = draw == DRAW_MOUSE_FACE;
- x_draw_glyphs (w, start_x, row, TEXT_AREA,
- start_hpos, end_hpos, draw, NULL, NULL, 0);
- }
- }
+ if (end_hpos > start_hpos)
+ {
+ x_draw_glyphs (w, start_x, row, TEXT_AREA,
+ start_hpos, end_hpos, draw, 0);
- /* If we turned the cursor off, turn it back on. */
- if (cursor_off_p)
- x_display_cursor (w, 1,
- output_cursor.hpos, output_cursor.vpos,
- output_cursor.x, output_cursor.y);
+ row->mouse_face_p
+ = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+ }
+ }
- output_cursor = saved_cursor;
+ /* When we've written over the cursor, arrange for it to
+ be displayed again. */
+ if (phys_cursor_on_p && !w->phys_cursor_on_p)
+ x_display_cursor (w, 1,
+ w->phys_cursor.hpos, w->phys_cursor.vpos,
+ w->phys_cursor.x, w->phys_cursor.y);
+ }
- set_x_cursor:
-
/* Change the mouse cursor. */
if (draw == DRAW_NORMAL_TEXT)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
}
/* 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;
}
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);
}
+#if defined USE_LUCID
+
+/* Return the Lucid menu bar WINDOW is part of. Return null
+ if WINDOW is not part of a menu bar. */
+
+static Widget
+x_window_to_menu_bar (window)
+ Window window;
+{
+ Lisp_Object tail;
+
+ for (tail = Vframe_list;
+ XGCTYPE (tail) == Lisp_Cons;
+ tail = XCDR (tail))
+ {
+ Lisp_Object frame = XCAR (tail);
+ Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+
+ if (menu_bar && xlwmenu_window_p (menu_bar, window))
+ return menu_bar;
+ }
+
+ return NULL;
+}
+
+#endif /* USE_LUCID */
+
\f
/************************************************************************
Toolkit scroll bars
{
struct scroll_bar *bar = (struct scroll_bar *) client_data;
XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
- double percent;
int part = -1, whole = 0, portion = 0;
switch (cs->reason)
UNBLOCK_INPUT;
/* At the max position of the scroll bar, do a line-wise
- movement. Without doing anything, the LessTif scroll bar
- calls us with the same cs->value again and again. If we
- want to make sure that we can reach the end of the buffer,
- we have to do something.
+ movement. Without doing anything, we would be called with
+ the same cs->value again and again. If we want to make
+ sure that we can reach the end of the buffer, we have to do
+ something.
Implementation note: setting bar->dragging always to
cs->value gives a smoother movement at the max position.
BLOCK_INPUT;
#ifdef USE_MOTIF
- /* LessTif 0.85, problems:
-
- 1. When the mouse if over the scroll bar, the scroll bar will
- get keyboard events. I didn't find a way to turn this off.
-
- 2. Do we have to explicitly set the cursor to get an arrow
- cursor (see below)? */
-
/* Set resources. Create the widget. */
XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
/* For smoother scrolling with Xaw3d -sm */
/* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
- /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
pixel = f->output_data.x->scroll_bar_foreground_pixel;
if (pixel != -1)
XtSetArg (av[ac], XtNbackground, pixel);
++ac;
}
-
+
+ /* Top/bottom shadow colors. */
+
+ /* Allocate them, if necessary. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ &pixel, 1.2, 0x8000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+ }
+ if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ {
+ pixel = f->output_data.x->scroll_bar_background_pixel;
+ if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ &pixel, 0.6, 0x4000))
+ pixel = -1;
+ f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+ }
+
+ /* Tell the toolkit about them. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
+ || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
+ /* We tried to allocate a color for the top/bottom shadow, and
+ failed, so tell Xaw3d to use dithering instead. */
+ {
+ XtSetArg (av[ac], XtNbeNiceToColormap, True);
+ ++ac;
+ }
+ else
+ /* Tell what colors Xaw3d should use for the top/bottom shadow, to
+ be more consistent with other emacs 3d colors, and since Xaw3d is
+ not good at dealing with allocation failure. */
+ {
+ /* This tells Xaw3d to use real colors instead of dithering for
+ the shadows. */
+ XtSetArg (av[ac], XtNbeNiceToColormap, False);
+ ++ac;
+
+ /* Specify the colors. */
+ pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], "topShadowPixel", pixel);
+ ++ac;
+ }
+ pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
+ if (pixel != -1)
+ {
+ XtSetArg (av[ac], "bottomShadowPixel", pixel);
+ ++ac;
+ }
+ }
+
widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
f->output_data.x->edit_widget, av, ac);
#ifdef USE_MOTIF
{
int size, value;
- Boolean arrow1_selected, arrow2_selected;
- unsigned char flags;
- XmScrollBarWidget sb;
/* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
is the scroll bar's maximum and MIN is the scroll bar's minimum
value = min (value, XM_SB_MAX - size);
value = max (value, XM_SB_MIN);
- /* LessTif: Calling XmScrollBarSetValues after an increment or
- decrement turns off auto-repeat LessTif-internally. This can
- be seen in ScrollBar.c which resets Arrow1Selected and
- Arrow2Selected. It also sets internal flags so that LessTif
- believes the mouse is in the slider. We either have to change
- our code, or work around that by accessing private data. */
-
- sb = (XmScrollBarWidget) widget;
- arrow1_selected = sb->scrollBar.arrow1_selected;
- arrow2_selected = sb->scrollBar.arrow2_selected;
- flags = sb->scrollBar.flags;
-
if (NILP (bar->dragging))
XmScrollBarSetValues (widget, value, size, 0, 0, False);
else if (last_scroll_bar_part == scroll_bar_down_arrow)
min (size, XM_SB_RANGE - old_value),
0, 0, False);
}
-
- sb->scrollBar.arrow1_selected = arrow1_selected;
- sb->scrollBar.arrow2_selected = arrow2_selected;
- sb->scrollBar.flags = flags;
}
#else /* !USE_MOTIF i.e. use Xaw */
{
/* Clear the area of W that will serve as a scroll bar. This is
for the case that a window has been split horizontally. In
this case, no clear_frame is generated to reduce flickering. */
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width,
- window_box_height (w), False);
+ if (width > 0 && height > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width,
+ window_box_height (w), False);
window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
/* Position and size of scroll bar. */
/* 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,
/* Does the scroll bar exist yet? */
if (NILP (w->vertical_scroll_bar))
{
- BLOCK_INPUT;
- if (width && height)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, False);
- UNBLOCK_INPUT;
+ if (width > 0 && height > 0)
+ {
+ BLOCK_INPUT;
+ 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);
}
else
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
- if (width && height)
+ if (width > 0 && height > 0)
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left, top, width, height, False);
#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 && height > 0)
+ {
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left + area_width - rest, top,
+ rest, height, False);
+ else
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, rest, height, False);
+ }
+ }
/* Move/size the scroll bar window. */
if (mask)
me that letting the compiler initialize it to zeros will work okay.
This must be defined outside of XTread_socket, for the same reasons
- given for enter_time stamp, above. */
+ given for enter_timestamp, above. */
static XComposeStatus compose_status;
&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);
f = x_window_to_frame (dpyinfo, event.xexpose.window);
if (f)
{
+ x_check_fullscreen (f);
+
if (f->async_visible == 0)
{
f->async_visible = 1;
}
else
{
+#ifndef USE_TOOLKIT_SCROLL_BARS
+ struct scroll_bar *bar;
+#endif
+#if defined USE_LUCID
+ /* Submenus of the Lucid menu bar aren't widgets
+ themselves, so there's no way to dispatch events
+ to them. Recognize this case separately. */
+ {
+ Widget widget
+ = x_window_to_menu_bar (event.xexpose.window);
+ if (widget)
+ xlwmenu_redisplay (widget);
+ }
+#endif /* USE_LUCID */
+
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Dispatch event to the widget. */
goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
- struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xexpose.window);
+ bar = x_window_to_scroll_bar (event.xexpose.window);
if (bar)
x_scroll_bar_expose (bar, &event);
break;
case GraphicsExpose: /* This occurs when an XCopyArea's
- source area was obscured or not
- available.*/
+ source area was obscured or not
+ available. */
f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
if (f)
{
case NoExpose: /* This occurs when an XCopyArea's
source area was completely
- available */
+ available. */
break;
case UnmapNotify:
f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
if (f) /* F may no longer exist if
- the frame was deleted. */
+ the frame was deleted. */
{
/* While a frame is unmapped, display generation is
disabled; you don't want to spend time updating a
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
- /* I couldn't find a way to prevent LessTif scroll bars
- from consuming key events. */
if (f == 0)
{
+ /* Scroll bars consume key events, but we want
+ the keys to go to the scroll bar's frame. */
Widget widget = XtWindowToWidget (dpyinfo->display,
event.xkey.window);
if (widget && XmIsScrollBar (widget))
status_return even if the input is too long to
fit in 81 bytes. So, we must prepare sufficient
bytes for copy_buffer. 513 bytes (256 chars for
- two-byte character set) seems to be a faily good
+ two-byte character set) seems to be a fairly good
approximation. -- 2000.8.10 handa@etl.go.jp */
unsigned char copy_buffer[513];
unsigned char *copy_bufptr = copy_buffer;
|| IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
|| IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
/* Any "vendor-specific" key is ok. */
- || (orig_keysym & (1 << 28)))
+ || (orig_keysym & (1 << 28))
+ || (keysym != NoSymbol && nbytes == 0))
&& ! (IsModifierKey (orig_keysym)
#ifndef HAVE_X11R5
#ifdef XK_Mode_switch
character events. */
for (i = 0; i < nbytes; i += len)
{
- c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
- nbytes - i, len);
+ if (nchars == nbytes)
+ c = copy_bufptr[i], len = 1;
+ else
+ c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+ nbytes - i, len);
+
bufp->kind = (SINGLE_BYTE_CHAR_P (c)
? ascii_keystroke
: multibyte_char_keystroke);
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 0
+ if (event.xcrossing.focus)
{
/* Avoid nasty pop/raise loops. */
if (f && (!(f->auto_raise)
}
else if (f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
-
+#endif
+
/* EnterNotify counts as mouse movement,
so update things that depend on mouse position. */
if (f && !f->output_data.x->hourglass_p)
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 0
+ if (event.xcrossing.focus)
x_mouse_leave (dpyinfo);
else
{
if (f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
}
+#endif
}
goto OTHER;
if (f)
{
#ifndef USE_X_TOOLKIT
+ /* If there is a pending resize for fullscreen, don't
+ do this one, the right one will come later.
+ The toolkit version doesn't seem to need this, but we
+ need to reset it below. */
+ int dont_resize =
+ ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+ && FRAME_NEW_WIDTH (f) != 0);
int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+ if (dont_resize)
+ goto OTHER;
/* In the toolkit version, change_frame_size
is called by the code that handles resizing
x_real_positions (f, &f->output_data.x->left_pos,
&f->output_data.x->top_pos);
+ x_check_fullscreen_move(f);
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+ f->output_data.x->want_fullscreen &=
+ ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
#ifdef HAVE_X_I18N
if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
xic_set_statusarea (f);
Text Cursor
***********************************************************************/
-/* Note if the text cursor of window W has been overwritten by a
- drawing operation that outputs N glyphs starting at HPOS in the
- line given by output_cursor.vpos. N < 0 means all the rest of the
- line after HPOS has been written. */
+/* Notice when the text cursor of window W has been completely
+ overwritten by a drawing operation that outputs glyphs in AREA
+ starting at X0 and ending at X1 in the line starting at Y0 and
+ ending at Y1. X coordinates are area-relative. X1 < 0 means all
+ the rest of the line after X0 has been written. Y coordinates
+ are window-relative. */
static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
struct window *w;
- int hpos, n;
-{
- if (updated_area == TEXT_AREA
- && output_cursor.vpos == w->phys_cursor.vpos
- && hpos <= w->phys_cursor.hpos
- && (n < 0
- || hpos + n > w->phys_cursor.hpos))
+ enum glyph_row_area area;
+ int x0, y0, x1, y1;
+{
+ if (area == TEXT_AREA
+ && w->phys_cursor_on_p
+ && y0 <= w->phys_cursor.y
+ && y1 >= w->phys_cursor.y + w->phys_cursor_height
+ && x0 <= w->phys_cursor.x
+ && (x1 < 0 || x1 > w->phys_cursor.x))
w->phys_cursor_on_p = 0;
}
the rectangle to the left and increase its width. */
if (whole_line_p)
{
- clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
- clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
+ clip_rect.x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+ clip_rect.width += FRAME_X_FRINGE_WIDTH (f);
}
XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
{
struct frame *f = XFRAME (w->frame);
struct glyph *cursor_glyph;
- GC gc;
- int x;
- unsigned long mask;
- XGCValues xgcv;
- Display *dpy;
- Window window;
/* If cursor is out of bounds, don't draw garbage. This can happen
in mini-buffer windows when switching between echo area glyphs
}
else
{
- xgcv.background = f->output_data.x->cursor_pixel;
- xgcv.foreground = f->output_data.x->cursor_pixel;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
+ GC gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+ unsigned long mask = GCForeground | GCBackground | GCGraphicsExposures;
+ struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
+ XGCValues xgcv;
+
+ /* If the glyph's background equals the color we normally draw
+ the bar cursor in, the bar cursor in its normal color is
+ invisible. Use the glyph's foreground color instead in this
+ case, on the assumption that the glyph's colors are chosen so
+ that the glyph is legible. */
+ if (face->background == f->output_data.x->cursor_pixel)
+ xgcv.background = xgcv.foreground = face->foreground;
+ else
+ xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
xgcv.graphics_exposures = 0;
- mask = GCForeground | GCBackground | GCGraphicsExposures;
- dpy = FRAME_X_DISPLAY (f);
- window = FRAME_X_WINDOW (f);
- gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
if (width < 0)
width = f->output_data.x->cursor_width;
+ width = min (cursor_glyph->pixel_width, width);
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
x_clip_to_row (w, row, gc, 0);
XFillRectangle (dpy, window, gc,
- x,
+ WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- min (cursor_glyph->pixel_width, width),
- row->height);
+ width, row->height);
XSetClipMask (dpy, gc, None);
}
}
glyphs and mini-buffer. */
if (w->phys_cursor.hpos < row->used[TEXT_AREA])
{
+ int on_p = w->phys_cursor_on_p;
+
x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
- hl, 0, 0, 0);
+ hl, 0);
+ w->phys_cursor_on_p = on_p;
/* When we erase the cursor, and ROW is overlapped by other
rows, make sure that these overlapping parts of other rows
if (!cursor_row->enabled_p)
goto mark_cursor_off;
+ /* If row is completely invisible, don't attempt to delete a cursor which
+ isn't there. This can happen if cursor is at top of a window, and
+ we switch to a buffer with a header line in that window. */
+ if (cursor_row->visible_height <= 0)
+ goto mark_cursor_off;
+
/* This can happen when the new row is shorter than the old one.
In this case, either x_draw_glyphs or clear_end_of_line
should have cleared the cursor. Note that we wouldn't be
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,
/* Erase the cursor by redrawing the character underneath it. */
if (mouse_face_here_p)
hl = DRAW_MOUSE_FACE;
- else if (cursor_row->inverse_p)
- hl = DRAW_INVERSE_VIDEO;
else
hl = DRAW_NORMAL_TEXT;
x_draw_phys_cursor_glyph (w, cursor_row, hl);
}
+/* 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. */
struct glyph_matrix *current_glyphs;
struct glyph_row *glyph_row;
struct glyph *glyph;
+ int cursor_non_selected;
/* This is pointless on invisible frames, and dangerous on garbaged
windows and frames; in the latter case, the frame or window may
the cursor type given by the frame parameter. If explicitly
marked off, draw no cursor. In all other cases, we want a hollow
box cursor. */
+ cursor_non_selected
+ = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+ w->buffer));
new_cursor_width = -1;
if (cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f)
{
if (w == XWINDOW (echo_area_window))
new_cursor_type = FRAME_DESIRED_CURSOR (f);
- else
+ else if (cursor_non_selected)
new_cursor_type = HOLLOW_BOX_CURSOR;
+ else
+ new_cursor_type = NO_CURSOR;
}
else
{
if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
|| w != XWINDOW (f->selected_window))
{
- extern int cursor_in_non_selected_windows;
-
- if (MINI_WINDOW_P (w)
- || !cursor_in_non_selected_windows
+ if ((MINI_WINDOW_P (w) && minibuf_level == 0)
+ || !cursor_non_selected
|| NILP (XBUFFER (w->buffer)->cursor_type))
new_cursor_type = NO_CURSOR;
else
\f
/* Icons. */
-/* Refresh bitmap kitchen sink icon for frame F
- when we get an expose event for it. */
-
-void
-refreshicon (f)
- struct frame *f;
-{
- /* Normally, the window manager handles this function. */
-}
-
/* Make the x-window of frame F use the gnu icon bitmap. */
int
Handling X errors
************************************************************************/
+/* Error message passed to x_connection_closed. */
+
+static char *error_msg;
+
+/* Function installed as fatal_error_signal_hook in
+ x_connection_closed. Print the X error message, and exit normally,
+ instead of dumping core when XtCloseDisplay fails. */
+
+static void
+x_fatal_error_signal ()
+{
+ fprintf (stderr, "%s\n", error_msg);
+ exit (70);
+}
+
/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
the text of an error message that lead to the connection loss. */
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
int count;
- char *msg;
- msg = (char *) alloca (strlen (error_message) + 1);
- strcpy (msg, error_message);
+ error_msg = (char *) alloca (strlen (error_message) + 1);
+ strcpy (error_msg, error_message);
handling_signal = 0;
/* Prevent being called recursively because of an error condition
/* If DPYINFO is null, this means we didn't open the display
in the first place, so don't try to close it. */
if (dpyinfo)
- XtCloseDisplay (dpy);
+ {
+ extern void (*fatal_error_signal_hook) P_ ((void));
+ fatal_error_signal_hook = x_fatal_error_signal;
+ XtCloseDisplay (dpy);
+ fatal_error_signal_hook = NULL;
+ }
#endif
/* Indicate that this display is dead. */
if (x_display_list == 0)
{
- fprintf (stderr, "%s\n", msg);
+ fprintf (stderr, "%s\n", error_msg);
shut_down_emacs (0, 0, Qnil);
exit (70);
}
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
- error ("%s", msg);
+ error ("%s", error_msg);
}
f->output_data.x->font = (XFontStruct *) (fontp->font);
f->output_data.x->baseline_offset = fontp->baseline_offset;
f->output_data.x->fontset = -1;
-
+
+ x_compute_fringe_widths (f, 1);
+
/* Compute the scroll bar width in character columns. */
if (f->scroll_bar_pixel_width > 0)
{
return build_string (fontsetname);
}
+/* Compute actual fringe widths */
+
+void
+x_compute_fringe_widths (f, redraw)
+ struct frame *f;
+ int redraw;
+{
+ int o_left = f->output_data.x->left_fringe_width;
+ int o_right = f->output_data.x->right_fringe_width;
+ int o_cols = f->output_data.x->fringe_cols;
+
+ Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+ Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+ int left_fringe_width, right_fringe_width;
+
+ if (!NILP (left_fringe))
+ left_fringe = Fcdr (left_fringe);
+ if (!NILP (right_fringe))
+ right_fringe = Fcdr (right_fringe);
+
+ left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+ XINT (left_fringe));
+ right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+ XINT (right_fringe));
+
+ if (left_fringe_width || right_fringe_width)
+ {
+ int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+ int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+ int conf_wid = left_wid + right_wid;
+ int font_wid = FONT_WIDTH (f->output_data.x->font);
+ int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+ int real_wid = cols * font_wid;
+ if (left_wid && right_wid)
+ {
+ if (left_fringe_width < 0)
+ {
+ /* Left fringe width is fixed, adjust right fringe if necessary */
+ f->output_data.x->left_fringe_width = left_wid;
+ f->output_data.x->right_fringe_width = real_wid - left_wid;
+ }
+ else if (right_fringe_width < 0)
+ {
+ /* Right fringe width is fixed, adjust left fringe if necessary */
+ f->output_data.x->left_fringe_width = real_wid - right_wid;
+ f->output_data.x->right_fringe_width = right_wid;
+ }
+ else
+ {
+ /* Adjust both fringes with an equal amount.
+ Note that we are doing integer arithmetic here, so don't
+ lose a pixel if the total width is an odd number. */
+ int fill = real_wid - conf_wid;
+ f->output_data.x->left_fringe_width = left_wid + fill/2;
+ f->output_data.x->right_fringe_width = right_wid + fill - fill/2;
+ }
+ }
+ else if (left_fringe_width)
+ {
+ f->output_data.x->left_fringe_width = real_wid;
+ f->output_data.x->right_fringe_width = 0;
+ }
+ else
+ {
+ f->output_data.x->left_fringe_width = 0;
+ f->output_data.x->right_fringe_width = real_wid;
+ }
+ f->output_data.x->fringe_cols = cols;
+ f->output_data.x->fringes_extra = real_wid;
+ }
+ else
+ {
+ f->output_data.x->left_fringe_width = 0;
+ f->output_data.x->right_fringe_width = 0;
+ f->output_data.x->fringe_cols = 0;
+ f->output_data.x->fringes_extra = 0;
+ }
+
+ if (redraw && FRAME_VISIBLE_P (f))
+ if (o_left != f->output_data.x->left_fringe_width ||
+ o_right != f->output_data.x->right_fringe_width ||
+ o_cols != f->output_data.x->fringe_cols)
+ redraw_frame (f);
+}
\f
/***********************************************************************
X Input Methods
#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
}
UNBLOCK_INPUT;
}
+/* Check if we need to resize the frame due to a fullscreen request.
+ If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+ struct frame *f;
+{
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
+ {
+ int width, height, ign;
+
+ x_real_positions (f, &f->output_data.x->left_pos,
+ &f->output_data.x->top_pos);
+
+ x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+
+ /* We do not need to move the window, it shall be taken care of
+ when setting WM manager hints.
+ If the frame is visible already, the position is checked by
+ x_check_fullscreen_move. */
+ if (f->width != width || f->height != height)
+ {
+ change_frame_size (f, height, width, 0, 1, 0);
+ SET_FRAME_GARBAGED (f);
+ cancel_mouse_face (f);
+
+ /* Wait for the change of frame size to occur */
+ f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
+
+ }
+ }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+ the window. This is done in xfns.c.
+ Some window managers moves the window to the right position, some
+ moves the outer window manager window to the specified position.
+ Here we check that we are in the right spot. If not, make a second
+ move, assuming we are dealing with the second kind of window manager. */
+static void
+x_check_fullscreen_move (f)
+ struct frame *f;
+{
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+ {
+ int expect_top = f->output_data.x->top_pos;
+ int expect_left = f->output_data.x->left_pos;
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+ expect_top = 0;
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+ expect_left = 0;
+
+ if (expect_top != f->output_data.x->top_pos
+ || expect_left != f->output_data.x->left_pos)
+ x_set_offset (f, expect_left, expect_top, 1);
+
+ /* Just do this once */
+ f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+ }
+}
+
+
+/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
+ wanted positions of the WM window (not emacs window).
+ Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+ window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+ struct frame *f;
+ int *width;
+ int *height;
+ int *top_pos;
+ int *left_pos;
+{
+ int newwidth = f->width, newheight = f->height;
+
+ *top_pos = f->output_data.x->top_pos;
+ *left_pos = f->output_data.x->left_pos;
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+ {
+ int ph;
+
+ ph = FRAME_X_DISPLAY_INFO (f)->height;
+ newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+ ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+ - f->output_data.x->y_pixels_diff;
+ newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+ *top_pos = 0;
+ }
+
+ if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+ {
+ int pw;
+
+ pw = FRAME_X_DISPLAY_INFO (f)->width;
+ newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+ pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+ - f->output_data.x->x_pixels_diff;
+ newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+ *left_pos = 0;
+ }
+
+ *width = newwidth;
+ *height = newheight;
+}
+
/* Change the size of frame F's X window to COLS/ROWS in the case F
doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
: FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
: (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
- f->output_data.x->flags_areas_extra
- = FRAME_FLAGS_AREA_WIDTH (f);
+
+ x_compute_fringe_widths (f, 0);
+
pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Lisp_Object bar;
+ struct scroll_bar *b;
BLOCK_INPUT;
{
if (f->output_data.x->icon_desc)
XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
-
+
+#ifdef USE_X_TOOLKIT
+ /* Explicitly destroy the scroll bars of the frame. Without
+ this, we get "BadDrawable" errors from the toolkit later on,
+ presumably from expose events generated for the disappearing
+ toolkit scroll bars. */
+ for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next)
+ {
+ b = XSCROLL_BAR (bar);
+ x_scroll_bar_remove (b);
+ }
+#endif
+
#ifdef HAVE_X_I18N
if (FRAME_XIC (f))
free_frame_xic (f);
#endif
-
- if (FRAME_X_WINDOW (f))
- XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-
+
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
- XtDestroyWidget (f->output_data.x->widget);
+ {
+ XtDestroyWidget (f->output_data.x->widget);
+ f->output_data.x->widget = NULL;
+ }
+ /* Tooltips don't have widgets, only a simple X window, even if
+ we are using a toolkit. */
+ else if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+
free_frame_menubar (f);
-#endif /* USE_X_TOOLKIT */
+#else /* !USE_X_TOOLKIT */
+ if (FRAME_X_WINDOW (f))
+ XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+#endif /* !USE_X_TOOLKIT */
unload_color (f, f->output_data.x->foreground_pixel);
unload_color (f, f->output_data.x->background_pixel);
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
unload_color (f, f->output_data.x->mouse_pixel);
-
+
if (f->output_data.x->scroll_bar_background_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_background_pixel);
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ /* Scrollbar shadow colors. */
+ if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
+ if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
+ unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
+#endif /* USE_TOOLKIT_SCROLL_BARS */
if (f->output_data.x->white_relief.allocated_p)
unload_color (f, f->output_data.x->white_relief.pixel);
if (f->output_data.x->black_relief.allocated_p)
}
}
}
+
if (!try_XLoadQueryFont)
- XFreeFontNames (names);
+ {
+ BLOCK_INPUT;
+ XFreeFontNames (names);
+ UNBLOCK_INPUT;
+ }
}
/* Now store the result in the cache. */
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
label_cached:
if (NILP (list)) continue; /* Try the remaining alternatives. */
if (thisinfo)
{
- XCDR (tem)
- = (thisinfo->min_bounds.width == 0
- ? make_number (0)
- : make_number (thisinfo->max_bounds.width));
+ XSETCDR (tem,
+ (thisinfo->min_bounds.width == 0
+ ? make_number (0)
+ : make_number (thisinfo->max_bounds.width)));
+ BLOCK_INPUT;
XFreeFont (dpy, thisinfo);
+ UNBLOCK_INPUT;
}
else
/* For unknown reason, the previous call of XListFont had
returned a font which can't be opened. Record the size
as 0 not to try to open it again. */
- XCDR (tem) = make_number (0);
+ XSETCDR (tem, make_number (0));
}
found_size = XINT (XCDR (tem));
Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
Qnil);
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key,
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
if (full_name)
{
key = Fcons (Fcons (lispy_full_name, make_number (256)),
Qnil);
- XCDR (dpyinfo->name_list_element)
- = Fcons (Fcons (key,
- Fcons (Fcons (lispy_full_name,
- make_number (fontp->size)),
- Qnil)),
- XCDR (dpyinfo->name_list_element));
+ XSETCDR (dpyinfo->name_list_element,
+ Fcons (Fcons (key,
+ Fcons (Fcons (lispy_full_name,
+ make_number (fontp->size)),
+ Qnil)),
+ XCDR (dpyinfo->name_list_element)));
}
}
/* Set global flag fonts_changed_p to non-zero if the font loaded
has a character with a smaller width than any other character
- before, or if the font loaded has a smalle>r height than any
+ before, or if the font loaded has a smaller height than any
other font loaded before. If this happens, it will make a
glyph matrix reallocation necessary. */
- fonts_changed_p = x_compute_min_glyph_bounds (f);
+ fonts_changed_p |= x_compute_min_glyph_bounds (f);
UNBLOCK_INPUT;
return fontp;
}
{
if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
{
- XCDR (tail) = XCDR (XCDR (tail));
+ XSETCDR (tail, XCDR (XCDR (tail)));
break;
}
tail = XCDR (tail);
clear_frame_hook = x_clear_frame;
ins_del_lines_hook = x_ins_del_lines;
- change_line_highlight_hook = x_change_line_highlight;
delete_glyphs_hook = x_delete_glyphs;
ring_bell_hook = XTring_bell;
reset_terminal_modes_hook = XTreset_terminal_modes;
set_terminal_window_hook = XTset_terminal_window;
read_socket_hook = XTread_socket;
frame_up_to_date_hook = XTframe_up_to_date;
- reassert_line_highlight_hook = XTreassert_line_highlight;
mouse_position_hook = XTmouse_position;
frame_rehighlight_hook = XTframe_rehighlight;
frame_raise_lower_hook = XTframe_raise_lower;
#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
help_echo_pos = -1;
DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
- "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.");
+ doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+For example, if a block cursor is over a tab, it will be drawn as
+wide as that tab on the display. */);
x_stretch_cursor_p = 0;
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ &x_use_underline_position_properties,
+ doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them. If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil. */);
+ x_use_underline_position_properties = 1;
+
DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
- "What X toolkit scroll bars Emacs uses.\n\
-A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
-Otherwise, value is a symbol describing the X toolkit.");
+ doc: /* What X toolkit scroll bars Emacs uses.
+A value of nil means Emacs doesn't use X toolkit scroll bars.
+Otherwise, value is a symbol describing the X toolkit. */);
#ifdef USE_TOOLKIT_SCROLL_BARS
#ifdef USE_MOTIF
Vx_toolkit_scroll_bars = intern ("motif");
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
-}
-
-#endif /* not HAVE_X_WINDOWS */
+
+ Qmodifier_value = intern ("modifier-value");
+ Qalt = intern ("alt");
+ Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+ Qhyper = intern ("hyper");
+ Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+ Qmeta = intern ("meta");
+ Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
+ Qsuper = intern ("super");
+ Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+
+ DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
+ doc: /* Which keys Emacs uses for the alt modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `alt' means use the Alt_L and Alt_R keysyms. The default
+is nil, which is the same as `alt'. */);
+ Vx_alt_keysym = Qnil;
+
+ DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
+ doc: /* Which keys Emacs uses for the hyper modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `hyper' means use the Hyper_L and Hyper_R keysyms. The
+default is nil, which is the same as `hyper'. */);
+ Vx_hyper_keysym = Qnil;
+
+ DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
+ doc: /* Which keys Emacs uses for the meta modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `meta' means use the Meta_L and Meta_R keysyms. The
+default is nil, which is the same as `meta'. */);
+ Vx_meta_keysym = Qnil;
+
+ DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
+ doc: /* Which keys Emacs uses for the super modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `super' means use the Super_L and Super_R keysyms. The
+default is nil, which is the same as `super'. */);
+ Vx_super_keysym = Qnil;
+
+}
+
+#endif /* HAVE_X_WINDOWS */