Implement bidi-sensitive movement with arrow keys.
[bpt/emacs.git] / src / cmds.c
index 45b3f87..b8a6532 100644 (file)
@@ -1,13 +1,14 @@
 /* Simple built-in editing commands.
    Copyright (C) 1985, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002,
-                 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,12 +16,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include <config.h>
+#include <setjmp.h>
 #include "lisp.h"
 #include "commands.h"
 #include "buffer.h"
@@ -30,6 +30,7 @@ Boston, MA 02110-1301, USA.  */
 #include "keyboard.h"
 #include "keymap.h"
 #include "dispextern.h"
+#include "frame.h"
 
 Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function;
 
@@ -55,9 +56,13 @@ DEFUN ("forward-point", Fforward_point, Sforward_point, 1, 1, 0,
   return make_number (PT + XINT (n));
 }
 
-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.  */)
+DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "^p",
+       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;
 {
@@ -91,9 +96,13 @@ On reaching end of buffer, stop and signal error.  */)
   return Qnil;
 }
 
-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.  */)
+DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "^p",
+       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;
 {
@@ -106,7 +115,7 @@ On attempt to pass beginning or end of buffer, stop and signal error.  */)
   return Fforward_char (n);
 }
 
-DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p",
+DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "^p",
        doc: /* Move N lines forward (backward if N is negative).
 Precisely, if point is on line I, move to the start of line I + N.
 If there isn't room, go as far as possible (no error).
@@ -152,7 +161,7 @@ With positive N, a non-empty line at the end counts as one line
   return make_number (count <= 0 ? - shortage : shortage);
 }
 
-DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line, 0, 1, "p",
+DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line, 0, 1, "^p",
        doc: /* Move point to beginning of current line.
 With argument N not nil or 1, move forward N - 1 lines first.
 If point reaches the beginning or end of buffer, it stops there.
@@ -177,7 +186,7 @@ instead.  For instance, `(forward-line 0)' does the same thing as
   return Qnil;
 }
 
-DEFUN ("end-of-line", Fend_of_line, Send_of_line, 0, 1, "p",
+DEFUN ("end-of-line", Fend_of_line, Send_of_line, 0, 1, "^p",
        doc: /* Move point to end of current line.
 With argument N not nil or 1, move forward N - 1 lines first.
 If point reaches the beginning or end of buffer, it stops there.
@@ -316,47 +325,71 @@ N was explicitly specified.  */)
   return value;
 }
 
