]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix bug #11943 with slow redisplay in large paragraphs full of weak characters.
authorEli Zaretskii <eliz@gnu.org>
Sun, 15 Jul 2012 14:41:08 +0000 (17:41 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sun, 15 Jul 2012 14:41:08 +0000 (17:41 +0300)
 src/bidi.c (MAX_STRONG_CHAR_SEARCH): New macro.
 (bidi_paragraph_init): Use it to limit search forward for a strong
 directional character in abnormally large paragraphs full of
 neutral or weak characters.

src/ChangeLog
src/bidi.c

index 5c946e6237323437a26830b8adf5be068fd8627d..d7deaf9244ce60e3a33227c8f24a954ec0a23100 100644 (file)
@@ -1,3 +1,10 @@
+2012-07-15  Eli Zaretskii  <eliz@gnu.org>
+
+       * bidi.c (MAX_STRONG_CHAR_SEARCH): New macro.
+       (bidi_paragraph_init): Use it to limit search forward for a strong
+       directional character in abnormally large paragraphs full of
+       neutral or weak characters.  (Bug#11943)
+
 2012-07-15  Stefano Facchini  <stefano.facchini@gmail.com>  (tiny change)
 
        * gtkutil.c (xg_create_tool_bar): Apply "primary-toolbar" style to
index 0fa1cc2b0e231c85976b8c99157b0c267ee88ccb..4df585d4f48db5327109d7de5af3d149b7e00bfd 100644 (file)
@@ -1123,6 +1123,12 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
   return pos_byte;
 }
 
+/* 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
+   bidi_paragraph_init to less than 10 ms even on slow machines.  */
+#define MAX_STRONG_CHAR_SEARCH 100000
+
 /* Determine the base direction, a.k.a. base embedding level, of the
    paragraph we are about to iterate through.  If DIR is either L2R or
    R2L, just use that.  Otherwise, determine the paragraph direction
@@ -1218,6 +1224,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
       /* The following loop is run more than once only if NO_DEFAULT_P
         is non-zero, and only if we are iterating on a buffer.  */
       do {
+       ptrdiff_t pos1;
+
        bytepos = pstartbyte;
        if (!string_p)
          pos = BYTE_TO_CHAR (bytepos);
@@ -1226,11 +1234,15 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
                              bidi_it->frame_window_p, &ch_len, &nchars);
        type = bidi_get_type (ch, NEUTRAL_DIR);
 
+       pos1 = pos;
        for (pos += nchars, bytepos += ch_len;
-            (bidi_get_category (type) != STRONG)
-              || (bidi_ignore_explicit_marks_for_paragraph_level
-                  && (type == RLE || type == RLO
-                      || type == LRE || type == LRO));
+            ((bidi_get_category (type) != STRONG)
+             || (bidi_ignore_explicit_marks_for_paragraph_level
+                 && (type == RLE || type == RLO
+                     || type == LRE || type == LRO)))
+              /* Stop when searched too far into an abnormally large
+                 paragraph full of weak or neutral characters.  */
+              && pos - pos1 < MAX_STRONG_CHAR_SEARCH;
             type = bidi_get_type (ch, NEUTRAL_DIR))
          {
            if (pos >= end)