]> code.delx.au - gnu-emacs/blobdiff - src/bidi.c
* frame.c (x_redo_mouse_highlight): New function
[gnu-emacs] / src / bidi.c
index c6bea62f67b12e67b588bfbe510366cfa94a5382..dc905cd9e5fc2d586b1658a7a5f0b7eca45e334a 100644 (file)
@@ -61,6 +61,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "character.h"
 #include "buffer.h"
 #include "dispextern.h"
+#include "region-cache.h"
 
 static bool bidi_initialized = 0;
 
@@ -869,8 +870,8 @@ bidi_line_init (struct bidi_it *bidi_it)
    are zero-based character positions in S, BEGBYTE is byte position
    corresponding to BEG.  UNIBYTE means S is a unibyte string.  */
 static ptrdiff_t
-bidi_count_bytes (const unsigned char *s, const ptrdiff_t beg,
-                 const ptrdiff_t begbyte, const ptrdiff_t end, bool unibyte)
+bidi_count_bytes (const unsigned char *s, ptrdiff_t beg,
+                 ptrdiff_t begbyte, ptrdiff_t end, bool unibyte)
 {
   ptrdiff_t pos = beg;
   const unsigned char *p = s + begbyte, *start = p;
@@ -927,6 +928,7 @@ bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte)
 static int
 bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
                 int *disp_prop, struct bidi_string_data *string,
+                struct window *w,
                 bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
 {
   int ch;
@@ -940,7 +942,7 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
   if (charpos < endpos && charpos > *disp_pos)
     {
       SET_TEXT_POS (pos, charpos, bytepos);
-      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
+      *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p,
                                              disp_prop);
     }
 
@@ -1045,7 +1047,7 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos,
       && *disp_prop)
     {
       SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len);
-      *disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
+      *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p,
                                              disp_prop);
     }
 
@@ -1084,6 +1086,29 @@ bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
   return val;
 }
 
+/* If the user has requested the long scans caching, make sure that
+   BIDI cache is enabled.  Otherwise, make sure it's disabled.  */
+
+static struct region_cache *
+bidi_paragraph_cache_on_off (void)
+{
+  if (NILP (BVAR (current_buffer, cache_long_scans)))
+    {
+      if (current_buffer->bidi_paragraph_cache)
+       {
+         free_region_cache (current_buffer->bidi_paragraph_cache);
+         current_buffer->bidi_paragraph_cache = 0;
+       }
+      return NULL;
+    }
+  else
+    {
+      if (!current_buffer->bidi_paragraph_cache)
+       current_buffer->bidi_paragraph_cache = new_region_cache ();
+      return current_buffer->bidi_paragraph_cache;
+    }
+}
+
 /* On my 2005-vintage machine, searching back for paragraph start
    takes ~1 ms per line.  And bidi_paragraph_init is called 4 times
    when user types C-p.  The number below limits each call to
@@ -1099,7 +1124,8 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
 {
   Lisp_Object re = paragraph_start_re;
   ptrdiff_t limit = ZV, limit_byte = ZV_BYTE;
-  ptrdiff_t n = 0;
+  struct region_cache *bpc = bidi_paragraph_cache_on_off ();
+  ptrdiff_t n = 0, oldpos = pos, next;
 
   while (pos_byte > BEGV_BYTE
         && n++ < MAX_PARAGRAPH_SEARCH
@@ -1110,10 +1136,18 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
         of the text over which we scan back includes
         paragraph_start_re?  */
       DEC_BOTH (pos, pos_byte);
-      pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
+      if (bpc && region_cache_backward (current_buffer, bpc, pos, &next))
+       {
+         pos = next, pos_byte = CHAR_TO_BYTE (pos);
+         break;
+       }
+      else
+       pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
     }
   if (n >= MAX_PARAGRAPH_SEARCH)
-    pos_byte = BEGV_BYTE;
+    pos = BEGV, pos_byte = BEGV_BYTE;
+  if (bpc)
+    know_region_cache (current_buffer, bpc, pos, oldpos);
   return pos_byte;
 }
 
@@ -1224,7 +1258,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
        if (!string_p)
          pos = BYTE_TO_CHAR (bytepos);
        ch = bidi_fetch_char (pos, bytepos, &disp_pos, &disp_prop,
-                             &bidi_it->string,
+                             &bidi_it->string, bidi_it->w,
                              bidi_it->frame_window_p, &ch_len, &nchars);
        type = bidi_get_type (ch, NEUTRAL_DIR);
 
@@ -1252,7 +1286,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
              break;
            /* Fetch next character and advance to get past it.  */
            ch = bidi_fetch_char (pos, bytepos, &disp_pos,
-                                 &disp_prop, &bidi_it->string,
+                                 &disp_prop, &bidi_it->string, bidi_it->w,
                                  bidi_it->frame_window_p, &ch_len, &nchars);
            pos += nchars;
            bytepos += ch_len;
@@ -1402,7 +1436,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
         a single character u+FFFC.  */
       curchar = bidi_fetch_char (bidi_it->charpos, bidi_it->bytepos,
                                 &bidi_it->disp_pos, &bidi_it->disp_prop,
-                                &bidi_it->string, bidi_it->frame_window_p,
+                                &bidi_it->string, bidi_it->w,
+                                bidi_it->frame_window_p,
                                 &bidi_it->ch_len, &bidi_it->nchars);
     }
   bidi_it->ch = curchar;
@@ -2194,7 +2229,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
        emacs_abort ();
       do {
        ch = bidi_fetch_char (cpos += nc, bpos += clen, &disp_pos, &dpp, &bs,
-                             fwp, &clen, &nc);
+                             bidi_it->w, fwp, &clen, &nc);
        if (ch == '\n' || ch == BIDI_EOB)
          chtype = NEUTRAL_B;
        else