# HG changeset patch # User Eli Zaretskii # Date 1273929828 -10800 # Node ID cd5442b2826bb078bfb980dcb6b8a493c9c895b1 # Parent a9dc4c72f652fdb47c70a884ce12da610a4ecd36 Implement bidi-sensitive movement with arrow keys. src/bidi.c (bidi_paragraph_init): Don't leave alone garbage values of bidi_it->paragraph_dir. Call bidi_initialize if needed. src/xdisp.c (Fcurrent_bidi_paragraph_direction): New function. (syms_of_xdisp): Defsubr it. src/cmds.c (Fforward_char, Fbackward_char): Doc fix. src/subr.el (right-arrow-command, left-arrow-command): New functions. src/bindings.el (global-map): Bind them to right and left arrow keys. etc/NEWS: Mention current-bidi-paragraph-direction diff -r a9dc4c72f652 -r cd5442b2826b etc/NEWS --- a/etc/NEWS Sat May 15 11:38:48 2010 +0300 +++ b/etc/NEWS Sat May 15 16:23:48 2010 +0300 @@ -63,6 +63,9 @@ default), Emacs determines the base direction of each paragraph from its text, as specified by the Unicode Bidirectional Algorithm. +The function `current-bidi-paragraph-direction' returns the actual +value of paragraph base direction at point. + Reordering of bidirectional text for display in Emacs is a "Full bidirectionality" class implementation of the Unicode Bidirectional Algorithm. diff -r a9dc4c72f652 -r cd5442b2826b lisp/ChangeLog --- a/lisp/ChangeLog Sat May 15 11:38:48 2010 +0300 +++ b/lisp/ChangeLog Sat May 15 16:23:48 2010 +0300 @@ -1,5 +1,10 @@ 2010-05-15 Eli Zaretskii + Bidi-sensitive movement with arrow keys. + * subr.el (right-arrow-command, left-arrow-command): New functions. + + * bindings.el (global-map): Bind them to right and left arrow keys. + Don't override standard definition of convert-standard-filename. * files.el (convert-standard-filename): Call w32-convert-standard-filename and dos-convert-standard-filename on diff -r a9dc4c72f652 -r cd5442b2826b lisp/bindings.el --- a/lisp/bindings.el Sat May 15 11:38:48 2010 +0300 +++ b/lisp/bindings.el Sat May 15 16:23:48 2010 +0300 @@ -828,9 +828,9 @@ (define-key global-map [C-home] 'beginning-of-buffer) (define-key global-map [M-home] 'beginning-of-buffer-other-window) (define-key esc-map [home] 'beginning-of-buffer-other-window) -(define-key global-map [left] 'backward-char) +(define-key global-map [left] 'left-arrow-command) (define-key global-map [up] 'previous-line) -(define-key global-map [right] 'forward-char) +(define-key global-map [right] 'right-arrow-command) (define-key global-map [down] 'next-line) (define-key global-map [prior] 'scroll-down-command) (define-key global-map [next] 'scroll-up-command) diff -r a9dc4c72f652 -r cd5442b2826b lisp/subr.el --- a/lisp/subr.el Sat May 15 11:38:48 2010 +0300 +++ b/lisp/subr.el Sat May 15 16:23:48 2010 +0300 @@ -3804,5 +3804,30 @@ (prin1-to-string (make-hash-table))))) (provide 'hashtable-print-readable)) +;; Moving with arrows in bidi-sensitive direction. +(defun right-arrow-command (&optional n) + "Move point N characters to the right (to the left if N is negative). +On reaching beginning or end of buffer, stop and signal error. + +Depending on the bidirectional context, this may move either forward +or backward in the buffer. This is in contrast with \\[forward-char] +and \\[backward-char], which see." + (interactive "^p") + (if (eq (current-bidi-paragraph-direction) 'left-to-right) + (forward-char n) + (backward-char n))) + +(defun left-arrow-command ( &optional n) + "Move point N characters to the left (to the right if N is negative). +On reaching beginning or end of buffer, stop and signal error. + +Depending on the bidirectional context, this may move either backward +or forward in the buffer. This is in contrast with \\[backward-char] +and \\[forward-char], which see." + (interactive "^p") + (if (eq (current-bidi-paragraph-direction) 'left-to-right) + (backward-char n) + (forward-char n))) + ;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc ;;; subr.el ends here diff -r a9dc4c72f652 -r cd5442b2826b src/ChangeLog --- a/src/ChangeLog Sat May 15 11:38:48 2010 +0300 +++ b/src/ChangeLog Sat May 15 16:23:48 2010 +0300 @@ -1,5 +1,11 @@ 2010-05-15 Eli Zaretskii + * bidi.c (bidi_paragraph_init): Don't leave alone garbage values + of bidi_it->paragraph_dir. Call bidi_initialize if needed. + + * xdisp.c (Fcurrent_bidi_paragraph_direction): New function. + (syms_of_xdisp): Defsubr it. + * Makefile.in: Fix MSDOS-related comments. 2010-05-15 Glenn Morris diff -r a9dc4c72f652 -r cd5442b2826b src/bidi.c --- a/src/bidi.c Sat May 15 11:38:48 2010 +0300 +++ b/src/bidi.c Sat May 15 16:23:48 2010 +0300 @@ -890,6 +890,9 @@ EMACS_INT pos; bidi_type_t type; + if (!bidi_initialized) + bidi_initialize (); + /* If we are inside a paragraph separator, we are just waiting for the separator to be exhausted; use the previous paragraph direction. But don't do that if we have been just reseated, @@ -957,7 +960,7 @@ /* Contrary to UAX#9 clause P3, we only default the paragraph direction to L2R if we have no previous usable paragraph direction. */ - if (bidi_it->paragraph_dir == NEUTRAL_DIR) + if (bidi_it->paragraph_dir != L2R && bidi_it->paragraph_dir != R2L) bidi_it->paragraph_dir = L2R; /* P3 and ``higher protocols'' */ if (bidi_it->paragraph_dir == R2L) bidi_it->level_stack[0].level = 1; diff -r a9dc4c72f652 -r cd5442b2826b src/cmds.c --- a/src/cmds.c Sat May 15 11:38:48 2010 +0300 +++ b/src/cmds.c Sat May 15 16:23:48 2010 +0300 @@ -57,8 +57,12 @@ } DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "^p", - doc: /* Move point right N characters (left if N is negative). -On reaching end of buffer, stop and signal error. */) + doc: /* Move point N characters forward (backward if N is negative). +On reaching end or beginning of buffer, stop and signal error. + +Depending on the bidirectional context, the movement may be to the +right or to the left on the screen. This is in contrast with +\\[right-arrow-command], which see. */) (n) Lisp_Object n; { @@ -93,8 +97,12 @@ } DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "^p", - doc: /* Move point left N characters (right if N is negative). -On attempt to pass beginning or end of buffer, stop and signal error. */) + doc: /* Move point N characters backward (forward if N is negative). +On attempt to pass beginning or end of buffer, stop and signal error. + +Depending on the bidirectional context, the movement may be to the +right or to the left on the screen. This is in contrast with +\\[left-arrow-command], which see. */) (n) Lisp_Object n; { diff -r a9dc4c72f652 -r cd5442b2826b src/xdisp.c --- a/src/xdisp.c Sat May 15 11:38:48 2010 +0300 +++ b/src/xdisp.c Sat May 15 16:23:48 2010 +0300 @@ -18241,6 +18241,84 @@ return row->displays_text_p; } +DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction, + Scurrent_bidi_paragraph_direction, 0, 1, 0, + doc: /* Return paragraph direction at point in BUFFER. +Value is either `left-to-right' or `right-to-left'. +If BUFFER is omitted or nil, it defaults to the current buffer. + +Paragraph direction determines how the text in the paragraph is displayed. +In left-to-right paragraphs, text begins at the left margin of the window +and the reading direction is generally left to right. In right-to-left +paragraphs, text begins at the right margin and is read from right to left. + +See also `bidi-paragraph-direction'. */) + (buffer) + Lisp_Object buffer; +{ + struct buffer *buf; + struct buffer *old; + + if (NILP (buffer)) + buf = current_buffer; + else + { + CHECK_BUFFER (buffer); + buf = XBUFFER (buffer); + old = current_buffer; + } + + if (NILP (buf->bidi_display_reordering)) + return Qleft_to_right; + else if (!NILP (buf->bidi_paragraph_direction)) + return buf->bidi_paragraph_direction; + else + { + /* Determine the direction from buffer text. We could try to + use current_matrix if it is up to date, but this seems fast + enough as it is. */ + struct bidi_it itb; + EMACS_INT pos = BUF_PT (buf); + EMACS_INT bytepos = BUF_PT_BYTE (buf); + + if (buf != current_buffer) + set_buffer_temp (buf); + /* Find previous non-empty line. */ + if (pos >= ZV && pos > BEGV) + { + pos--; + bytepos = CHAR_TO_BYTE (pos); + } + while (FETCH_BYTE (bytepos) == '\n') + { + if (bytepos <= BEGV_BYTE) + break; + bytepos--; + pos--; + } + while (!CHAR_HEAD_P (FETCH_BYTE (bytepos))) + bytepos--; + itb.charpos = pos; + itb.bytepos = bytepos; + itb.first_elt = 1; + + bidi_paragraph_init (NEUTRAL_DIR, &itb); + if (buf != current_buffer) + set_buffer_temp (old); + switch (itb.paragraph_dir) + { + case L2R: + return Qleft_to_right; + break; + case R2L: + return Qright_to_left; + break; + default: + abort (); + } + } +} + /*********************************************************************** @@ -25940,6 +26018,7 @@ #endif defsubr (&Sformat_mode_line); defsubr (&Sinvisible_p); + defsubr (&Scurrent_bidi_paragraph_direction); staticpro (&Qmenu_bar_update_hook); Qmenu_bar_update_hook = intern_c_string ("menu-bar-update-hook");