X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/1399490e2bb58e1e7212d7a8469e1286ced9423a..ec6e26b8112dd5eea3558a5bb7e0b44f3122dea0:/src/bidi.c diff --git a/src/bidi.c b/src/bidi.c index c31d208ecb..18dce1931d 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -61,21 +61,21 @@ along with GNU Emacs. If not, see . */ #include "character.h" #include "buffer.h" #include "dispextern.h" +#include "region-cache.h" static bool bidi_initialized = 0; static Lisp_Object bidi_type_table, bidi_mirror_table; -#define LRM_CHAR 0x200E -#define RLM_CHAR 0x200F -#define BIDI_EOB -1 +#define BIDI_EOB (-1) /* Data type for describing the bidirectional character categories. */ typedef enum { UNKNOWN_BC, NEUTRAL, WEAK, - STRONG + STRONG, + EXPLICIT_FORMATTING } bidi_category_t; /* UAX#9 says to search only for L, AL, or R types of characters, and @@ -114,13 +114,9 @@ bidi_get_type (int ch, bidi_dir_t override) if (default_type == UNKNOWN_BT) emacs_abort (); - if (override == NEUTRAL_DIR) - return default_type; - switch (default_type) { - /* Although UAX#9 does not tell, it doesn't make sense to - override NEUTRAL_B and LRM/RLM characters. */ + case WEAK_BN: case NEUTRAL_B: case LRE: case LRO: @@ -128,20 +124,20 @@ bidi_get_type (int ch, bidi_dir_t override) case RLO: case PDF: return default_type; + /* FIXME: The isolate controls are treated as BN until we add + support for UBA v6.3. */ + case LRI: + case RLI: + case FSI: + case PDI: + return WEAK_BN; default: - switch (ch) - { - case LRM_CHAR: - case RLM_CHAR: - return default_type; - default: - if (override == L2R) /* X6 */ - return STRONG_L; - else if (override == R2L) - return STRONG_R; - else - emacs_abort (); /* can't happen: handled above */ - } + if (override == L2R) + return STRONG_L; + else if (override == R2L) + return STRONG_R; + else + return default_type; } } @@ -162,12 +158,7 @@ bidi_get_category (bidi_type_t type) case STRONG_L: case STRONG_R: case STRONG_AL: - case LRE: - case LRO: - case RLE: - case RLO: return STRONG; - case PDF: /* ??? really?? */ case WEAK_EN: case WEAK_ES: case WEAK_ET: @@ -175,12 +166,30 @@ bidi_get_category (bidi_type_t type) case WEAK_CS: case WEAK_NSM: case WEAK_BN: + /* FIXME */ + case LRI: + case RLI: + case FSI: + case PDI: return WEAK; case NEUTRAL_B: case NEUTRAL_S: case NEUTRAL_WS: case NEUTRAL_ON: return NEUTRAL; + case LRE: + case LRO: + case RLE: + case RLO: + case PDF: +#if 0 + /* FIXME: This awaits implementation of isolate support. */ + case LRI: + case RLI: + case FSI: + case PDI: +#endif + return EXPLICIT_FORMATTING; default: emacs_abort (); } @@ -869,8 +878,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; @@ -1085,6 +1094,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 @@ -1100,7 +1132,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 @@ -1111,10 +1144,21 @@ 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); + /* Positions returned by the region cache are not limited to + BEGV..ZV range, so we limit them here. */ + pos_byte = clip_to_bounds (BEGV_BYTE, pos_byte, ZV_BYTE); return pos_byte; }