X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e2a57b3428b71a77de165cd665069c9a02e6fd23..6c4a22e6a88d26011875e50eed0111791b3034d4:/src/xterm.c diff --git a/src/xterm.c b/src/xterm.c index 11a8e07bc4..13bc4d3a19 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -155,11 +155,11 @@ extern void _XEditResCheckMessages (); #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, @@ -172,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: `<-'. */ @@ -274,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; @@ -463,13 +469,13 @@ 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 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 *)); @@ -659,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), @@ -758,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 @@ -769,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; @@ -825,93 +845,151 @@ 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); + /* Clip bitmap if too high. */ + if (h > row->height) + h = row->height; + + /* Set dy to the offset in the row to start drawing the bitmap. */ 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); + face = FACE_FROM_ID (f, FRINGE_FACE_ID); + PREPARE_FACE_FOR_DISPLAY (f, face); + + /* 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 + { + 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 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 (display, face->gc, FillOpaqueStippled); + else + XSetForeground (display, face->gc, face->background); + + XFillRectangle (display, window, face->gc, + b1, + WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, + row->y)), + b2, + row->visible_height); + if (!face->stipple) + XSetForeground (display, face->gc, face->foreground); + } + + if (which != NO_FRINGE_BITMAP) + { + /* 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); + } + XSetClipMask (display, gc, None); } -/* Draw flags bitmaps for glyph row ROW on window W. Call this +/* Draw fringe bitmaps for glyph row ROW on window W. Call this function with input blocked. */ static void -x_draw_row_bitmaps (w, row) +x_draw_row_fringe_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; + enum fringe_bitmap_type bitmap; xassert (interrupt_input_blocked); @@ -920,103 +998,37 @@ x_draw_row_bitmaps (w, row) if (row->visible_height <= 0) return; - face = FACE_FROM_ID (f, BITMAP_AREA_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; - 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); - - /* 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); + 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 - XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background); - - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - face->gc, - (left - - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - + border), - WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, - row->y)), - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border, - row->visible_height); - if (!face->stipple) - XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground); - } - - /* Draw the left bitmap. */ - if (bitmap != NO_BITMAP) - x_draw_bitmap (w, row, bitmap); + bitmap = NO_FRINGE_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; + x_draw_fringe_bitmap (w, row, bitmap, 1); + } - /* 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 (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0) { - 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); + /* 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 - 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); - } + bitmap = NO_FRINGE_BITMAP; - /* Draw the right bitmap. */ - if (bitmap != NO_BITMAP) - x_draw_bitmap (w, row, bitmap); + x_draw_fringe_bitmap (w, row, bitmap, 0); + } } @@ -3896,7 +3908,7 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, for (i = 0; i < width; ++i) XDrawLine (dpy, window, gc, left_x + i * left_p, bottom_y - i, - right_x + 2 - i * right_p, bottom_y - i); + right_x + 1 - i * right_p, bottom_y - i); /* Right. */ if (right_p) @@ -3966,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); } @@ -3993,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) @@ -4117,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 : 3; raised_p = s->hl == DRAW_IMAGE_RAISED; } else @@ -4815,7 +4827,9 @@ x_set_glyph_string_background_width (s, start, last_x) || 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_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 @@ -5050,9 +5064,8 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) 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; @@ -5174,7 +5187,12 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) for (s = head; s; s = s->next) x_draw_glyph_string (s); - if (area == TEXT_AREA && !row->full_width_p) + 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; @@ -5182,7 +5200,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0); x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1); - if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0) + if (XFASTINT (w->left_margin_width) != 0) { int left_area_width = window_box_width (w, LEFT_MARGIN_AREA); x0 -= left_area_width; @@ -5718,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); @@ -5966,7 +5984,7 @@ 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; @@ -6722,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 @@ -6750,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) @@ -7115,7 +7133,7 @@ note_mouse_highlight (f, x, y) { Lisp_Object before = Foverlay_start (overlay); Lisp_Object after = Foverlay_end (overlay); - Lisp_Object ignore; + int ignore; /* Note that we might not be able to find position BEFORE in the glyph matrix if the overlay is @@ -7300,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 @@ -7722,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) - { - x_draw_glyphs (w, start_x, row, TEXT_AREA, - start_hpos, end_hpos, draw, 0); - row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED; - } - } + 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), @@ -8966,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. */ @@ -9211,7 +9206,7 @@ XTset_vertical_scroll_bar (w, portion, whole, position) /* Does the scroll bar exist yet? */ if (NILP (w->vertical_scroll_bar)) { - if (width && height) + if (width > 0 && height > 0) { BLOCK_INPUT; x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), @@ -9243,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); @@ -9277,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, top, - 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. */ @@ -9824,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; @@ -10407,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; @@ -10611,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); @@ -10668,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. */ @@ -10681,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) @@ -10745,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 @@ -10754,6 +10762,7 @@ XTread_socket (sd, bufp, numchars, expected) if (f == dpyinfo->x_focus_frame) x_new_focus_frame (dpyinfo, 0); } +#endif } goto OTHER; @@ -11092,7 +11101,7 @@ XTread_socket (sd, bufp, numchars, expected) /* 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 means all the rest + Coordinates are area-relative. END_X < 0 means all the rest of the line after START_X has been written. */ static void @@ -11104,7 +11113,7 @@ notice_overwritten_cursor (w, start_x, end_x) && w->phys_cursor_on_p && output_cursor.vpos == w->phys_cursor.vpos && start_x <= w->phys_cursor.x - && end_x > w->phys_cursor.x) + && (end_x < 0 || end_x > w->phys_cursor.x)) w->phys_cursor_on_p = 0; } @@ -11141,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); @@ -11218,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 @@ -11243,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); @@ -11261,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); } } @@ -11459,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 @@ -11494,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) @@ -11501,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 @@ -11897,7 +11913,7 @@ x_connection_signal (signalnum) /* If we don't have an argument, */ static char *error_msg; -/* Function installed as fatal_error_signal_hook.in +/* 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. */ @@ -12084,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) { @@ -12162,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 @@ -12552,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);