summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-06-25 14:44:30 +0300
committerEli Zaretskii <eliz@gnu.org>2011-06-25 14:44:30 +0300
commit0c22566f00ee467af8d41ef7dc9f18c3b66630c5 (patch)
tree7db72a0297d9f21e0582d94286c21cad2c64dfa9 /src
parent58b9f433ad4a4ea20e0c51997ca8a9aaab79a213 (diff)
downloademacs-0c22566f00ee467af8d41ef7dc9f18c3b66630c5.tar.gz
Set up the bidi iterator for iterating display strings and overlay strings.
Not tested yet, just compiled. src/xdisp.c (handle_single_display_spec, next_overlay_string) (get_overlay_strings_1, push_display_prop): Set up the bidi iterator for displaying display or overlay strings. (forward_to_next_line_start): Don't use the shortcut if bidi-iterating. (back_to_previous_visible_line_start): If handle_display_prop pushed the iterator stack, restore the internal state of the bidi iterator by calling bidi_pop_it same number of times. (reseat_at_next_visible_line_start): If ON_NEWLINE_P is non-zero, and we are bidi-iterating, don't decrement the iterator position; instead, set the first_elt flag in the bidi iterator, to produce the same effect. (reseat_1): Remove redundant setting of string_from_display_prop_p. (push_display_prop): xassert that we are iterating a buffer. (push_it, pop_it): Save and restore the state of the bidi iterator. Save and restore the bidi_p flag. (pop_it): Iterate out of display property for string iteration as well. (iterate_out_of_display_property): Support iteration over strings. (handle_single_display_spec): Set up it->bidi_it for iteration over a display string, and call bidi_init_it. src/bidi.c (bidi_cache_start_stack, bidi_push_it): Use IT_STACK_SIZE. src/dispextern.h (struct iterator_stack_entry): New member bidi_p. (struct it): Member bidi_p is now a bit field 1 bit wide.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog32
-rw-r--r--src/bidi.c11
-rw-r--r--src/dispextern.h7
-rw-r--r--src/xdisp.c202
4 files changed, 214 insertions, 38 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 40576554636..083aaaaa4bd 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,35 @@
+2011-06-25 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (handle_single_display_spec, next_overlay_string)
+ (get_overlay_strings_1, push_display_prop): Set up the bidi
+ iterator for displaying display or overlay strings.
+ (forward_to_next_line_start): Don't use the shortcut if
+ bidi-iterating.
+ (back_to_previous_visible_line_start): If handle_display_prop
+ pushed the iterator stack, restore the internal state of the bidi
+ iterator by calling bidi_pop_it same number of times.
+ (reseat_at_next_visible_line_start): If ON_NEWLINE_P is non-zero,
+ and we are bidi-iterating, don't decrement the iterator position;
+ instead, set the first_elt flag in the bidi iterator, to produce
+ the same effect.
+ (reseat_1): Remove redundant setting of string_from_display_prop_p.
+ (push_display_prop): xassert that we are iterating a buffer.
+
+ * bidi.c (bidi_cache_start_stack, bidi_push_it): Use IT_STACK_SIZE.
+
+2011-06-24 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (push_it, pop_it): Save and restore the state of the
+ bidi iterator. Save and restore the bidi_p flag.
+ (pop_it): Iterate out of display property for string iteration as
+ well.
+ (iterate_out_of_display_property): Support iteration over strings.
+ (handle_single_display_spec): Set up it->bidi_it for iteration
+ over a display string, and call bidi_init_it.
+
+ * dispextern.h (struct iterator_stack_entry): New member bidi_p.
+ (struct it): Member bidi_p is now a bit field 1 bit wide.
+
2011-06-23 Eli Zaretskii <eliz@gnu.org>
* dispextern.h (bidi_push_it, bidi_pop_it): Add prototypes.
diff --git a/src/bidi.c b/src/bidi.c
index b03e93df817..b518dd45782 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -548,11 +548,10 @@ bidi_peek_at_next_level (struct bidi_it *bidi_it)
/***********************************************************************
Pushing and popping the bidi iterator state
***********************************************************************/
-/* 10-slot stack for saving the start of the previous level of the
- cache. xdisp.c maintains a 5-slot cache for its iterator state,
- and we need just a little bit more. */
-#define CACHE_STACK_SIZE 10
-static int bidi_cache_start_stack[CACHE_STACK_SIZE];
+/* 5-slot stack for saving the start of the previous level of the
+ cache. xdisp.c maintains a 5-slot stack for its iterator state,
+ and we need the same size of our stack. */
+static int bidi_cache_start_stack[IT_STACK_SIZE];
static int bidi_cache_sp;
/* Push the bidi iterator state in preparation for reordering a
@@ -569,7 +568,7 @@ bidi_push_it (struct bidi_it *bidi_it)
memcpy (&bidi_cache[bidi_cache_idx++], bidi_it, sizeof (struct bidi_it));
/* Push the current cache start onto the stack. */
- if (bidi_cache_sp >= CACHE_STACK_SIZE)
+ if (bidi_cache_sp >= IT_STACK_SIZE)
abort ();
bidi_cache_start_stack[bidi_cache_sp++] = bidi_cache_start;
diff --git a/src/dispextern.h b/src/dispextern.h
index acd7862e5dc..d5479c7a64e 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2157,7 +2157,9 @@ struct it
Lisp_Object *dpvec, *dpend;
/* Length in bytes of the char that filled dpvec. A value of zero
- means that no such character is involved. */
+ means that no such character is involved. A negative value means
+ the rest of the line from the current iterator position onwards
+ is hidden by selective display or ellipsis. */
int dpvec_char_len;
/* Face id to use for all characters in display vector. -1 if unused. */
@@ -2253,6 +2255,7 @@ struct it
unsigned string_from_display_prop_p : 1;
unsigned display_ellipsis_p : 1;
unsigned avoid_cursor_p : 1;
+ unsigned bidi_p:1;
enum line_wrap_method line_wrap;
/* properties from display property that are reset by another display property. */
@@ -2473,7 +2476,7 @@ struct it
/* Non-zero means we need to reorder bidirectional text for display
in the visual order. */
- int bidi_p;
+ unsigned bidi_p : 1;
/* For iterating over bidirectional text. */
struct bidi_it bidi_it;
diff --git a/src/xdisp.c b/src/xdisp.c
index 74afa80ada7..dc9a62fc0b6 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -4482,12 +4482,43 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->end_charpos = it->string_nchars = SCHARS (it->string);
it->method = GET_FROM_STRING;
it->stop_charpos = 0;
+ it->prev_stop = 0;
+ it->base_level_stop = 0;
it->string_from_display_prop_p = 1;
/* Say that we haven't consumed the characters with
`display' property yet. The call to pop_it in
set_iterator_to_next will clean this up. */
if (BUFFERP (object))
*position = start_pos;
+
+ /* Force paragraph direction to be that of the parent
+ 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)
+ {
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ it->bidi_it.string.schars = it->end_charpos;
+ it->bidi_it.string.bufpos = bufpos;
+ it->bidi_it.string.from_disp_str = 1;
+ bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
+ }
}
else if (CONSP (value) && EQ (XCAR (value), Qspace))
{
@@ -4839,6 +4870,24 @@ next_overlay_string (struct it *it)
it->stop_charpos = 0;
if (it->cmp_it.stop_pos >= 0)
it->cmp_it.stop_pos = 0;
+ 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)
+ {
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ 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;
+ bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
+ }
}
CHECK_IT (it);
@@ -5105,8 +5154,32 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
it->stop_charpos = 0;
xassert (STRINGP (it->string));
it->end_charpos = SCHARS (it->string);
+ it->prev_stop = 0;
+ it->base_level_stop = 0;
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);
+
+ /* Set up the bidi iterator for this overlay string. */
+ if (it->bidi_p)
+ {
+ EMACS_INT pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
+
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ 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;
+ bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
+ }
return 1;
}
@@ -5181,19 +5254,28 @@ push_it (struct it *it, struct text_pos *position)
p->string_from_display_prop_p = it->string_from_display_prop_p;
p->display_ellipsis_p = 0;
p->line_wrap = it->line_wrap;
+ p->bidi_p = it->bidi_p;
++it->sp;
+
+ /* Save the state of the bidi iterator as well. */
+ if (it->bidi_p)
+ bidi_push_it (&it->bidi_it);
}
static void
iterate_out_of_display_property (struct it *it)
{
+ int buffer_p = BUFFERP (it->object);
+ EMACS_INT eob = (buffer_p ? ZV : it->end_charpos);
+ EMACS_INT bob = (buffer_p ? BEGV : 0);
+
/* Maybe initialize paragraph direction. If we are at the beginning
of a new paragraph, next_element_from_buffer may not have a
chance to do that. */
- if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+ if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, 1);
/* prev_stop can be zero, so check against BEGV as well. */
- while (it->bidi_it.charpos >= BEGV
+ while (it->bidi_it.charpos >= bob
&& it->prev_stop <= it->bidi_it.charpos
&& it->bidi_it.charpos < CHARPOS (it->position))
bidi_move_to_visually_next (&it->bidi_it);
@@ -5207,7 +5289,10 @@ iterate_out_of_display_property (struct it *it)
{
SET_TEXT_POS (it->position,
it->bidi_it.charpos, it->bidi_it.bytepos);
- it->current.pos = it->position;
+ if (buffer_p)
+ it->current.pos = it->position;
+ else
+ it->current.string_pos = it->position;
}
}
@@ -5249,18 +5334,6 @@ pop_it (struct it *it)
break;
case GET_FROM_BUFFER:
it->object = it->w->buffer;
- if (it->bidi_p)
- {
- /* Bidi-iterate until we get out of the portion of text, if
- any, covered by a `display' text property or an overlay
- with `display' property. (We cannot just jump there,
- because the internal coherency of the bidi iterator state
- can not be preserved across such jumps.) We also must
- determine the paragraph base direction if the overlay we
- just processed is at the beginning of a new
- paragraph. */
- iterate_out_of_display_property (it);
- }
break;
case GET_FROM_STRING:
it->object = it->string;
@@ -5286,6 +5359,20 @@ pop_it (struct it *it)
it->voffset = p->voffset;
it->string_from_display_prop_p = p->string_from_display_prop_p;
it->line_wrap = p->line_wrap;
+ it->bidi_p = p->bidi_p;
+ if (it->bidi_p)
+ {
+ bidi_pop_it (&it->bidi_it);
+ /* Bidi-iterate until we get out of the portion of text, if any,
+ covered by a `display' text property or by an overlay with
+ `display' property. (We cannot just jump there, because the
+ internal coherency of the bidi iterator state can not be
+ preserved across such jumps.) We also must determine the
+ paragraph base direction if the overlay we just processed is
+ at the beginning of a new paragraph. */
+ if (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING)
+ iterate_out_of_display_property (it);
+ }
}
@@ -5368,15 +5455,16 @@ forward_to_next_line_start (struct it *it, int *skipped_p)
xassert (!STRINGP (it->string));
- /* If there isn't any `display' property in sight, and no
- overlays, we can just use the position of the newline in
- buffer text. */
- if (it->stop_charpos >= limit
- || ((pos = Fnext_single_property_change (make_number (start),
- Qdisplay,
- Qnil, make_number (limit)),
- NILP (pos))
- && next_overlay_change (start) == ZV))
+ /* If we are not bidi-reordering, and there isn't any `display'
+ property in sight, and no overlays, we can just use the
+ position of the newline in buffer text. */
+ if (!it->bidi_p
+ && (it->stop_charpos >= limit
+ || ((pos = Fnext_single_property_change (make_number (start),
+ Qdisplay, Qnil,
+ make_number (limit)),
+ NILP (pos))
+ && next_overlay_change (start) == ZV)))
{
IT_CHARPOS (*it) = limit;
IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
@@ -5456,7 +5544,20 @@ back_to_previous_visible_line_start (struct it *it)
&& (OVERLAYP (overlay)
? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
: get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
- goto replaced;
+ {
+ /* If the call to handle_display_prop above pushed the
+ iterator state, that causes side effects for the bidi
+ iterator by calling bidi_push_it. Undo those side
+ effects. */
+ while (it2.sp > 0)
+ {
+ /* push_it calls bidi_push_it only if the bidi_p flag
+ is set in the iterator being pushed. */
+ if (it2.stack[--it2.sp].bidi_p)
+ bidi_pop_it (&it2.bidi_it);
+ }
+ goto replaced;
+ }
/* Newline is not replaced by anything -- so we are done. */
break;
@@ -5525,14 +5626,29 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p)
{
if (IT_STRING_CHARPOS (*it) > 0)
{
- --IT_STRING_CHARPOS (*it);
- --IT_STRING_BYTEPOS (*it);
+ if (!it->bidi_p)
+ {
+ --IT_STRING_CHARPOS (*it);
+ --IT_STRING_BYTEPOS (*it);
+ }
+ else
+ /* Setting this flag will cause
+ bidi_move_to_visually_next not to advance, but
+ instead deliver the current character (newline),
+ which is what the ON_NEWLINE_P flag wants. */
+ it->bidi_it.first_elt = 1;
}
}
else if (IT_CHARPOS (*it) > BEGV)
{
- --IT_CHARPOS (*it);
- --IT_BYTEPOS (*it);
+ if (!it->bidi_p)
+ {
+ --IT_CHARPOS (*it);
+ --IT_BYTEPOS (*it);
+ }
+ /* With bidi iteration, the call to `reseat' will cause
+ bidi_move_to_visually_next deliver the current character,
+ the newline, instead of advancing. */
reseat (it, it->current.pos, 0);
}
}
@@ -5614,7 +5730,6 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
IT_STRING_CHARPOS (*it) = -1;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
- it->string_from_display_prop_p = 0;
it->method = GET_FROM_BUFFER;
it->object = it->w->buffer;
it->area = TEXT_AREA;
@@ -17644,6 +17759,8 @@ cursor_row_p (struct glyph_row *row)
static int
push_display_prop (struct it *it, Lisp_Object prop)
{
+ xassert (it->method == GET_FROM_BUFFER);
+
push_it (it, NULL);
if (STRINGP (prop))
@@ -17661,6 +17778,30 @@ push_display_prop (struct it *it, Lisp_Object prop)
it->end_charpos = it->string_nchars = SCHARS (it->string);
it->method = GET_FROM_STRING;
it->stop_charpos = 0;
+ it->prev_stop = 0;
+ it->base_level_stop = 0;
+ it->string_from_display_prop_p = 1;
+
+ /* Force paragraph direction to be that of the parent
+ 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)
+ {
+ it->bidi_it.string.lstring = it->string;
+ it->bidi_it.string.s = NULL;
+ it->bidi_it.string.schars = it->end_charpos;
+ it->bidi_it.string.bufpos = IT_CHARPOS (*it);
+ it->bidi_it.string.from_disp_str = 1;
+ bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
+ }
}
else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
{
@@ -17707,6 +17848,7 @@ static void
handle_line_prefix (struct it *it)
{
Lisp_Object prefix;
+
if (it->continuation_lines_width > 0)
{
prefix = get_it_property (it, Qwrap_prefix);