Implement GUI display of R2L lines, fix TTY display of R2L lines.
xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for append_stretch_glyph. (set_cursor_from_row) <cursor_x>: Remove unused variable. Fix off-by-one error in computing x at end of text in the row. (append_stretch_glyph): In reversed row, prepend the glyph rather than append it. Set resolved_level and bidi_type of the glyph. (extend_face_to_end_of_line): If the row is reversed, prepend a stretch glyph whose width is such that the rightmost glyph will be drawn at the right margin of the window. Fix off-by-one error on TTY frames in testing whether a line needs face extension. Fix face extension at ZV. If this is the last glyph row, use DEFAULT_FACE_ID, to avoid painting the rest of the window with the region face. (set_cursor_from_row, display_line): Use MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of row->continuation_lines_width. (next_element_from_buffer): Don't call bidi_paragraph_init if we are at ZV. Fixes a crash when reseated to ZV by try_window_reusing_current_matrix. (display_and_set_cursor, erase_phys_cursor): Handle negative HPOS, which happens with R2L glyph rows. Fixes a crash when inserting a character at end of an R2L line. (set_cursor_from_row): Don't be fooled by truncated rows: don't treat them as having zero-width characters. Improve comments. Don't reverse pos_before and pos_after for reversed glyph rows. Set cursor.x to negative value when the cursor might be on the left fringe. (IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the left fringe, not the right one. (notice_overwritten_cursor, draw_phys_cursor_glyph) (erase_phys_cursor): For reversed cursor_row, support cursor on the left fringe. fringe.c (update_window_fringes): For R2L rows, swap the bitmaps of continuation indicators on the fringes. (draw_fringe_bitmap): For reversed glyph rows, allow cursor on the left fringe. w32term.c (w32_draw_window_cursor): For reversed glyph rows, draw cursor on the left fringe. xterm.c (x_draw_window_cursor): For reversed glyph rows, draw cursor on the left fringe. dispnew.c (update_text_area): Handle reversed desired rows when the cursor is on the left fringe. (set_window_cursor_after_update): Limit cursor's hpos by -1 from below, not by 0, for when the cursor is on the left fringe. xdisp.c (unproduce_glyphs): New function. (display_line): Use it when produced glyphs are discarded from R2L glyph rows. (append_composite_glyph): In R2L rows, prepend the glyph rather than appending it. term.c (append_composite_glyph): In R2L rows, prepend the glyph rather than append it. Set up the resolved_level and bidi_type attributes of the appended glyph. (produce_special_glyphs): Mirror the backslash continuation character in R2L lines.
This commit is contained in:
commit
283ccc1841
7 changed files with 325 additions and 75 deletions
|
@ -1,3 +1,70 @@
|
|||
2010-04-20 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Fix R2L paragraph display on TTY.
|
||||
|
||||
* xdisp.c (unproduce_glyphs): New function.
|
||||
(display_line): Use it when produced glyphs are discarded from R2L
|
||||
glyph rows.
|
||||
(append_composite_glyph): In R2L rows, prepend the glyph rather
|
||||
than appending it.
|
||||
|
||||
* term.c (append_composite_glyph): In R2L rows, prepend the glyph
|
||||
rather than append it. Set up the resolved_level and bidi_type
|
||||
attributes of the appended glyph.
|
||||
(produce_special_glyphs): Mirror the backslash continuation
|
||||
character in R2L lines.
|
||||
|
||||
Implement display of R2L paragraphs in GUI sessions.
|
||||
|
||||
* xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for
|
||||
append_stretch_glyph.
|
||||
(set_cursor_from_row) <cursor_x>: Remove unused variable. Fix
|
||||
off-by-one error in computing x at end of text in the row.
|
||||
(append_stretch_glyph): In reversed row, prepend the glyph rather
|
||||
than append it. Set resolved_level and bidi_type of the glyph.
|
||||
(extend_face_to_end_of_line): If the row is reversed, prepend a
|
||||
stretch glyph whose width is such that the rightmost glyph will be
|
||||
drawn at the right margin of the window. Fix off-by-one error on
|
||||
TTY frames in testing whether a line needs face extension. Fix
|
||||
face extension at ZV. If this is the last glyph row, use
|
||||
DEFAULT_FACE_ID, to avoid painting the rest of the window with the
|
||||
region face.
|
||||
(set_cursor_from_row, display_line): Use
|
||||
MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of
|
||||
row->continuation_lines_width.
|
||||
(next_element_from_buffer): Don't call bidi_paragraph_init if we
|
||||
are at ZV. Fixes a crash when reseated to ZV by
|
||||
try_window_reusing_current_matrix.
|
||||
(display_and_set_cursor, erase_phys_cursor): Handle negative HPOS,
|
||||
which happens with R2L glyph rows. Fixes a crash when inserting a
|
||||
character at end of an R2L line.
|
||||
(set_cursor_from_row): Don't be fooled by truncated rows: don't
|
||||
treat them as having zero-width characters. Improve comments.
|
||||
Don't reverse pos_before and pos_after for reversed glyph rows.
|
||||
Set cursor.x to negative value when the cursor might be on the
|
||||
left fringe.
|
||||
(IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the
|
||||
left fringe, not the right one.
|
||||
(notice_overwritten_cursor, draw_phys_cursor_glyph)
|
||||
(erase_phys_cursor): For reversed cursor_row, support cursor on
|
||||
the left fringe.
|
||||
|
||||
* fringe.c (update_window_fringes): For R2L rows, swap the bitmaps
|
||||
of continuation indicators on the fringes.
|
||||
(draw_fringe_bitmap): For reversed glyph rows, allow cursor on the
|
||||
left fringe.
|
||||
|
||||
* w32term.c (w32_draw_window_cursor): For reversed glyph rows,
|
||||
draw cursor on the left fringe.
|
||||
|
||||
* xterm.c (x_draw_window_cursor): For reversed glyph rows, draw
|
||||
cursor on the left fringe.
|
||||
|
||||
* dispnew.c (update_text_area): Handle reversed desired rows when
|
||||
the cursor is on the left fringe.
|
||||
(set_window_cursor_after_update): Limit cursor's hpos by -1 from
|
||||
below, not by 0, for when the cursor is on the left fringe.
|
||||
|
||||
2010-04-20 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed
|
||||
|
|
|
@ -4251,7 +4251,9 @@ update_text_area (w, vpos)
|
|||
doesn't work with lbearing/rbearing), so we must do it
|
||||
this way. */
|
||||
if (vpos == w->phys_cursor.vpos
|
||||
&& w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])
|
||||
&& (desired_row->reversed_p
|
||||
? (w->phys_cursor.hpos < 0)
|
||||
: (w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])))
|
||||
{
|
||||
w->phys_cursor_on_p = 0;
|
||||
x = -1;
|
||||
|
@ -4415,7 +4417,7 @@ set_window_cursor_after_update (w)
|
|||
}
|
||||
|
||||
/* Window cursor can be out of sync for horizontally split windows. */
|
||||
hpos = max (0, hpos);
|
||||
hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */
|
||||
hpos = min (w->current_matrix->matrix_w - 1, hpos);
|
||||
vpos = max (0, vpos);
|
||||
vpos = min (w->current_matrix->nrows - 1, vpos);
|
||||
|
|
10
src/fringe.c
10
src/fringe.c
|
@ -825,7 +825,7 @@ draw_fringe_bitmap (w, row, left_p)
|
|||
{
|
||||
int overlay = 0;
|
||||
|
||||
if (!left_p && row->cursor_in_fringe_p)
|
||||
if (left_p == row->reversed_p && row->cursor_in_fringe_p)
|
||||
{
|
||||
Lisp_Object cursor = Qnil;
|
||||
|
||||
|
@ -857,7 +857,7 @@ draw_fringe_bitmap (w, row, left_p)
|
|||
int bm = get_logical_cursor_bitmap (w, cursor);
|
||||
if (bm != NO_FRINGE_BITMAP)
|
||||
{
|
||||
draw_fringe_bitmap_1 (w, row, 0, 2, bm);
|
||||
draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
|
||||
overlay = EQ (cursor, Qbox) ? 3 : 1;
|
||||
}
|
||||
}
|
||||
|
@ -1090,7 +1090,8 @@ update_window_fringes (w, keep_current_p)
|
|||
: LEFT_FRINGE (2, Qtop, 0));
|
||||
else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
|
||||
left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
|
||||
else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
|
||||
else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
|
||||
|| (row->reversed_p && row->continued_p))
|
||||
left = LEFT_FRINGE (4, Qcontinuation, 0);
|
||||
else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
|
||||
left = LEFT_FRINGE (5, Qempty_line, 0);
|
||||
|
@ -1117,7 +1118,8 @@ update_window_fringes (w, keep_current_p)
|
|||
: RIGHT_FRINGE (2, Qtop, 0));
|
||||
else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
|
||||
right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
|
||||
else if (row->continued_p)
|
||||
else if ((!row->reversed_p && row->continued_p)
|
||||
|| (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
|
||||
right = RIGHT_FRINGE (4, Qcontinuation, 0);
|
||||
else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
|
||||
right = RIGHT_FRINGE (6, Qup, 0);
|
||||
|
|
33
src/term.c
33
src/term.c
|
@ -1589,7 +1589,6 @@ append_glyph (it)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Produce glyphs for the display element described by IT. *IT
|
||||
specifies what we want to produce a glyph for (character, image, ...),
|
||||
and where in the glyph matrix we currently are (glyph row and hpos).
|
||||
|
@ -1808,6 +1807,17 @@ append_composite_glyph (it)
|
|||
glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
|
||||
if (glyph < it->glyph_row->glyphs[1 + it->area])
|
||||
{
|
||||
/* If the glyph row is reversed, we need to prepend the glyph
|
||||
rather than append it. */
|
||||
if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
|
||||
{
|
||||
struct glyph *g;
|
||||
|
||||
/* Make room for the new glyph. */
|
||||
for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
|
||||
g[1] = *g;
|
||||
glyph = it->glyph_row->glyphs[it->area];
|
||||
}
|
||||
glyph->type = COMPOSITE_GLYPH;
|
||||
glyph->pixel_width = it->pixel_width;
|
||||
glyph->u.cmp.id = it->cmp_it.id;
|
||||
|
@ -1828,6 +1838,18 @@ append_composite_glyph (it)
|
|||
glyph->padding_p = 0;
|
||||
glyph->charpos = CHARPOS (it->position);
|
||||
glyph->object = it->object;
|
||||
if (it->bidi_p)
|
||||
{
|
||||
glyph->resolved_level = it->bidi_it.resolved_level;
|
||||
if ((it->bidi_it.type & 7) != it->bidi_it.type)
|
||||
abort ();
|
||||
glyph->bidi_type = it->bidi_it.type;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->resolved_level = 0;
|
||||
glyph->bidi_type = UNKNOWN_BT;
|
||||
}
|
||||
|
||||
++it->glyph_row->used[it->area];
|
||||
++glyph;
|
||||
|
@ -1889,12 +1911,16 @@ produce_special_glyphs (it, what)
|
|||
|
||||
if (what == IT_CONTINUATION)
|
||||
{
|
||||
/* Continuation glyph. */
|
||||
SET_GLYPH_FROM_CHAR (glyph, '\\');
|
||||
/* Continuation glyph. For R2L lines, we mirror it by hand. */
|
||||
if (it->bidi_it.paragraph_dir == R2L)
|
||||
SET_GLYPH_FROM_CHAR (glyph, '/');
|
||||
else
|
||||
SET_GLYPH_FROM_CHAR (glyph, '\\');
|
||||
if (it->dp
|
||||
&& (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
|
||||
&& GLYPH_CODE_CHAR_VALID_P (gc))
|
||||
{
|
||||
/* FIXME: Should we mirror GC for R2L lines? */
|
||||
SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
|
||||
spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
|
||||
}
|
||||
|
@ -1907,6 +1933,7 @@ produce_special_glyphs (it, what)
|
|||
&& (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
|
||||
&& GLYPH_CODE_CHAR_VALID_P (gc))
|
||||
{
|
||||
/* FIXME: Should we mirror GC for R2L lines? */
|
||||
SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
|
||||
spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
|
||||
}
|
||||
|
|
|
@ -5136,10 +5136,12 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
|
|||
}
|
||||
|
||||
if (glyph_row->exact_window_width_line_p
|
||||
&& w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
|
||||
&& (glyph_row->reversed_p
|
||||
? (w->phys_cursor.hpos < 0)
|
||||
: (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
|
||||
{
|
||||
glyph_row->cursor_in_fringe_p = 1;
|
||||
draw_fringe_bitmap (w, glyph_row, 0);
|
||||
draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
234
src/xdisp.c
234
src/xdisp.c
|
@ -404,12 +404,14 @@ extern Lisp_Object Voverflow_newline_into_fringe;
|
|||
/* Test if overflow newline into fringe. Called with iterator IT
|
||||
at or past right window margin, and with IT->current_x set. */
|
||||
|
||||
#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) \
|
||||
(!NILP (Voverflow_newline_into_fringe) \
|
||||
&& FRAME_WINDOW_P (it->f) \
|
||||
&& WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \
|
||||
&& it->current_x == it->last_visible_x \
|
||||
&& it->line_wrap != WORD_WRAP)
|
||||
#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
|
||||
(!NILP (Voverflow_newline_into_fringe) \
|
||||
&& FRAME_WINDOW_P ((IT)->f) \
|
||||
&& ((IT)->bidi_it.paragraph_dir == R2L \
|
||||
? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
|
||||
: (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
|
||||
&& (IT)->current_x == (IT)->last_visible_x \
|
||||
&& (IT)->line_wrap != WORD_WRAP)
|
||||
|
||||
#else /* !HAVE_WINDOW_SYSTEM */
|
||||
#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
|
||||
|
@ -1077,6 +1079,8 @@ static void display_tool_bar_line P_ ((struct it *, int));
|
|||
static void notice_overwritten_cursor P_ ((struct window *,
|
||||
enum glyph_row_area,
|
||||
int, int, int, int));
|
||||
static void append_stretch_glyph P_ ((struct it *, Lisp_Object,
|
||||
int, int, int));
|
||||
|
||||
|
||||
|
||||
|
@ -6709,13 +6713,20 @@ next_element_from_buffer (it)
|
|||
{
|
||||
it->bidi_it.charpos = IT_CHARPOS (*it);
|
||||
it->bidi_it.bytepos = IT_BYTEPOS (*it);
|
||||
/* If we are at the beginning of a line, we can produce the next
|
||||
element right away. */
|
||||
if (it->bidi_it.bytepos == BEGV_BYTE
|
||||
if (it->bidi_it.bytepos == ZV_BYTE)
|
||||
{
|
||||
/* Nothing to do, but reset the FIRST_ELT flag, like
|
||||
bidi_paragraph_init does, because we are not going to
|
||||
call it. */
|
||||
it->bidi_it.first_elt = 0;
|
||||
}
|
||||
else if (it->bidi_it.bytepos == BEGV_BYTE
|
||||
/* FIXME: Should support all Unicode line separators. */
|
||||
|| FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n'
|
||||
|| FETCH_CHAR (it->bidi_it.bytepos) == '\n')
|
||||
{
|
||||
/* If we are at the beginning of a line, we can produce the
|
||||
next element right away. */
|
||||
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it);
|
||||
bidi_get_next_char_visually (&it->bidi_it);
|
||||
}
|
||||
|
@ -12619,7 +12630,6 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
/* The last known character position in row. */
|
||||
int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
|
||||
int x = row->x;
|
||||
int cursor_x = x;
|
||||
EMACS_INT pt_old = PT - delta;
|
||||
EMACS_INT pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
|
||||
EMACS_INT pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
|
||||
|
@ -12655,8 +12665,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
}
|
||||
while (end > glyph
|
||||
&& INTEGERP ((end - 1)->object)
|
||||
/* CHARPOS is zero for blanks inserted by
|
||||
extend_face_to_end_of_line. */
|
||||
/* CHARPOS is zero for blanks and stretch glyphs
|
||||
inserted by extend_face_to_end_of_line. */
|
||||
&& (end - 1)->charpos <= 0)
|
||||
--end;
|
||||
glyph_before = glyph - 1;
|
||||
|
@ -12670,9 +12680,6 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
to front, so swap the edge pointers. */
|
||||
glyphs_end = end = glyph - 1;
|
||||
glyph += row->used[TEXT_AREA] - 1;
|
||||
/* Reverse the known positions in the row. */
|
||||
last_pos = pos_after = MATRIX_ROW_START_CHARPOS (row) + delta;
|
||||
pos_before = MATRIX_ROW_END_CHARPOS (row) + delta;
|
||||
|
||||
while (glyph > end + 1
|
||||
&& INTEGERP (glyph->object)
|
||||
|
@ -12687,7 +12694,6 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
rightmost (first in the reading order) glyph. */
|
||||
for (g = end + 1; g < glyph; g++)
|
||||
x += g->pixel_width;
|
||||
cursor_x = x;
|
||||
while (end < glyph
|
||||
&& INTEGERP ((end + 1)->object)
|
||||
&& (end + 1)->charpos <= 0)
|
||||
|
@ -12702,7 +12708,7 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
rightmost glyph. Case in point: an empty last line that is
|
||||
part of an R2L paragraph. */
|
||||
cursor = end - 1;
|
||||
x = -1; /* will be computed below, at lable compute_x */
|
||||
x = -1; /* will be computed below, at label compute_x */
|
||||
}
|
||||
|
||||
/* Step 1: Try to find the glyph whose character position
|
||||
|
@ -12838,8 +12844,11 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
string_seen = 1;
|
||||
}
|
||||
--glyph;
|
||||
if (glyph == end)
|
||||
break;
|
||||
if (glyph == glyphs_end) /* don't dereference outside TEXT_AREA */
|
||||
{
|
||||
x--; /* can't use any pixel_width */
|
||||
break;
|
||||
}
|
||||
x -= glyph->pixel_width;
|
||||
}
|
||||
|
||||
|
@ -12879,7 +12888,10 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
}
|
||||
else if (match_with_avoid_cursor
|
||||
/* zero-width characters produce no glyphs */
|
||||
|| eabs (glyph_after - glyph_before) == 1)
|
||||
|| ((row->reversed_p
|
||||
? glyph_after > glyphs_end
|
||||
: glyph_after < glyphs_end)
|
||||
&& eabs (glyph_after - glyph_before) == 1))
|
||||
{
|
||||
cursor = glyph_after;
|
||||
x = -1;
|
||||
|
@ -12998,16 +13010,17 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
|
|||
}
|
||||
}
|
||||
|
||||
/* ROW could be part of a continued line, which might have other
|
||||
rows whose start and end charpos occlude point. Only set
|
||||
w->cursor if we found a better approximation to the cursor
|
||||
position than we have from previously examined rows. */
|
||||
/* ROW could be part of a continued line, which, under bidi
|
||||
reordering, might have other rows whose start and end charpos
|
||||
occlude point. Only set w->cursor if we found a better
|
||||
approximation to the cursor position than we have from previously
|
||||
examined candidate rows belonging to the same continued line. */
|
||||
if (/* we already have a candidate row */
|
||||
w->cursor.vpos >= 0
|
||||
/* that candidate is not the row we are processing */
|
||||
&& MATRIX_ROW (matrix, w->cursor.vpos) != row
|
||||
/* this row is part of a continued line */
|
||||
&& (row->continued_p || row->continuation_lines_width)
|
||||
/* the row we are processing is part of a continued line */
|
||||
&& (row->continued_p || MATRIX_ROW_CONTINUATION_LINE_P (row))
|
||||
/* Make sure cursor.vpos specifies a row whose start and end
|
||||
charpos occlude point. This is because some callers of this
|
||||
function leave cursor.vpos at the row where the cursor was
|
||||
|
@ -16850,9 +16863,11 @@ append_space_for_newline (it, default_face_p)
|
|||
|
||||
|
||||
/* Extend the face of the last glyph in the text area of IT->glyph_row
|
||||
to the end of the display line. Called from display_line.
|
||||
If the glyph row is empty, add a space glyph to it so that we
|
||||
know the face to draw. Set the glyph row flag fill_line_p. */
|
||||
to the end of the display line. Called from display_line. If the
|
||||
glyph row is empty, add a space glyph to it so that we know the
|
||||
face to draw. Set the glyph row flag fill_line_p. If the glyph
|
||||
row is R2L, prepend a stretch glyph to cover the empty space to the
|
||||
left of the leftmost glyph. */
|
||||
|
||||
static void
|
||||
extend_face_to_end_of_line (it)
|
||||
|
@ -16861,15 +16876,17 @@ extend_face_to_end_of_line (it)
|
|||
struct face *face;
|
||||
struct frame *f = it->f;
|
||||
|
||||
/* If line is already filled, do nothing. */
|
||||
if (it->current_x >= it->last_visible_x)
|
||||
/* If line is already filled, do nothing. Non window-system frames
|
||||
get a grace of one more ``pixel'' because their characters are
|
||||
1-``pixel'' wide, so they hit the equality too early. */
|
||||
if (it->current_x >= it->last_visible_x + !FRAME_WINDOW_P (f))
|
||||
return;
|
||||
|
||||
/* Face extension extends the background and box of IT->face_id
|
||||
to the end of the line. If the background equals the background
|
||||
of the frame, we don't have to do anything. */
|
||||
if (it->face_before_selective_p)
|
||||
face = FACE_FROM_ID (it->f, it->saved_face_id);
|
||||
face = FACE_FROM_ID (f, it->saved_face_id);
|
||||
else
|
||||
face = FACE_FROM_ID (f, it->face_id);
|
||||
|
||||
|
@ -16877,7 +16894,8 @@ extend_face_to_end_of_line (it)
|
|||
&& it->glyph_row->displays_text_p
|
||||
&& face->box == FACE_NO_BOX
|
||||
&& face->background == FRAME_BACKGROUND_PIXEL (f)
|
||||
&& !face->stipple)
|
||||
&& !face->stipple
|
||||
&& !it->glyph_row->reversed_p)
|
||||
return;
|
||||
|
||||
/* Set the glyph row flag indicating that the face of the last glyph
|
||||
|
@ -16904,6 +16922,50 @@ extend_face_to_end_of_line (it)
|
|||
it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
|
||||
it->glyph_row->used[TEXT_AREA] = 1;
|
||||
}
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (it->glyph_row->reversed_p)
|
||||
{
|
||||
/* Prepend a stretch glyph to the row, such that the
|
||||
rightmost glyph will be drawn flushed all the way to the
|
||||
right margin of the window. The stretch glyph that will
|
||||
occupy the empty space, if any, to the left of the
|
||||
glyphs. */
|
||||
struct font *font = face->font ? face->font : FRAME_FONT (f);
|
||||
struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
|
||||
struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
|
||||
struct glyph *g;
|
||||
int row_width, stretch_ascent, stretch_width;
|
||||
struct text_pos saved_pos;
|
||||
int saved_face_id, saved_avoid_cursor;
|
||||
|
||||
for (row_width = 0, g = row_start; g < row_end; g++)
|
||||
row_width += g->pixel_width;
|
||||
stretch_width = window_box_width (it->w, TEXT_AREA) - row_width;
|
||||
if (stretch_width > 0)
|
||||
{
|
||||
stretch_ascent =
|
||||
(((it->ascent + it->descent)
|
||||
* FONT_BASE (font)) / FONT_HEIGHT (font));
|
||||
saved_pos = it->position;
|
||||
bzero (&it->position, sizeof it->position);
|
||||
saved_avoid_cursor = it->avoid_cursor_p;
|
||||
it->avoid_cursor_p = 1;
|
||||
saved_face_id = it->face_id;
|
||||
/* The last row's stretch glyph should get the default
|
||||
face, to avoid painting the rest of the window with
|
||||
the region face, if the region ends at ZV. */
|
||||
if (it->glyph_row->ends_at_zv_p)
|
||||
it->face_id = DEFAULT_FACE_ID;
|
||||
else
|
||||
it->face_id = face->id;
|
||||
append_stretch_glyph (it, make_number (0), stretch_width,
|
||||
it->ascent + it->descent, stretch_ascent);
|
||||
it->position = saved_pos;
|
||||
it->avoid_cursor_p = saved_avoid_cursor;
|
||||
it->face_id = saved_face_id;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_WINDOW_SYSTEM */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -16922,7 +16984,13 @@ extend_face_to_end_of_line (it)
|
|||
it->object = make_number (0);
|
||||
it->c = ' ';
|
||||
it->len = 1;
|
||||
it->face_id = face->id;
|
||||
/* The last row's blank glyphs should get the default face, to
|
||||
avoid painting the rest of the window with the region face,
|
||||
if the region ends at ZV. */
|
||||
if (it->glyph_row->ends_at_zv_p)
|
||||
it->face_id = DEFAULT_FACE_ID;
|
||||
else
|
||||
it->face_id = face->id;
|
||||
|
||||
PRODUCE_GLYPHS (it);
|
||||
|
||||
|
@ -17208,6 +17276,31 @@ handle_line_prefix (struct it *it)
|
|||
|
||||
|
||||
|
||||
/* Remove N glyphs at the start of a reversed IT->glyph_row. Called
|
||||
only for R2L lines from display_line, when it decides that too many
|
||||
glyphs were produced by PRODUCE_GLYPHS, and the line needs to be
|
||||
continued. */
|
||||
static void
|
||||
unproduce_glyphs (it, n)
|
||||
struct it *it;
|
||||
int n;
|
||||
{
|
||||
struct glyph *glyph, *end;
|
||||
|
||||
xassert (it->glyph_row);
|
||||
xassert (it->glyph_row->reversed_p);
|
||||
xassert (it->area == TEXT_AREA);
|
||||
xassert (n <= it->glyph_row->used[TEXT_AREA]);
|
||||
|
||||
if (n > it->glyph_row->used[TEXT_AREA])
|
||||
n = it->glyph_row->used[TEXT_AREA];
|
||||
glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
|
||||
end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
|
||||
for ( ; glyph < end; glyph++)
|
||||
glyph[-n] = *glyph;
|
||||
}
|
||||
|
||||
|
||||
/* Construct the glyph row IT->glyph_row in the desired matrix of
|
||||
IT->w from text at the current position of IT. See dispextern.h
|
||||
for an overview of struct it. Value is non-zero if
|
||||
|
@ -17472,6 +17565,9 @@ display_line (it)
|
|||
/* A padding glyph that doesn't fit on this line.
|
||||
This means the whole character doesn't fit
|
||||
on the line. */
|
||||
if (row->reversed_p)
|
||||
unproduce_glyphs (it, row->used[TEXT_AREA]
|
||||
- n_glyphs_before);
|
||||
row->used[TEXT_AREA] = n_glyphs_before;
|
||||
|
||||
/* Fill the rest of the row with continuation
|
||||
|
@ -17494,6 +17590,9 @@ display_line (it)
|
|||
else if (wrap_row_used > 0)
|
||||
{
|
||||
back_to_wrap:
|
||||
if (row->reversed_p)
|
||||
unproduce_glyphs (it,
|
||||
row->used[TEXT_AREA] - wrap_row_used);
|
||||
*it = wrap_it;
|
||||
it->continuation_lines_width += wrap_x;
|
||||
row->used[TEXT_AREA] = wrap_row_used;
|
||||
|
@ -17529,6 +17628,9 @@ display_line (it)
|
|||
/* Something other than a TAB that draws past
|
||||
the right edge of the window. Restore
|
||||
positions to values before the element. */
|
||||
if (row->reversed_p)
|
||||
unproduce_glyphs (it, row->used[TEXT_AREA]
|
||||
- (n_glyphs_before + i));
|
||||
row->used[TEXT_AREA] = n_glyphs_before + i;
|
||||
|
||||
/* Display continuation glyphs. */
|
||||
|
@ -17634,9 +17736,22 @@ display_line (it)
|
|||
{
|
||||
int i, n;
|
||||
|
||||
for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
|
||||
if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
|
||||
break;
|
||||
if (!row->reversed_p)
|
||||
{
|
||||
for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
|
||||
if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < row->used[TEXT_AREA]; i++)
|
||||
if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
|
||||
break;
|
||||
/* Remove padding glyphs at the front of ROW, to
|
||||
make room for the truncation glyphs we will be
|
||||
adding below. */
|
||||
unproduce_glyphs (it, i);
|
||||
}
|
||||
|
||||
for (n = row->used[TEXT_AREA]; i < n; ++i)
|
||||
{
|
||||
|
@ -17823,7 +17938,7 @@ display_line (it)
|
|||
*it = save_it;
|
||||
}
|
||||
else if (!row->continued_p
|
||||
&& row->continuation_lines_width
|
||||
&& MATRIX_ROW_CONTINUATION_LINE_P (row)
|
||||
&& it->eol_pos.charpos > 0)
|
||||
{
|
||||
/* Last row of a continued line. Use the position
|
||||
|
@ -21493,6 +21608,17 @@ append_composite_glyph (it)
|
|||
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
|
||||
if (glyph < it->glyph_row->glyphs[area + 1])
|
||||
{
|
||||
/* If the glyph row is reversed, we need to prepend the glyph
|
||||
rather than append it. */
|
||||
if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
|
||||
{
|
||||
struct glyph *g;
|
||||
|
||||
/* Make room for the new glyph. */
|
||||
for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
|
||||
g[1] = *g;
|
||||
glyph = it->glyph_row->glyphs[it->area];
|
||||
}
|
||||
glyph->charpos = CHARPOS (it->position);
|
||||
glyph->object = it->object;
|
||||
glyph->pixel_width = it->pixel_width;
|
||||
|
@ -21738,6 +21864,17 @@ append_stretch_glyph (it, object, width, height, ascent)
|
|||
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
|
||||
if (glyph < it->glyph_row->glyphs[area + 1])
|
||||
{
|
||||
/* If the glyph row is reversed, we need to prepend the glyph
|
||||
rather than append it. */
|
||||
if (it->glyph_row->reversed_p && area == TEXT_AREA)
|
||||
{
|
||||
struct glyph *g;
|
||||
|
||||
/* Make room for the additional glyph. */
|
||||
for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
|
||||
g[1] = *g;
|
||||
glyph = it->glyph_row->glyphs[area];
|
||||
}
|
||||
glyph->charpos = CHARPOS (it->position);
|
||||
glyph->object = object;
|
||||
glyph->pixel_width = width;
|
||||
|
@ -21764,6 +21901,11 @@ append_stretch_glyph (it, object, width, height, ascent)
|
|||
abort ();
|
||||
glyph->bidi_type = it->bidi_it.type;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->resolved_level = 0;
|
||||
glyph->bidi_type = UNKNOWN_BT;
|
||||
}
|
||||
++it->glyph_row->used[area];
|
||||
}
|
||||
else
|
||||
|
@ -23244,7 +23386,7 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
|
|||
if (row->cursor_in_fringe_p)
|
||||
{
|
||||
row->cursor_in_fringe_p = 0;
|
||||
draw_fringe_bitmap (w, row, 0);
|
||||
draw_fringe_bitmap (w, row, row->reversed_p);
|
||||
w->phys_cursor_on_p = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -23345,7 +23487,9 @@ draw_phys_cursor_glyph (w, row, hl)
|
|||
/* If cursor hpos is out of bounds, don't draw garbage. This can
|
||||
happen in mini-buffer windows when switching between echo area
|
||||
glyphs and mini-buffer. */
|
||||
if (w->phys_cursor.hpos < row->used[TEXT_AREA])
|
||||
if ((row->reversed_p
|
||||
? (w->phys_cursor.hpos >= 0)
|
||||
: (w->phys_cursor.hpos < row->used[TEXT_AREA])))
|
||||
{
|
||||
int on_p = w->phys_cursor_on_p;
|
||||
int x1;
|
||||
|
@ -23425,7 +23569,7 @@ erase_phys_cursor (w)
|
|||
if (cursor_row->cursor_in_fringe_p)
|
||||
{
|
||||
cursor_row->cursor_in_fringe_p = 0;
|
||||
draw_fringe_bitmap (w, cursor_row, 0);
|
||||
draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
|
||||
goto mark_cursor_off;
|
||||
}
|
||||
|
||||
|
@ -23434,7 +23578,9 @@ erase_phys_cursor (w)
|
|||
should have cleared the cursor. Note that we wouldn't be
|
||||
able to erase the cursor in this case because we don't have a
|
||||
cursor glyph at hand. */
|
||||
if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
|
||||
if ((cursor_row->reversed_p
|
||||
? (w->phys_cursor.hpos < 0)
|
||||
: (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
|
||||
goto mark_cursor_off;
|
||||
|
||||
/* If the cursor is in the mouse face area, redisplay that when
|
||||
|
@ -23450,7 +23596,7 @@ erase_phys_cursor (w)
|
|||
/* Don't redraw the cursor's spot in mouse face if it is at the
|
||||
end of a line (on a newline). The cursor appears there, but
|
||||
mouse highlighting does not. */
|
||||
&& cursor_row->used[TEXT_AREA] > hpos)
|
||||
&& cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
|
||||
mouse_face_here_p = 1;
|
||||
|
||||
/* Maybe clear the display under the cursor. */
|
||||
|
@ -23532,7 +23678,7 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
|
|||
|
||||
glyph = NULL;
|
||||
if (!glyph_row->exact_window_width_line_p
|
||||
|| hpos < glyph_row->used[TEXT_AREA])
|
||||
|| (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
|
||||
glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
|
||||
|
||||
xassert (interrupt_input_blocked);
|
||||
|
|
44
src/xterm.c
44
src/xterm.c
|
@ -7492,36 +7492,40 @@ x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, activ
|
|||
w->phys_cursor_on_p = 1;
|
||||
|
||||
if (glyph_row->exact_window_width_line_p
|
||||
&& w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
|
||||
&& (glyph_row->reversed_p
|
||||
? (w->phys_cursor.hpos < 0)
|
||||
: (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
|
||||
{
|
||||
glyph_row->cursor_in_fringe_p = 1;
|
||||
draw_fringe_bitmap (w, glyph_row, 0);
|
||||
draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
|
||||
}
|
||||
else
|
||||
switch (cursor_type)
|
||||
{
|
||||
case HOLLOW_BOX_CURSOR:
|
||||
x_draw_hollow_cursor (w, glyph_row);
|
||||
break;
|
||||
switch (cursor_type)
|
||||
{
|
||||
case HOLLOW_BOX_CURSOR:
|
||||
x_draw_hollow_cursor (w, glyph_row);
|
||||
break;
|
||||
|
||||
case FILLED_BOX_CURSOR:
|
||||
draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
|
||||
break;
|
||||
case FILLED_BOX_CURSOR:
|
||||
draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
|
||||
break;
|
||||
|
||||
case BAR_CURSOR:
|
||||
x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
|
||||
break;
|
||||
case BAR_CURSOR:
|
||||
x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
|
||||
break;
|
||||
|
||||
case HBAR_CURSOR:
|
||||
x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
|
||||
break;
|
||||
case HBAR_CURSOR:
|
||||
x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
|
||||
break;
|
||||
|
||||
case NO_CURSOR:
|
||||
w->phys_cursor_width = 0;
|
||||
break;
|
||||
case NO_CURSOR:
|
||||
w->phys_cursor_width = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
|
|
Loading…
Add table
Reference in a new issue