aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman <[email protected]>1994-04-10 06:06:51 +0000
committerRichard M. Stallman <[email protected]>1994-04-10 06:06:51 +0000
commit0cdd0c9f3e3438b1fe05f1c00f3262ac534898b7 (patch)
tree9b3e76754af9312544e70ec046a9730e5b7cd578
parent8fc2766b6434feb36832e5f150a288c00d3d19bb (diff)
(dumpglyphs): Clear any extra pixel rows below the text.
(x_display_box_cursor): Explicitly clear full height of line. (dumpglyphs): New arg just_foreground. Callers changed. (x_set_window_size): Call XSync. (note_mouse_highlight): Do nothing if buffer has changed.
-rw-r--r--src/xterm.c250
1 files changed, 217 insertions, 33 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 70a527a27f..54880dc843 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -347,6 +347,7 @@ extern FONT_TYPE *XOpenFont ();
static void flashback ();
static void redraw_previous_char ();
+static void redraw_following_char ();
static unsigned int x_x_to_emacs_modifiers ();
static void note_mouse_highlight ();
@@ -541,6 +542,8 @@ XTcursor_to (row, col)
WINDOW is the x-window to output to. LEFT and TOP are starting coords.
HL is 1 if this text is highlighted, 2 if the cursor is on it,
3 if should appear in its mouse-face.
+ JUST_FOREGROUND if 1 means draw only the foreground;
+ don't alter the background.
FONT is the default font to use (for glyphs whose font-code is 0).
@@ -555,12 +558,13 @@ XTcursor_to (row, col)
/* This is the multi-face code. */
static void
-dumpglyphs (f, left, top, gp, n, hl)
+dumpglyphs (f, left, top, gp, n, hl, just_foreground)
struct frame *f;
int left, top;
register GLYPH *gp; /* Points to first GLYPH. */
register int n; /* Number of glyphs to display. */
int hl;
+ int just_foreground;
{
/* Holds characters to be displayed. */
char *buf = (char *) alloca (f->width * sizeof (*buf));
@@ -568,6 +572,7 @@ dumpglyphs (f, left, top, gp, n, hl)
register int tlen = GLYPH_TABLE_LENGTH;
register Lisp_Object *tbase = GLYPH_TABLE_BASE;
Window window = FRAME_X_WINDOW (f);
+ int orig_left = left;
while (n > 0)
{
@@ -691,8 +696,36 @@ dumpglyphs (f, left, top, gp, n, hl)
if ((int) font == FACE_DEFAULT)
font = f->display.x->font;
- XDrawImageString (x_current_display, window, gc,
- left, top + FONT_BASE (font), buf, len);
+ if (just_foreground)
+ XDrawString (x_current_display, window, gc,
+ left, top + FONT_BASE (font), buf, len);
+ else
+ {
+ XDrawImageString (x_current_display, window, gc,
+ left, top + FONT_BASE (font), buf, len);
+ /* Clear the rest of the line's height. */
+ if (f->display.x->line_height != FONT_HEIGHT (font))
+ XClearArea (x_current_display, window, left,
+ top + FONT_HEIGHT (font),
+ FONT_WIDTH (font) * len,
+ /* This is how many pixels of height
+ we have to clear. */
+ f->display.x->line_height - FONT_HEIGHT (font),
+ False);
+ }
+
+#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
+ which often is not up to date yet. */
+ if (!just_foreground)
+ {
+ if (left == orig_left)
+ redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
+ PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+ if (n == 0)
+ redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
+ PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+ }
+#endif
if (gc_temporary)
XFreeGC (x_current_display, gc);
@@ -783,7 +816,7 @@ XTwrite_glyphs (start, len)
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, curs_x),
CHAR_TO_PIXEL_ROW (f, curs_y),
- start, len, highlight);
+ start, len, highlight, 0);
/* If we drew on top of the cursor, note that it is turned off. */
if (curs_y == f->phys_cursor_y
@@ -841,7 +874,7 @@ XTclear_end_of_line (first_unused)
FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
f->display.x->line_height, False);
#if 0
- redraw_previous_char (f, curs_x, curs_y);
+ redraw_previous_char (f, curs_x, curs_y, highlight);
#endif
#else /* ! defined (HAVE_X11) */
XPixSet (FRAME_X_WINDOW (f),
@@ -855,6 +888,44 @@ XTclear_end_of_line (first_unused)
UNBLOCK_INPUT;
}
+static
+XTclear_frame ()
+{
+ int mask;
+ struct frame *f = updating_frame;
+
+ if (f == 0)
+ f = selected_frame;
+
+ f->phys_cursor_x = -1; /* Cursor not visible. */
+ curs_x = 0; /* Nominal cursor position is top left. */
+ curs_y = 0;
+
+ BLOCK_INPUT;
+
+ XClear (FRAME_X_WINDOW (f));
+
+ /* We have to clear the scroll bars, too. If we have changed
+ colors or something like that, then they should be notified. */
+ x_scroll_bar_clear (f);
+
+#ifndef HAVE_X11
+ dumpborder (f, 0);
+#endif /* HAVE_X11 */
+
+ XFlushQueue ();
+ UNBLOCK_INPUT;
+}
+
+#if 0
+/* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
+ always contain the right glyphs to use.
+
+ It also needs to be changed to look at the details of the font and
+ see whether there is really overlap, and do nothing when there is
+ not. This can use font_char_overlap_left and font_char_overlap_right,
+ but just how to use them is not clear. */
+
/* Erase the character (if any) at the position just before X, Y in frame F,
then redraw it and the character before it.
This is necessary when we erase starting at X,
@@ -862,9 +933,10 @@ XTclear_end_of_line (first_unused)
Call this function with input blocked. */
static void
-redraw_previous_char (f, x, y)
+redraw_previous_char (f, x, y, highlight_flag)
FRAME_PTR f;
int x, y;
+ int highlight_flag;
{
/* Erase the character before the new ones, in case
what was here before overlaps it.
@@ -884,38 +956,139 @@ redraw_previous_char (f, x, y)
dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
CHAR_TO_PIXEL_ROW (f, y),
&FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
- x - start_x, highlight);
+ x - start_x, highlight_flag, 1);
}
}
-static
-XTclear_frame ()
+/* Erase the character (if any) at the position X, Y in frame F,
+ then redraw it and the character after it.
+ This is necessary when we erase endng at X,
+ in case the character after X overlaps into the one before X.
+ Call this function with input blocked. */
+
+static void
+redraw_following_char (f, x, y, highlight_flag)
+ FRAME_PTR f;
+ int x, y;
+ int highlight_flag;
{
- int mask;
- struct frame *f = updating_frame;
+ int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
+ /* Erase the character after the new ones, in case
+ what was here before overlaps it.
+ Reoutput that character, and the following character
+ (in case the following character overlaps it). */
+ if (x < limit
+ && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
+ {
+ int end_x = x + 2;
+ if (end_x > limit)
+ end_x = limit;
+ XClearArea (x_current_display, FRAME_X_WINDOW (f),
+ CHAR_TO_PIXEL_COL (f, x),
+ CHAR_TO_PIXEL_ROW (f, y),
+ FONT_WIDTH (f->display.x->font),
+ f->display.x->line_height, False);
- if (f == 0)
- f = selected_frame;
+ dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
+ CHAR_TO_PIXEL_ROW (f, y),
+ &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
+ end_x - x, highlight_flag, 1);
+ }
+}
+#endif /* 0 */
+
+#if 0 /* Not in use yet */
- f->phys_cursor_x = -1; /* Cursor not visible. */
- curs_x = 0; /* Nominal cursor position is top left. */
- curs_y = 0;
-
- BLOCK_INPUT;
+/* Return 1 if character C in font F extends past its left edge. */
- XClear (FRAME_X_WINDOW (f));
+static int
+font_char_overlap_left (font, c)
+ XFontStruct *font;
+ int c;
+{
+ XCharStruct *s;
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
+ /* Find the bounding-box info for C. */
+ if (font->per_char == 0)
+ s = &font->max_bounds;
+ else
+ {
+ int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+ int row, within;
+
+ /* Decode char into row number (byte 1) and code within row (byte 2). */
+ row = c >> 8;
+ within = c & 0177;
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ {
+ /* If char is out of range, try the font's default char instead. */
+ c = font->default_char;
+ row = c >> (INTBITS - 8);
+ within = c & 0177;
+ }
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ /* Still out of range means this char does not overlap. */
+ return 0;
+ else
+ /* We found the info for this char. */
+ s = (font->per_char + (within - font->min_char_or_byte2)
+ + row * rowlen);
+ }
-#ifndef HAVE_X11
- dumpborder (f, 0);
-#endif /* HAVE_X11 */
+ return (s && s->lbearing < 0);
+}
- XFlushQueue ();
- UNBLOCK_INPUT;
+/* Return 1 if character C in font F extends past its right edge. */
+
+static int
+font_char_overlap_right (font, c)
+ XFontStruct *font;
+ int c;
+{
+ XCharStruct *s;
+
+ /* Find the bounding-box info for C. */
+ if (font->per_char == 0)
+ s = &font->max_bounds;
+ else
+ {
+ int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+ int row, within;
+
+ /* Decode char into row number (byte 1) and code within row (byte 2). */
+ row = c >> 8;
+ within = c & 0177;
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ {
+ /* If char is out of range, try the font's default char instead. */
+ c = font->default_char;
+ row = c >> (INTBITS - 8);
+ within = c & 0177;
+ }
+ if (!(within >= font->min_char_or_byte2
+ && within <= font->max_char_or_byte2
+ && row >= font->min_byte1
+ && row <= font->max_byte1))
+ /* Still out of range means this char does not overlap. */
+ return 0;
+ else
+ /* We found the info for this char. */
+ s = (font->per_char + (within - font->min_char_or_byte2)
+ + row * rowlen);
+ }
+
+ return (s && s->rbearing >= s->width);
}
+#endif /* 0 */
/* Invert the middle quarter of the frame for .15 sec. */
@@ -1336,7 +1509,7 @@ dumprectangle (f, left, top, cols, rows)
CHAR_TO_PIXEL_COL (f, left),
CHAR_TO_PIXEL_ROW (f, y),
line, min (cols, active_frame->used[y] - left),
- active_frame->highlight[y]);
+ active_frame->highlight[y], 0);
}
/* Turn the cursor on if we turned it off. */
@@ -1981,9 +2154,11 @@ note_mouse_highlight (f, x, y)
if (! EQ (window, mouse_face_window))
clear_mouse_face ();
- /* Are we in a window whose display is up to date? */
+ /* Are we in a window whose display is up to date?
+ And verify the buffer's text has not changed. */
if (WINDOWP (window) && portion == 0
- && EQ (w->window_end_valid, w->buffer))
+ && EQ (w->window_end_valid, w->buffer)
+ && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
{
int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
int i, pos;
@@ -2202,7 +2377,7 @@ show_mouse_face (hl)
FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
endcolumn - column,
/* Highlight with mouse face if hl > 0. */
- hl > 0 ? 3 : 0);
+ hl > 0 ? 3 : 0, 0);
}
/* If we turned the cursor off, turn it back on. */
@@ -4275,7 +4450,7 @@ x_draw_single_glyph (f, row, column, glyph, highlight)
dumpglyphs (f,
CHAR_TO_PIXEL_COL (f, column),
CHAR_TO_PIXEL_ROW (f, row),
- &glyph, 1, highlight);
+ &glyph, 1, highlight, 0);
}
static void
@@ -4383,6 +4558,14 @@ x_display_box_cursor (f, on)
|| (f->display.x->current_cursor != hollow_box_cursor
&& (f != x_highlight_frame))))
{
+ /* If the font is not as tall as a whole line,
+ we must explicitly clear the line's whole height. */
+ if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height)
+ XClearArea (x_current_display, FRAME_X_WINDOW (f),
+ CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
+ CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
+ FONT_WIDTH (f->display.x->font),
+ f->display.x->line_height, False);
/* Erase the cursor by redrawing the character underneath it. */
x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
f->phys_cursor_glyph,
@@ -4903,7 +5086,7 @@ x_new_font (f, fontname)
else
/* If we are setting a new frame's font for the first time,
there are no faces yet, so this font's height is the line height. */
- f->display.x->line_height = FONT_HEIGHT (f);
+ f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
{
Lisp_Object lispy_name;
@@ -5051,6 +5234,7 @@ x_set_window_size (f, change_gravity, cols, rows)
#ifdef HAVE_X11
x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
#endif /* ! defined (HAVE_X11) */
+ XSync (x_current_display, False);
XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
/* Now, strictly speaking, we can't be sure that this is accurate,