/* Low-level bidirectional buffer/string-scanning functions for GNU Emacs.
- Copyright (C) 2000-2001, 2004-2005, 2009-2011
+ Copyright (C) 2000-2001, 2004-2005, 2009-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
A note about references to UAX#9 rules: if the reference says
something like "X9/Retaining", it means that you need to refer to
- rule X9 and to its modifications decribed in the "Implementation
+ rule X9 and to its modifications described in the "Implementation
Notes" section of UAX#9, under "Retaining Format Codes". */
#include <config.h>
#include <stdio.h>
-#include <setjmp.h>
#include "lisp.h"
-#include "buffer.h"
#include "character.h"
+#include "buffer.h"
#include "dispextern.h"
-static int bidi_initialized = 0;
+static bool bidi_initialized = 0;
static Lisp_Object bidi_type_table, bidi_mirror_table;
/* UAX#9 says to search only for L, AL, or R types of characters, and
ignore RLE, RLO, LRE, and LRO, when determining the base paragraph
level. Yudit indeed ignores them. This variable is therefore set
- by default to ignore them, but setting it to zero will take them
- into account. */
-extern int bidi_ignore_explicit_marks_for_paragraph_level EXTERNALLY_VISIBLE;
-int bidi_ignore_explicit_marks_for_paragraph_level = 1;
+ by default to ignore them, but clearing it will take them into
+ account. */
+extern bool bidi_ignore_explicit_marks_for_paragraph_level EXTERNALLY_VISIBLE;
+bool bidi_ignore_explicit_marks_for_paragraph_level = 1;
static Lisp_Object paragraph_start_re, paragraph_separate_re;
static Lisp_Object Qparagraph_start, Qparagraph_separate;
/* Return the bidi type of a character CH, subject to the current
directional OVERRIDE. */
-static inline bidi_type_t
+static bidi_type_t
bidi_get_type (int ch, bidi_dir_t override)
{
bidi_type_t default_type;
if (ch == BIDI_EOB)
return NEUTRAL_B;
if (ch < 0 || ch > MAX_CHAR)
- abort ();
+ emacs_abort ();
default_type = (bidi_type_t) XINT (CHAR_TABLE_REF (bidi_type_table, ch));
/* Every valid character code, even those that are unassigned by the
DerivedBidiClass.txt file. Therefore, if we ever get UNKNOWN_BT
(= zero) code from CHAR_TABLE_REF, that's a bug. */
if (default_type == UNKNOWN_BT)
- abort ();
+ emacs_abort ();
if (override == NEUTRAL_DIR)
return default_type;
else if (override == R2L)
return STRONG_R;
else
- abort (); /* can't happen: handled above */
+ emacs_abort (); /* can't happen: handled above */
}
}
}
-static inline void
+static void
bidi_check_type (bidi_type_t type)
{
- xassert (UNKNOWN_BT <= type && type <= NEUTRAL_ON);
+ eassert (UNKNOWN_BT <= type && type <= NEUTRAL_ON);
}
/* Given a bidi TYPE of a character, return its category. */
-static inline bidi_category_t
+static bidi_category_t
bidi_get_category (bidi_type_t type)
{
switch (type)
case NEUTRAL_ON:
return NEUTRAL;
default:
- abort ();
+ emacs_abort ();
}
}
if (c == BIDI_EOB)
return c;
if (c < 0 || c > MAX_CHAR)
- abort ();
+ emacs_abort ();
val = CHAR_TABLE_REF (bidi_mirror_table, c);
if (INTEGERP (val))
{
- EMACS_INT v = XINT (val);
+ int v;
+
+ /* When debugging, check before assigning to V, so that the check
+ isn't broken by undefined behavior due to int overflow. */
+ eassert (CHAR_VALID_P (XINT (val)));
+
+ v = XINT (val);
+ /* Minimal test we must do in optimized builds, to prevent weird
+ crashes further down the road. */
if (v < 0 || v > MAX_CHAR)
- abort ();
+ emacs_abort ();
return v;
}
embedding levels on either side of the run boundary. Also, update
the saved info about previously seen characters, since that info is
generally valid for a single level run. */
-static inline void
+static void
bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after)
{
- int higher_level = level_before > level_after ? level_before : level_after;
+ int higher_level = (level_before > level_after ? level_before : level_after);
/* The prev_was_pdf gork is required for when we have several PDFs
in a row. In that case, we want to compute the sor type for the
level to which we descend after processing all the PDFs. */
if (!bidi_it->prev_was_pdf || level_before < level_after)
/* FIXME: should the default sor direction be user selectable? */
- bidi_it->sor = (higher_level & 1) != 0 ? R2L : L2R;
+ bidi_it->sor = ((higher_level & 1) != 0 ? R2L : L2R);
if (level_before > level_after)
bidi_it->prev_was_pdf = 1;
bidi_it->prev.type = UNKNOWN_BT;
- bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 =
- bidi_it->last_strong.orig_type = UNKNOWN_BT;
- bidi_it->prev_for_neutral.type = bidi_it->sor == R2L ? STRONG_R : STRONG_L;
+ bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1
+ = bidi_it->last_strong.orig_type = UNKNOWN_BT;
+ bidi_it->prev_for_neutral.type = (bidi_it->sor == R2L ? STRONG_R : STRONG_L);
bidi_it->prev_for_neutral.charpos = bidi_it->charpos;
bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos;
- bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 =
- bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
+ bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1
+ = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
bidi_it->ignore_bn_limit = -1; /* meaning it's unknown */
}
/* Push the current embedding level and override status; reset the
current level to LEVEL and the current override status to OVERRIDE. */
-static inline void
+static void
bidi_push_embedding_level (struct bidi_it *bidi_it,
int level, bidi_dir_t override)
{
bidi_it->stack_idx++;
- xassert (bidi_it->stack_idx < BIDI_MAXLEVEL);
+ eassert (bidi_it->stack_idx < BIDI_MAXLEVEL);
bidi_it->level_stack[bidi_it->stack_idx].level = level;
bidi_it->level_stack[bidi_it->stack_idx].override = override;
}
/* Pop the embedding level and directional override status from the
stack, and return the new level. */
-static inline int
+static int
bidi_pop_embedding_level (struct bidi_it *bidi_it)
{
/* UAX#9 says to ignore invalid PDFs. */
}
/* Record in SAVED_INFO the information about the current character. */
-static inline void
+static void
bidi_remember_char (struct bidi_saved_info *saved_info,
struct bidi_it *bidi_it)
{
/* Copy the bidi iterator from FROM to TO. To save cycles, this only
copies the part of the level stack that is actually in use. */
-static inline void
+static void
bidi_copy_it (struct bidi_it *to, struct bidi_it *from)
{
- int i;
-
- /* Copy everything except the level stack and beyond. */
- memcpy (to, from, offsetof (struct bidi_it, level_stack[0]));
-
- /* Copy the active part of the level stack. */
- to->level_stack[0] = from->level_stack[0]; /* level zero is always in use */
- for (i = 1; i <= from->stack_idx; i++)
- to->level_stack[i] = from->level_stack[i];
+ /* Copy everything from the start through the active part of
+ the level stack. */
+ memcpy (to, from,
+ (offsetof (struct bidi_it, level_stack[1])
+ + from->stack_idx * sizeof from->level_stack[0]));
}
\f
/* Size of header used by bidi_shelve_cache. */
enum
{
- bidi_shelve_header_size =
- (sizeof (bidi_cache_idx) + sizeof (bidi_cache_start_stack)
- + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
- + sizeof (bidi_cache_last_idx))
+ bidi_shelve_header_size
+ = (sizeof (bidi_cache_idx) + sizeof (bidi_cache_start_stack)
+ + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
+ + sizeof (bidi_cache_last_idx))
};
/* Reset the cache state to the empty state. We only reset the part
intact. This is called when the cached information is no more
useful for the current iteration, e.g. when we were reseated to a
new position on the same object. */
-static inline void
+static void
bidi_cache_reset (void)
{
bidi_cache_idx = bidi_cache_start;
iterator for reordering a buffer or a string that does not come
from display properties, because that means all the previously
cached info is of no further use. */
-static inline void
+static void
bidi_cache_shrink (void)
{
if (bidi_cache_size > BIDI_CACHE_CHUNK)
{
- bidi_cache =
- (struct bidi_it *) xrealloc (bidi_cache, BIDI_CACHE_CHUNK * elsz);
+ bidi_cache = xrealloc (bidi_cache, BIDI_CACHE_CHUNK * elsz);
bidi_cache_size = BIDI_CACHE_CHUNK;
}
bidi_cache_reset ();
}
-static inline void
+static void
bidi_cache_fetch_state (ptrdiff_t idx, struct bidi_it *bidi_it)
{
int current_scan_dir = bidi_it->scan_dir;
if (idx < bidi_cache_start || idx >= bidi_cache_idx)
- abort ();
+ emacs_abort ();
bidi_copy_it (bidi_it, &bidi_cache[idx]);
bidi_it->scan_dir = current_scan_dir;
level less or equal to LEVEL. if LEVEL is -1, disregard the
resolved levels in cached states. DIR, if non-zero, means search
in that direction from the last cache hit. */
-static inline ptrdiff_t
+static ptrdiff_t
bidi_cache_search (ptrdiff_t charpos, int level, int dir)
{
ptrdiff_t i, i_start;
that is lower than LEVEL, and return its cache slot index. DIR is
the direction to search, starting with the last used cache slot.
If DIR is zero, we search backwards from the last occupied cache
- slot. BEFORE, if non-zero, means return the index of the slot that
+ slot. BEFORE means return the index of the slot that
is ``before'' the level change in the search direction. That is,
given the cached levels like this:
and assuming we are at the position cached at the slot marked with
C, searching backwards (DIR = -1) for LEVEL = 2 will return the
index of slot B or A, depending whether BEFORE is, respectively,
- non-zero or zero. */
+ true or false. */
static ptrdiff_t
-bidi_cache_find_level_change (int level, int dir, int before)
+bidi_cache_find_level_change (int level, int dir, bool before)
{
if (bidi_cache_idx)
{
ptrdiff_t i = dir ? bidi_cache_last_idx : bidi_cache_idx - 1;
int incr = before ? 1 : 0;
- xassert (!dir || bidi_cache_last_idx >= 0);
+ eassert (!dir || bidi_cache_last_idx >= 0);
if (!dir)
dir = -1;
return -1;
}
-static inline void
+static void
bidi_cache_ensure_space (ptrdiff_t idx)
{
/* Enlarge the cache as needed. */
{
/* The bidi cache cannot be larger than the largest Lisp string
or buffer. */
- ptrdiff_t string_or_buffer_bound =
- max (BUF_BYTES_MAX, STRING_BYTES_BOUND);
+ ptrdiff_t string_or_buffer_bound
+ = max (BUF_BYTES_MAX, STRING_BYTES_BOUND);
/* Also, it cannot be larger than what C can represent. */
- ptrdiff_t c_bound =
- (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz;
+ ptrdiff_t c_bound
+ = (min (PTRDIFF_MAX, SIZE_MAX) - bidi_shelve_header_size) / elsz;
- bidi_cache =
- xpalloc (bidi_cache, &bidi_cache_size,
- max (BIDI_CACHE_CHUNK, idx - bidi_cache_size + 1),
- min (string_or_buffer_bound, c_bound), elsz);
+ bidi_cache
+ = xpalloc (bidi_cache, &bidi_cache_size,
+ max (BIDI_CACHE_CHUNK, idx - bidi_cache_size + 1),
+ min (string_or_buffer_bound, c_bound), elsz);
}
}
-static inline void
-bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
+static void
+bidi_cache_iterator_state (struct bidi_it *bidi_it, bool resolved)
{
ptrdiff_t idx;
/* We should never cache on backward scans. */
if (bidi_it->scan_dir == -1)
- abort ();
+ emacs_abort ();
idx = bidi_cache_search (bidi_it->charpos, -1, 1);
if (idx < 0)
idx = bidi_cache_start;
}
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
bidi_copy_it (&bidi_cache[idx], bidi_it);
if (!resolved)
bidi_cache[idx].resolved_level = -1;
bidi_cache_idx = idx + 1;
}
-static inline bidi_type_t
+static bidi_type_t
bidi_cache_find (ptrdiff_t charpos, int level, struct bidi_it *bidi_it)
{
ptrdiff_t i = bidi_cache_search (charpos, level, bidi_it->scan_dir);
bidi_copy_it (bidi_it, &bidi_cache[i]);
bidi_cache_last_idx = i;
- /* Don't let scan direction from from the cached state override
+ /* Don't let scan direction from the cached state override
the current scan direction. */
bidi_it->scan_dir = current_scan_dir;
return bidi_it->type;
return UNKNOWN_BT;
}
-static inline int
+static int
bidi_peek_at_next_level (struct bidi_it *bidi_it)
{
if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1)
- abort ();
+ emacs_abort ();
return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level;
}
/* Save the current iterator state in its entirety after the last
used cache slot. */
bidi_cache_ensure_space (bidi_cache_idx);
- memcpy (&bidi_cache[bidi_cache_idx++], bidi_it, sizeof (struct bidi_it));
+ bidi_cache[bidi_cache_idx++] = *bidi_it;
/* Push the current cache start onto the stack. */
- xassert (bidi_cache_sp < IT_STACK_SIZE);
+ eassert (bidi_cache_sp < IT_STACK_SIZE);
bidi_cache_start_stack[bidi_cache_sp++] = bidi_cache_start;
/* Start a new level of cache, and make it empty. */
bidi_pop_it (struct bidi_it *bidi_it)
{
if (bidi_cache_start <= 0)
- abort ();
+ emacs_abort ();
/* Reset the next free cache slot index to what it was before the
call to bidi_push_it. */
bidi_cache_idx = bidi_cache_start - 1;
/* Restore the bidi iterator state saved in the cache. */
- memcpy (bidi_it, &bidi_cache[bidi_cache_idx], sizeof (struct bidi_it));
+ *bidi_it = bidi_cache[bidi_cache_idx];
/* Pop the previous cache start from the stack. */
if (bidi_cache_sp <= 0)
- abort ();
+ emacs_abort ();
bidi_cache_start = bidi_cache_start_stack[--bidi_cache_sp];
/* Invalidate the last-used cache slot data. */
/* Restore the cache state from a copy stashed away by
bidi_shelve_cache, and free the buffer used to stash that copy.
- JUST_FREE non-zero means free the buffer, but don't restore the
+ JUST_FREE means free the buffer, but don't restore the
cache; used when the corresponding iterator is discarded instead of
being restored. */
void
-bidi_unshelve_cache (void *databuf, int just_free)
+bidi_unshelve_cache (void *databuf, bool just_free)
{
unsigned char *p = databuf;
ptrdiff_t idx;
memcpy (&idx, p, sizeof (bidi_cache_idx));
- bidi_cache_total_alloc -=
- bidi_shelve_header_size + idx * sizeof (struct bidi_it);
+ bidi_cache_total_alloc
+ -= bidi_shelve_header_size + idx * sizeof (struct bidi_it);
}
else
{
+ sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ sizeof (bidi_cache_start),
sizeof (bidi_cache_last_idx));
- bidi_cache_total_alloc -=
- bidi_shelve_header_size + bidi_cache_idx * sizeof (struct bidi_it);
+ bidi_cache_total_alloc
+ -= (bidi_shelve_header_size
+ + bidi_cache_idx * sizeof (struct bidi_it));
}
xfree (p);
{
bidi_type_table = uniprop_table (intern ("bidi-class"));
if (NILP (bidi_type_table))
- abort ();
+ emacs_abort ();
staticpro (&bidi_type_table);
bidi_mirror_table = uniprop_table (intern ("mirroring"));
if (NILP (bidi_mirror_table))
- abort ();
+ emacs_abort ();
staticpro (&bidi_mirror_table);
Qparagraph_start = intern ("paragraph-start");
/* Do whatever UAX#9 clause X8 says should be done at paragraph's
end. */
-static inline void
+static void
bidi_set_paragraph_end (struct bidi_it *bidi_it)
{
bidi_it->invalid_levels = 0;
/* Initialize the bidi iterator from buffer/string position CHARPOS. */
void
-bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, int frame_window_p,
+bidi_init_it (ptrdiff_t charpos, ptrdiff_t bytepos, bool frame_window_p,
struct bidi_it *bidi_it)
{
if (! bidi_initialized)
bidi_it->type_after_w1 = NEUTRAL_B;
bidi_it->orig_type = NEUTRAL_B;
bidi_it->prev_was_pdf = 0;
- bidi_it->prev.type = bidi_it->prev.type_after_w1 =
- bidi_it->prev.orig_type = UNKNOWN_BT;
- bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1 =
- bidi_it->last_strong.orig_type = UNKNOWN_BT;
+ bidi_it->prev.type = bidi_it->prev.type_after_w1
+ = bidi_it->prev.orig_type = UNKNOWN_BT;
+ bidi_it->last_strong.type = bidi_it->last_strong.type_after_w1
+ = bidi_it->last_strong.orig_type = UNKNOWN_BT;
bidi_it->next_for_neutral.charpos = -1;
- bidi_it->next_for_neutral.type =
- bidi_it->next_for_neutral.type_after_w1 =
- bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
+ bidi_it->next_for_neutral.type
+ = bidi_it->next_for_neutral.type_after_w1
+ = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
bidi_it->prev_for_neutral.charpos = -1;
- bidi_it->prev_for_neutral.type =
- bidi_it->prev_for_neutral.type_after_w1 =
- bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
+ bidi_it->prev_for_neutral.type
+ = bidi_it->prev_for_neutral.type_after_w1
+ = bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT;
bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */
bidi_it->disp_pos = -1; /* invalid/unknown */
bidi_it->disp_prop = 0;
bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */
bidi_it->invalid_levels = 0;
bidi_it->invalid_rl_levels = -1;
- bidi_it->next_en_pos = -1;
+ /* Setting this to zero will force its recomputation the first time
+ we need it for W5. */
+ bidi_it->next_en_pos = 0;
+ bidi_it->next_en_type = UNKNOWN_BT;
bidi_it->next_for_ws.type = UNKNOWN_BT;
bidi_set_sor_type (bidi_it,
- bidi_it->paragraph_dir == R2L ? 1 : 0,
+ (bidi_it->paragraph_dir == R2L ? 1 : 0),
bidi_it->level_stack[0].level); /* X10 */
bidi_cache_reset ();
/* Count bytes in string S between BEG/BEGBYTE and END. BEG and END
are zero-based character positions in S, BEGBYTE is byte position
- corresponding to BEG. UNIBYTE, if non-zero, means S is a unibyte
- string. */
-static inline ptrdiff_t
+ 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, int unibyte)
+ const ptrdiff_t begbyte, const ptrdiff_t end, bool unibyte)
{
ptrdiff_t pos = beg;
const unsigned char *p = s + begbyte, *start = p;
else
{
if (!CHAR_HEAD_P (*p))
- abort ();
+ emacs_abort ();
while (pos < end)
{
return p - start;
}
-/* Fetch and returns the character at byte position BYTEPOS. If S is
+/* Fetch and return the character at byte position BYTEPOS. If S is
non-NULL, fetch the character from string S; otherwise fetch the
- character from the current buffer. UNIBYTE non-zero means S is a
+ character from the current buffer. UNIBYTE means S is a
unibyte string. */
-static inline int
-bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, int unibyte)
+static int
+bidi_char_at_pos (ptrdiff_t bytepos, const unsigned char *s, bool unibyte)
{
if (s)
{
+ s += bytepos;
if (unibyte)
- return s[bytepos];
- else
- return STRING_CHAR (s + bytepos);
+ return *s;
}
else
- return FETCH_MULTIBYTE_CHAR (bytepos);
+ s = BYTE_POS_ADDR (bytepos);
+ return STRING_CHAR (s);
}
/* Fetch and return the character at BYTEPOS/CHARPOS. If that
specifies the character position of the next display string, or -1
if not yet computed. When the next character is at or beyond that
position, the function updates DISP_POS with the position of the
- next display string. DISP_PROP non-zero means that there's really
+ next display string. *DISP_PROP non-zero means that there's really
a display string at DISP_POS, as opposed to when we searched till
- DISP_POS without finding one. If DISP_PROP is 2, it means the
+ DISP_POS without finding one. If *DISP_PROP is 2, it means the
display spec is of the form `(space ...)', which is replaced with
u+2029 to handle it as a paragraph separator. STRING->s is the C
string to iterate, or NULL if iterating over a buffer or a Lisp
string; in the latter case, STRING->lstring is the Lisp string. */
-static inline int
+static int
bidi_fetch_char (ptrdiff_t bytepos, ptrdiff_t charpos, ptrdiff_t *disp_pos,
int *disp_prop, struct bidi_string_data *string,
- int frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
+ bool frame_window_p, ptrdiff_t *ch_len, ptrdiff_t *nchars)
{
int ch;
- ptrdiff_t endpos =
- (string->s || STRINGP (string->lstring)) ? string->schars : ZV;
+ ptrdiff_t endpos
+ = (string->s || STRINGP (string->lstring)) ? string->schars : ZV;
struct text_pos pos;
+ int len;
/* If we got past the last known position of display string, compute
the position of the next one. That position could be at CHARPOS. */
/* We don't expect to find ourselves in the middle of a display
property. Hopefully, it will never be needed. */
if (charpos > *disp_pos)
- abort ();
+ emacs_abort ();
/* Text covered by `display' properties and overlays with
display properties or display strings is handled as a single
character that represents the entire run of characters
ch = 0xFFFC;
}
disp_end_pos = compute_display_string_end (*disp_pos, string);
+ if (disp_end_pos < 0)
+ {
+ /* Somebody removed the display string from the buffer
+ behind our back. Recover by processing this buffer
+ position as if no display property were present there to
+ begin with. */
+ *disp_prop = 0;
+ goto normal_char;
+ }
*nchars = disp_end_pos - *disp_pos;
if (*nchars <= 0)
- abort ();
+ emacs_abort ();
if (string->s)
*ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos,
disp_end_pos, string->unibyte);
}
else
{
+ normal_char:
if (string->s)
{
- int len;
if (!string->unibyte)
{
}
else if (STRINGP (string->lstring))
{
- int len;
-
if (!string->unibyte)
{
ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos,
}
else
{
- ch = FETCH_MULTIBYTE_CHAR (bytepos);
- *ch_len = CHAR_BYTES (ch);
+ ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (bytepos), len);
+ *ch_len = len;
}
*nchars = 1;
}
return val;
}
+/* 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
+ bidi_paragraph_init to about 10 ms. */
+#define MAX_PARAGRAPH_SEARCH 7500
+
/* Find the beginning of this paragraph by looking back in the buffer.
- Value is the byte position of the paragraph's beginning. */
+ Value is the byte position of the paragraph's beginning, or
+ BEGV_BYTE if paragraph_start_re is still not found after looking
+ back MAX_PARAGRAPH_SEARCH lines in the buffer. */
static ptrdiff_t
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;
while (pos_byte > BEGV_BYTE
+ && n++ < MAX_PARAGRAPH_SEARCH
&& fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0)
{
/* FIXME: What if the paragraph beginning is covered by a
pos = find_next_newline_no_quit (pos - 1, -1);
pos_byte = CHAR_TO_BYTE (pos);
}
+ if (n >= MAX_PARAGRAPH_SEARCH)
+ pos_byte = BEGV_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
from the first strong directional character of the paragraph.
- NO_DEFAULT_P non-zero means don't default to L2R if the paragraph
+ NO_DEFAULT_P means don't default to L2R if the paragraph
has no strong directional characters and both DIR and
bidi_it->paragraph_dir are NEUTRAL_DIR. In that case, search back
in the buffer until a paragraph is found with a strong character,
Note that this function gives the paragraph separator the same
direction as the preceding paragraph, even though Emacs generally
- views the separartor as not belonging to any paragraph. */
+ views the separator as not belonging to any paragraph. */
void
-bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
+bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p)
{
ptrdiff_t bytepos = bidi_it->bytepos;
- int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring);
+ bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring);
ptrdiff_t pstartbyte;
/* Note that begbyte is a byte position, while end is a character
position. Yes, this is ugly, but we are trying to avoid costly
dir = L2R;
/* We should never be called at EOB or before BEGV. */
else if (bidi_it->charpos >= end || bytepos < begbyte)
- abort ();
+ emacs_abort ();
if (dir == L2R)
{
we are potentially in a new paragraph that doesn't yet
exist. */
pos = bidi_it->charpos;
- s = STRINGP (bidi_it->string.lstring) ?
- SDATA (bidi_it->string.lstring) : bidi_it->string.s;
+ s = (STRINGP (bidi_it->string.lstring)
+ ? SDATA (bidi_it->string.lstring)
+ : bidi_it->string.s);
if (bytepos > begbyte
&& bidi_char_at_pos (bytepos, s, bidi_it->string.unibyte) == '\n')
{
bidi_it->separator_limit = -1;
bidi_it->new_paragraph = 0;
- /* 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. */
+ /* The following loop is run more than once only if NO_DEFAULT_P,
+ and only if we are iterating on a buffer. */
do {
+ ptrdiff_t pos1;
+
bytepos = pstartbyte;
if (!string_p)
pos = BYTE_TO_CHAR (bytepos);
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)
&& no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR);
}
else
- abort ();
+ emacs_abort ();
/* Contrary to UAX#9 clause P3, we only default the paragraph
direction to L2R if we have no previous usable paragraph
The rest of this file constitutes the core of the UBA implementation.
***********************************************************************/
-static inline int
+static bool
bidi_explicit_dir_char (int ch)
{
bidi_type_t ch_type;
if (!bidi_initialized)
- abort ();
+ emacs_abort ();
ch_type = (bidi_type_t) XINT (CHAR_TABLE_REF (bidi_type_table, ch));
return (ch_type == LRE || ch_type == LRO
|| ch_type == RLE || ch_type == RLO
int current_level;
int new_level;
bidi_dir_t override;
- int string_p = bidi_it->string.s != NULL || STRINGP (bidi_it->string.lstring);
+ bool string_p = bidi_it->string.s || STRINGP (bidi_it->string.lstring);
/* If reseat()'ed, don't advance, so as to start iteration from the
position where we were reseated. bidi_it->bytepos can be less
bidi_it->first_elt = 0;
if (string_p)
{
- const unsigned char *p =
- STRINGP (bidi_it->string.lstring)
- ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
+ const unsigned char *p
+ = (STRINGP (bidi_it->string.lstring)
+ ? SDATA (bidi_it->string.lstring)
+ : bidi_it->string.s);
if (bidi_it->charpos < 0)
bidi_it->charpos = 0;
/* Advance to the next character, skipping characters covered by
display strings (nchars > 1). */
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
bidi_it->charpos += bidi_it->nchars;
if (bidi_it->ch_len == 0)
- abort ();
+ emacs_abort ();
bidi_it->bytepos += bidi_it->ch_len;
}
}
}
else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
- || bidi_it->next_en_pos > bidi_it->charpos)
+ || (bidi_it->next_en_pos > bidi_it->charpos
+ && bidi_it->next_en_type == WEAK_EN))
type = WEAK_EN;
break;
case LRE: /* X3 */
}
}
else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
- || bidi_it->next_en_pos > bidi_it->charpos)
+ || (bidi_it->next_en_pos > bidi_it->charpos
+ && bidi_it->next_en_type == WEAK_EN))
type = WEAK_EN;
break;
case PDF: /* X7 */
}
}
else if (bidi_it->prev.type_after_w1 == WEAK_EN /* W5/Retaining */
- || bidi_it->next_en_pos > bidi_it->charpos)
+ || (bidi_it->next_en_pos > bidi_it->charpos
+ && bidi_it->next_en_type == WEAK_EN))
type = WEAK_EN;
break;
default:
int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level;
int new_level = bidi_resolve_explicit_1 (bidi_it);
ptrdiff_t eob = bidi_it->string.s ? bidi_it->string.schars : ZV;
- const unsigned char *s = STRINGP (bidi_it->string.lstring)
- ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
+ const unsigned char *s
+ = (STRINGP (bidi_it->string.lstring)
+ ? SDATA (bidi_it->string.lstring)
+ : bidi_it->string.s);
if (prev_level < new_level
&& bidi_it->type == WEAK_BN
}
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
if (level == prev_level) /* empty embedding */
saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars;
else /* this embedding is non-empty */
int next_char;
bidi_type_t type_of_next;
struct bidi_it saved_it;
- ptrdiff_t eob =
- (STRINGP (bidi_it->string.lstring) || bidi_it->string.s)
- ? bidi_it->string.schars : ZV;
+ ptrdiff_t eob
+ = ((STRINGP (bidi_it->string.lstring) || bidi_it->string.s)
+ ? bidi_it->string.schars : ZV);
type = bidi_it->type;
override = bidi_it->level_stack[bidi_it->stack_idx].override;
|| type == RLE
|| type == RLO
|| type == PDF)
- abort ();
+ emacs_abort ();
if (new_level != prev_level
|| bidi_it->type == NEUTRAL_B)
else if (bidi_it->sor == L2R)
type = STRONG_L;
else /* shouldn't happen! */
- abort ();
+ emacs_abort ();
}
if (type == WEAK_EN /* W2 */
&& bidi_it->last_strong.type_after_w1 == STRONG_AL)
&& bidi_it->prev.orig_type == WEAK_EN)
|| bidi_it->prev.type_after_w1 == WEAK_AN)))
{
- const unsigned char *s =
- STRINGP (bidi_it->string.lstring)
- ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
-
- next_char =
- bidi_it->charpos + bidi_it->nchars >= eob
- ? BIDI_EOB
- : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s,
- bidi_it->string.unibyte);
+ const unsigned char *s
+ = (STRINGP (bidi_it->string.lstring)
+ ? SDATA (bidi_it->string.lstring)
+ : bidi_it->string.s);
+
+ next_char = (bidi_it->charpos + bidi_it->nchars >= eob
+ ? BIDI_EOB
+ : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len,
+ s, bidi_it->string.unibyte));
type_of_next = bidi_get_type (next_char, override);
if (type_of_next == WEAK_BN
else if (type == WEAK_ET /* W5: ET with EN before or after it */
|| type == WEAK_BN) /* W5/Retaining */
{
- if (bidi_it->prev.type_after_w1 == WEAK_EN /* ET/BN w/EN before it */
- || bidi_it->next_en_pos > bidi_it->charpos)
+ if (bidi_it->prev.type_after_w1 == WEAK_EN) /* ET/BN w/EN before it */
type = WEAK_EN;
- else /* W5: ET/BN with EN after it. */
+ else if (bidi_it->next_en_pos > bidi_it->charpos
+ && bidi_it->next_en_type != WEAK_BN)
+ {
+ if (bidi_it->next_en_type == WEAK_EN) /* ET/BN with EN after it */
+ type = WEAK_EN;
+ }
+ else if (bidi_it->next_en_pos >=0)
{
ptrdiff_t en_pos = bidi_it->charpos + bidi_it->nchars;
- const unsigned char *s =
- STRINGP (bidi_it->string.lstring)
- ? SDATA (bidi_it->string.lstring) : bidi_it->string.s;
+ const unsigned char *s = (STRINGP (bidi_it->string.lstring)
+ ? SDATA (bidi_it->string.lstring)
+ : bidi_it->string.s);
if (bidi_it->nchars <= 0)
- abort ();
- next_char =
- bidi_it->charpos + bidi_it->nchars >= eob
- ? BIDI_EOB
- : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s,
- bidi_it->string.unibyte);
+ emacs_abort ();
+ next_char
+ = (bidi_it->charpos + bidi_it->nchars >= eob
+ ? BIDI_EOB
+ : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s,
+ bidi_it->string.unibyte));
type_of_next = bidi_get_type (next_char, override);
if (type_of_next == WEAK_ET
en_pos = bidi_it->charpos;
bidi_copy_it (bidi_it, &saved_it);
}
+ /* Remember this position, to speed up processing of the
+ next ETs. */
+ bidi_it->next_en_pos = en_pos;
if (type_of_next == WEAK_EN)
{
/* If the last strong character is AL, the EN we've
found will become AN when we get to it (W2). */
- if (bidi_it->last_strong.type_after_w1 != STRONG_AL)
- {
- type = WEAK_EN;
- /* Remember this EN position, to speed up processing
- of the next ETs. */
- bidi_it->next_en_pos = en_pos;
- }
+ if (bidi_it->last_strong.type_after_w1 == STRONG_AL)
+ type_of_next = WEAK_AN;
else if (type == WEAK_BN)
type = NEUTRAL_ON; /* W6/Retaining */
+ else
+ type = WEAK_EN;
}
+ else if (type_of_next == NEUTRAL_B)
+ /* Record the fact that there are no more ENs from
+ here to the end of paragraph, to avoid entering the
+ loop above ever again in this paragraph. */
+ bidi_it->next_en_pos = -1;
+ /* Record the type of the character where we ended our search. */
+ bidi_it->next_en_type = type_of_next;
}
}
}
/* Resolve the type of a neutral character according to the type of
surrounding strong text and the current embedding level. */
-static inline bidi_type_t
+static bidi_type_t
bidi_resolve_neutral_1 (bidi_type_t prev_type, bidi_type_t next_type, int lev)
{
/* N1: European and Arabic numbers are treated as though they were R. */
|| type == NEUTRAL_S
|| type == NEUTRAL_WS
|| type == NEUTRAL_ON))
- abort ();
+ emacs_abort ();
- if (bidi_get_category (type) == NEUTRAL
+ if ((type != NEUTRAL_B /* Don't risk entering the long loop below if
+ we are already at paragraph end. */
+ && bidi_get_category (type) == NEUTRAL)
|| (type == WEAK_BN && prev_level == current_level))
{
if (bidi_it->next_for_neutral.type != UNKNOWN_BT)
type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
bidi_it->next_for_neutral.type,
current_level);
+ /* The next two "else if" clauses are shortcuts for the
+ important special case when we have a long sequence of
+ neutral or WEAK_BN characters, such as whitespace or nulls or
+ other control characters, on the base embedding level of the
+ paragraph, and that sequence goes all the way to the end of
+ the paragraph and follows a character whose resolved
+ directionality is identical to the base embedding level.
+ (This is what happens in a buffer with plain L2R text that
+ happens to include long sequences of control characters.) By
+ virtue of N1, the result of examining this long sequence will
+ always be either STRONG_L or STRONG_R, depending on the base
+ embedding level. So we use this fact directly instead of
+ entering the expensive loop in the "else" clause. */
+ else if (current_level == 0
+ && bidi_it->prev_for_neutral.type == STRONG_L
+ && !bidi_explicit_dir_char (bidi_it->ch))
+ type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
+ STRONG_L, current_level);
+ else if (/* current level is 1 */
+ current_level == 1
+ /* base embedding level is also 1 */
+ && bidi_it->level_stack[0].level == 1
+ /* previous character is one of those considered R for
+ the purposes of W5 */
+ && (bidi_it->prev_for_neutral.type == STRONG_R
+ || bidi_it->prev_for_neutral.type == WEAK_EN
+ || bidi_it->prev_for_neutral.type == WEAK_AN)
+ && !bidi_explicit_dir_char (bidi_it->ch))
+ type = bidi_resolve_neutral_1 (bidi_it->prev_for_neutral.type,
+ STRONG_R, current_level);
else
{
/* Arrrgh!! The UAX#9 algorithm is too deeply entrenched in
bidi_type_t next_type;
if (bidi_it->scan_dir == -1)
- abort ();
+ emacs_abort ();
bidi_copy_it (&saved_it, bidi_it);
/* Scan the text forward until we find the first non-neutral
&& bidi_get_category (type) != NEUTRAL)
/* This is all per level run, so stop when we
reach the end of this level run. */
- || bidi_it->level_stack[bidi_it->stack_idx].level !=
- current_level));
+ || (bidi_it->level_stack[bidi_it->stack_idx].level
+ != current_level)));
bidi_remember_char (&saved_it.next_for_neutral, bidi_it);
case STRONG_L:
case STRONG_R:
case STRONG_AL:
+ /* Actually, STRONG_AL cannot happen here, because
+ bidi_resolve_weak converts it to STRONG_R, per W3. */
+ eassert (type != STRONG_AL);
next_type = type;
break;
case WEAK_EN:
/* N1: ``European and Arabic numbers are treated as
though they were R.'' */
next_type = STRONG_R;
- saved_it.next_for_neutral.type = STRONG_R;
break;
case WEAK_BN:
if (!bidi_explicit_dir_char (bidi_it->ch))
- abort (); /* can't happen: BNs are skipped */
+ emacs_abort (); /* can't happen: BNs are skipped */
/* FALLTHROUGH */
case NEUTRAL_B:
/* Marched all the way to the end of this level run.
member. */
if (saved_it.type != WEAK_BN
|| bidi_get_category (bidi_it->prev.type_after_w1) == NEUTRAL)
- {
- next_type = bidi_it->prev_for_neutral.type;
- saved_it.next_for_neutral.type = next_type;
- bidi_check_type (next_type);
- }
+ next_type = bidi_it->prev_for_neutral.type;
else
{
/* This is a BN which does not adjoin neutrals.
}
break;
default:
- abort ();
+ emacs_abort ();
}
type = bidi_resolve_neutral_1 (saved_it.prev_for_neutral.type,
next_type, current_level);
+ saved_it.next_for_neutral.type = next_type;
saved_it.type = type;
+ bidi_check_type (next_type);
bidi_check_type (type);
bidi_copy_it (bidi_it, &saved_it);
}
/* This should always be called during a forward scan. */
if (bidi_it->scan_dir != 1)
- abort ();
+ emacs_abort ();
/* Reset the limit until which to ignore BNs if we step out of the
area where we found only empty levels. */
if (bidi_it->scan_dir == 1)
{
- ptrdiff_t eob =
- (bidi_it->string.s || STRINGP (bidi_it->string.lstring))
- ? bidi_it->string.schars : ZV;
+ ptrdiff_t eob
+ = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
+ ? bidi_it->string.schars : ZV);
/* There's no sense in trying to advance if we hit end of text. */
if (bidi_it->charpos >= eob)
bidi_it->next_for_neutral.type = UNKNOWN_BT;
if (bidi_it->next_en_pos >= 0
&& bidi_it->charpos >= bidi_it->next_en_pos)
- bidi_it->next_en_pos = -1;
+ {
+ bidi_it->next_en_pos = 0;
+ bidi_it->next_en_type = UNKNOWN_BT;
+ }
if (bidi_it->next_for_ws.type != UNKNOWN_BT
&& bidi_it->charpos >= bidi_it->next_for_ws.charpos)
bidi_it->next_for_ws.type = UNKNOWN_BT;
UNKNOWN_BT. */
if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt)
{
- int bob =
- (bidi_it->string.s || STRINGP (bidi_it->string.lstring)) ? 0 : 1;
-
+ int bob = ((bidi_it->string.s || STRINGP (bidi_it->string.lstring))
+ ? 0 : 1);
if (bidi_it->scan_dir > 0)
{
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
next_char_pos = bidi_it->charpos + bidi_it->nchars;
}
else if (bidi_it->charpos >= bob)
if (bidi_it->scan_dir == -1)
/* If we are going backwards, the iterator state is already cached
from previous scans, and should be fully resolved. */
- abort ();
+ emacs_abort ();
if (type == UNKNOWN_BT)
type = bidi_type_of_next_char (bidi_it);
|| (type == WEAK_BN && prev_level == level))
{
if (bidi_it->next_for_neutral.type == UNKNOWN_BT)
- abort ();
+ emacs_abort ();
/* If the cached state shows a neutral character, it was not
resolved by bidi_resolve_neutral, so do it now. */
|| type == WEAK_BN
|| type == WEAK_EN
|| type == WEAK_AN))
- abort ();
+ emacs_abort ();
bidi_it->type = type;
bidi_check_type (bidi_it->type);
ptrdiff_t nc = bidi_it->nchars;
struct bidi_string_data bs = bidi_it->string;
bidi_type_t chtype;
- int fwp = bidi_it->frame_window_p;
+ bool fwp = bidi_it->frame_window_p;
int dpp = bidi_it->disp_prop;
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
do {
ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &dpp, &bs,
fwp, &clen, &nc);
- if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */)
+ if (ch == '\n' || ch == BIDI_EOB)
chtype = NEUTRAL_B;
else
chtype = bidi_get_type (ch, NEUTRAL_DIR);
}
/* Resolve implicit levels, with a twist: PDFs get the embedding
- level of the enbedding they terminate. See below for the
+ level of the embedding they terminate. See below for the
reason. */
if (bidi_it->orig_type == PDF
/* Don't do this if this formatting code didn't change the
else if (bidi_it->orig_type == NEUTRAL_B /* L1 */
|| bidi_it->orig_type == NEUTRAL_S
|| bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB
- /* || bidi_it->ch == LINESEP_CHAR */
|| (bidi_it->orig_type == NEUTRAL_WS
&& (bidi_it->next_for_ws.type == NEUTRAL_B
|| bidi_it->next_for_ws.type == NEUTRAL_S)))
return level;
}
-/* Move to the other edge of a level given by LEVEL. If END_FLAG is
- non-zero, we are at the end of a level, and we need to prepare to
+/* Move to the other edge of a level given by LEVEL. If END_FLAG,
+ we are at the end of a level, and we need to prepare to
resume the scan of the lower level.
If this level's other edge is cached, we simply jump to it, filling
function moves to point C, whereas the UAX#9 ``level 2 run'' ends
at point B. */
static void
-bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag)
+bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag)
{
int dir = end_flag ? -bidi_it->scan_dir : bidi_it->scan_dir;
ptrdiff_t idx;
{
int new_level;
+ /* If we are at end of level, its edges must be cached. */
if (end_flag)
- abort (); /* if we are at end of level, its edges must be cached */
+ emacs_abort ();
bidi_cache_iterator_state (bidi_it, 1);
do {
struct gcpro gcpro1;
if (bidi_it->charpos < 0 || bidi_it->bytepos < 0)
- abort ();
+ emacs_abort ();
if (bidi_it->scan_dir == 0)
{
GCPRO1 (bidi_it->string.lstring);
/* If we just passed a newline, initialize for the next line. */
- if (!bidi_it->first_elt && bidi_it->orig_type == NEUTRAL_B)
+ if (!bidi_it->first_elt
+ && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
bidi_line_init (bidi_it);
/* Prepare the sentinel iterator state, and cache it. When we bump
scanning the text whenever we find a level change. */
if (new_level != old_level)
{
- int ascending = new_level > old_level;
+ bool ascending = new_level > old_level;
int level_to_search = ascending ? old_level + 1 : old_level;
int incr = ascending ? 1 : -1;
int expected_next_level = old_level + incr;
reordering, whereas we _must_ know the paragraph base direction
_before_ we process the paragraph's text, since the base
direction affects the reordering. */
- if (bidi_it->scan_dir == 1 && bidi_it->orig_type == NEUTRAL_B)
+ if (bidi_it->scan_dir == 1
+ && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
{
/* The paragraph direction of the entire string, once
determined, is in effect for the entire string. Setting the
bidi_it->separator_limit = bidi_it->string.schars;
else if (bidi_it->bytepos < ZV_BYTE)
{
- ptrdiff_t sep_len =
- bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars,
- bidi_it->bytepos + bidi_it->ch_len);
+ ptrdiff_t sep_len
+ = bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars,
+ bidi_it->bytepos + bidi_it->ch_len);
if (bidi_it->nchars <= 0)
- abort ();
+ emacs_abort ();
if (sep_len >= 0)
{
bidi_it->new_paragraph = 1;
/* Record the buffer position of the last character of the
paragraph separator. */
- bidi_it->separator_limit =
- bidi_it->charpos + bidi_it->nchars + sep_len;
+ bidi_it->separator_limit
+ = bidi_it->charpos + bidi_it->nchars + sep_len;
}
}
}
fputs ("\n", stderr);
fputs ("pos ", stderr);
for (i = 0; i < bidi_cache_idx; i++)
- fprintf (stderr, "%*"pI"d", ndigits, bidi_cache[i].charpos);
+ fprintf (stderr, "%*"pD"d", ndigits, bidi_cache[i].charpos);
fputs ("\n", stderr);
}