Commit 88e6b646 authored by Kim F. Storm's avatar Kim F. Storm

(Voverflow_newline_into_fringe): New variable.

(IT_OVERFLOW_NEWLINE_INTO_FRINGE): New macro.
(move_it_in_display_line_to): Overflow newline into fringe for
rows that are exactly as wide as the window.
(up_arrow_bits, down_arrow_bits, first_line_bits, last_line_bits)
(filled_box_cursor_bits, hollow_box_cursor_bits, bar_cursor_bits)
(hbar_cursor_bits, hollow_square_bits): New fringe bitmaps.
(fringe_bitmaps): Add new bitmaps.
(draw_fringe_bitmap): Make extern.  Remove WHICH arg.
Select proper bitmap for cursor in fringe when appropriate.
Handle alignment of bitmap to top or bottom of row.
(draw_row_fringe_bitmaps): Don't select bitmaps here; that is now
done by update_window_fringes.
(update_window_fringes, draw_window_fringes): New functions.
(redisplay_internal): Call update_window_fringes in case only
cursor row is updated.
(redisplay_window): Call update_window_fringes.
Explicitly call draw_window_fringes if redisplay was done using
the current matrix or the overlay arrow is in the window.
(try_window_reusing_current_matrix): Mark scrolled rows for
fringe update (to update buffer-boundaries / scrolling icons).
(find_last_unchanged_at_beg_row): Handle exact width lines line
continued lines.
(display_line): Overflow newline into fringe for rows that are
exactly as wide as the window.  Don't append space for newline
in this case.
(notice_overwritten_cursor): Explicitly clear cursor bitmap
in fringe as if it had been overwritten.
(erase_phys_cursor): Erase cursor bitmap in fringe.
(syms_of_xdisp): Mark show-trailing-whitespace and
void-text-area-pointer as user options.
DEFVAR_LISP Voverflow_newline_into_fringe.  Enable by default.
parent 5fbcdd19
......@@ -310,6 +310,19 @@ extern Lisp_Object Qscroll_bar;
Lisp_Object Vshow_trailing_whitespace;
/* Non-nil means that newline may flow into the right fringe. */
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)
/* Non-nil means show the text cursor in void text areas
i.e. in blank areas after eol and eob. This used to be
the default in 21.3. */
......@@ -5594,7 +5607,18 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
++it->hpos;
it->current_x = new_x;
if (i == it->nglyphs - 1)
set_iterator_to_next (it, 1);
{
set_iterator_to_next (it, 1);
if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
get_next_display_element (it);
if (ITERATOR_AT_END_OF_LINE_P (it))
{
result = MOVE_NEWLINE_OR_CR;
break;
}
}
}
}
else
{
......@@ -5651,6 +5675,15 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
if (it->truncate_lines_p
&& it->current_x >= it->last_visible_x)
{
if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
get_next_display_element (it);
if (ITERATOR_AT_END_OF_LINE_P (it))
{
result = MOVE_NEWLINE_OR_CR;
break;
}
}
result = MOVE_LINE_TRUNCATED;
break;
}
......@@ -8899,26 +8932,205 @@ note_tool_bar_highlight (f, x, y)
#ifdef HAVE_WINDOW_SYSTEM
/* Notice that all bitmaps bits are "mirrored". */
/* An arrow like this: `<-'. */
/*
...xx...
....xx..
.....xx.
..xxxxxx
..xxxxxx
.....xx.
....xx..
...xx...
*/
static unsigned char left_bits[] = {
0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
/* Right truncation arrow bitmap `->'. */
/*
...xx...
..xx....
.xx.....
xxxxxx..
xxxxxx..
.xx.....
..xx....
...xx...
*/
static unsigned char right_bits[] = {
0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
/* Up arrow bitmap. */
/*
...xx...
..xxxx..
.xxxxxx.
xxxxxxxx
...xx...
...xx...
...xx...
...xx...
*/
static unsigned char up_arrow_bits[] = {
0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
/* Down arrow bitmap. */
/*
...xx...
...xx...
...xx...
...xx...
xxxxxxxx
.xxxxxx.
..xxxx..
...xx...
*/
static unsigned char down_arrow_bits[] = {
0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
/* Marker for continued lines. */
/*
..xxxx..
.xxxxx..
xx......
xxx..x..
xxxxxx..
.xxxxx..
..xxxx..
.xxxxx..
*/
static unsigned char continued_bits[] = {
0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
/* Marker for continuation lines. */
/*
..xxxx..
..xxxxx.
......xx
..x..xxx
..xxxxxx
..xxxxx.
..xxxx..
..xxxxx.
*/
static unsigned char continuation_bits[] = {
0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
/* Overlay arrow bitmap. A triangular arrow. */
/*
......xx
....xxxx
...xxxxx
..xxxxxx
..xxxxxx
...xxxxx
....xxxx
......xx
*/
static unsigned char ov_bits[] = {
0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
/* First line bitmap. An left-up angle. */
/*
..xxxxxx
..xxxxxx
......xx
......xx
......xx
......xx
......xx
........
*/
static unsigned char first_line_bits[] = {
0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
/* Last line bitmap. An left-down angle. */
/*
........
xx......
xx......
xx......
xx......
xx......
xxxxxx..
xxxxxx..
*/
static unsigned char last_line_bits[] = {
0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
/* Filled box cursor bitmap. A filled box; max 13 pixels high. */
/*
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
.xxxxxxx
*/
static unsigned char filled_box_cursor_bits[] = {
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f};
/* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
/*
.xxxxxxx
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.x.....x
.xxxxxxx
*/
static unsigned char hollow_box_cursor_bits[] = {
0x7f, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7f};
/* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
/*
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
......xx
*/
static unsigned char bar_cursor_bits[] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
/* HBar cursor bitmap. A horisontal bar; 2 pixels high. */
/*
.xxxxxxx
.xxxxxxx
*/
static unsigned char hbar_cursor_bits[] = {
0x7f, 0x7f};
/* Bitmap drawn to indicate lines not displaying text if
`indicate-empty-lines' is non-nil. */
static unsigned char zv_bits[] = {
......@@ -8931,32 +9143,89 @@ static unsigned char zv_bits[] = {
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
/* Hollow square bitmap. */
/*
.xxxxxx.
.x....x.
.x....x.
.x....x.
.x....x.
.xxxxxx.
*/
static unsigned char hollow_square_bits[] = {
0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
{
{ 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
{ 8, sizeof (left_bits), 0, left_bits },
{ 8, sizeof (right_bits), 0, right_bits },
{ 8, sizeof (up_arrow_bits), -1, up_arrow_bits },
{ 8, sizeof (down_arrow_bits), -2, down_arrow_bits },
{ 8, sizeof (continued_bits), 0, continued_bits },
{ 8, sizeof (continuation_bits), 0, continuation_bits },
{ 8, sizeof (ov_bits), 0, ov_bits },
{ 8, sizeof (zv_bits), 3, zv_bits }
{ 8, sizeof (first_line_bits), -1, first_line_bits },
{ 8, sizeof (last_line_bits), -2, last_line_bits },
{ 8, sizeof (filled_box_cursor_bits), 0, filled_box_cursor_bits },
{ 8, sizeof (hollow_box_cursor_bits), 0, hollow_box_cursor_bits },
{ 8, sizeof (bar_cursor_bits), 0, bar_cursor_bits },
{ 8, sizeof (hbar_cursor_bits), -2, hbar_cursor_bits },
{ 8, sizeof (zv_bits), 3, zv_bits },
{ 8, sizeof (hollow_square_bits), 0, hollow_square_bits },
};
/* 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. */
drawn.
LEFT_P is 1 for left fringe, 0 for right fringe.
*/
static void
draw_fringe_bitmap (w, row, which, left_p)
void
draw_fringe_bitmap (w, row, left_p)
struct window *w;
struct glyph_row *row;
enum fringe_bitmap_type which;
int left_p;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct draw_fringe_bitmap_params p;
enum fringe_bitmap_type which;
int period;
if (left_p)
which = row->left_fringe_bitmap;
else if (!row->cursor_in_fringe_p)
which = row->right_fringe_bitmap;
else
switch (w->phys_cursor_type)
{
case HOLLOW_BOX_CURSOR:
if (row->visible_height >= sizeof(hollow_box_cursor_bits))
which = HOLLOW_BOX_CURSOR_BITMAP;
else
which = HOLLOW_SQUARE_BITMAP;
break;
case FILLED_BOX_CURSOR:
which = FILLED_BOX_CURSOR_BITMAP;
break;
case BAR_CURSOR:
which = BAR_CURSOR_BITMAP;
break;
case HBAR_CURSOR:
which = HBAR_CURSOR_BITMAP;
break;
case NO_CURSOR:
default:
w->phys_cursor_on_p = 0;
row->cursor_in_fringe_p = 0;
which = row->right_fringe_bitmap;
break;
}
period = fringe_bitmaps[which].period;
/* Convert row to frame coordinates. */
p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
......@@ -8965,9 +9234,7 @@ draw_fringe_bitmap (w, row, which, left_p)
p.wd = fringe_bitmaps[which].width;
p.h = fringe_bitmaps[which].height;
p.dh = (fringe_bitmaps[which].period
? (p.y % fringe_bitmaps[which].period)
: 0);
p.dh = (period > 0 ? (p.y % period) : 0);
p.h -= p.dh;
/* Clip bitmap if too high. */
if (p.h > row->height)
......@@ -9027,7 +9294,13 @@ draw_fringe_bitmap (w, row, which, left_p)
}
/* Adjust y to the offset in the row to start drawing the bitmap. */
p.y += (row->height - p.h) / 2;
if (period == 0)
p.y += (row->height - p.h) / 2;
else if (period == -2)
{
p.h = fringe_bitmaps[which].height;
p.y += (row->visible_height - p.h);
}
rif->draw_fringe_bitmap (w, row, &p);
}
......@@ -9040,8 +9313,6 @@ draw_row_fringe_bitmaps (w, row)
struct window *w;
struct glyph_row *row;
{
enum fringe_bitmap_type bitmap;
xassert (interrupt_input_blocked);
/* If row is completely invisible, because of vscrolling, we
......@@ -9050,35 +9321,35 @@ draw_row_fringe_bitmaps (w, row)
return;
if (WINDOW_LEFT_FRINGE_WIDTH (w) != 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;
draw_fringe_bitmap (w, row, bitmap, 1);
}
draw_fringe_bitmap (w, row, 1);
if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 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 && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
bitmap = ZV_LINE_BITMAP;
else
bitmap = NO_FRINGE_BITMAP;
draw_fringe_bitmap (w, row, 0);
}
/* Draw the fringes of window W. Only fringes for rows marked for
update in redraw_fringe_bitmaps_p are drawn. */
draw_fringe_bitmap (w, row, bitmap, 0);
void
draw_window_fringes (w)
struct window *w;
{
struct glyph_row *row;
int yb = window_text_bottom_y (w);
int nrows = w->current_matrix->nrows;
int y = 0, rn;
if (w->pseudo_window_p)
return;
for (y = 0, rn = 0, row = w->current_matrix->rows;
y < yb && rn < nrows;
y += row->height, ++row, ++rn)
{
if (!row->redraw_fringe_bitmaps_p)
continue;
draw_row_fringe_bitmaps (w, row);
row->redraw_fringe_bitmaps_p = 0;
}
}
......@@ -9986,6 +10257,7 @@ redisplay_internal (preserve_echo_area)
*w->desired_matrix->method = 0;
debug_method_add (w, "optimization 1");
#endif
update_window_fringes (w, 0);
goto update;
}
else
......@@ -11396,6 +11668,135 @@ set_vertical_scroll_bar (w)
set_vertical_scroll_bar_hook (w, end - start, whole, start);
}
/* Recalculate the bitmaps to show in the fringes of window W.
If FORCE_P is 0, only mark rows with modified bitmaps for update in
redraw_fringe_bitmaps_p; else mark all rows for update. */
int
update_window_fringes (w, force_p)
struct window *w;
int force_p;
{
struct glyph_row *row, *cur = 0;
int yb = window_text_bottom_y (w);
int rn, nrows = w->current_matrix->nrows;
int y;
int redraw_p = 0;
Lisp_Object ind;
if (w->pseudo_window_p)
return 0;
if (!MINI_WINDOW_P (w)
&& (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
{
int do_eob = 1, do_bob = 1;
for (y = 0, rn = 0;
y < yb && rn < nrows;
y += row->height, ++rn)
{
unsigned indicate_bob_p, indicate_top_line_p;
unsigned indicate_eob_p, indicate_bottom_line_p;
row = w->desired_matrix->rows + rn;
if (!row->enabled_p)
row = w->current_matrix->rows + rn;
indicate_bob_p = row->indicate_bob_p;
indicate_top_line_p = row->indicate_top_line_p;
indicate_eob_p = row->indicate_eob_p;
indicate_bottom_line_p = row->indicate_bottom_line_p;
row->indicate_bob_p = row->indicate_top_line_p = 0;
row->indicate_eob_p = row->indicate_bottom_line_p = 0;
if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
row->indicate_bob_p = do_bob, do_bob = 0;
else if (EQ (ind, Qt)
&& (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
row->indicate_top_line_p = 1;
if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
row->indicate_eob_p = do_eob, do_eob = 0;
else if (EQ (ind, Qt)
&& y + row->height >= yb)
row->indicate_bottom_line_p = 1;
if (indicate_bob_p != row->indicate_bob_p
|| indicate_top_line_p != row->indicate_top_line_p
|| indicate_eob_p != row->indicate_eob_p
|| indicate_bottom_line_p != row->indicate_bottom_line_p)
row->redraw_fringe_bitmaps_p = 1;
}
}
for (y = 0, rn = 0;
y < yb && rn < nrows;
y += row->height, rn++)
{
enum fringe_bitmap_type left, right;
row = w->desired_matrix->rows + rn;
cur = w->current_matrix->rows + rn;
if (!row->enabled_p)
row = cur;
/* Decide which bitmap to draw in the left fringe. */
if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
left = NO_FRINGE_BITMAP;
else if (row->overlay_arrow_p)
left = OVERLAY_ARROW_BITMAP;
else if (row->truncated_on_left_p)
left = LEFT_TRUNCATION_BITMAP;
else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
left = CONTINUATION_LINE_BITMAP;
else if (row->indicate_empty_line_p)
left = ZV_LINE_BITMAP;
else if (row->indicate_bob_p)
left = FIRST_LINE_BITMAP;
else
left = NO_FRINGE_BITMAP;
/* Decide which bitmap to draw in the right fringe. */
if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
right = NO_FRINGE_BITMAP;
else if (row->truncated_on_right_p)
right = RIGHT_TRUNCATION_BITMAP;
else if (row->continued_p)
right = CONTINUED_LINE_BITMAP;
else if (row->indicate_eob_p)
right = LAST_LINE_BITMAP;
else if (row->indicate_top_line_p)
right = UP_ARROW_BITMAP;
else if (row->indicate_bottom_line_p)
right = DOWN_ARROW_BITMAP;
else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
right = ZV_LINE_BITMAP;
else
right = NO_FRINGE_BITMAP;
if (force_p
|| row->y != cur->y
|| row->visible_height != cur->visible_height
|| left != cur->left_fringe_bitmap
|| right != cur->right_fringe_bitmap
|| cur->redraw_fringe_bitmaps_p)
{
redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
cur->left_fringe_bitmap = left;
cur->right_fringe_bitmap = right;
}
row->left_fringe_bitmap = left;
row->right_fringe_bitmap = right;
}
return redraw_p;
}
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
selected_window is redisplayed.
......@@ -11418,6 +11819,7 @@ redisplay_window (window, just_this_one_p)
struct it it;
/* Record it now because it's overwritten. */
int current_matrix_up_to_date_p = 0;
int used_current_matrix_p = 0;
/* This is less strict than current_matrix_up_to_date_p.
It indictes that the buffer contents and narrowing are unchanged. */
int buffer_unchanged_p = 0;
......@@ -11724,6 +12126,7 @@ redisplay_window (window, just_this_one_p)
switch (rc)
{
case CURSOR_MOVEMENT_SUCCESS:
used_current_matrix_p = 1;
goto done;
#if 0 /* try_cursor_movement never returns this value. */
......@@ -11788,7 +12191,8 @@ redisplay_window (window, just_this_one_p)
buffer. */
|| !NILP (Vwindow_scroll_functions)
|| MINI_WINDOW_P (w)
|| !try_window_reusing_current_matrix (w))
|| !(used_current_matrix_p =
try_window_reusing_current_matrix (w)))
{
IF_DEBUG (debug_method_add (w, "1"));
try_window (window, startp);
......@@ -11917,7 +12321,8 @@ redisplay_window (window, just_this_one_p)
|| !NILP (Vwindow_scroll_functions)
|| !just_this_one_p
|| MINI_WINDOW_P (w)
|| !try_window_reusing_current_matrix (w))
|| !(used_current_matrix_p =
try_window_reusing_current_matrix (w)))
try_window (window, startp);
/* If new fonts have been loaded (due to fontsets), give up. We
......@@ -12079,6 +12484,17 @@ redisplay_window (window, just_this_one_p)
#endif
}
if (update_window_fringes (w, 0)
&& (used_current_matrix_p || overlay_arrow_seen)
&& !w->pseudo_window_p)
{
update_begin (f);
BLOCK_INPUT;
draw_window_fringes (w);
UNBLOCK_INPUT;
update_end (f);
}
/* We go to this label, with fonts_changed_p nonzero,
if it is necessary to try again using larger glyph matrices.
We have to redeem the scroll bar even in this case,
......@@ -12335,6 +12751,7 @@ try_window_reusing_current_matrix (w)
row->visible_height -= min_y - row->y;
if (row->y + row->height > max_y)
row->visible_height -= row->y + row->height - max_y;
row->redraw_fringe_bitmaps_p = 1;
it.current_y += row->height;
......@@ -12474,7 +12891,6 @@ try_window_reusing_current_matrix (w)
if (run.height)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
update_begin (f);
rif->update_window_begin_hook (w);
rif->clear_window_mouse_face (w);
......@@ -12495,6 +12911,7 @@ try_window_reusing_current_matrix (w)
row->visible_height -= min_y - row->y;
if (row->y + row->height > max_y)
row->visible_height -= row->y + row->height - max_y;
row->redraw_fringe_bitmaps_p = 1;
}
/* Scroll the current matrix. */
......@@ -12617,7 +13034,8 @@ find_last_unchanged_at_beg_row (w)
row is not unchanged because it may be no longer
continued. */
&& !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
&& row->continued_p))
&& (row->continued_p
|| row->exact_window_width_line_p)))
row_found = row;