Function: bidi-find-overridden-directionality
bidi-find-overridden-directionality is a function defined in xdisp.c.
Signature
(bidi-find-overridden-directionality FROM TO OBJECT &optional BASE-DIR)
Documentation
Return position between FROM and TO where directionality was overridden.
This function returns the first character position in the specified
region of OBJECT where characters have their bidirectional
properties affected in a way that might make its text look confusingly
on display. For example, characters whose bidi-class property is L,
could be forced to display as R by a directional override, and
likewise characters whose bidi-class is R or AL that are
forced to display as L.
If no such character is found, the function returns nil.
OBJECT is a Lisp string or buffer to search for overridden directionality, and defaults to the current buffer if nil. OBJECT can also be a window, in which case the function will search the buffer displayed in that window. Passing the window instead of a buffer is preferable when the buffer is displayed in some window, because this function will then be able to correctly account for window-specific overlays, which can affect the results.
Optional argument BASE-DIR specifies the base paragraph directory
of the text. It should be a symbol, either left-to-right
or right-to-left, and defaults to left-to-right.
Strong directional characters L, R, and AL can have their
intrinsic directionality overridden by directional override control
characters RLO (u+202E) and LRO (u+202D). They can also have their
directionality affected by other formatting control characters: LRE
(u+202A), RLE (u+202B), LRI (u+2066), and RLI (u+2067). See the
function get-char-code-property for a way to inquire about the
bidi-class property of a character. Characters whose intrinsic
directionality is weak or neutral, such as numbers or punctuation
characters, can be forced to display in a very different place with
respect of its surrounding characters, so as to make the surrounding
text confuse the user regarding what the text says.
Also see the highlight-confusing-reorderings function, which can be
useful in similar circumstances as this function.
Probably introduced at or before Emacs version 25.1.
Source Code
// Defined in /usr/src/emacs/src/xdisp.c
{
struct buffer *buf = current_buffer;
struct buffer *old = buf;
struct window *w = NULL;
bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
struct bidi_it itb;
ptrdiff_t from_pos, to_pos, from_bpos;
void *itb_data;
if (!NILP (object))
{
if (BUFFERP (object))
buf = XBUFFER (object);
else if (WINDOWP (object))
{
w = decode_live_window (object);
buf = XBUFFER (w->contents);
frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
}
else
CHECK_STRING (object);
}
if (STRINGP (object))
{
/* Characters in unibyte strings are always treated by bidi.c as
strong LTR. */
if (!STRING_MULTIBYTE (object)
/* When we are loading loadup.el, the character property
tables needed for bidi iteration are not yet
available. */
|| redisplay__inhibit_bidi)
return Qnil;
validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
if (from_pos >= SCHARS (object))
return Qnil;
/* Set up the bidi iterator. */
itb_data = bidi_shelve_cache ();
itb.paragraph_dir = NEUTRAL_DIR;
itb.string.lstring = object;
itb.string.s = NULL;
itb.string.schars = SCHARS (object);
itb.string.bufpos = 0;
itb.string.from_disp_str = false;
itb.string.unibyte = false;
itb.w = w;
bidi_init_it (0, 0, frame_window_p, &itb);
}
else
{
/* Nothing this fancy can happen in unibyte buffers, or in a
buffer that disabled reordering, or if FROM is at EOB. */
if (NILP (BVAR (buf, bidi_display_reordering))
|| NILP (BVAR (buf, enable_multibyte_characters))
/* When we are loading loadup.el, the character property
tables needed for bidi iteration are not yet
available. */
|| redisplay__inhibit_bidi)
return Qnil;
set_buffer_temp (buf);
validate_region (&from, &to);
from_pos = XFIXNUM (from);
to_pos = XFIXNUM (to);
if (from_pos >= ZV)
return Qnil;
/* Set up the bidi iterator. */
itb_data = bidi_shelve_cache ();
from_bpos = CHAR_TO_BYTE (from_pos);
if (from_pos == BEGV)
{
itb.charpos = BEGV;
itb.bytepos = BEGV_BYTE;
}
else if (FETCH_BYTE (from_bpos - 1) == '\n')
{
itb.charpos = from_pos;
itb.bytepos = from_bpos;
}
else
itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
-1, &itb.bytepos);
itb.paragraph_dir = NEUTRAL_DIR;
itb.string.s = NULL;
itb.string.lstring = Qnil;
itb.string.bufpos = 0;
itb.string.from_disp_str = false;
itb.string.unibyte = false;
itb.w = w;
bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
}
ptrdiff_t found;
bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
do {
bidi_paragraph_init (bdir, &itb, false);
while ((found = bidi_find_first_overridden (&itb)) < from_pos)
;
} while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
bidi_unshelve_cache (itb_data, false);
set_buffer_temp (old);
return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
}