diff src/keyboard.c @ 83533:02e39decdc84

Merged from emacs@sv.gnu.org Patches applied: * emacs@sv.gnu.org/emacs--devo--0--patch-351 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-352 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-353 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-354 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-355 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-356 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-357 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-358 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-359 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-360 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-361 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-362 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-363 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-364 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-365 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-366 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-367 Merge from gnus--rel--5.10 * emacs@sv.gnu.org/emacs--devo--0--patch-368 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-369 Update from CVS * emacs@sv.gnu.org/emacs--devo--0--patch-370 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-115 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-116 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-117 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-118 Merge from emacs--devo--0 * emacs@sv.gnu.org/gnus--rel--5.10--patch-119 Update from CVS * emacs@sv.gnu.org/gnus--rel--5.10--patch-120 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-573
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 29 Jul 2006 09:59:12 +0000
parents b19aaf4ab0ee 3cc6bfe3a15d
children 4a2f192917db
line wrap: on
line diff
--- a/src/keyboard.c	Fri Jul 14 05:56:32 2006 +0000
+++ b/src/keyboard.c	Sat Jul 29 09:59:12 2006 +0000
@@ -238,6 +238,9 @@
 /* Nonzero means C-g should cause immediate error-signal.  */
 int immediate_quit;
 
+/* The user's hook function for outputting an error message.  */
+Lisp_Object Vcommand_error_function;
+
 /* The user's ERASE setting.  */
 Lisp_Object Vtty_erase_char;
 
@@ -682,8 +685,6 @@
 static void timer_stop_idle P_ ((void));
 static void timer_resume_idle P_ ((void));
 
-Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, int *));
-
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
 static int cannot_suspend;
@@ -990,7 +991,7 @@
   /* Handle throw from read_minibuf when using minibuffer
      while it's active but we're in another window.  */
   if (STRINGP (val))
-    Fsignal (Qerror, Fcons (val, Qnil));
+    xsignal1 (Qerror, val);
 
   return unbind_to (count, Qnil);
 }
@@ -1185,11 +1186,12 @@
     {
       if (f != NULL && FRAME_KBOARD (f) != current_kboard)
         /* We can not switch keyboards while in single_kboard mode.
-           This can legally happen when Lisp code calls
-           `recursive-edit' (or `read-minibuffer' or `y-or-n-p') after
-           it switched to a locked frame.  This kind of situation is
-           likely to happen when server.el connects to a new
-           terminal.  */
+           In rare cases, Lisp code may call `recursive-edit' (or
+           `read-minibuffer' or `y-or-n-p') after it switched to a
+           locked frame.  For example, this is likely to happen
+           when server.el connects to a new terminal while Emacs is in
+           single_kboard mode.  It is best to throw an error instead
+           of presenting the user with a frozen screen.  */
         error ("Terminal %d is locked, cannot read from it",
                FRAME_TERMINAL (f)->id);
       else
@@ -1304,48 +1306,43 @@
      Lisp_Object data;
      char *context;
 {
-  Lisp_Object stream;
-  int kill_emacs_p = 0;
   struct frame *sf = SELECTED_FRAME ();
 
-  Vquit_flag = Qnil;
-  Vinhibit_quit = Qt;
-  clear_message (1, 0);
-
-  /* If the window system or terminal frame hasn't been initialized
-     yet, or we're not interactive, it's best to dump this message out
-     to stderr and exit.  */
-  if (!sf->glyphs_initialized_p
-      || FRAME_INITIAL_P (sf)
-      || noninteractive)
-    {
-      stream = Qexternal_debugging_output;
-      kill_emacs_p = 1;
-    }
-  else
-    {
-      Fdiscard_input ();
-      message_log_maybe_newline ();
-      bitch_at_user ();
-      stream = Qt;
-    }
-
   /* The immediate context is not interesting for Quits,
      since they are asyncronous.  */
   if (EQ (XCAR (data), Qquit))
     Vsignaling_function = Qnil;
 
-  print_error_message (data, stream, context, Vsignaling_function);
+  Vquit_flag = Qnil;
+  Vinhibit_quit = Qt;
+
+  /* Use user's specified output function if any.  */
+  if (!NILP (Vcommand_error_function))
+    call3 (Vcommand_error_function, data,
+	   build_string (context ? context : ""),
+	   Vsignaling_function);
+  /* If the window system or terminal frame hasn't been initialized
+     yet, or we're not interactive, write the message to stderr and exit.  */
+  else if (!sf->glyphs_initialized_p
+	   || FRAME_INITIAL_P (sf)
+	   || noninteractive)
+    {
+      print_error_message (data, Qexternal_debugging_output,
+			   context, Vsignaling_function);
+      Fterpri (Qexternal_debugging_output);
+      Fkill_emacs (make_number (-1));
+    }
+  else
+    {
+      clear_message (1, 0);
+      Fdiscard_input ();
+      message_log_maybe_newline ();
+      bitch_at_user ();
+
+      print_error_message (data, Qt, context, Vsignaling_function);
+    }
 
   Vsignaling_function = Qnil;
-
-  /* If the window system or terminal frame hasn't been initialized
-     yet, or we're in -batch mode, this error should cause Emacs to exit.  */
-  if (kill_emacs_p)
-    {
-      Fterpri (stream);
-      Fkill_emacs (make_number (-1));
-    }
 }
 
 Lisp_Object command_loop_1 ();
