X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c296fc0108b4a7c7b59bfb208da32d33d5c3fcb5..b3561514f631090ea1af4b6a04aaa8790654595d:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index be86909b23..51b94c9fb3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -76,10 +76,6 @@ Boston, MA 02111-1307, USA. */ #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" @@ -88,6 +84,7 @@ Boston, MA 02111-1307, USA. */ #include "intervals.h" #include "process.h" #include "atimer.h" +#include "keymap.h" #ifdef USE_X_TOOLKIT #include @@ -100,6 +97,11 @@ Boston, MA 02111-1307, USA. */ #include #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 *)); @@ -148,23 +150,16 @@ extern void _XEditResCheckMessages (); #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)) -/* 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, @@ -177,9 +172,17 @@ enum bitmap_type `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: `<-'. */ @@ -279,8 +282,6 @@ Lisp_Object x_display_name_list; 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; @@ -410,7 +411,7 @@ 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 *)); @@ -441,8 +442,6 @@ static void x_draw_phys_cursor_glyph P_ ((struct window *, 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)); @@ -460,24 +459,24 @@ static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, 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 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 *, 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 *)); @@ -666,7 +665,7 @@ x_draw_vertical_border (w) 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), @@ -765,7 +764,7 @@ XTframe_up_to_date (f) /* 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 @@ -776,53 +775,67 @@ x_after_update_window_line (desired_row) 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; @@ -832,227 +845,193 @@ x_draw_bitmap (w, row, which) /* 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; + /* Clip bitmap if too high. */ + if (h > row->height) + h = row->height; - /* 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); - - /* 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); } - -/*********************************************************************** - 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); + } } + /* This is called when starting Emacs and when restarting after suspend. When starting Emacs, no X window is mapped. And nothing @@ -2491,7 +2470,7 @@ struct glyph_string }; -#if 1 +#if GLYPH_DEBUG static void x_dump_glyph_string (s) @@ -2539,7 +2518,7 @@ static void x_init_glyph_string P_ ((struct glyph_string *, 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 *, @@ -2841,20 +2820,6 @@ x_get_glyph_string_clip_rect (s, r) 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. */ @@ -2863,7 +2828,23 @@ x_get_glyph_string_clip_rect (s, r) 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); } @@ -3854,6 +3835,9 @@ x_setup_relief_colors (s) if (s->face->use_box_color_for_shadows_p) color = s->face->box_color; + else if (s->first_glyph->type == IMAGE_GLYPH + && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) + color = IMAGE_BACKGROUND (s->img, s->f, 0); else { XGCValues xgcv; @@ -3890,6 +3874,8 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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; @@ -3897,40 +3883,40 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 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, + 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, - left_x + i * left_p + 1, bottom_y - i, + 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); } @@ -3992,7 +3978,7 @@ x_draw_glyph_string_box (s) 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); } @@ -4019,7 +4005,7 @@ x_draw_glyph_string_box (s) || (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) @@ -4087,8 +4073,6 @@ x_draw_image_foreground (s) } else { - unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction; - XGCValues xgcv; XRectangle clip_rect, image_rect, r; x_get_glyph_string_clip_rect (s, &clip_rect); @@ -4145,7 +4129,7 @@ x_draw_image_relief (s) 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 @@ -4446,7 +4430,6 @@ x_draw_glyph_string (s) /* 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. */ @@ -4456,10 +4439,14 @@ x_draw_glyph_string (s) || 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) { @@ -4834,12 +4821,16 @@ x_set_glyph_string_background_width (s, start, last_x) 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 @@ -5042,27 +5033,19 @@ x_set_glyph_string_background_width (s, start, last_x) 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; @@ -5075,19 +5058,14 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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; @@ -5150,8 +5128,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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); } @@ -5171,8 +5147,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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); } @@ -5189,8 +5163,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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 @@ -5208,8 +5180,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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; } } @@ -5217,12 +5187,35 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end, 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, x0, x1); + } + /* 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); @@ -5267,9 +5260,7 @@ x_fix_overlapping_area (w, row, 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 { @@ -5293,7 +5284,7 @@ x_write_glyphs (start, len) struct glyph *start; int len; { - int x, hpos, real_start, real_end; + int x, hpos; xassert (updated_window && updated_row); BLOCK_INPUT; @@ -5304,13 +5295,7 @@ x_write_glyphs (start, len) 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; @@ -5332,7 +5317,7 @@ x_insert_glyphs (start, len) 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; @@ -5365,8 +5350,7 @@ x_insert_glyphs (start, len) /* 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; @@ -5445,7 +5429,7 @@ x_clear_end_of_line (to_x) /* Notice if the cursor will be cleared by this operation. */ if (!updated_row->full_width_p) - note_overwritten_text_cursor (w, output_cursor.hpos, -1); + notice_overwritten_cursor (w, output_cursor.x, -1); from_x = output_cursor.x; @@ -5752,11 +5736,11 @@ x_scroll_run (w, run) 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); @@ -5814,6 +5798,7 @@ expose_frame (f, x, y, w, h) int x, y, w, h; { XRectangle r; + int mouse_face_overwritten_p = 0; TRACE ((stderr, "expose_frame ")); @@ -5849,36 +5834,69 @@ expose_frame (f, x, y, w, h) } 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)) - expose_window (XWINDOW (f->tool_bar_window), &r); + mouse_face_overwritten_p + |= expose_window (XWINDOW (f->tool_bar_window), &r); #ifndef USE_X_TOOLKIT if (WINDOWP (f->menu_bar_window)) - expose_window (XWINDOW (f->menu_bar_window), &r); + mouse_face_overwritten_p + |= expose_window (XWINDOW (f->menu_bar_window), &r); #endif /* not USE_X_TOOLKIT */ + + /* 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); + } + } } /* 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); - else if (expose_window (w, r) == 0) - break; + mouse_face_overwritten_p + |= expose_window_tree (XWINDOW (w->vchild), r); + else + mouse_face_overwritten_p |= expose_window (w, r); + w = NILP (w->next) ? NULL : XWINDOW (w->next); } + + return mouse_face_overwritten_p; } @@ -5899,10 +5917,8 @@ expose_area (w, row, r, area) 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 @@ -5940,16 +5956,16 @@ expose_area (w, row, r, area) 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; @@ -5959,8 +5975,7 @@ expose_line (w, row, r) 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]) @@ -5969,8 +5984,10 @@ expose_line (w, row, r) 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; } @@ -6000,7 +6017,8 @@ x_phys_cursor_in_rect_p (w, r) /* Redraw the part of window W intersection rectangle FR. Pixel coordinates in FR are frame-relative. Call this function with - input blocked. */ + input blocked. Value is non-zero if the exposure overwrites + mouse-face. */ static int expose_window (w, fr) @@ -6009,13 +6027,14 @@ expose_window (w, fr) { struct frame *f = XFRAME (w->frame); XRectangle wr, r; + int mouse_face_overwritten_p = 0; /* If window is not yet fully initialized, do nothing. This can happen when toolkit scroll bars are used and a window is split. Reconfiguring the scroll bar will generate an expose for a newly created window. */ if (w->current_matrix == NULL) - return 1; + return 0; /* When we're currently updating the window, display and current matrix usually don't agree. Arrange for a thorough display @@ -6067,8 +6086,11 @@ expose_window (w, fr) || (y1 > r.y && y1 < r.y + r.height) || (r.y >= y0 && r.y < y1) || (r.y + r.height > y0 && r.y + r.height < y1)) - expose_line (w, row, &r); - + { + if (expose_line (w, row, &r)) + mouse_face_overwritten_p = 1; + } + if (y1 >= yb) break; } @@ -6078,7 +6100,10 @@ expose_window (w, fr) && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), row->enabled_p) && row->y < r.y + r.height) - expose_line (w, row, &r); + { + if (expose_line (w, row, &r)) + mouse_face_overwritten_p = 1; + } if (!w->pseudo_window_p) { @@ -6090,8 +6115,8 @@ expose_window (w, fr) x_update_window_cursor (w, 1); } } - - return 1; + + return mouse_face_overwritten_p; } @@ -6715,7 +6740,7 @@ frame_to_window_pixel_xy (w, x, y) /* 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 @@ -6743,7 +6768,7 @@ note_mode_line_highlight (w, x, mode_line_p) 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) @@ -7000,13 +7025,14 @@ note_mouse_highlight (f, x, y) &dpyinfo->mouse_face_beg_col, &dpyinfo->mouse_face_beg_row, &dpyinfo->mouse_face_beg_x, - &dpyinfo->mouse_face_beg_y); + &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); + &dpyinfo->mouse_face_end_y, Qnil); dpyinfo->mouse_face_window = window; dpyinfo->mouse_face_face_id = face_at_buffer_position (w, pos, 0, 0, @@ -7040,13 +7066,13 @@ note_mouse_highlight (f, x, y) &dpyinfo->mouse_face_beg_col, &dpyinfo->mouse_face_beg_row, &dpyinfo->mouse_face_beg_x, - &dpyinfo->mouse_face_beg_y); + &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); + &dpyinfo->mouse_face_end_y, Qnil); dpyinfo->mouse_face_window = window; if (BUFFERP (object)) @@ -7090,6 +7116,54 @@ note_mouse_highlight (f, x, y) show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); cursor = None; } + else if (STRINGP (object) && NILP (mouse_face)) + { + /* 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)) + { + 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; + } + } } check_help_echo: @@ -7135,7 +7209,7 @@ note_mouse_highlight (f, x, y) int pos = string_buffer_position (w, object, start); if (pos > 0) { - help = Fget_text_property (make_number (pos), + help = Fget_char_property (make_number (pos), Qhelp_echo, w->buffer); if (!NILP (help)) { @@ -7244,7 +7318,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) /* 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 @@ -7399,17 +7473,88 @@ note_tool_bar_highlight (f, x, y) -/* 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; @@ -7459,22 +7604,26 @@ fast_find_position (w, pos, hpos, vpos, x, y) 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; } @@ -7496,6 +7645,8 @@ fast_find_position (w, pos, hpos, vpos, x, y) return 0; } +#endif /* not 0 */ + /* Find the position of the the glyph for position POS in OBJECT in window W's current matrix, and return in *X/*Y the pixel @@ -7589,82 +7740,58 @@ show_mouse_face (dpyinfo, draw) { 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 || DRAW_IMAGE_RAISED; - 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_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), @@ -7763,7 +7890,6 @@ glyph_rect (f, x, y, rect) 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); @@ -8079,7 +8205,7 @@ x_window_to_scroll_bar (window_id) } -#if defined USE_X_TOOLKIT && defined USE_LUCID +#if defined USE_LUCID /* Return the Lucid menu bar WINDOW is part of. Return null if WINDOW is not part of a menu bar. */ @@ -8104,7 +8230,7 @@ x_window_to_menu_bar (window) return NULL; } -#endif /* USE_X_TOOLKIT && USE_LUCID */ +#endif /* USE_LUCID */ /************************************************************************ @@ -8311,7 +8437,6 @@ xm_scroll_callback (widget, client_data, call_data) { 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) @@ -8563,7 +8688,6 @@ x_create_toolkit_scroll_bar (f, bar) 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) @@ -8578,7 +8702,61 @@ x_create_toolkit_scroll_bar (f, bar) 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); @@ -8644,7 +8822,6 @@ x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) #ifdef USE_MOTIF { int size, value; - 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 @@ -8783,9 +8960,10 @@ x_scroll_bar_create (w, top, left, width, height) /* 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. */ @@ -9028,11 +9206,14 @@ XTset_vertical_scroll_bar (w, portion, whole, position) /* 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 @@ -9057,7 +9238,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position) /* 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); @@ -9091,10 +9272,16 @@ XTset_vertical_scroll_bar (w, portion, whole, position) { int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f); int rest = area_width - sb_width; - if (rest > 0) - x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - left + area_width - rest, 0, - rest, max (height, 1), False); + 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. */ @@ -9638,7 +9825,7 @@ static Time enter_timestamp; 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; @@ -10067,7 +10254,7 @@ XTread_socket (sd, bufp, numchars, expected) #ifndef USE_TOOLKIT_SCROLL_BARS struct scroll_bar *bar; #endif -#if defined USE_X_TOOLKIT && defined USE_LUCID +#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. */ @@ -10077,8 +10264,8 @@ XTread_socket (sd, bufp, numchars, expected) if (widget) xlwmenu_redisplay (widget); } -#endif /* USE_X_TOOLKIT && USE_LUCID */ - +#endif /* USE_LUCID */ + #ifdef USE_TOOLKIT_SCROLL_BARS /* Dispatch event to the widget. */ goto OTHER; @@ -10096,8 +10283,8 @@ XTread_socket (sd, bufp, numchars, expected) 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) { @@ -10114,7 +10301,7 @@ XTread_socket (sd, bufp, numchars, expected) case NoExpose: /* This occurs when an XCopyArea's source area was completely - available */ + available. */ break; case UnmapNotify: @@ -10127,7 +10314,7 @@ XTread_socket (sd, bufp, numchars, expected) 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 @@ -10221,7 +10408,7 @@ XTread_socket (sd, bufp, numchars, expected) 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; @@ -10353,7 +10540,8 @@ XTread_socket (sd, bufp, numchars, expected) || 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 @@ -10424,8 +10612,12 @@ XTread_socket (sd, bufp, numchars, expected) 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); @@ -10481,6 +10673,7 @@ XTread_socket (sd, bufp, numchars, expected) { f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); +#if 0 if (event.xcrossing.focus) { /* Avoid nasty pop/raise loops. */ @@ -10494,7 +10687,8 @@ XTread_socket (sd, bufp, numchars, expected) } 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) @@ -10558,6 +10752,7 @@ XTread_socket (sd, bufp, numchars, expected) bufp += n, count += n, numchars -= n; } +#if 0 if (event.xcrossing.focus) x_mouse_leave (dpyinfo); else @@ -10567,6 +10762,7 @@ XTread_socket (sd, bufp, numchars, expected) if (f == dpyinfo->x_focus_frame) x_new_focus_frame (dpyinfo, 0); } +#endif } goto OTHER; @@ -10902,21 +11098,22 @@ XTread_socket (sd, bufp, numchars, expected) 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 if the text cursor of window W has been overwritten by a + drawing operation that outputs N glyphs starting at START_X and + ending at END_X in the line given by output_cursor.vpos. + Coordinates are area-relative. END_X < 0 means all the rest + of the line after START_X has been written. */ static void -note_overwritten_text_cursor (w, hpos, n) +notice_overwritten_cursor (w, start_x, end_x) struct window *w; - int hpos, n; + int start_x, end_x; { if (updated_area == TEXT_AREA + && w->phys_cursor_on_p && output_cursor.vpos == w->phys_cursor.vpos - && hpos <= w->phys_cursor.hpos - && (n < 0 - || hpos + n > w->phys_cursor.hpos)) + && start_x <= w->phys_cursor.x + && (end_x < 0 || end_x > w->phys_cursor.x)) w->phys_cursor_on_p = 0; } @@ -10953,8 +11150,8 @@ x_clip_to_row (w, row, gc, whole_line_p) 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); @@ -11030,12 +11227,6 @@ x_draw_bar_cursor (w, row, width) { 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 @@ -11055,13 +11246,23 @@ x_draw_bar_cursor (w, row, width) } 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); @@ -11073,14 +11274,13 @@ x_draw_bar_cursor (w, row, width) 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); } } @@ -11113,9 +11313,12 @@ x_draw_phys_cursor_glyph (w, row, hl) 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 @@ -11214,8 +11417,6 @@ x_erase_phys_cursor (w) /* 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); @@ -11270,6 +11471,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, 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 @@ -11305,6 +11507,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) 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) @@ -11312,18 +11517,18 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y) { 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 @@ -11478,16 +11683,6 @@ x_update_window_cursor (w, on) /* 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 @@ -11714,6 +11909,21 @@ x_connection_signal (signalnum) /* If we don't have an argument, */ 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. */ @@ -11725,10 +11935,9 @@ x_connection_closed (dpy, error_message) 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 @@ -11756,7 +11965,12 @@ x_connection_closed (dpy, error_message) /* 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. */ @@ -11797,7 +12011,7 @@ x_connection_closed (dpy, error_message) if (x_display_list == 0) { - fprintf (stderr, "%s\n", msg); + fprintf (stderr, "%s\n", error_msg); shut_down_emacs (0, 0, Qnil); exit (70); } @@ -11810,7 +12024,7 @@ x_connection_closed (dpy, error_message) TOTALLY_UNBLOCK_INPUT; clear_waiting_for_input (); - error ("%s", msg); + error ("%s", error_msg); } @@ -11886,7 +12100,9 @@ x_new_font (f, fontname) 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) { @@ -11964,6 +12180,90 @@ x_new_fontset (f, fontsetname) 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); +} /*********************************************************************** X Input Methods @@ -12354,8 +12654,9 @@ x_set_window_size_1 (f, change_gravity, cols, rows) : 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); @@ -12918,6 +13219,8 @@ x_free_frame_resources (f) struct frame *f; { struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + Lisp_Object bar; + struct scroll_bar *b; BLOCK_INPUT; @@ -12927,23 +13230,40 @@ x_free_frame_resources (f) { 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); 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); @@ -12951,11 +13271,18 @@ x_free_frame_resources (f) 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) @@ -13452,8 +13779,8 @@ x_list_fonts (f, pattern, size, maxnames) } /* 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. */ @@ -13496,10 +13823,10 @@ x_list_fonts (f, pattern, size, maxnames) 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; @@ -13508,7 +13835,7 @@ x_list_fonts (f, pattern, size, maxnames) /* 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)); @@ -13774,22 +14101,22 @@ x_load_font (f, fontname, size) 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))); } } @@ -14360,7 +14687,7 @@ x_delete_display (dpyinfo) { if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element)) { - XCDR (tail) = XCDR (XCDR (tail)); + XSETCDR (tail, XCDR (XCDR (tail))); break; } tail = XCDR (tail); @@ -14428,7 +14755,6 @@ x_initialize () 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; @@ -14438,7 +14764,6 @@ x_initialize () 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; @@ -14538,23 +14863,23 @@ syms_of_xterm () 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, - "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\ -Nil means ignore them. If you encounter fonts with bogus\n\ -UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\ -to 4.1, set this to nil."); + 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"); @@ -14571,4 +14896,4 @@ Otherwise, value is a symbol describing the X toolkit."); last_mouse_motion_frame = Qnil; } -#endif /* not HAVE_X_WINDOWS */ +#endif /* HAVE_X_WINDOWS */