+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
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
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
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
+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.
(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
+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.
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;
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)
/* 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;
{
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. */
*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;
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)
/* 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;
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;
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);
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;
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
{
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);
}
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 ();
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
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 =
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
/* C strings cannot have display properties. */
|| (string->s && !STRINGP (object)))
{
- *disp_prop_p = 0;
+ *disp_prop = 0;
return eob;
}
|| !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;
}
CHARPOS (tpos) = XFASTINT (pos);
if (CHARPOS (tpos) >= lim)
{
- *disp_prop_p = 0;
+ *disp_prop = 0;
break;
}
if (STRINGP (object))
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);
}
/* 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
EMACS_INT bufpos, int frame_window_p)
{
int replacing_p = 0;
+ int rv;
if (CONSP (spec)
/* Simple specerties. */
{
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))
{
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))
}
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;
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. */
it->method = GET_FROM_STRETCH;
it->object = value;
*position = it->position = start_pos;
+ retval = 1 + (it->area == TEXT_AREA);
}
#ifdef HAVE_WINDOW_SYSTEM
else
}
#endif /* HAVE_WINDOW_SYSTEM */
- return 1;
+ return retval;
}
/* Invalid property or property not supported. Restore
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;