Handle `(space ...)' display spec as paragraph separator.

src/xdisp.c (compute_display_string_pos): Return 2 in DISP_PROP when
 the display spec is of the form `(space ...)'.
 (handle_display_spec): Return the value returned by
 handle_single_display_spec, not just 1 or zero.
 (handle_single_display_spec): If the display spec is of the form
 `(space ...)', and specifies display in the text area, return 2
 rather than 1.
 src/dispextern.h (struct bidi_it): Rename the disp_prop_p member
 into disp_prop; all users changed.
 src/bidi.c (bidi_fetch_char): If compute_display_string_pos returns
 DISP_PROP = 2, substitute the u+2029 PARAGRAPH SEPARATOR character
 for the text covered by the display property.
 lisp/buff-menu.el (Buffer-menu-buffer+size): Remove calls to
 bidi-string-mark-left-to-right; they are unnecessary now.
 doc/lispref/display.texi (Specified Space): Mention that `space' specs
 influence bidi reordering.
 (Bidirectional Display): Explain how to use `(space . PROPS)' for
 separating fields with bidirectional content.
This commit is contained in:
Eli Zaretskii 2011-08-25 13:45:33 +03:00
parent a2ebe600c9
commit 0c95fcf739
8 changed files with 140 additions and 57 deletions

View file

@ -1,3 +1,10 @@
2011-08-25 Eli Zaretskii <eliz@gnu.org>
* display.texi (Specified Space): Mention that `space' specs
influence bidi reordering.
(Bidirectional Display): Explain how to use `(space . PROPS)' for
separating fields with bidirectional content.
2011-08-24 Eli Zaretskii <eliz@gnu.org>
* display.texi (Bidirectional Display): Document return value in

View file

@ -3794,6 +3794,10 @@ with a @dfn{pixel ascent} specification (@pxref{Pixel Specification}).
non-graphic terminals, but the other space properties in this section
are not.
Note that space properties are treated as paragraph separators for
the purposes of reordering bidirectional text for display.
@xref{Bidirectional Display}, for the details.
@node Pixel Specification
@subsection Pixel Specification for Spaces
@cindex spaces, pixel specification
@ -6126,8 +6130,8 @@ with bidirectional content can be displayed @emph{to the left} of the
preceding field, producing a jumbled display and messing up the
expected layout.
To countermand this, you can use one of the following techniques for
forcing correct order of fields on display:
To countermand this, we recommend that you use one of the following
techniques for forcing correct order of fields on display:
@itemize @minus
@item
@ -6146,6 +6150,15 @@ Include the tab character in the field separator. The tab character
plays the role of @dfn{segment separator} in the @acronym{UBA}
reordering, whose effect is to make each field a separate segment, and
thus reorder them separately.
@cindex @code{space} display spec, and bidirectional text
@item
Separate fields with a @code{display} property or overlay with the
property value of the form @code{(space . PROPS)} (@pxref{Specified
Space}). This display specification is treated by Emacs as a
@dfn{paragraph separator}; the text before and after the separator is
reordered separately, which avoids the influence of any field on its
neighboring fields.
@end itemize
@defun bidi-string-mark-left-to-right string

View file

@ -1,3 +1,8 @@
2011-08-25 Eli Zaretskii <eliz@gnu.org>
* buff-menu.el (Buffer-menu-buffer+size): Remove calls to
bidi-string-mark-left-to-right; they are unnecessary now.
2011-08-25 Deniz Dogan <deniz@dogan.se>
* net/quickurl.el: Documentation typo fixes.

View file

@ -681,9 +681,9 @@ For more information, see the function `buffer-menu'."
(string-width tail)
2))
Buffer-menu-short-ellipsis
(bidi-string-mark-left-to-right tail))))
tail)))
;; Don't put properties on (buffer-name).
(setq name (bidi-string-mark-left-to-right name)))
(setq name (copy-sequence name)))
(add-text-properties 0 (length name) name-props name)
(add-text-properties 0 (length size) size-props size)
(let ((name+space-width (- Buffer-menu-buffer+size-width

View file

@ -1,3 +1,20 @@
2011-08-25 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (compute_display_string_pos): Return 2 in DISP_PROP when
the display spec is of the form `(space ...)'.
(handle_display_spec): Return the value returned by
handle_single_display_spec, not just 1 or zero.
(handle_single_display_spec): If the display spec is of the form
`(space ...)', and specifies display in the text area, return 2
rather than 1.
* dispextern.h (struct bidi_it): Rename the disp_prop_p member
into disp_prop; all users changed.
* bidi.c (bidi_fetch_char): If compute_display_string_pos returns
DISP_PROP = 2, substitute the u+2029 PARAGRAPH SEPARATOR character
for the text covered by the display property.
2011-08-25 Chong Yidong <cyd@stupidchicken.com>
* buffer.c (Fbury_buffer_internal): Rename from Funrecord_buffer.

View file

@ -540,7 +540,7 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved)
bidi_cache[idx].next_for_ws = bidi_it->next_for_ws;
bidi_cache[idx].ignore_bn_limit = bidi_it->ignore_bn_limit;
bidi_cache[idx].disp_pos = bidi_it->disp_pos;
bidi_cache[idx].disp_prop_p = bidi_it->disp_prop_p;
bidi_cache[idx].disp_prop = bidi_it->disp_prop;
}
bidi_cache_last_idx = idx;
@ -828,7 +828,7 @@ bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p,
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_p = 0;
bidi_it->disp_prop = 0;
/* We can only shrink the cache if we are at the bottom level of its
"stack". */
if (bidi_cache_start == 0)
@ -908,19 +908,22 @@ bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s, int unibyte)
/* Fetch and return the character at BYTEPOS/CHARPOS. If that
character is covered by a display string, treat the entire run of
covered characters as a single character u+FFFC, and return their
combined length in CH_LEN and NCHARS. DISP_POS specifies the
character position of the next display string, or -1 if not yet
computed. DISP_PROP_P non-zero means that there's really a display
string at DISP_POS, as opposed to when we searched till DISP_POS
without findingone. When the next character is at or beyond that
position, the function updates DISP_POS with the position of the
next display string. 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. */
covered characters as a single character, either u+2029 or u+FFFC,
and return their combined length in CH_LEN and NCHARS. DISP_POS
specifies the character position of the next display string, or -1
if not yet computed. 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
display spec is of the form `(space ...)', which is replaced with
u+2029 to handle it as a paragraph separator. When the next
character is at or beyond that position, the function updates
DISP_POS with the position of the next display string. 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
bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
int *disp_prop_p, struct bidi_string_data *string,
int *disp_prop, struct bidi_string_data *string,
int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars)
{
int ch;
@ -934,7 +937,7 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
{
SET_TEXT_POS (pos, charpos, bytepos);
*disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
disp_prop_p);
disp_prop);
}
/* Fetch the character at BYTEPOS. */
@ -944,9 +947,9 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
*ch_len = 1;
*nchars = 1;
*disp_pos = endpos;
*disp_prop_p = 0;
*disp_prop = 0;
}
else if (charpos >= *disp_pos && *disp_prop_p)
else if (charpos >= *disp_pos && *disp_prop)
{
EMACS_INT disp_end_pos;
@ -954,9 +957,23 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
property. Hopefully, it will never be needed. */
if (charpos > *disp_pos)
abort ();
/* Return the Unicode Object Replacement Character to represent
the entire run of characters covered by the display string. */
ch = 0xFFFC;
/* 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
covered by the display property. */
if (*disp_prop == 2)
{
/* `(space ...)' display specs are handled as paragraph
separators for the purposes of the reordering; see UAX#9
section 3 and clause HL1 in section 4.3 there. */
ch = 0x2029;
}
else
{
/* All other display specs are handled as the Unicode Object
Replacement Character. */
ch = 0xFFFC;
}
disp_end_pos = compute_display_string_end (*disp_pos, string);
*nchars = disp_end_pos - *disp_pos;
if (*nchars <= 0)
@ -1014,11 +1031,11 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos,
/* If we just entered a run of characters covered by a display
string, compute the position of the next display string. */
if (charpos + *nchars <= endpos && charpos + *nchars > *disp_pos
&& *disp_prop_p)
&& *disp_prop)
{
SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len);
*disp_pos = compute_display_string_pos (&pos, string, frame_window_p,
disp_prop_p);
disp_prop);
}
return ch;
@ -1126,7 +1143,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
int ch;
EMACS_INT ch_len, nchars;
EMACS_INT pos, disp_pos = -1;
int disp_prop_p = 0;
int disp_prop = 0;
bidi_type_t type;
const unsigned char *s;
@ -1174,7 +1191,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
bytepos = pstartbyte;
if (!string_p)
pos = BYTE_TO_CHAR (bytepos);
ch = bidi_fetch_char (bytepos, pos, &disp_pos, &disp_prop_p,
ch = bidi_fetch_char (bytepos, pos, &disp_pos, &disp_prop,
&bidi_it->string,
bidi_it->frame_window_p, &ch_len, &nchars);
type = bidi_get_type (ch, NEUTRAL_DIR);
@ -1199,7 +1216,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p)
break;
/* Fetch next character and advance to get past it. */
ch = bidi_fetch_char (bytepos, pos, &disp_pos,
&disp_prop_p, &bidi_it->string,
&disp_prop, &bidi_it->string,
bidi_it->frame_window_p, &ch_len, &nchars);
pos += nchars;
bytepos += ch_len;
@ -1336,7 +1353,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
bidi_it->ch_len = 1;
bidi_it->nchars = 1;
bidi_it->disp_pos = (string_p ? bidi_it->string.schars : ZV);
bidi_it->disp_prop_p = 0;
bidi_it->disp_prop = 0;
}
else
{
@ -1344,7 +1361,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it)
display string, treat the entire run of covered characters as
a single character u+FFFC. */
curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos,
&bidi_it->disp_pos, &bidi_it->disp_prop_p,
&bidi_it->disp_pos, &bidi_it->disp_prop,
&bidi_it->string, bidi_it->frame_window_p,
&bidi_it->ch_len, &bidi_it->nchars);
}
@ -2079,7 +2096,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it)
struct bidi_string_data bs = bidi_it->string;
bidi_type_t chtype;
int fwp = bidi_it->frame_window_p;
int dpp = bidi_it->disp_prop_p;
int dpp = bidi_it->disp_prop;
if (bidi_it->nchars <= 0)
abort ();

