[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[6438] more efficient redisplay when there is underlining or standout
From: |
Gavin D. Smith |
Subject: |
[6438] more efficient redisplay when there is underlining or standout |
Date: |
Mon, 20 Jul 2015 16:55:19 +0000 |
Revision: 6438
http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=6438
Author: gavin
Date: 2015-07-20 16:55:18 +0000 (Mon, 20 Jul 2015)
Log Message:
-----------
more efficient redisplay when there is underlining or standout
Modified Paths:
--------------
trunk/ChangeLog
trunk/info/display.c
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2015-07-20 16:53:56 UTC (rev 6437)
+++ trunk/ChangeLog 2015-07-20 16:55:18 UTC (rev 6438)
@@ -1,3 +1,12 @@
+2015-07-20 Gavin Smith <address@hidden>
+
+ * info/display.c (display_update_window_1, display_update_node_text):
+ Rename function. Avoid outputting line with standout or underline if
+ nothing has changed on it.
+ (display_process_line): Function split out from
+ display_update_node_text.
+ (writing_out): New file-level variable.
+
2015-07-19 Gavin Smith <address@hidden>
* info/nodes.c (find_node_from_tag) <resetting tag table>: Don't
Modified: trunk/info/display.c
===================================================================
--- trunk/info/display.c 2015-07-20 16:53:56 UTC (rev 6437)
+++ trunk/info/display.c 2015-07-20 16:55:18 UTC (rev 6438)
@@ -1,8 +1,8 @@
/* display.c -- How to display Info windows.
$Id$
- Copyright 1993, 1997, 2003, 2004, 2006, 2007, 2008, 2012, 2013, 2014
- Free Software Foundation, Inc.
+ Copyright 1993, 1997, 2003, 2004, 2006, 2007, 2008, 2012, 2013,
+ 2014, 2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -143,9 +143,9 @@
/* Update line PL_NUM of the screen to be PRINTED_LINE, which is PL_BYTES long
and takes up PL_CHARS columns. */
-int
-display_node_text (long pl_num, char *printed_line,
- long pl_bytes, long pl_chars)
+static int
+display_update_line (long pl_num, char *printed_line,
+ long pl_bytes, long pl_chars)
{
DISPLAY_LINE **display = the_display;
DISPLAY_LINE *entry;
@@ -283,114 +283,116 @@
*in_ref = m;
}
-/* Print each line in the window into our local buffer, and then
- check the contents of that buffer against the display. If they
- differ, update the display.
- Return value: number of lines processed. */
-long
-display_update_window_1 (WINDOW *win)
+/* Used when processing a line to be displayed from a node. DEFAULT is the
+ value when the line has no special styles like underlined references or
+ highlighted search matches. Otherwise, a line is processed once with
+ COLLECT as the value, and if it differs to what is on the display already,
+ it is processed with WRITEOUT and written to the display. */
+static int writing_out;
+#define DEFAULT 0
+#define COLLECT 1
+#define WRITEOUT 2 /* Values for writing_out global. */
+
+static void
+wrap_terminal_begin_standout (struct text_buffer *printed_line)
{
- char *start = win->node->contents + win->line_starts[win->pagetop];
+ if (writing_out == WRITEOUT)
+ terminal_begin_standout ();
+ else /* writing_out == COLLECT */
+ /* Add marker to string to record that standout starts here. The text
+ added here, and in the other functions, is not output to the terminal,
+ and is only used internally. */
+ text_buffer_add_string (printed_line, "\033so", 3);
+}
- struct text_buffer tb_printed_line; /* Buffer for a printed line. */
- long pl_chars = 0; /* Number of characters written to printed_line */
- long pl_num = 0; /* Number of physical lines done so far. */
- mbi_iterator_t iter;
+static void
+wrap_terminal_end_standout (struct text_buffer *printed_line)
+{
+ if (writing_out == WRITEOUT)
+ terminal_end_standout ();
+ else
+ text_buffer_add_string (printed_line, "\033se", 3);
+}
- /* If there are no highlighted regions in a line, we output the line with
- display_node_text, which does some optimization of the redisplay.
- Otherwise, the entire line is output in this function. */
- int match_seen_in_line = 0;
+static void
+wrap_terminal_begin_underline (struct text_buffer *printed_line)
+{
+ if (writing_out == WRITEOUT)
+ terminal_begin_underline ();
+ else
+ text_buffer_add_string (printed_line, "\033us", 3);
+}
- regmatch_t *matches = 0;
- size_t match_index = 0;
- int in_match = 0; /* If we have highlighting on for a match. */
+static void
+wrap_terminal_end_underline (struct text_buffer *printed_line)
+{
+ if (writing_out == WRITEOUT)
+ terminal_end_underline ();
+ else
+ text_buffer_add_string (printed_line, "\033ue", 3);
+}
- REFERENCE **refs = 0;
- int ref_index = 0, in_ref = 0;
- int ref_seen_in_line = 0;
+/* Set in display_update_node_text if matches or references are to be
+ distinguished with terminal appearance modes. */
+static regmatch_t *matches;
+static REFERENCE **refs;
+static size_t match_index;
+static int ref_index;
- /* Set to 1 when we are in the text of a cross-reference and at the start of
- a new line, and haven't seen a non-whitespace character yet. */
- int ref_leading_whitespace = 0;
+/* Number of screen columns output so far in a line. */
+static int pl_chars;
- int cur_line = win->pagetop;
- int point_in_line = 0; /* Point is on the line being update. */
- int ref_highlighted = 0;
+/* Whether we are currently outputting a highlighted reference. This can be
+ carried over from one line to another. */
+static int ref_highlighted;
- if (highlight_searches_p)
- matches = win->matches;
+static int pl_num; /* Number of printed lines done so far. */
- if (xref_rendition_p)
- refs = win->node->references;
+/* Process a line from the node in WIN starting at ITER, and advancing ITER
+ to the end of the line. What is done with the line depends on the value
+ of WRITING_OUT.
+ If the line ends in a newline character, set *DELIM to 1. */
+static void
+display_process_line (WINDOW *win,
+ mbi_iterator_t *iter_inout,
+ struct text_buffer *tb_printed_line,
+ int *delim)
+{
+ mbi_iterator_t iter;
+ const char *cur_ptr;
+ size_t pchars = 0; /* Printed chars */
+ size_t pbytes = 0; /* Bytes to output. */
+ char *rep;
+ int in_match = 0, in_ref = 0;
- /* Find first search match after the start of the page, and check whether
- we start inside a match. */
- if (matches)
- {
- match_index = 0;
- decide_if_in_match (win->line_starts[cur_line], &in_match,
- matches, win->match_count, &match_index);
- }
+ /* Set to 1 when we are in the text of a cross-reference and at the start
+ of a new line, and haven't seen a non-whitespace character yet. */
+ int ref_leading_whitespace = 1;
+ int point_in_line;
- /* Likewise, check whether we start within a cross-reference or menu
- entry. */
- if (refs)
- {
- ref_index = 0;
- decide_if_in_reference (win->line_starts[cur_line], &in_ref,
- refs, &ref_index);
- }
-
- text_buffer_init (&tb_printed_line);
-
- if (in_match)
- {
- terminal_begin_standout ();
- match_seen_in_line = 1;
- terminal_goto_xy (0, win->first_row);
- }
-
- if (win->point >= win->line_starts[cur_line]
- && win->point < win->line_starts[cur_line + 1])
+ if (win->point >= win->line_starts[win->pagetop + pl_num]
+ && win->point < win->line_starts[win->pagetop + pl_num + 1])
point_in_line = 1;
else
point_in_line = 0;
- if (in_ref)
- {
- ref_leading_whitespace = 1;
- ref_seen_in_line = 1;
- terminal_goto_xy (0, win->first_row);
- }
+ iter = *iter_inout;
- for (mbi_init (iter, start,
- win->node->contents + win->node->nodelen - start);
- mbi_avail (iter);
- mbi_advance (iter))
+ while (1)
{
- const char *cur_ptr;
- char *rep;
-
- size_t pchars = 0; /* Printed chars */
- size_t pbytes = 0; /* Bytes to output. */
- int delim = 0;
- int finish = 0;
-
- /* Check if we have processed all the lines in the window. */
- if (pl_num == win->height)
+ if (!mbi_avail (iter))
break;
+ cur_ptr = mbi_cur_ptr (iter);
- /* Check if this line of the window is off the screen. This might
- happen if the screen was resized very small. */
- if (win->first_row + pl_num >= screenheight)
- break;
+ if (ref_leading_whitespace && !strchr (" \t", *cur_ptr))
+ {
+ ref_leading_whitespace = 0;
+ if (in_ref)
+ wrap_terminal_begin_underline (tb_printed_line);
+ if (!in_match && ref_highlighted)
+ wrap_terminal_begin_standout (tb_printed_line);
+ }
- rep = printed_representation (&iter, &delim, pl_chars,
- &pchars, &pbytes);
-
- cur_ptr = mbi_cur_ptr (iter);
-
if (matches && match_index != win->match_count)
{
int was_in_match = in_match;
@@ -399,25 +401,12 @@
&match_index);
if (was_in_match && !in_match && !ref_highlighted)
- {
- terminal_end_standout ();
- }
+ wrap_terminal_end_standout (tb_printed_line);
else if (!was_in_match && in_match)
{
- if (!match_seen_in_line)
- {
- match_seen_in_line = 1;
-
- if (!ref_seen_in_line)
- {
- /* Output the line so far. */
- terminal_goto_xy (0, win->first_row + pl_num);
- terminal_write_chars
- (text_buffer_base (&tb_printed_line),
- text_buffer_off (&tb_printed_line));
- }
- }
- terminal_begin_standout ();
+ if (writing_out == DEFAULT)
+ writing_out = COLLECT;
+ wrap_terminal_begin_standout (tb_printed_line);
}
}
@@ -430,29 +419,19 @@
if (was_in_ref && !in_ref)
{
ref_leading_whitespace = 0;
- terminal_end_underline ();
+ wrap_terminal_end_underline (tb_printed_line);
if (ref_highlighted && !in_match)
{
ref_highlighted = 0;
- terminal_end_standout ();
+ wrap_terminal_end_standout (tb_printed_line);
}
}
- else if (!was_in_ref && in_ref || ref_leading_whitespace)
+ else if (!was_in_ref && in_ref)
{
- if (!ref_seen_in_line)
- {
- ref_seen_in_line = 1;
+ if (writing_out == DEFAULT)
+ writing_out = COLLECT;
- if (!match_seen_in_line)
- {
- /* Output the line so far. */
- terminal_goto_xy (0, win->first_row + pl_num);
- terminal_write_chars
- (text_buffer_base (&tb_printed_line),
- text_buffer_off (&tb_printed_line));
- }
- }
-
+ /* Decide if this reference should be highlighted. */
if (point_in_line && win->point < refs[ref_index]->end)
{
/* The reference in is the part of the line after
@@ -463,7 +442,7 @@
else if (point_in_line
&& (!refs[ref_index + 1]
|| refs[ref_index + 1]->start
- >= win->line_starts[cur_line + 1]))
+ >= win->line_starts[win->pagetop + pl_num + 1]))
{
/* The reference label is before the cursor in
the current line and none occurs after it in
@@ -478,13 +457,15 @@
current line. */
ref_highlighted = 1;
}
- else if (win->point >= win->line_starts[cur_line + 1]
- && win->point < win->line_starts[cur_line + 2]
+ else if (win->point >= win->line_starts
+ [win->pagetop + pl_num + 1]
+ && win->point < win->line_starts
+ [win->pagetop + pl_num + 2]
&& refs[ref_index]->end
- >= win->line_starts[cur_line + 1]
+ >= win->line_starts[win->pagetop + pl_num + 1]
&& (!refs[ref_index + 1]
|| refs[ref_index + 1]->start
- >= win->line_starts[cur_line + 2]))
+ >= win->line_starts[win->pagetop + pl_num + 2]))
{
/* Point is in the next line, not inside this reference,
but this reference continues onto the next line and
@@ -492,159 +473,200 @@
ref_highlighted = 1;
}
- if (ref_leading_whitespace && !strchr (" \t", *cur_ptr))
- ref_leading_whitespace = 0;
-
if (!ref_leading_whitespace)
{
- terminal_begin_underline ();
+ wrap_terminal_begin_underline (tb_printed_line);
if (ref_highlighted)
{
- terminal_begin_standout ();
+ wrap_terminal_begin_standout (tb_printed_line);
point_in_line = 0;
}
}
}
}
+ rep = printed_representation (&iter, delim, pl_chars,
+ &pchars, &pbytes);
+
/* If a newline character has been seen, or we have reached the
edge of the display. */
- if (delim || pl_chars + pchars >= win->width)
+ if (*delim || pl_chars + pchars >= win->width)
+ break;
+
+ if (rep)
{
- text_buffer_add_char (&tb_printed_line, '\0');
-
- if (!match_seen_in_line && !ref_seen_in_line)
- {
- finish = display_node_text (win->first_row + pl_num,
- text_buffer_base (&tb_printed_line),
- text_buffer_off (&tb_printed_line) - 1,
- pl_chars);
- }
+ if (writing_out != WRITEOUT)
+ text_buffer_add_string (tb_printed_line, rep, pbytes);
else
- {
- terminal_clear_to_eol ();
- /* Let display_node_text know to clear this entire line. */
- the_display[win->first_row + pl_num]->inverse = 1;
- }
+ terminal_write_chars (rep, pbytes);
- /* Check if a line continuation character should be displayed.
- Don't print one on the very last line of the display as this
could
- cause scrolling. */
- if (!delim && 1 + pl_num + win->first_row < the_screen->height)
- {
- terminal_goto_xy (win->width - 1, win->first_row + pl_num);
+ pl_chars += pchars;
+ }
+ mbi_advance (iter);
+ }
- if (!(win->flags & W_NoWrap))
- terminal_put_text ("\\");
- else
- {
- terminal_put_text ("$");
- rep = 0; /* Don't display this character. */
+ if (in_ref)
+ wrap_terminal_end_underline (tb_printed_line);
+ if (ref_highlighted || in_match)
+ wrap_terminal_end_standout (tb_printed_line);
- /* If this window has chosen not to wrap lines, skip to the
- end of the logical line in the buffer, and start a new
- line here. */
- for (; mbi_avail (iter); mbi_advance (iter))
- if (mb_len (mbi_cur (iter)) == 1
- && *mbi_cur_ptr (iter) == '\n')
- break;
+ *iter_inout = iter;
+}
- if (matches)
- {
- /* Check if the next line starts in a match. */
- decide_if_in_match
- (mbi_cur_ptr (iter) - win->node->contents,
- &in_match, matches, win->match_count,
- &match_index);
- if (!in_match)
- terminal_end_standout ();
- }
+/* Update the part of WIN containing text from a node, i.e. not the blank
+ part at the end or a modeline.
+ Print each line in the window into our local buffer, and then
+ check the contents of that buffer against the display. If they
+ differ, update the display. Return number of lines printed. */
+int
+display_update_node_text (WINDOW *win)
+{
+ static struct text_buffer tb_printed_line; /* Buffer for a printed line. */
- if (refs)
- {
- /* Check if the next line starts in a match. */
- decide_if_in_reference
- (mbi_cur_ptr (iter) - win->node->contents,
- &in_ref, refs, &ref_index);
- /* TODO: Something here? */
- }
- }
- fflush (stdout);
- }
+ mbi_iterator_t iter; /* Used to iterate through part of node displayed. */
+ mbi_iterator_t bol_iter; /* Keep reference to beginning of each line. */
+ int bol_ref_index = 0, bol_match_index = 0;
+ int bol_ref_highlighted;
- if (refs)
- {
- if (in_ref)
- {
- /* Don't underline or highlight leading
- whitespace when a cross-reference is split
- across lines. */
- terminal_end_underline ();
- if (ref_highlighted && !in_match)
- terminal_end_standout ();
- }
- }
+ int finish;
- /* Set for next line. */
- match_seen_in_line = in_match;
- ref_seen_in_line = in_ref;
- ref_leading_whitespace = in_ref;
- terminal_end_underline ();
- ++pl_num;
+ matches = 0;
+ refs = 0;
+ if (highlight_searches_p)
+ matches = win->matches;
+ if (xref_rendition_p)
+ refs = win->node->references;
- cur_line++;
- if (win->point >= win->line_starts[cur_line]
- && win->point < win->line_starts[cur_line + 1])
- point_in_line = 1;
- else
- point_in_line = 0;
+ pl_num = 0;
- pl_chars = 0;
- text_buffer_reset (&tb_printed_line);
+ ref_highlighted = 0;
- if (finish)
- break;
+ writing_out = DEFAULT; /* Global variable, declared above. */
+ ref_index = match_index = 0;
- /* Go to the start of the next line if we are outputting in this
- function. */
- if (match_seen_in_line || ref_seen_in_line)
- terminal_goto_xy (0, win->first_row + pl_num);
+ mbi_init (iter, win->node->contents + win->line_starts[win->pagetop],
+ win->node->nodelen - win->line_starts[win->pagetop]);
+ mbi_avail (iter);
+ while (1)
+ {
+ mbi_copy (&bol_iter, &iter);
+ bol_ref_index = ref_index;
+ bol_match_index = match_index;
+ bol_ref_highlighted = ref_highlighted;
+
+ /* Come back here at end of line when write_out == COLLECT */
+start_of_line:
+ pl_chars = 0;
+
+ text_buffer_reset (&tb_printed_line);
+
+ int delim = 0;
+ /* Check if we have processed all the lines in the window. */
+ if (pl_num == win->height)
+ break;
+
+ /* Check if this line of the window is off the screen. This might
+ happen if the screen was resized very small. */
+ if (win->first_row + pl_num >= screenheight)
+ break;
+
+ display_process_line (win, &iter, &tb_printed_line, &delim);
+
+ /* End of printed line. */
+ text_buffer_add_char (&tb_printed_line, '\0');
+
+ finish = 0;
+ /* If there are no highlighted regions in a line, we output the line with
+ display_update_line, which does some optimization of the redisplay.
+ Otherwise, the entire line is output in this function. */
+ if (writing_out == DEFAULT)
+ {
+ finish = display_update_line (win->first_row + pl_num,
+ text_buffer_base (&tb_printed_line),
+ text_buffer_off (&tb_printed_line) - 1,
+ pl_chars);
}
+ else if (writing_out == COLLECT)
+ {
+ /* Check if the line differs from what is already on the display,
+ and if so, go back to the start of the line and display it for
+ real. */
+ DISPLAY_LINE *entry = the_display[win->first_row + pl_num];
+ if (strcmp (tb_printed_line.base,
+ the_display[win->first_row + pl_num]->text))
+ {
+ if (tb_printed_line.off > screenwidth)
+ {
+ entry->text = xrealloc (entry->text,
+ tb_printed_line.off + 1);
+ }
+ strcpy (entry->text, tb_printed_line.base);
+ /* Record that the contents of this DISPLAY_LINE isn't
+ literally what is on the display. */
+ entry->textlen = 0;
+ entry->inverse = 1;
+ mbi_copy (&iter, &bol_iter);
+ mbi_avail (bol_iter);
+ ref_index = bol_ref_index;
+ match_index = bol_match_index;
+ terminal_goto_xy (0, win->first_row + pl_num);
+ ref_highlighted = bol_ref_highlighted;
+ writing_out = WRITEOUT;
+ goto start_of_line;
+ }
+ else
+ writing_out = DEFAULT;
+ }
+ else /* writing_out == WRITEOUT */
+ {
+ /* We have just written out this line to the display. */
+ terminal_clear_to_eol ();
+ writing_out = DEFAULT;
+ }
- if (*cur_ptr != '\n' && rep)
+ /* Check if a line continuation character should be displayed.
+ Don't print one on the very last line of the display, as this could
+ cause it to scroll. */
+ if (delim)
+ mbi_advance (iter);
+ else if (win->first_row + pl_num <= the_screen->height - 2)
{
- if (!match_seen_in_line && !ref_seen_in_line)
- text_buffer_add_string (&tb_printed_line, rep, pbytes);
+ terminal_goto_xy (win->width - 1, win->first_row + pl_num);
+
+ if (!(win->flags & W_NoWrap))
+ terminal_put_text ("\\");
else
- terminal_write_chars (rep, pbytes);
+ {
+ terminal_put_text ("$");
- pl_chars += pchars;
- continue;
+ /* If this window has chosen not to wrap lines, skip to the
+ end of the logical line in the buffer, and start a new
+ line here. */
+ for (; mbi_avail (iter); mbi_advance (iter))
+ if (mb_len (mbi_cur (iter)) == 1
+ && *mbi_cur_ptr (iter) == '\n')
+ break;
+ }
+ fflush (stdout);
}
- }
- /* This would be the very last line of the node. */
- if (pl_chars && !match_seen_in_line && !ref_seen_in_line)
- {
- text_buffer_add_char (&tb_printed_line, '\0');
- display_node_text (win->first_row + pl_num,
- text_buffer_base (&tb_printed_line),
- text_buffer_off (&tb_printed_line),
- pl_chars);
pl_num++;
+ if (finish)
+ break; /* Display was interrupted by typed input. */
+
+ if (!mbi_avail (iter))
+ break;
}
- if (in_match)
- terminal_end_standout ();
-
/* Unlike search match highlighting, we always turn reference highlighting
- off at the end of each line. */
- /*if (in_ref)
- terminal_end_underline (); */
+ off at the end of each line, so the following isn't needed. */
+ /* terminal_end_underline (); */
- text_buffer_free (&tb_printed_line);
return pl_num;
}
+#undef DEFAULT
+#undef COLLECT
+#undef WRITEOUT /* values for writing_out global */
/* Update one window on the screen. */
void
@@ -679,7 +701,7 @@
if (win->node && win->line_starts)
{
- line_index = display_update_window_1 (win);
+ line_index = display_update_node_text (win);
if (display_was_interrupted_p)
goto funexit;
@@ -698,6 +720,7 @@
{
entry->textlen = 0;
entry->text[0] = '\0';
+ entry->inverse = 0;
terminal_goto_xy (0, win->first_row + line_index);
terminal_clear_to_eol ();
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [6438] more efficient redisplay when there is underlining or standout,
Gavin D. Smith <=