Initial support for bidirectional editing.

Makefile.in (obj): Include bidi.o.
 (bidi.o): New target.
 makefile.w32-in (OBJ1): Add $(BLD)/bidi.$(O).
 ($(BLD)/bidi.$(O)): New target.
 bidi.c: New file.
 buffer.h (struct buffer): New members bidi_display_reordering
 and bidi_paragraph_direction.
 buffer.c (init_buffer_once): Initialize bidi_display_reordering
 and bidi_paragraph_direction.
 (syms_of_buffer): Declare Lisp variables bidi-display-reordering
 and bidi-paragraph-direction.
 (Fbuffer_swap_text): Swap the values of
 bidi_display_reordering and bidi_paragraph_direction.
 dispextern.h (BIDI_MAXLEVEL, BIDI_AT_BASE_LEVEL): New macros.
 (bidi_type_t, bidi_dir_t): New types.
 (bidi_saved_info, bidi_stack, bidi_it): New structures.
 (struct it): New members bidi_p, bidi_it, paragraph_embedding,
 prev_stop, base_level_stop, and eol_pos.
 (bidi_init_it, bidi_get_next_char_visually): New prototypes.
 (IT_STACK_SIZE): Enlarge to 5.
 (struct glyph_row): New member reversed_p.
 <string_buffer_position>: Update prototype.
 (PRODUCE_GLYPHS): Set the reversed_p flag in the iterator's
 glyph_row if bidi_it.paragraph_dir == R2L.
 (struct glyph): New members resolved_level and bidi_type.
 dispnew.c (direct_output_forward_char): Give up if we need bidi
 processing or buffer's direction is right-to-left.
 (prepare_desired_row): Preserve the reversed_p flag.
 (row_equal_p): Compare the reversed_p attributes as well.
 xdisp.c (init_iterator): Initialize it->bidi_p.  Call
 bidi_init_it and set it->paragraph_embedding from the current
 buffer's value of bidi_paragraph_direction.
 (reseat_1): Initialize bidi_it.first_elt.
 (set_iterator_to_next, next_element_from_buffer): Use the value of
 paragraph_embedding to determine the paragraph direction.
 (set_iterator_to_next): Under bidi reordering, call
 bidi_get_next_char_visually.  Call bidi_paragraph_init if the
 new_paragraph flag is set in the bidi iterator.
 (next_element_from_buffer): If bidi_it.first_elt is set,
 initialize paragraph direction and find the first character to
 display in the visual order.  If reseated to a middle of a line,
 prime the bidi iterator starting at the line's beginning.  Handle
 the situation where we overstepped stop_charpos due to
 non-linearity of the bidi iteration.  Likewise for when we back up
 beyond the previous stop_charpos.  When moving across stop_charpos,
 record it in prev_stop.
 (display_line): Set row->end and it->start for the next row to the
 next character in logical order.  Always extend reversed_p rows to
 the end of line, even if they end at ZV.  Copy the reversed_p flag
 to the next glyph row.  Keep calling set_cursor_from_row for
 bidi-reordered rows even if we already have a possible candidate
 for cursor position.  Set row_end after all the row's glyphs have
 been produced, by looping over the glyphs.  Record the position
 after EOL in it->eol_pos, and use it to set end_pos of the last
 row produced for a continued line.
 <Qright_to_left, Qleft_to_right>: New variables.
 (syms_of_xdisp): Initialize and staticpro them.
 (string_buffer_position_lim): New function.
 (string_buffer_position): Most of code moved to
 string_buffer_position_lim.  Last argument and return value are
 now EMACS_INT; all callers changed.
 (set_cursor_from_row): Rewritten to support bidirectional text and
 reversed glyph rows.
 (text_outside_line_unchanged_p, try_window_id): Disable
 optimizations if we are reordering bidirectional text and the
 paragraph direction can be affected by the change.
 (append_glyph, append_composite_glyph)
 (produce_image_glyph, append_stretch_glyph): Set the
 resolved_level and bidi_type members of each glyph.
 (append_glyph): If the glyph row is reversed, prepend the glyph
 rather than appending it.
 (handle_stop_backwards): New function.
 (reseat_1, pop_it, push_it): Set prev_stop and base_level_stop.
 (reseat): call handle_stop_backwards to recompute prev_stop and
 base_level_stop for the new position.
 (handle_invisible_prop): Under bidi iteration, skip invisible text
 using bidi_get_next_char_visually.  If we are `reseat'ed, init the
 paragraph direction.  Update IT->prev_stop after skipping
 invisible text.
 (move_it_in_display_line_to): New variables prev_method
 and prev_pos.  Compare for strict equality in
 BUFFER_POS_REACHED_P.
 (try_cursor_movement): Examine all the candidate rows that occlude
 point, to return the best match.  If rows are bidi-reordered
 and point moved backwards, back up to the row that is not a
 continuation line, and start looking for a suitable row from
 there.
 term.c (append_glyph): Reverse glyphs by pre-pending them,
 rather than appending, if the glyph_row's reversed_p flag is set.
 Set the resolved_level and bidi_type members of each glyph.
 .gdbinit (pbiditype): New command.
 (pgx): Use it to display bidi level and type of the glyph.
 (pitx): Display some bidi information about the iterator.
 (prowlims, pmtxrows): New commands.
 files.el: Make bidi-display-reordering safe variable for boolean
 values.
 mule.texi (International): Mention support of bidirectional editing.
 (Bidirectional Editing): New section.
 HELLO: Reorder Arabic and Hebrew into logical order, and
 insert RLM before the opening paren, to make the display more
 reasonable.  Add setting for bidi-display-reordering in the local
 variables section.
 NEWS: Mention initial support for bidirectional editing.
This commit is contained in:
Eli Zaretskii 2010-03-30 05:13:07 -04:00
commit a7b0282034
19 changed files with 3631 additions and 229 deletions

View file

@ -1,3 +1,8 @@
2010-03-30 Eli Zaretskii <eliz@gnu.org>
* mule.texi (International): Mention support of bidirectional editing.
(Bidirectional Editing): New section.
2010-03-28 Nick Roberts <nickrob@snap.net.nz>
* emacs.texi (Top): Update node names to those in building.texi.

View file

@ -66,6 +66,12 @@ displays (@pxref{Terminal Coding}). If some characters are displayed
incorrectly, refer to @ref{Undisplayable Characters}, which describes
possible problems and explains how to solve them.
@item
Characters from scripts whose natural ordering of text is from right
to left are reordered for display (@pxref{Bidirectional Editing}).
These scripts include Arabic, Hebrew, Syriac, Thaana, and a few
others.
@item
You can insert non-@acronym{ASCII} characters or search for them. To do that,
you can specify an input method (@pxref{Select Input Method}) suitable
@ -107,6 +113,7 @@ to make sure Emacs interprets keyboard input correctly; see
* Unibyte Mode:: You can pick one European character set
to use without multibyte characters.
* Charsets:: How Emacs groups its internal character codes.
* Bidirectional Editing:: Support for right-to-left scripts.
@end menu
@node International Chars
@ -1653,6 +1660,84 @@ older Emacs versions.
point before it and type @kbd{C-u C-x =} (@pxref{International
Chars}).
@node Bidirectional Editing
@section Bidirectional Editing
@cindex bidirectional editing
@cindex right-to-left text
Emacs supports editing text written in scripts, such as Arabic and
Hebrew, whose natural ordering of horizontal text for display is from
right to left. However, digits and Latin text embedded in these
scripts are still displayed left to right. It is also not uncommon to
have small portions of text in Arabic or Hebrew embedded in otherwise
Latin document, e.g., as comments and strings in a program source
file. For these reasons, text that uses these scripts is actually
@dfn{bidirectional}: a mixture of runs of left-to-right and
right-to-left characters.
This section describes the facilities and options provided by Emacs
for editing bidirectional text.
@cindex logical order
@cindex visual order
Emacs stores right-to-left and bidirectional text in the so-called
@dfn{logical} (or @dfn{reading}) order: the buffer or string position
of the first character you read precedes that of the next character.
Reordering of bidirectional text into the @dfn{visual} order happens
at display time. As result, character positions no longer increase
monotonically with their positions on display. Emacs implements the
Unicode Bidirectional Algorithm described in the Unicode Standard
Annex #9, for reordering of bidirectional text for display.
@vindex bidi-display-reordering
The buffer-local variable @code{bidi-display-reordering} controls
whether text in the buffer is reordered for display. If its value is
non-@code{nil}, Emacs reorders characters that have right-to-left
directionality when they are displayed. The default value is
@code{nil}.
Each paragraph of bidirectional text can have its own @dfn{base
direction}, either right-to-left or left-to-right. (Paragraph
boundaries are defined by the regular expressions
@code{paragraph-start} and @code{paragraph-separate}, see
@ref{Paragraphs}.) Text in left-to-right paragraphs begins at the
left margin of the window and is truncated or continued when it
reaches the right margin. By contrast, text in right-to-left
paragraphs begins at the right margin and is continued or truncated at
the left margin.
@vindex bidi-paragraph-direction
Emacs determines the base direction of each paragraph dynamically,
based on the text at the beginning of the paragraph. However,
sometimes a buffer may need to force a certain base direction for its
paragraphs. The variable @code{bidi-paragraph-direction}, if
non-@code{nil}, disables the dynamic determination of the base
direction, and instead forces all paragraphs in the buffer to have the
direction specified by its buffer-local value. The value can be either
@code{right-to-left} or @code{left-to-right}. Any other value is
interpreted as @code{nil}.
@cindex LRM
@cindex RLM
Alternatively, you can control the base direction of a paragraph by
inserting special formatting characters in front of the paragraph.
The special character @code{RIGHT-TO-LEFT MARK}, or @sc{rlm}, forces
the right-to-left direction on the following paragraph, while
@code{LEFT-TO-RIGHT MARK}, or @sc{lrm} forces the left-to-right
direction. (You can use @kbd{C-x 8 RET} to insert these characters.)
In a GUI session, the @sc{lrm} and @sc{rlm} characters display as
blanks.
Because characters are reordered for display, Emacs commands that
operate in the logical order or on stretches of buffer positions may
produce unusual effects. For example, @kbd{C-f} and @kbd{C-b}
commands move point in the logical order, so the cursor will sometimes
jump when point traverses reordered bidirectional text. Similarly, a
highlighted region covering a contiguous range of character positions
may look discontinuous if the region spans reordered text. This is
normal and similar to behavior of other programs that support
bidirectional text.
@ignore
arch-tag: 310ba60d-31ef-4ce7-91f1-f282dd57b6b3
@end ignore

View file

@ -1,3 +1,11 @@
2010-03-28 Eli Zaretskii <eliz@gnu.org>
* HELLO: Reorder Arabic and Hebrew into logical order, and
insert RLM before the opening paren, to make the display more
reasonable. Add setting for bidi-display-reordering in the local
variables section.
* NEWS: Mention initial support for bidirectional editing.
2010-03-24 Francesc Rocher <rocher@member.fsf.org>
* MORE.STUFF: Remove CEDET entry, now distributed as part of

View file

@ -16,7 +16,7 @@ Non-ASCII examples:
LANGUAGE (NATIVE NAME) HELLO
---------------------- -----
Amharic ($,1O M[MmN{(B) $,1M`MKM](B
Arabic (,GIqjHQYdG(B) ,GecjdY(B ,GeGdqSdG(B
Arabic $,1ro(B(,GGdYQHjqI(B) ,GecjdY(B ,GeGdqSdG(B
Bengali ($,17,7>6b727>(B) $,17(7.787M6u7>70(B
Braille $,2(3(1('('(5(B
Burmese ($,1H9HYH;H4HYrlH9HL(B) $,1H9H$HYrmH"H<HLH5HL(B
@ -34,7 +34,7 @@ Georgian ($,1JEJ0J@J7J5J4J:J8(B) $,1J2J0J;J0J@JOJ=J1J0(B
German (Deutsch) Guten Tag / Gr,A|_(B Gott
Greek (,Fekkgmij\(B) ,FCei\(B ,Fsar(B
Gujarati ($,19W:!9\9p9~9d: (B) $,19h9n9x:-9d:'(B
Hebrew (,Hzixar(B) ,Hylem(B
Hebrew $,1ro(B($,1-",q-(,y-*(B) ,Hylem(B
Hungarian (magyar) Sz,Bi(Bp j,Bs(B napot!
Hindi ($,15y55B5f6 (B) $,15h5n5x6-5d6'(B / $,15h5n5x6-5U5~5p(B $,16D(B
Italian (italiano) Ciao / Buon giorno
@ -91,4 +91,5 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Local Variables:
;;; tab-width: 32
;;; bidi-display-reordering: t
;;; End:

View file

@ -36,6 +36,30 @@ lib-src/Makefile by hand in order to use the associated features.
* Changes in Emacs 24.1
+++
** Emacs now supports display and editing of bidirectional text.
Warning: This is still very much experimental! The existing support
is minimal, and when it's turned on (see below), many features are
likely to give unexpected results, or break, or even crash! Use at
your own risk!
See the node "Bidirectional Editing" in the Emacs Manual for some
initial documentation.
To turn this on in any given buffer, set the buffer-local variable
`bidi-display-reordering' to a non-nil value. The default is nil.
The buffer-local variable `bidi-paragraph-direction', if non-nil,
forces each paragraph in the buffer to have its base direction
according to the value of this variable. Possible values are
`right-to-left' and `left-to-right'. If the value is nil (the
default), Emacs determines the base direction of each paragraph from
its text, as specified by the Unicode Bidirectional Algorithm.
Reordering of bidirectional text for display in Emacs is a "Full
bidirectionality" class implementation of the Unicode Bidirectional
Algorithm.
** GTK scroll-bars are now placed on the right by default.
Use `set-scroll-bar-mode' to change this.

View file

@ -1,3 +1,8 @@
2010-03-30 Eli Zaretskii <eliz@gnu.org>
* files.el: Make bidi-display-reordering safe variable for boolean
values.
2010-03-29 Phil Hagelberg <phil@evri.com>
Chong Yidong <cyd@stupidchicken.com>

View file

@ -2768,14 +2768,15 @@ asking you for confirmation."
(mapc (lambda (pair)
(put (car pair) 'safe-local-variable (cdr pair)))
'((buffer-read-only . booleanp) ;; C source code
(default-directory . stringp) ;; C source code
(fill-column . integerp) ;; C source code
(indent-tabs-mode . booleanp) ;; C source code
(left-margin . integerp) ;; C source code
(no-update-autoloads . booleanp)
(tab-width . integerp) ;; C source code
(truncate-lines . booleanp))) ;; C source code
'((buffer-read-only . booleanp) ;; C source code
(default-directory . stringp) ;; C source code
(fill-column . integerp) ;; C source code
(indent-tabs-mode . booleanp) ;; C source code
(left-margin . integerp) ;; C source code
(no-update-autoloads . booleanp)
(tab-width . integerp) ;; C source code
(truncate-lines . booleanp) ;; C source code
(bidi-display-reordering . booleanp))) ;; C source code
(put 'c-set-style 'safe-local-eval-function t)

View file

@ -271,6 +271,9 @@ define pitx
end
end
printf "\n"
if ($it->bidi_p)
printf "BIDI: base_stop=%d prev_stop=%d level=%d\n", $it->base_level_stop, $it->prev_stop, $it->bidi_it.resolved_level
end
if ($it->region_beg_charpos >= 0)
printf "reg=%d-%d ", $it->region_beg_charpos, $it->region_end_charpos
end
@ -447,6 +450,36 @@ document pwin
Pretty print window structure w.
end
define pbiditype
if ($arg0 == 0)
printf "UNDEF"
end
if ($arg0 == 1)
printf "L"
end
if ($arg0 == 2)
printf "R"
end
if ($arg0 == 3)
printf "EN"
end
if ($arg0 == 4)
printf "AN"
end
if ($arg0 == 5)
printf "BN"
end
if ($arg0 == 6)
printf "B"
end
if ($arg0 < 0 || $arg0 > 6)
printf "%d??", $arg0
end
end
document pbiditype
Print textual description of bidi type given as first argument.
end
define pgx
set $g = $arg0
# CHAR_GLYPH
@ -475,6 +508,11 @@ define pgx
else
printf " pos=%d", $g->charpos
end
# For characters, print their resolved level and bidi type
if ($g->type == 0)
printf " blev=%d,btyp=", $g->resolved_level
pbiditype $g->bidi_type
end
printf " w=%d a+d=%d+%d", $g->pixel_width, $g->ascent, $g->descent
# If not DEFAULT_FACE_ID
if ($g->face_id != 0)
@ -575,6 +613,28 @@ document pgrowit
Pretty print all glyphs in it->glyph_row.
end
define prowlims
printf "start=%d,end=%d,reversed=%d,cont=%d,at_zv=%d\n", $arg0->start.pos.charpos, $arg0->end.pos.charpos, $arg0->reversed_p, $arg0->continued_p, $arg0->ends_at_zv_p
end
document prowlims
Print important attributes of a glyph_row structure.
Takes one argument, a pointer to a glyph_row structure.
end
define pmtxrows
set $mtx = $arg0
set $gl = $mtx->rows
set $glend = $mtx->rows + $mtx->nrows
while ($gl < $glend)
prowlims $gl
set $gl = $gl + 1
end
end
document pmtxrows
Print data about glyph rows in a glyph matrix.
Takes one argument, a pointer to a glyph_matrix structure.
end
define xtype
xgettype $
output $type

View file

@ -1,3 +1,111 @@
2010-03-30 Eli Zaretskii <eliz@gnu.org>
Initial support for bidirectional editing.
* Makefile.in (obj): Include bidi.o.
(bidi.o): New target.
* makefile.w32-in (OBJ1): Add $(BLD)/bidi.$(O).
($(BLD)/bidi.$(O)): New target.
* bidi.c: New file.
* buffer.h (struct buffer): New members bidi_display_reordering
and bidi_paragraph_direction.
* buffer.c (init_buffer_once): Initialize bidi_display_reordering
and bidi_paragraph_direction.
(syms_of_buffer): Declare Lisp variables bidi-display-reordering
and bidi-paragraph-direction.
(Fbuffer_swap_text): Swap the values of
bidi_display_reordering and bidi_paragraph_direction.
* dispextern.h (BIDI_MAXLEVEL, BIDI_AT_BASE_LEVEL): New macros.
(bidi_type_t, bidi_dir_t): New types.
(bidi_saved_info, bidi_stack, bidi_it): New structures.
(struct it): New members bidi_p, bidi_it, paragraph_embedding,
prev_stop, base_level_stop, and eol_pos.
(bidi_init_it, bidi_get_next_char_visually): New prototypes.
(IT_STACK_SIZE): Enlarge to 5.
(struct glyph_row): New member reversed_p.
<string_buffer_position>: Update prototype.
(PRODUCE_GLYPHS): Set the reversed_p flag in the iterator's
glyph_row if bidi_it.paragraph_dir == R2L.
(struct glyph): New members resolved_level and bidi_type.
* dispnew.c (direct_output_forward_char): Give up if we need bidi
processing or buffer's direction is right-to-left.
(prepare_desired_row): Preserve the reversed_p flag.
(row_equal_p): Compare the reversed_p attributes as well.
* xdisp.c (init_iterator): Initialize it->bidi_p. Call
bidi_init_it and set it->paragraph_embedding from the current
buffer's value of bidi_paragraph_direction.
(reseat_1): Initialize bidi_it.first_elt.
(set_iterator_to_next, next_element_from_buffer): Use the value of
paragraph_embedding to determine the paragraph direction.
(set_iterator_to_next): Under bidi reordering, call
bidi_get_next_char_visually. Call bidi_paragraph_init if the
new_paragraph flag is set in the bidi iterator.
(next_element_from_buffer): If bidi_it.first_elt is set,
initialize paragraph direction and find the first character to
display in the visual order. If reseated to a middle of a line,
prime the bidi iterator starting at the line's beginning. Handle
the situation where we overstepped stop_charpos due to
non-linearity of the bidi iteration. Likewise for when we back up
beyond the previous stop_charpos. When moving across stop_charpos,
record it in prev_stop.
(display_line): Set row->end and it->start for the next row to the
next character in logical order. Always extend reversed_p rows to
the end of line, even if they end at ZV. Copy the reversed_p flag
to the next glyph row. Keep calling set_cursor_from_row for
bidi-reordered rows even if we already have a possible candidate
for cursor position. Set row_end after all the row's glyphs have
been produced, by looping over the glyphs. Record the position
after EOL in it->eol_pos, and use it to set end_pos of the last
row produced for a continued line.
<Qright_to_left, Qleft_to_right>: New variables.
(syms_of_xdisp): Initialize and staticpro them.
(string_buffer_position_lim): New function.
(string_buffer_position): Most of code moved to
string_buffer_position_lim. Last argument and return value are
now EMACS_INT; all callers changed.
(set_cursor_from_row): Rewritten to support bidirectional text and
reversed glyph rows.
(text_outside_line_unchanged_p, try_window_id): Disable
optimizations if we are reordering bidirectional text and the
paragraph direction can be affected by the change.
(append_glyph, append_composite_glyph)
(produce_image_glyph, append_stretch_glyph): Set the
resolved_level and bidi_type members of each glyph.
(append_glyph): If the glyph row is reversed, prepend the glyph
rather than appending it.
(handle_stop_backwards): New function.
(reseat_1, pop_it, push_it): Set prev_stop and base_level_stop.
(reseat): call handle_stop_backwards to recompute prev_stop and
base_level_stop for the new position.
(handle_invisible_prop): Under bidi iteration, skip invisible text
using bidi_get_next_char_visually. If we are `reseat'ed, init the
paragraph direction. Update IT->prev_stop after skipping
invisible text.
(move_it_in_display_line_to): New variables prev_method
and prev_pos. Compare for strict equality in
BUFFER_POS_REACHED_P.
(try_cursor_movement): Examine all the candidate rows that occlude
point, to return the best match. If rows are bidi-reordered
and point moved backwards, back up to the row that is not a
continuation line, and start looking for a suitable row from
there.
* term.c (append_glyph): Reverse glyphs by pre-pending them,
rather than appending, if the glyph_row's reversed_p flag is set.
Set the resolved_level and bidi_type members of each glyph.
* .gdbinit (pbiditype): New command.
(pgx): Use it to display bidi level and type of the glyph.
(pitx): Display some bidi information about the iterator.
(prowlims, pmtxrows): New commands.
2010-03-30 Dan Nicolaescu <dann@ics.uci.edu>
Remove all uses of C_DEBUG_SWITCH and LIBS_DEBUG.

View file

@ -496,7 +496,7 @@ FONT_DRIVERS = xfont.o
/* lastfile must follow all files
whose initialized data areas should be dumped as pure by dump-emacs. */
obj= dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
charset.o coding.o category.o ccl.o character.o chartab.o \
charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \
cm.o term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \
emacs.o keyboard.o macros.o keymap.o sysdep.o \
buffer.o filelock.o insdel.o marker.o \
@ -982,6 +982,7 @@ doc.o: buildobj.h
atimer.o: atimer.c atimer.h syssignal.h systime.h lisp.h blockinput.h \
$(config_h)
bidi.o: bidi.c buffer.h character.h dispextern.h lisp.h $(config_h)
buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \
$(INTERVALS_H) blockinput.h atimer.h systime.h character.h \
indent.h keyboard.h coding.h keymap.h frame.h lisp.h $(config_h)

2028
src/bidi.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -2279,6 +2279,8 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
swapfield (undo_list, Lisp_Object);
swapfield (mark, Lisp_Object);
swapfield (enable_multibyte_characters, Lisp_Object);
swapfield (bidi_display_reordering, Lisp_Object);
swapfield (bidi_paragraph_direction, Lisp_Object);
/* FIXME: Not sure what we should do with these *_marker fields.
Hopefully they're just nil anyway. */
swapfield (pt_marker, Lisp_Object);
@ -5206,7 +5208,9 @@ init_buffer_once ()
buffer_defaults.truncate_lines = Qnil;
buffer_defaults.word_wrap = Qnil;
buffer_defaults.ctl_arrow = Qt;
buffer_defaults.bidi_display_reordering = Qnil;
buffer_defaults.direction_reversed = Qnil;
buffer_defaults.bidi_paragraph_direction = Qnil;
buffer_defaults.cursor_type = Qt;
buffer_defaults.extra_line_spacing = Qnil;
buffer_defaults.cursor_in_non_selected_windows = Qt;
@ -5291,7 +5295,9 @@ init_buffer_once ()
XSETFASTINT (buffer_local_flags.syntax_table, idx); ++idx;
XSETFASTINT (buffer_local_flags.cache_long_line_scans, idx); ++idx;
XSETFASTINT (buffer_local_flags.category_table, idx); ++idx;
XSETFASTINT (buffer_local_flags.bidi_display_reordering, idx); ++idx;
XSETFASTINT (buffer_local_flags.direction_reversed, idx); ++idx;
XSETFASTINT (buffer_local_flags.bidi_paragraph_direction, idx); ++idx;
XSETFASTINT (buffer_local_flags.buffer_file_coding_system, idx);
/* Make this one a permanent local. */
buffer_permanent_local_flags[idx++] = 1;
@ -5548,11 +5554,6 @@ This is the same as (default-value 'abbrev-mode). */);
doc: /* Default value of `ctl-arrow' for buffers that do not override it.
This is the same as (default-value 'ctl-arrow). */);
DEFVAR_LISP_NOPRO ("default-direction-reversed",
&buffer_defaults.direction_reversed,
doc: /* Default value of `direction-reversed' for buffers that do not override it.
This is the same as (default-value 'direction-reversed). */);
DEFVAR_LISP_NOPRO ("default-enable-multibyte-characters",
&buffer_defaults.enable_multibyte_characters,
doc: /* *Default value of `enable-multibyte-characters' for buffers not overriding it.
@ -5809,11 +5810,29 @@ The variable `coding-system-for-write', if non-nil, overrides this variable.
This variable is never applied to a way of decoding a file while reading it. */);
DEFVAR_PER_BUFFER ("direction-reversed", &current_buffer->direction_reversed,
Qnil,
doc: /* *Non-nil means lines in the buffer are displayed right to left. */);
DEFVAR_PER_BUFFER ("direction-reversed",
&current_buffer->direction_reversed, Qnil,
doc: /* Non-nil means set beginning of lines at the right edge of the window.
See also the variable `bidi-display-reordering'. */);
DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines, Qnil,
DEFVAR_PER_BUFFER ("bidi-display-reordering",
&current_buffer->bidi_display_reordering, Qnil,
doc: /* Non-nil means reorder bidirectional text for display in the visual order.
See also the variable `direction-reversed'. */);
DEFVAR_PER_BUFFER ("bidi-paragraph-direction",
&current_buffer->bidi_paragraph_direction, Qnil,
doc: /* *If non-nil, forces directionality of text paragraphs in the buffer.
If this is nil (the default), the direction of each paragraph is
determined by the first strong directional character of its text.
The values of `right-to-left' and `left-to-right' override that.
Any other value is treated as nil.
This variable has no effect unless the buffer's value of
\`bidi-display-reordering' is non-nil. */);
DEFVAR_PER_BUFFER ("truncate-lines", &current_buffer->truncate_lines, Qnil,
doc: /* *Non-nil means do not display continuation lines.
Instead, give each line of text just one screen line.

View file

@ -662,8 +662,16 @@ struct buffer
Lisp_Object word_wrap;
/* Non-nil means display ctl chars with uparrow. */
Lisp_Object ctl_arrow;
/* Non-nil means display text from right to left. */
/* Non-nil means reorder bidirectional text for display in the
visual order. */
Lisp_Object bidi_display_reordering;
/* Non-nil means set beginning of lines at the right edge of
windows. */
Lisp_Object direction_reversed;
/* If non-nil, specifies which direction of text to force in all the
paragraphs of the buffer. Nil means determine paragraph
direction dynamically for each paragraph. */
Lisp_Object bidi_paragraph_direction;
/* Non-nil means do selective display;
see doc string in syms_of_buffer (buffer.c) for details. */
Lisp_Object selective_display;

View file

@ -370,6 +370,16 @@ struct glyph
/* Non-zero means don't display cursor here. */
unsigned avoid_cursor_p : 1;
/* Resolved bidirectional level of this character [0..63]. */
unsigned resolved_level : 5;
/* Resolved bidirectional type of this character, see enum
bidi_type_t below. Note that according to UAX#9, only some
values (STRONG_L, STRONG_R, WEAK_AN, WEAK_EN, WEAK_BN, and
NEUTRAL_B) can appear in the resolved type, so we only reserve
space for those that can. */
unsigned bidi_type : 3;
#define FACE_ID_BITS 20
/* Face of the glyph. This is a realized face ID,
@ -739,14 +749,18 @@ struct glyph_row
/* First position in this row. This is the text position, including
overlay position information etc, where the display of this row
started, and can thus be less the position of the first glyph
(e.g. due to invisible text or horizontal scrolling). */
(e.g. due to invisible text or horizontal scrolling). BIDI Note:
This is the smallest character position in the row, but not
necessarily the character that is the leftmost on the display. */
struct display_pos start;
/* Text position at the end of this row. This is the position after
the last glyph on this row. It can be greater than the last
glyph position + 1, due to truncation, invisible text etc. In an
up-to-date display, this should always be equal to the start
position of the next row. */
position of the next row. BIDI Note: this is the character whose
buffer position is the largest, but not necessarily the rightmost
one on the display. */
struct display_pos end;
/* Non-zero means the overlay arrow bitmap is on this line.
@ -872,6 +886,10 @@ struct glyph_row
the bottom line of the window, but not end of the buffer. */
unsigned indicate_bottom_line_p : 1;
/* Non-zero means the row was reversed to display text in a
right-to-left paragraph. */
unsigned reversed_p : 1;
/* Continuation lines width at the start of the row. */
int continuation_lines_width;
@ -924,12 +942,18 @@ struct glyph_row *matrix_row P_ ((struct glyph_matrix *, int));
(MATRIX_ROW ((MATRIX), (ROW))->used[TEXT_AREA])
/* Return the character/ byte position at which the display of ROW
starts. */
starts. BIDI Note: this is the smallest character/byte position
among characters in ROW, i.e. the first logical-order character
displayed by ROW, which is not necessarily the smallest horizontal
position. */
#define MATRIX_ROW_START_CHARPOS(ROW) ((ROW)->start.pos.charpos)
#define MATRIX_ROW_START_BYTEPOS(ROW) ((ROW)->start.pos.bytepos)
/* Return the character/ byte position at which ROW ends. */
/* Return the character/ byte position at which ROW ends. BIDI Note:
this is the largest character/byte position among characters in
ROW, i.e. the last logical-order character displayed by ROW, which
is not necessarily the largest horizontal position. */
#define MATRIX_ROW_END_CHARPOS(ROW) ((ROW)->end.pos.charpos)
#define MATRIX_ROW_END_BYTEPOS(ROW) ((ROW)->end.pos.bytepos)
@ -1702,7 +1726,93 @@ struct face_cache
extern int face_change_count;
/* For reordering of bidirectional text. */
#define BIDI_MAXLEVEL 64
/* Data type for describing the bidirectional character types. The
first 7 must be at the beginning, because they are the only values
valid in the `bidi_type' member of `struct glyph'; we only reserve
3 bits for it, so we cannot use there values larger than 7. */
typedef enum {
UNKNOWN_BT = 0,
STRONG_L, /* strong left-to-right */
STRONG_R, /* strong right-to-left */
WEAK_EN, /* european number */
WEAK_AN, /* arabic number */
WEAK_BN, /* boundary neutral */
NEUTRAL_B, /* paragraph separator */
STRONG_AL, /* arabic right-to-left letter */
LRE, /* left-to-right embedding */
LRO, /* left-to-right override */
RLE, /* right-to-left embedding */
RLO, /* right-to-left override */
PDF, /* pop directional format */
WEAK_ES, /* european number separator */
WEAK_ET, /* european number terminator */
WEAK_CS, /* common separator */
WEAK_NSM, /* non-spacing mark */
NEUTRAL_S, /* segment separator */
NEUTRAL_WS, /* whitespace */
NEUTRAL_ON /* other neutrals */
} bidi_type_t;
/* The basic directionality data type. */
typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t;
/* Data type for storing information about characters we need to
remember. */
struct bidi_saved_info {
int bytepos, charpos; /* character's buffer position */
bidi_type_t type; /* character's resolved bidi type */
bidi_type_t type_after_w1; /* original type of the character, after W1 */
bidi_type_t orig_type; /* type as we found it in the buffer */
};
/* Data type for keeping track of saved embedding levels and override
status information. */
struct bidi_stack {
int level;
bidi_dir_t override;
};
/* Data type for iterating over bidi text. */
struct bidi_it {
EMACS_INT bytepos; /* iterator's position in buffer */
EMACS_INT charpos;
int ch; /* character itself */
int ch_len; /* length of its multibyte sequence */
bidi_type_t type; /* bidi type of this character, after
resolving weak and neutral types */
bidi_type_t type_after_w1; /* original type, after overrides and W1 */
bidi_type_t orig_type; /* original type, as found in the buffer */
int resolved_level; /* final resolved level of this character */
int invalid_levels; /* how many PDFs to ignore */
int invalid_rl_levels; /* how many PDFs from RLE/RLO to ignore */
int prev_was_pdf; /* if non-zero, previous char was PDF */
struct bidi_saved_info prev; /* info about previous character */
struct bidi_saved_info last_strong; /* last-seen strong directional char */
struct bidi_saved_info next_for_neutral; /* surrounding characters for... */
struct bidi_saved_info prev_for_neutral; /* ...resolving neutrals */
struct bidi_saved_info next_for_ws; /* character after sequence of ws */
EMACS_INT next_en_pos; /* position of next EN char for ET */
EMACS_INT ignore_bn_limit; /* position until which to ignore BNs */
bidi_dir_t sor; /* direction of start-of-run in effect */
int scan_dir; /* direction of text scan */
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
stuff that is not part of the bidi iterator's state! */
struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */
int first_elt; /* if non-zero, examine current char first */
bidi_dir_t paragraph_dir; /* current paragraph direction */
int new_paragraph; /* if non-zero, we expect a new paragraph */
EMACS_INT separator_limit; /* where paragraph separator should end */
};
/* Value is non-zero when the bidi iterator is at base paragraph
embedding level. */
#define BIDI_AT_BASE_LEVEL(BIDI_IT) \
((BIDI_IT).resolved_level == (BIDI_IT).level_stack[0].level)
/***********************************************************************
@ -1854,7 +1964,7 @@ enum it_method {
NUM_IT_METHODS
};
#define IT_STACK_SIZE 4
#define IT_STACK_SIZE 5
/* Iterator for composition (both for static and automatic). */
struct composition_it
@ -1902,6 +2012,14 @@ struct it
text, overlay strings, end of text etc., which see. */
EMACS_INT stop_charpos;
/* Previous stop position, i.e. the last one before the current
iterator position in `current'. */
EMACS_INT prev_stop;
/* Last stop position iterated across whose bidi embedding level is
equal to the current paragraph's base embedding level. */
EMACS_INT base_level_stop;
/* Maximum string or buffer position + 1. ZV when iterating over
current_buffer. */
EMACS_INT end_charpos;
@ -2008,6 +2126,8 @@ struct it
int string_nchars;
EMACS_INT end_charpos;
EMACS_INT stop_charpos;
EMACS_INT prev_stop;
EMACS_INT base_level_stop;
struct composition_it cmp_it;
int face_id;
@ -2207,6 +2327,14 @@ struct it
incremented/reset by display_line, move_it_to etc. */
int continuation_lines_width;
/* Buffer position that ends the buffer text line being iterated.
This is normally the position after the newline at EOL. If this
is the last line of the buffer and it doesn't have a newline,
value is ZV/ZV_BYTE. Set and used only if IT->bidi_p, for
setting the end position of glyph rows produced for continuation
lines, see display_line. */
struct text_pos eol_pos;
/* Current y-position. Automatically incremented by the height of
glyph_row in move_it_to and display_line. */
int current_y;
@ -2233,6 +2361,14 @@ struct it
/* Face of the right fringe glyph. */
unsigned right_user_fringe_face_id : FACE_ID_BITS;
/* Non-zero means we need to reorder bidirectional text for display
in the visual order. */
int bidi_p;
/* For iterating over bidirectional text. */
struct bidi_it bidi_it;
bidi_dir_t paragraph_embedding;
};
@ -2263,6 +2399,13 @@ struct it
#define PRODUCE_GLYPHS(IT) \
do { \
extern int inhibit_free_realized_faces; \
if ((IT)->glyph_row != NULL && (IT)->bidi_p) \
{ \
if ((IT)->bidi_it.paragraph_dir == R2L) \
(IT)->glyph_row->reversed_p = 1; \
else \
(IT)->glyph_row->reversed_p = 0; \
} \
if (FRAME_RIF ((IT)->f) != NULL) \
FRAME_RIF ((IT)->f)->produce_glyphs ((IT)); \
else \
@ -2704,12 +2847,20 @@ extern EMACS_INT tool_bar_button_relief;
Function Prototypes
***********************************************************************/
/* Defined in bidi.c */
extern void bidi_init_it P_ ((EMACS_INT, EMACS_INT, struct bidi_it *));
extern void bidi_get_next_char_visually P_ ((struct bidi_it *));
extern void bidi_paragraph_init P_ ((bidi_dir_t, struct bidi_it *));
extern int bidi_mirror_char P_ ((int));
/* Defined in xdisp.c */
struct glyph_row *row_containing_pos P_ ((struct window *, int,
struct glyph_row *,
struct glyph_row *, int));
int string_buffer_position P_ ((struct window *, Lisp_Object, int));
EMACS_INT string_buffer_position P_ ((struct window *, Lisp_Object,
EMACS_INT));
int line_bottom_y P_ ((struct it *));
int display_prop_intangible_p P_ ((Lisp_Object));
void resize_echo_area_exactly P_ ((void));

View file

@ -1388,8 +1388,11 @@ prepare_desired_row (row)
{
if (!row->enabled_p)
{
unsigned rp = row->reversed_p;
clear_glyph_row (row);
row->enabled_p = 1;
row->reversed_p = rp;
}
}
@ -1540,6 +1543,7 @@ row_equal_p (w, a, b, mouse_face_p)
|| a->overlapped_p != b->overlapped_p
|| (MATRIX_ROW_CONTINUATION_LINE_P (a)
!= MATRIX_ROW_CONTINUATION_LINE_P (b))
|| a->reversed_p != b->reversed_p
/* Different partially visible characters on left margin. */
|| a->x != b->x
/* Different height. */
@ -3500,6 +3504,8 @@ direct_output_for_insert (g)
|| !display_completed
/* Give up if buffer appears in two places. */
|| buffer_shared > 1
/* Give up if we need to reorder bidirectional text. */
|| !NILP (current_buffer->bidi_display_reordering)
/* Give up if currently displaying a message instead of the
minibuffer contents. */
|| (EQ (selected_window, minibuf_window)
@ -3776,6 +3782,10 @@ direct_output_forward_char (n)
if (!display_completed || cursor_in_echo_area)
return 0;
/* Give up if we need to reorder bidirectional text. */
if (!NILP (XBUFFER (w->buffer)->bidi_display_reordering))
return 0;
/* Give up if the buffer's direction is reversed. */
if (!NILP (XBUFFER (w->buffer)->direction_reversed))
return 0;

View file

@ -115,6 +115,7 @@ OBJ1 = $(BLD)/alloc.$(O) \
$(BLD)/vm-limit.$(O) \
$(BLD)/region-cache.$(O) \
$(BLD)/strftime.$(O) \
$(BLD)/bidi.$(O) \
$(BLD)/charset.$(O) \
$(BLD)/character.$(O) \
$(BLD)/chartab.$(O) \
@ -338,6 +339,14 @@ $(BLD)/atimer.$(O) : \
$(SRC)/syssignal.h \
$(SRC)/systime.h
$(BLD)/bidi.$(O) : \
$(SRC)/bidi.c \
$(CONFIG_H) \
$(SRC)/lisp.h \
$(SRC)/buffer.h \
$(SRC)/character.h \
$(SRC)/dispextern.h
$(BLD)/buffer.$(O) : \
$(SRC)/buffer.c \
$(CONFIG_H) \

View file

@ -1540,6 +1540,26 @@ append_glyph (it)
+ it->glyph_row->used[it->area]);
end = it->glyph_row->glyphs[1 + it->area];
/* If the glyph row is reversed, we need to prepend the glyph rather
than append it. */
if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
{
struct glyph *g;
int move_by = it->pixel_width;
/* Make room for the new glyphs. */
if (move_by > end - glyph) /* don't overstep end of this area */
move_by = end - glyph;
for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
g[move_by] = *g;
glyph = it->glyph_row->glyphs[it->area];
end = glyph + move_by;
}
/* BIDI Note: we put the glyphs of a "multi-pixel" character left to
right, even in the REVERSED_P case, since (a) all of its u.ch are
identical, and (b) the PADDING_P flag needs to be set for the
leftmost one, because we write to the terminal left-to-right. */
for (i = 0;
i < it->pixel_width && glyph < end;
++i)
@ -1551,6 +1571,18 @@ append_glyph (it)
glyph->padding_p = i > 0;
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
if (it->bidi_p)
{
glyph->resolved_level = it->bidi_it.resolved_level;
if ((it->bidi_it.type & 7) != it->bidi_it.type)
abort ();
glyph->bidi_type = it->bidi_it.type;
}
else
{
glyph->resolved_level = 0;
glyph->bidi_type = UNKNOWN_BT;
}
++it->glyph_row->used[it->area];
++glyph;

View file

@ -117,7 +117,10 @@ struct window
/* The buffer displayed in this window */
/* Of the fields vchild, hchild and buffer, only one is non-nil. */
Lisp_Object buffer;
/* A marker pointing to where in the text to start displaying */
/* A marker pointing to where in the text to start displaying.
BIDI Note: This is the _logical-order_ start, i.e. the smallest
buffer position visible in the window, not necessarily the
character displayed in the top left corner of the window. */
Lisp_Object start;
/* A marker pointing to where in the text point is in this window,
used only when the window is not selected.

File diff suppressed because it is too large Load diff