+static int nonundocount;
+
 /* Note that there's code in command_loop_1 which typically avoids
    calling this.  */
 DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p",
        doc: /* Insert the character you type.
-Whichever character you type to run this command is inserted.  */)
+Whichever character you type to run this command is inserted.
+Before insertion, `expand-abbrev' is executed if the inserted character does
+not have word syntax and the previous character in the buffer does.
+After insertion, the value of `auto-fill-function' is called if the
+`auto-fill-chars' table has a non-nil value for the inserted character.  */)
      (n)
      Lisp_Object n;
 {
+  int remove_boundary = 1;
   CHECK_NUMBER (n);
 
+  if (!EQ (Vthis_command, current_kboard->Vlast_command))
+    nonundocount = 0;
+
+  if (NILP (Vexecuting_kbd_macro)
+      && !EQ (minibuf_window, selected_window))
+    {
+      if (nonundocount <= 0 || nonundocount >= 20)
+       {
+         remove_boundary = 0;
+         nonundocount = 0;
+       }
+      nonundocount++;
+    }
+
+  if (remove_boundary
+      && CONSP (current_buffer->undo_list)
+      && NILP (XCAR (current_buffer->undo_list)))
+    /* Remove the undo_boundary that was just pushed.  */
+    current_buffer->undo_list = XCDR (current_buffer->undo_list);
+
   /* Barf if the key that invoked this was not a character.  */
-  if (!CHARACTERP (last_command_char))
+  if (!CHARACTERP (last_command_event))
     bitch_at_user ();
   {
     int character = translate_char (Vtranslation_table_for_input,
-                                   XINT (last_command_char));
+                                   XINT (last_command_event));
     if (XINT (n) >= 2 && NILP (current_buffer->overwrite_mode))
       {
-       int modified_char = character;
-       /* Add the offset to the character, for Finsert_char.
-          We pass internal_self_insert the unmodified character
-          because it itself does this offsetting.  */
-       if (! NILP (current_buffer->enable_multibyte_characters))
-         modified_char = unibyte_char_to_multibyte (modified_char);
-
        XSETFASTINT (n, XFASTINT (n) - 2);
        /* The first one might want to expand an abbrev.  */
        internal_self_insert (character, 1);
        /* The bulk of the copies of this char can be inserted simply.
           We don't have to handle a user-specified face specially
           because it will get inherited from the first char inserted.  */
-       Finsert_char (make_number (modified_char), n, Qt);
+       Finsert_char (make_number (character), n, Qt);
        /* The last one might want to auto-fill.  */
        internal_self_insert (character, 0);
       }
     else
       while (XINT (n) > 0)
        {
+         int val;
          /* Ok since old and new vals both nonneg */
          XSETFASTINT (n, XFASTINT (n) - 1);
-         internal_self_insert (character, XFASTINT (n) != 0);
+         val = internal_self_insert (character, XFASTINT (n) != 0);
+         if (val == 2)
+           nonundocount = 0;
+         frame_make_pointer_invisible ();
        }
   }
 
@@ -472,8 +505,6 @@ internal_self_insert (c, noautofill)
       hairy = 2;
     }
 
-  if (NILP (current_buffer->enable_multibyte_characters))
-    MAKE_CHAR_MULTIBYTE (c);
   synt = SYNTAX (c);
 
   if (!NILP (current_buffer->abbrev_mode)
@@ -482,7 +513,7 @@ internal_self_insert (c, noautofill)
       && PT > BEGV
       && (!NILP (current_buffer->enable_multibyte_characters)
          ? SYNTAX (XFASTINT (Fprevious_char ())) == Sword
-         : (SYNTAX (unibyte_char_to_multibyte (XFASTINT (Fprevious_char ())))
+         : (SYNTAX (UNIBYTE_TO_CHAR (XFASTINT (Fprevious_char ())))
             == Sword)))
     {
       int modiff = MODIFF;
@@ -493,7 +524,7 @@ internal_self_insert (c, noautofill)
       /* If we expanded an abbrev which has a hook,
         and the hook has a non-nil `no-self-insert' property,
         return right away--don't really self-insert.  */
-      if (! NILP (sym) && ! NILP (XSYMBOL (sym)->function)
+      if (SYMBOLP (sym) && ! NILP (sym) && ! NILP (XSYMBOL (sym)->function)
          && SYMBOLP (XSYMBOL (sym)->function))
        {
          Lisp_Object prop;
@@ -567,16 +598,16 @@ internal_self_insert (c, noautofill)
 void
 syms_of_cmds ()
 {
-  Qkill_backward_chars = intern ("kill-backward-chars");
+  Qkill_backward_chars = intern_c_string ("kill-backward-chars");
   staticpro (&Qkill_backward_chars);
 
-  Qkill_forward_chars = intern ("kill-forward-chars");
+  Qkill_forward_chars = intern_c_string ("kill-forward-chars");
   staticpro (&Qkill_forward_chars);
 
-  Qoverwrite_mode_binary = intern ("overwrite-mode-binary");
+  Qoverwrite_mode_binary = intern_c_string ("overwrite-mode-binary");
   staticpro (&Qoverwrite_mode_binary);
 
-  Qexpand_abbrev = intern ("expand-abbrev");
+  Qexpand_abbrev = intern_c_string ("expand-abbrev");
   staticpro (&Qexpand_abbrev);
 
   DEFVAR_LISP ("self-insert-face", &Vself_insert_face,
@@ -612,6 +643,7 @@ keys_of_cmds ()
 {
   int n;
 
+  nonundocount = 0;
   initial_define_key (global_map, Ctl ('I'), "self-insert-command");
   for (n = 040; n < 0177; n++)
     initial_define_key (global_map, n, "self-insert-command");