diff options
author | Eli Zaretskii <eliz@gnu.org> | 2022-06-19 14:56:43 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2022-06-19 14:56:43 +0300 |
commit | 287e714fe0f8819dbfd2dea82e5432665493ff50 (patch) | |
tree | 8a2673a2949060c8df767f59d144f742bd976dcf /src | |
parent | 4b00bc47c7e07bb2a329fa6d0220f39a45289875 (diff) | |
download | emacs-287e714fe0f8819dbfd2dea82e5432665493ff50.tar.gz |
Update redisplay ticks for more operations, and misc modifications
* src/xdisp.c (update_redisplay_ticks): Don't disable redisplay of
mini-windows.
* src/regex-emacs.c (re_match_2_internal):
* src/bidi.c (bidi_find_bracket_pairs, bidi_fetch_char)
(bidi_paragraph_init, bidi_find_other_level_edge): Update the
redisplay tick count as appropriate, when moving the iterator by
one character position actually requires to examine many more
positions.
* doc/emacs/trouble.texi (Long Lines):
* src/xdisp.c (syms_of_xdisp) <max_redisplay_ticks>: Update
recommended non-zero values.
Diffstat (limited to 'src')
-rw-r--r-- | src/bidi.c | 42 | ||||
-rw-r--r-- | src/dispnew.c | 17 | ||||
-rw-r--r-- | src/regex-emacs.c | 30 | ||||
-rw-r--r-- | src/xdisp.c | 7 |
4 files changed, 87 insertions, 9 deletions
diff --git a/src/bidi.c b/src/bidi.c index 4d2c74b17cd..267b62fb0bc 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -1277,6 +1277,12 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, SET_TEXT_POS (pos, charpos, bytepos); *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p, disp_prop); + /* The factor of 100 below is a heuristic that needs to be + tuned. It means we consider 100 buffer positions examined by + the above call roughly equivalent to the display engine + iterating over a single buffer position. */ + if (*disp_pos > charpos) + update_redisplay_ticks ((*disp_pos - charpos) / 100 + 1, w); } /* Fetch the character at BYTEPOS. */ @@ -1385,6 +1391,8 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len); *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p, disp_prop); + if (*disp_pos > charpos + *nchars) + update_redisplay_ticks ((*disp_pos - charpos - *nchars) / 100 + 1, w); } return ch; @@ -1583,6 +1591,9 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte) return pos_byte; } +/* This tracks how far we needed to search for first strong character. */ +static ptrdiff_t nsearch_for_strong; + /* On a 3.4 GHz machine, searching forward for a strong directional character in a long paragraph full of weaks or neutrals takes about 1 ms for each 20K characters. The number below limits each call to @@ -1652,6 +1663,8 @@ find_first_strong_char (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t end, pos += *nchars; bytepos += *ch_len; } + + nsearch_for_strong += pos - pos1; return type; } @@ -1681,6 +1694,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) calls to BYTE_TO_CHAR and its ilk. */ ptrdiff_t begbyte = string_p ? 0 : BEGV_BYTE; ptrdiff_t end = string_p ? bidi_it->string.schars : ZV; + ptrdiff_t pos = bidi_it->charpos; + + nsearch_for_strong = 0; /* Special case for an empty buffer. */ if (bytepos == begbyte && bidi_it->charpos == end) @@ -1702,7 +1718,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) else if (dir == NEUTRAL_DIR) /* P2 */ { ptrdiff_t ch_len, nchars; - ptrdiff_t pos, disp_pos = -1; + ptrdiff_t disp_pos = -1; int disp_prop = 0; bidi_type_t type; const unsigned char *s; @@ -1800,6 +1816,14 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) bidi_it->level_stack[0].level = 0; bidi_line_init (bidi_it); + + /* The factor of 50 below is a heuristic that needs to be tuned. It + means we consider 50 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + ptrdiff_t nexamined = bidi_it->charpos - pos + nsearch_for_strong; + if (nexamined > 0) + update_redisplay_ticks (nexamined / 50, bidi_it->w); } @@ -2566,6 +2590,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) bidi_bracket_type_t btype; bidi_type_t type = bidi_it->type; bool retval = false; + ptrdiff_t n = 0; /* When scanning backwards, we don't expect any unresolved bidi bracket characters. */ @@ -2695,6 +2720,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) } old_sidx = bidi_it->stack_idx; type = bidi_resolve_weak (bidi_it); + n++; /* Skip level runs excluded from this isolating run sequence. */ new_sidx = bidi_it->stack_idx; if (bidi_it->level_stack[new_sidx].level > current_level @@ -2718,6 +2744,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) goto give_up; } type = bidi_resolve_weak (bidi_it); + n++; } } if (type == NEUTRAL_B @@ -2794,6 +2821,12 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) } give_up: + /* The factor of 20 below is a heuristic that needs to be tuned. It + means we consider 20 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + if (n > 0) + update_redisplay_ticks (n / 20 + 1, bidi_it->w); return retval; } @@ -3363,6 +3396,7 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) else { int new_level; + ptrdiff_t pos0 = bidi_it->charpos; /* If we are at end of level, its edges must be cached. */ if (end_flag) @@ -3398,6 +3432,12 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) bidi_cache_iterator_state (bidi_it, 1, 1); } } while (new_level >= level); + /* The factor of 50 below is a heuristic that needs to be + tuned. It means we consider 50 buffer positions examined by + the above call roughly equivalent to the display engine + iterating over a single buffer position. */ + if (bidi_it->charpos > pos0) + update_redisplay_ticks ((bidi_it->charpos - pos0) / 50 + 1, bidi_it->w); } } diff --git a/src/dispnew.c b/src/dispnew.c index 9d587ea00e3..4509262ea62 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -2732,18 +2732,23 @@ set_frame_matrix_frame (struct frame *f) operations in window matrices of frame_matrix_frame. */ static void -make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row) +make_current (struct glyph_matrix *desired_matrix, + struct glyph_matrix *current_matrix, int row) { struct glyph_row *current_row = MATRIX_ROW (current_matrix, row); struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); bool mouse_face_p = current_row->mouse_face_p; /* If we aborted redisplay of this window, a row in the desired - matrix might not have its hash computed. */ - if (!(!desired_row->used[0] - && !desired_row->used[1] - && !desired_row->used[2]) - && !desired_row->hash) + matrix might not have its hash computed. But update_window + relies on each row having its correct hash, so do it here if + needed. */ + if (!desired_row->hash + /* A glyph row that is not completely empty is unlikely to have + a zero hash value. */ + && !(!desired_row->used[0] + && !desired_row->used[1] + && !desired_row->used[2])) desired_row->hash = row_hash (desired_row); /* Do current_row = desired_row. This exchanges glyph pointers diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 8662fe8d6d0..4d87418eeaf 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -33,6 +33,7 @@ #include "buffer.h" #include "syntax.h" #include "category.h" +#include "dispextern.h" /* Maximum number of duplicates an interval can allow. Some systems define this in other header files, but we want our value, so remove @@ -3953,6 +3954,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, and need to test it, it's not garbage. */ re_char *match_end = NULL; + /* This keeps track of how many buffer/string positions we examined. */ + ptrdiff_t nchars = 0; + #ifdef DEBUG_COMPILES_ARGUMENTS /* Counts the total number of registers pushed. */ ptrdiff_t num_regs_pushed = 0; @@ -4209,6 +4213,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp, unbind_to (count, Qnil); SAFE_FREE (); + /* The factor of 50 below is a heuristic that needs to be tuned. It + means we consider 50 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + if (nchars > 0) + update_redisplay_ticks (nchars / 50 + 1, NULL); return dcnt; } @@ -4261,6 +4271,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, p += pat_charlen; d += buf_charlen; mcnt -= pat_charlen; + nchars++; } while (mcnt > 0); else @@ -4298,6 +4309,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, p += pat_charlen; d++; mcnt -= pat_charlen; + nchars++; } while (mcnt > 0); @@ -4321,6 +4333,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, DEBUG_PRINT (" Matched \"%d\".\n", *d); d += buf_charlen; + nchars++; } break; @@ -4373,6 +4386,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, goto fail; d += len; + nchars++; } break; @@ -4492,6 +4506,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, goto fail; } d += dcnt, d2 += dcnt; + nchars++; } } break; @@ -4773,10 +4788,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); PREFETCH_NOLIMIT (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; s2 = SYNTAX (c2); if (/* Case 2: Only one of S1 and S2 is Sword. */ @@ -4812,6 +4829,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, UPDATE_SYNTAX_TABLE (charpos); PREFETCH (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; s2 = SYNTAX (c2); /* Case 2: S2 is not Sword. */ @@ -4822,6 +4840,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if (!AT_STRINGS_BEG (d)) { GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1); s1 = SYNTAX (c1); @@ -4852,6 +4871,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); /* Case 2: S1 is not Sword. */ @@ -4863,6 +4883,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, { PREFETCH_NOLIMIT (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); s2 = SYNTAX (c2); @@ -4893,6 +4914,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, UPDATE_SYNTAX_TABLE (charpos); PREFETCH (); c2 = RE_STRING_CHAR (d, target_multibyte); + nchars++; s2 = SYNTAX (c2); /* Case 2: S2 is neither Sword nor Ssymbol. */ @@ -4903,6 +4925,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if (!AT_STRINGS_BEG (d)) { GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1); s1 = SYNTAX (c1); @@ -4931,6 +4954,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); /* Case 2: S1 is neither Ssymbol nor Sword. */ @@ -4942,6 +4966,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, { PREFETCH_NOLIMIT (); c2 = RE_STRING_CHAR (d, target_multibyte); + nchars++; UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); s2 = SYNTAX (c2); @@ -4973,6 +4998,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if ((SYNTAX (c) != (enum syntaxcode) mcnt) ^ not) goto fail; d += len; + nchars++; } } break; @@ -4999,6 +5025,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if ((!CHAR_HAS_CATEGORY (c, mcnt)) ^ not) goto fail; d += len; + nchars++; } } break; @@ -5060,6 +5087,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, unbind_to (count, Qnil); SAFE_FREE (); + if (nchars > 0) + update_redisplay_ticks (nchars / 50 + 1, NULL); + return -1; /* Failure to match. */ } diff --git a/src/xdisp.c b/src/xdisp.c index 1d52bbc6c93..f95aeb6149a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17218,7 +17218,10 @@ update_redisplay_ticks (int ticks, struct window *w) } /* Some callers can be run in contexts unrelated to display code, so don't abort them and don't update the tick count in those cases. */ - if (!w && !redisplaying_p && !display_working_on_window_p) + if ((!w && !redisplaying_p && !display_working_on_window_p) + /* We never disable redisplay of a mini-window, since that is + absolutely essential for communicating with Emacs. */ + || (w && MINI_WINDOW_P (w))) return; if (ticks > 0) @@ -36765,7 +36768,7 @@ You can also decide to kill the buffer and visit it in some other way, like under `so-long-mode' or literally. The default value is zero, which disables this feature. -The recommended non-zero value is between 50000 and 200000, +The recommended non-zero value is between 100000 and 1000000, depending on your patience and the speed of your system. */); max_redisplay_ticks = 0; } |