@@ -2470,15 +2467,20 @@
    Value is -2 when we find input on another keyboard.  A second call
    to read_char will read it. 
 
+   If END_TIME is non-null, it is a pointer to an EMACS_TIME
+   specifying the maximum time to wait until.  If no input arrives by
+   that time, stop waiting and return nil.
+
    Value is t if we showed a menu and the user rejected it.  */
 
 Lisp_Object
-read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
+read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
      int commandflag;
      int nmaps;
      Lisp_Object *maps;
      Lisp_Object prev_event;
      int *used_mouse_menu;
+     EMACS_TIME *end_time;
 {
   volatile Lisp_Object c;
   int count;
@@ -2764,6 +2766,7 @@
      start echoing if enough time elapses.  */
 
   if (minibuf_level == 0
+      && !end_time
       && !current_kboard->immediate_echo
       && this_command_key_count > 0
       && ! noninteractive
@@ -2959,11 +2962,19 @@
     {
       KBOARD *kb;
 
+      if (end_time)
+	{
+	  EMACS_TIME now;
+	  EMACS_GET_TIME (now);
+	  if (EMACS_TIME_GE (now, *end_time))
+	    goto exit;
+	}
+
       /* Actually read a character, waiting if necessary.  */
       save_getcjmp (save_jump);
       restore_getcjmp (local_getcjmp);
       timer_start_idle ();
-      c = kbd_buffer_get_event (&kb, used_mouse_menu);
+      c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
       restore_getcjmp (save_jump);
 
 #ifdef MULTI_KBOARD
@@ -3307,7 +3318,7 @@
 
       cancel_echoing ();
       do
-	c = read_char (0, 0, 0, Qnil, 0);
+	c = read_char (0, 0, 0, Qnil, 0, NULL);
       while (BUFFERP (c));
       /* Remove the help from the frame */
       unbind_to (count, Qnil);
@@ -3317,7 +3328,7 @@
 	{
 	  cancel_echoing ();
 	  do
-	    c = read_char (0, 0, 0, Qnil, 0);
+	    c = read_char (0, 0, 0, Qnil, 0, NULL);
 	  while (BUFFERP (c));
 	}
     }
@@ -3994,9 +4005,10 @@
    We always read and discard one event.  */
 
 static Lisp_Object
-kbd_buffer_get_event (kbp, used_mouse_menu)
+kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
      KBOARD **kbp;
      int *used_mouse_menu;
+     EMACS_TIME *end_time;
 {
   register int c;
   Lisp_Object obj;
@@ -4040,13 +4052,24 @@
       if (!NILP (do_mouse_tracking) && some_mouse_moved ())
 	break;
 #endif
-      {
+      if (end_time)
+	{
+	  EMACS_TIME duration;
+	  EMACS_GET_TIME (duration);
+	  EMACS_SUB_TIME (duration, *end_time, duration);
+	  if (EMACS_TIME_NEG_P (duration))
+	    return Qnil;
+	  else
+	    wait_reading_process_output (EMACS_SECS (duration),
+					 EMACS_USECS (duration), 
+					 -1, 1, Qnil, NULL, 0);
+	}
+      else
 	wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
 
-	if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
-	  /* Pass 1 for EXPECT since we just waited to have input.  */
-	  read_avail_input (1);
-      }
+      if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
+	/* Pass 1 for EXPECT since we just waited to have input.  */
+	read_avail_input (1);
 #endif /* not VMS */
     }
 
@@ -8469,7 +8492,7 @@
       orig_defn_macro = current_kboard->defining_kbd_macro;
       current_kboard->defining_kbd_macro = Qnil;
       do
-	obj = read_char (commandflag, 0, 0, Qt, 0);
+	obj = read_char (commandflag, 0, 0, Qt, 0, NULL);
       while (BUFFERP (obj));
       current_kboard->defining_kbd_macro = orig_defn_macro;
 
@@ -8839,7 +8862,7 @@
   /* Read the first char of the sequence specially, before setting
      up any keymaps, in case a filter runs and switches buffers on us.  */
   first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
-			   &junk);
+			   &junk, NULL);
 #endif /* GOBBLE_FIRST_EVENT */
 
   orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
@@ -9018,7 +9041,7 @@
 #endif
 	    key = read_char (NILP (prompt), nmaps,
 			     (Lisp_Object *) submaps, last_nonmenu_event,
-			     &used_mouse_menu);
+			     &used_mouse_menu, NULL);
 #ifdef MULTI_KBOARD
 	    if (INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
 	      {
@@ -11948,6 +11971,15 @@
 peculiar kind of quitting.  */);
   Vthrow_on_input = Qnil;
 
+  DEFVAR_LISP ("command-error-function", &Vcommand_error_function,
+	       doc: /* If non-nil, function to output error messages.
+The arguments are the error data, a list of the form
+ (SIGNALED-CONDITIONS . SIGNAL-DATA)
+such as just as `condition-case' would bind its variable to,
+the context (a string which normally goes at the start of the message),
+and the Lisp function within which the error was signaled.  */);
+  Vcommand_error_function = Qnil;
+
   DEFVAR_LISP ("enable-disabled-menus-and-buttons",
 	       &Venable_disabled_menus_and_buttons,
 	       doc: /* If non-nil, don't ignore events produced by disabled menu items and tool-bar.