View file

@ -1860,8 +1860,9 @@ struct bidi_it {
bidi_dir_t sor; /* direction of start-of-run in effect */
int scan_dir; /* direction of text scan, 1: forw, -1: back */
EMACS_INT disp_pos; /* position of display string after ch */
int disp_prop_p; /* if non-zero, there really is a
`display' property/string at disp_pos */
int disp_prop; /* if non-zero, there really is a
`display' property/string at disp_pos;
if 2, the property is a `space' spec */
int stack_idx; /* index of current data on the stack */
/* Note: Everything from here on is not copied/saved when the bidi
iterator state is saved, pushed, or popped. So only put here

View file

@ -3146,11 +3146,15 @@ next_overlay_change (EMACS_INT pos)
text property whose value is a string. STRING is data about the
string to iterate; if STRING->lstring is nil, we are iterating a
buffer. FRAME_WINDOW_P is non-zero when we are displaying a window
on a GUI frame. */
on a GUI frame. DISP_PROP is set to zero if we searched
MAX_DISP_SCAN characters forward without finding any display
strings, non-zero otherwise. It is set to 2 if the display string
uses any kind of `(space ...)' spec that will produce a stretch of
white space in the text area. */
EMACS_INT
compute_display_string_pos (struct text_pos *position,
struct bidi_string_data *string,
int frame_window_p, int *disp_prop_p)
int frame_window_p, int *disp_prop)
{
/* OBJECT = nil means current buffer. */
Lisp_Object object =
@ -3163,8 +3167,9 @@ compute_display_string_pos (struct text_pos *position,
EMACS_INT lim =
(charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
struct text_pos tpos;
int rv = 0;
*disp_prop_p = 1;
*disp_prop = 1;
if (charpos >= eob
/* We don't support display properties whose values are strings
@ -3173,7 +3178,7 @@ compute_display_string_pos (struct text_pos *position,
/* C strings cannot have display properties. */
|| (string->s && !STRINGP (object)))
{
*disp_prop_p = 0;
*disp_prop = 0;
return eob;
}
@ -3190,9 +3195,11 @@ compute_display_string_pos (struct text_pos *position,
|| !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay,
object),
spec))
&& handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos,
frame_window_p))
&& (rv = handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos,
frame_window_p)))
{
if (rv == 2)
*disp_prop = 2;
return charpos;
}
@ -3204,7 +3211,7 @@ compute_display_string_pos (struct text_pos *position,
CHARPOS (tpos) = XFASTINT (pos);
if (CHARPOS (tpos) >= lim)
{
*disp_prop_p = 0;
*disp_prop = 0;
break;
}
if (STRINGP (object))
@ -3215,8 +3222,10 @@ compute_display_string_pos (struct text_pos *position,
if (!STRINGP (object))
bufpos = CHARPOS (tpos);
} while (NILP (spec)
|| !handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos,
frame_window_p));
|| !(rv = handle_display_spec (NULL, spec, object, Qnil, &tpos,
bufpos, frame_window_p)));
if (rv == 2)
*disp_prop = 2;
return CHARPOS (tpos);
}
@ -4078,7 +4087,9 @@ handle_display_prop (struct it *it)
/* Subroutine of handle_display_prop. Returns non-zero if the display
specification in SPEC is a replacing specification, i.e. it would
replace the text covered by `display' property with something else,
such as an image or a display string.
such as an image or a display string. If SPEC includes any kind or
`(space ...) specification, the value is 2; this is used by
compute_display_string_pos, which see.
See handle_single_display_spec for documentation of arguments.
frame_window_p is non-zero if the window being redisplayed is on a
@ -4095,6 +4106,7 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
EMACS_INT bufpos, int frame_window_p)
{
int replacing_p = 0;
int rv;
if (CONSP (spec)
/* Simple specerties. */
@ -4113,11 +4125,11 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
{
for (; CONSP (spec); spec = XCDR (spec))
{
if (handle_single_display_spec (it, XCAR (spec), object, overlay,
position, bufpos, replacing_p,
frame_window_p))
if ((rv = handle_single_display_spec (it, XCAR (spec), object,
overlay, position, bufpos,
replacing_p, frame_window_p)))
{
replacing_p = 1;
replacing_p = rv;
/* If some text in a string is replaced, `position' no
longer points to the position of `object'. */
if (!it || STRINGP (object))
@ -4129,11 +4141,11 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
{
int i;
for (i = 0; i < ASIZE (spec); ++i)
if (handle_single_display_spec (it, AREF (spec, i), object, overlay,
position, bufpos, replacing_p,
frame_window_p))
if ((rv = handle_single_display_spec (it, AREF (spec, i), object,
overlay, position, bufpos,
replacing_p, frame_window_p)))
{
replacing_p = 1;
replacing_p = rv;
/* If some text in a string is replaced, `position' no
longer points to the position of `object'. */
if (!it || STRINGP (object))
@ -4142,9 +4154,10 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
}
else
{
if (handle_single_display_spec (it, spec, object, overlay,
position, bufpos, 0, frame_window_p))
replacing_p = 1;
if ((rv = handle_single_display_spec (it, spec, object, overlay,
position, bufpos, 0,
frame_window_p)))
replacing_p = rv;
}
return replacing_p;
@ -4520,8 +4533,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
if (valid_p && !display_replaced_p)
{
int retval = 1;
if (!it)
return 1;
{
/* Callers need to know whether the display spec is any kind
of `(space ...)' spec that is about to affect text-area
display. */
if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
retval = 2;
return retval;
}
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
@ -4579,6 +4601,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->method = GET_FROM_STRETCH;
it->object = value;
*position = it->position = start_pos;
retval = 1 + (it->area == TEXT_AREA);
}
#ifdef HAVE_WINDOW_SYSTEM
else
@ -4596,7 +4619,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
}
#endif /* HAVE_WINDOW_SYSTEM */
return 1;
return retval;
}
/* Invalid property or property not supported. Restore
@ -5557,7 +5580,7 @@ forward_to_next_line_start (struct it *it, int *skipped_p,
if (it->bidi_it.disp_pos < limit)
{
it->bidi_it.disp_pos = limit;
it->bidi_it.disp_prop_p = 0;
it->bidi_it.disp_prop = 0;
}
do {
bprev = it->bidi_it;