Function: bidi-find-overridden-directionality
bidi-find-overridden-directionality is a function defined in xdisp.c.
Signature
(bidi-find-overridden-directionality FROM TO &optional OBJECT)
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 there is a character whose bidi-class property
is L, but which was forced to display as R by a directional
override, and likewise with characters whose bidi-class is R
or AL that were 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 or omitted. 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.
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). See the
function get-char-code-property for a way to inquire about
the bidi-class property of a character.
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;
do {
/* For the purposes of this function, the actual base direction of
the paragraph doesn't matter, so just set it to L2R. */
bidi_paragraph_init (L2R, &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;
}