Commit f3014ef5 authored by Eli Zaretskii's avatar Eli Zaretskii

Support bidi reordering of unibyte strings. Fix crash displaying "All" in...

Support bidi reordering of unibyte strings.  Fix crash displaying "All" in mode line of an empty buffer.

 src/dispextern.h (struct bidi_string_data): New member `unibyte'.
 src/xdisp.c (handle_single_display_spec, next_overlay_string)
 (get_overlay_strings_1, reseat_1, reseat_to_string)
 (push_display_prop): Set up the `unibyte' member of bidi_it.string
 correctly.  Don't assume unibyte strings are not bidi-reordered.
 (compute_display_string_pos)
 (compute_display_string_end): Fix handling the case of C string.
 src/bidi.c (bidi_count_bytes, bidi_char_at_pos): Accept an
 additional argument UNIBYTE, and support unibyte strings.  All
 callers changed.
 (bidi_fetch_char): Support unibyte strings.
parent 7e2ad32c
2011-07-01 Eli Zaretskii <eliz@gnu.org>
* dispextern.h (struct bidi_string_data): New member `unibyte'.
* xdisp.c (handle_single_display_spec, next_overlay_string)
(get_overlay_strings_1, reseat_1, reseat_to_string)
(push_display_prop): Set up the `unibyte' member of bidi_it.string
correctly. Don't assume unibyte strings are not bidi-reordered.
(compute_display_string_pos)
(compute_display_string_end): Fix handling the case of C string.
* bidi.c (bidi_count_bytes, bidi_char_at_pos): Accept an
additional argument UNIBYTE, and support unibyte strings. All
callers changed.
(bidi_fetch_char): Support unibyte strings.
2011-06-25 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (set_iterator_to_next, get_visually_first_element): Use
......
......@@ -721,23 +721,29 @@ bidi_line_init (struct bidi_it *bidi_it)
Fetching characters
***********************************************************************/
/* Count bytes in multibyte string S between BEG/BEGBYTE and END. BEG
and END are zero-based character positions in S, BEGBYTE is byte
position corresponding to BEG. */
/* 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 EMACS_INT
bidi_count_bytes (const unsigned char *s, const EMACS_INT beg,
const EMACS_INT begbyte, const EMACS_INT end)
const EMACS_INT begbyte, const EMACS_INT end, int unibyte)
{
EMACS_INT pos = beg;
const unsigned char *p = s + begbyte, *start = p;
if (!CHAR_HEAD_P (*p))
abort ();
while (pos < end)
if (unibyte)
p = s + end;
else
{
p += BYTES_BY_CHAR_HEAD (*p);
pos++;
if (!CHAR_HEAD_P (*p))
abort ();
while (pos < end)
{
p += BYTES_BY_CHAR_HEAD (*p);
pos++;
}
}
return p - start;
......@@ -745,12 +751,18 @@ bidi_count_bytes (const unsigned char *s, const EMACS_INT beg,
/* Fetch and returns 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. */
character from the current buffer. UNIBYTE non-zero means S is a
unibyte string. */
static inline int
bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s)
bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte)
{
if (s)
return STRING_CHAR (s + bytepos);
{
if (unibyte)
return s[bytepos];
else
return STRING_CHAR (s + bytepos);
}
else
return FETCH_MULTIBYTE_CHAR (bytepos);
}
......@@ -804,12 +816,14 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
ch = 0xFFFC;
disp_end_pos = compute_display_string_end (*disp_pos, string);
*nchars = disp_end_pos - *disp_pos;
if (*nchars <= 0)
abort ();
if (string->s)
*ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos,
disp_end_pos);
disp_end_pos, string->unibyte);
else if (STRINGP (string->lstring))
*ch_len = bidi_count_bytes (SDATA (string->lstring), *disp_pos,
bytepos, disp_end_pos);
bytepos, disp_end_pos, string->unibyte);
else
*ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos;
}
......@@ -819,15 +833,32 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
{
EMACS_INT len;
ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len);
*ch_len = len;
if (!string->unibyte)
{
ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len);
*ch_len = len;
}
else
{
ch = UNIBYTE_TO_CHAR (string->s[bytepos]);
*ch_len = 1;
}
}
else if (STRINGP (string->lstring))
{
EMACS_INT len;
ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos, len);
*ch_len = len;
if (!string->unibyte)
{
ch = STRING_CHAR_AND_LENGTH (SDATA (string->lstring) + bytepos,
len);
*ch_len = len;
}
else
{
ch = UNIBYTE_TO_CHAR (SREF (string->lstring, bytepos));
*ch_len = 1;
}
}
else
{
......@@ -971,7 +1002,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
pos = bidi_it->charpos;
s = STRINGP (bidi_it->string.lstring) ?
SDATA (bidi_it->string.lstring) : bidi_it->string.s;
if (bytepos > begbyte && bidi_char_at_pos (bytepos, s) == '\n')
if (bytepos > begbyte
&& bidi_char_at_pos (bytepos, s, bidi_it->string.unibyte) == '\n')
{
bytepos++;
pos++;
......@@ -1123,7 +1155,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
if (bidi_it->charpos < 0)
bidi_it->charpos = 0;
bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos);
bidi_it->bytepos = bidi_count_bytes (p, 0, 0, bidi_it->charpos,
bidi_it->string.unibyte);
}
else
{
......@@ -1308,7 +1341,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
&& bidi_it->ignore_bn_limit == -1 /* only if not already known */
&& bidi_it->charpos < eob /* not already at EOB */
&& bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
+ bidi_it->ch_len, s)))
+ bidi_it->ch_len, s,
bidi_it->string.unibyte)))
{
/* Avoid pushing and popping embedding levels if the level run
is empty, as this breaks level runs where it shouldn't.
......@@ -1321,7 +1355,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
bidi_copy_it (&saved_it, bidi_it);
while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos
+ bidi_it->ch_len, s)))
+ bidi_it->ch_len, s,
bidi_it->string.unibyte)))
{
/* This advances to the next character, skipping any
characters covered by display strings. */
......@@ -1459,7 +1494,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
next_char =
bidi_it->charpos + bidi_it->nchars >= eob
? BIDI_EOB
: bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
: 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
......@@ -1517,7 +1553,8 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
next_char =
bidi_it->charpos + bidi_it->nchars >= eob
? BIDI_EOB
: bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, s);
: 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
......
......@@ -1821,6 +1821,7 @@ struct bidi_string_data {
EMACS_INT bufpos; /* buffer position of lstring, or 0 if N/A */
unsigned from_disp_str : 1; /* 1 means the string comes from a
display property */
unsigned unibyte : 1; /* 1 means the string is unibyte */
};
/* Data type for reordering bidirectional text. */
......
......@@ -3113,8 +3113,9 @@ compute_display_string_pos (struct text_pos *position,
Lisp_Object object =
(string && STRINGP (string->lstring)) ? string->lstring : Qnil;
Lisp_Object pos, spec;
EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
EMACS_INT begb = STRINGP (object) ? 0 : BEGV;
int string_p = (string && (STRINGP (string->lstring) || string->s));
EMACS_INT eob = string_p ? string->schars : ZV;
EMACS_INT begb = string_p ? 0 : BEGV;
EMACS_INT bufpos, charpos = CHARPOS (*position);
struct text_pos tpos;
......@@ -3175,7 +3176,8 @@ compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
Lisp_Object object =
(string && STRINGP (string->lstring)) ? string->lstring : Qnil;
Lisp_Object pos = make_number (charpos);
EMACS_INT eob = STRINGP (object) ? string->schars : ZV;
EMACS_INT eob =
(STRINGP (object) || (string && string->s)) ? string->schars : ZV;
if (charpos >= eob || (string->s && !STRINGP (object)))
return eob;
......@@ -4496,19 +4498,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->paragraph_embedding =
(it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
/* Do we need to reorder this display string? */
if (it->multibyte_p)
{
if (BUFFERP (object))
it->bidi_p =
!NILP (BVAR (XBUFFER (object), bidi_display_reordering));
else
it->bidi_p =
!NILP (BVAR (&buffer_defaults, bidi_display_reordering));
}
else
it->bidi_p = 0;
/* Set up the bidi iterator for this display string. */
if (it->bidi_p)
{
......@@ -4517,6 +4506,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->bidi_it.string.schars = it->end_charpos;
it->bidi_it.string.bufpos = bufpos;
it->bidi_it.string.from_disp_str = 1;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
}
}
......@@ -4873,11 +4863,6 @@ next_overlay_string (struct it *it)
it->prev_stop = 0;
it->base_level_stop = 0;
/* Do we need to reorder this overlay string? */
it->bidi_p =
it->multibyte_p
&& !NILP (BVAR (current_buffer, bidi_display_reordering));
/* Set up the bidi iterator for this overlay string. */
if (it->bidi_p)
{
......@@ -4886,6 +4871,7 @@ next_overlay_string (struct it *it)
it->bidi_it.string.schars = SCHARS (it->string);
it->bidi_it.string.bufpos = it->overlay_strings_charpos;
it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
}
}
......@@ -5159,11 +5145,6 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
it->multibyte_p = STRING_MULTIBYTE (it->string);
it->method = GET_FROM_STRING;
/* Do we need to reorder this overlay string? */
it->bidi_p =
it->multibyte_p
&& !NILP (BVAR (current_buffer, bidi_display_reordering));
/* Force paragraph direction to be that of the parent
buffer. */
it->paragraph_embedding = (it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
......@@ -5178,6 +5159,7 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
it->bidi_it.string.schars = SCHARS (it->string);
it->bidi_it.string.bufpos = pos;
it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
}
return 1;
......@@ -5747,6 +5729,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
it->bidi_it.string.s = NULL;
it->bidi_it.string.lstring = Qnil;
it->bidi_it.string.bufpos = 0;
it->bidi_it.string.unibyte = 0;
}
if (set_stop_p)
......@@ -5799,9 +5782,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
/* Bidirectional reordering of strings is controlled by the default
value of bidi-display-reordering. */
it->bidi_p =
!NILP (BVAR (&buffer_defaults, bidi_display_reordering))
&& it->multibyte_p;
it->bidi_p = !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
if (s == NULL)
{
......@@ -5819,6 +5800,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
it->bidi_it.string.schars = it->end_charpos;
it->bidi_it.string.bufpos = 0;
it->bidi_it.string.from_disp_str = 0;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
FRAME_WINDOW_P (it->f), &it->bidi_it);
}
......@@ -5835,25 +5817,24 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
{
it->current.pos = c_string_pos (charpos, s, 1);
it->end_charpos = it->string_nchars = number_of_chars (s, 1);
if (it->bidi_p)
{
it->bidi_it.string.lstring = Qnil;
it->bidi_it.string.s = s;
it->bidi_it.string.schars = it->end_charpos;
it->bidi_it.string.bufpos = 0;
it->bidi_it.string.from_disp_str = 0;
bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it);
}
}
else
{
/* Unibyte (a.k.a. ASCII) C strings are never bidi-reordered. */
IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
it->end_charpos = it->string_nchars = strlen (s);
}
if (it->bidi_p)
{
it->bidi_it.string.lstring = Qnil;
it->bidi_it.string.s = s;
it->bidi_it.string.schars = it->end_charpos;
it->bidi_it.string.bufpos = 0;
it->bidi_it.string.from_disp_str = 0;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it);
}
it->method = GET_FROM_C_STRING;
}
......@@ -17788,12 +17769,6 @@ push_display_prop (struct it *it, Lisp_Object prop)
buffer. */
it->paragraph_embedding = (it->bidi_p ? it->bidi_it.paragraph_dir : L2R);
/* Do we need to reorder this string? */
if (it->multibyte_p)
it->bidi_p = !NILP (BVAR (current_buffer, bidi_display_reordering));
else
it->bidi_p = 0;
/* Set up the bidi iterator for this display string. */
if (it->bidi_p)
{
......@@ -17802,6 +17777,7 @@ push_display_prop (struct it *it, Lisp_Object prop)
it->bidi_it.string.schars = it->end_charpos;
it->bidi_it.string.bufpos = IT_CHARPOS (*it);
it->bidi_it.string.from_disp_str = 1;
it->bidi_it.string.unibyte = !it->multibyte_p;
bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment