update.
[chise/xemacs-chise.git.1] / src / event-stream.c
index d6a5cfe..de65d4e 100644 (file)
@@ -100,7 +100,7 @@ Boston, MA 02111-1307, USA.  */
 #include <errno.h>
 
 /* The number of keystrokes between auto-saves. */
-static int auto_save_interval;
+static Fixnum auto_save_interval;
 
 Lisp_Object Qundefined_keystroke_sequence;
 
@@ -250,7 +250,7 @@ Lisp_Object Qself_insert_defer_undo;
 extern Lisp_Object Fmake_keymap (Lisp_Object name);
 
 #ifdef DEBUG_XEMACS
-int debug_emacs_events;
+Fixnum debug_emacs_events;
 
 static void
 external_debugging_print_event (char *event_description, Lisp_Object event)
@@ -423,7 +423,7 @@ check_event_stream_ok (enum event_stream_operation op)
        case EVENT_STREAM_READ:
          error ("Can't read events in -batch mode");
        default:
-         abort ();
+         ABORT ();
        }
     }
   else if (!event_stream)
@@ -701,7 +701,8 @@ reset_key_echo (struct command_builder *command_builder,
   /* This function can GC */
   struct frame *f = selected_frame ();
 
-  command_builder->echo_buf_index = -1;
+  if (command_builder)
+    command_builder->echo_buf_index = -1;
 
   if (remove_echo_area_echo)
     clear_echo_area (f, Qcommand, 0);
@@ -745,7 +746,7 @@ maybe_kbd_translate (Lisp_Object event)
             This way is safer. */
          zero_event (&ev2);
          character_to_event (XCHAR (traduit), &ev2,
-                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 1, 1);
+                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 0, 1);
          XEVENT (event)->event.key.keysym = ev2.event.key.keysym;
          XEVENT (event)->event.key.modifiers = ev2.event.key.modifiers;
          did_translate = 1;
@@ -767,7 +768,7 @@ maybe_kbd_translate (Lisp_Object event)
 
          zero_event (&ev2);
          character_to_event (XCHAR (traduit), &ev2,
-                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 1, 1);
+                             XCONSOLE (EVENT_CHANNEL (XEVENT (event))), 0, 1);
          XEVENT (event)->event.key.keysym = ev2.event.key.keysym;
          XEVENT (event)->event.key.modifiers |= ev2.event.key.modifiers;
          did_translate = 1;
@@ -1386,7 +1387,7 @@ is a race condition.  That's why the RESIGNAL argument exists.
   Lisp_Object lid;
   id = event_stream_generate_wakeup (msecs, msecs2, function, object, 0);
   lid = make_int (id);
-  if (id != XINT (lid)) abort ();
+  if (id != XINT (lid)) ABORT ();
   return lid;
 }
 
@@ -1465,7 +1466,7 @@ is a race condition.  That's why the RESIGNAL argument exists.
   Lisp_Object lid;
   id = event_stream_generate_wakeup (msecs, msecs2, function, object, 1);
   lid = make_int (id);
-  if (id != XINT (lid)) abort ();
+  if (id != XINT (lid)) ABORT ();
   return lid;
 }
 
@@ -1807,7 +1808,8 @@ emacs_handle_focus_change_preliminary (Lisp_Object frame_inp_and_dev)
        MARK_WINDOWS_CHANGED (w);
       }
 
-      if (FRAMEP (focus_frame) && !EQ (frame, focus_frame))
+      if (FRAMEP (focus_frame) && FRAME_LIVE_P (XFRAME (focus_frame))
+         && !EQ (frame, focus_frame))
        {
          /* Oops, we missed a focus-out event. */
          DEVICE_FRAME_WITH_FOCUS_REAL (d) = Qnil;
@@ -2009,6 +2011,7 @@ static void push_this_command_keys (Lisp_Object event);
 static void push_recent_keys (Lisp_Object event);
 static void dribble_out_event (Lisp_Object event);
 static void execute_internal_event (Lisp_Object event);
+static int is_scrollbar_event (Lisp_Object event);
 
 DEFUN ("next-event", Fnext_event, 0, 2, 0, /*
 Return the next available event.
@@ -2201,8 +2204,6 @@ The returned event will be one of the following types:
 
   switch (XEVENT_TYPE (event))
     {
-    default:
-      goto RETURN;
     case button_release_event:
     case misc_user_event:
       /* don't echo menu accelerator keys */
@@ -2212,6 +2213,8 @@ The returned event will be one of the following types:
       goto STORE_AND_EXECUTE_KEY;
     case key_press_event:         /* any key input can trigger autosave */
       break;
+    default:
+      goto RETURN;
     }
 
   maybe_do_auto_save ();
@@ -2269,7 +2272,9 @@ The returned event will be one of the following types:
      */
   if (store_this_key)
     {
-      push_this_command_keys (event);
+      if (!is_scrollbar_event (event)) /* #### not quite right, see
+                                         comment in execute_command_event */
+       push_this_command_keys (event);
       if (!inhibit_input_event_recording)
        push_recent_keys (event);
       dribble_out_event (event);
@@ -2461,7 +2466,7 @@ A user event is a key press, button press, button release, or
     }
 
   if (!NILP (command_event_queue) || !NILP (command_event_queue_tail))
-    abort ();
+    ABORT ();
 
   /* Now tack our chain of events back on to the front of the queue.
      Actually, since the queue is now drained, we can just replace it.
@@ -3036,7 +3041,7 @@ execute_internal_event (Lisp_Object event)
        return;
       }
     default:
-      abort ();
+      ABORT ();
     }
 }
 
@@ -3404,7 +3409,7 @@ modify them.
     Lisp_Object e = XVECTOR_DATA (Vrecent_keys_ring)[j];
 
     if (NILP (e))
-      abort ();
+      ABORT ();
     XVECTOR_DATA (val)[i] = Fcopy_event (e, Qnil);
     if (++j >= recent_keys_ring_size)
       j = 0;
@@ -3500,16 +3505,24 @@ Set the maximum number of events to be stored internally.
 void
 reset_this_command_keys (Lisp_Object console, int clear_echo_area_p)
 {
-  struct command_builder *command_builder =
-    XCOMMAND_BUILDER (XCONSOLE (console)->command_builder);
-
-  reset_key_echo (command_builder, clear_echo_area_p);
+  if (!NILP (console))
+    {
+      /* console is nil if we just deleted the console as a result of C-x 5
+        0.  Unfortunately things are currently in a messy situation where
+        some stuff is console-local and other stuff isn't, so we need to
+        do everything that's not console-local. */
+      struct command_builder *command_builder =
+       XCOMMAND_BUILDER (XCONSOLE (console)->command_builder);
+
+      reset_key_echo (command_builder, clear_echo_area_p);
+      reset_current_events (command_builder);
+    }
+  else
+    reset_key_echo (0, clear_echo_area_p);
 
   deallocate_event_chain (Vthis_command_keys);
   Vthis_command_keys = Qnil;
   Vthis_command_keys_tail = Qnil;
-
-  reset_current_events (command_builder);
 }
 
 static void
@@ -3540,7 +3553,7 @@ extract_this_command_keys_nth_mouse_event (int n)
        {
          if (!n)
            {
-             /* must copy to avoid an abort() in next_event_internal() */
+             /* must copy to avoid an ABORT() in next_event_internal() */
              if (!NILP (XEVENT_NEXT (event)))
                 return Fcopy_event (event, Qnil);
              else
@@ -3671,7 +3684,7 @@ lookup_command_event (struct command_builder *command_builder,
                 || e->event_type == button_release_event)
          e->event.button.modifiers |= XEMACS_MOD_META;
        else
-         abort ();
+         ABORT ();
 
        {
          int tckn = event_chain_count (Vthis_command_keys);
@@ -3756,6 +3769,35 @@ lookup_command_event (struct command_builder *command_builder,
   }
 }
 
+static int
+is_scrollbar_event (Lisp_Object event)
+{
+#ifdef HAVE_SCROLLBARS
+  Lisp_Object fun;
+
+  if (XEVENT (event)->event_type != misc_user_event)
+    return 0;
+  fun = XEVENT (event)->event.misc.function;
+
+  return (EQ (fun, Qscrollbar_line_up) ||
+         EQ (fun, Qscrollbar_line_down) ||
+         EQ (fun, Qscrollbar_page_up) ||
+         EQ (fun, Qscrollbar_page_down) ||
+         EQ (fun, Qscrollbar_to_top) ||
+         EQ (fun, Qscrollbar_to_bottom) ||
+         EQ (fun, Qscrollbar_vertical_drag) ||
+         EQ (fun, Qscrollbar_char_left) ||
+         EQ (fun, Qscrollbar_char_right) ||
+         EQ (fun, Qscrollbar_page_left) ||
+         EQ (fun, Qscrollbar_page_right) ||
+         EQ (fun, Qscrollbar_to_left) ||
+         EQ (fun, Qscrollbar_to_right) ||
+         EQ (fun, Qscrollbar_horizontal_drag));
+#else
+  return 0;
+#endif /* HAVE_SCROLLBARS */
+}
+
 static void
 execute_command_event (struct command_builder *command_builder,
                        Lisp_Object event)
@@ -3766,8 +3808,57 @@ execute_command_event (struct command_builder *command_builder,
 
   GCPRO1 (event); /* event may be freshly created */
 
-  /* To fix C-x @ h <scrollbar-drag> x crash. */
-  if (XEVENT (event)->event_type != misc_user_event)
+  /* #### This call to is_scrollbar_event() isn't quite right, but
+     fixing properly it requires more work than can go into 21.4.
+     (We really need to split out menu, scrollbar, dialog, and other
+     types of events from misc-user, and put the remaining ones in a
+     new `user-eval' type that behaves like an eval event but is a
+     user event and thus has all of its semantics -- e.g. being
+     delayed during `accept-process-output' and similar wait states.)
+
+     The real issue here is that "user events" and "command events"
+     are not the same thing, but are very much confused in
+     event-stream.c.  User events are, essentially, any event that
+     should be delayed by accept-process-output, should terminate a
+     sit-for, etc. -- basically, any event that needs to be processed
+     synchronously with key and mouse events.  Command events are
+     those that participate in command building; scrollbar events
+     clearly don't belong because they should be transparent in a
+     sequence like C-x @ h <scrollbar-drag> x, which used to cause a
+     crash before checks similar to the is_scrollbar_event() call were
+     added.  Do other events belong with scrollbar events?  I'm not
+     sure; we need to categorize all misc-user events and see what
+     their semantics are.
+
+     (You might ask, why do scrollbar events need to be user events?
+     That's a good question.  The answer seems to be that they can
+     change point, and having this happen asynchronously would be a
+     very bad idea.  According to the "proper" functioning of
+     scrollbars, this should not happen, but XEmacs does not allow
+     point to go outside of the window.)
+
+     Scrollbar events and similar non-command events should obviously
+     not be recorded in this-command-keys, so we need to check for
+     this in next-event.
+
+     #### We call reset_current_events() twice in this function --
+     #### here, and later as a result of reset_this_command_keys().
+     #### This is almost certainly wrong; need to figure out what's
+     #### correct.
+
+     #### We need to figure out what's really correct w.r.t. scrollbar
+     #### events.  With these new fixes in, it actually works to do
+     #### C-x <scrollbar-drag> 5 2, but the key echo gets messed up
+     #### (starts over at 5).  We really need to be special-casing
+     #### scrollbar events at a lower level, and not really passing
+     #### them through the command builder at all.  (e.g. do scrollbar
+     #### events belong in macros???  doubtful; probably only the
+     #### point movement, if any, belongs, special-cased as a
+     #### pseudo-issued M-x goto-char command).  #### Need more work
+     #### here.  Do this when separating out scrollbar events.
+  */
+
+  if (!is_scrollbar_event (event))
     reset_current_events (command_builder);
 
   switch (XEVENT (event)->event_type)
@@ -3835,7 +3926,8 @@ execute_command_event (struct command_builder *command_builder,
 
     post_command_hook ();
 
-    if (!NILP (con->prefix_arg))
+    /* Console might have been deleted by command */
+    if (CONSOLE_LIVE_P (con) && !NILP (con->prefix_arg))
       {
        /* Commands that set the prefix arg don't update last-command, don't
           reset the echoing state, and don't go into keyboard macros unless
@@ -3862,8 +3954,10 @@ execute_command_event (struct command_builder *command_builder,
 
        /* Emacs 18 doesn't unconditionally clear the echoed keystrokes,
           so we don't either */
-       if (XEVENT (event)->event_type != misc_user_event)
-         reset_this_command_keys (make_console (con), 0);
+
+       if (!is_scrollbar_event (event))
+         reset_this_command_keys (CONSOLE_LIVE_P (con) ? make_console (con)
+                                  : Qnil, 0);
       }
   }
 
@@ -4220,6 +4314,7 @@ See `function-key-map' for more details.
   struct gcpro gcpro1;
   GCPRO1 (event);
 
+  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
   if (!NILP (prompt))
     CHECK_STRING (prompt);
   /* else prompt = Fkeymap_prompt (current_buffer->keymap); may GC */
@@ -4386,7 +4481,7 @@ CONSOLE defaults to the selected console if omitted.
   /* This junk is so that timestamps don't get to be negative, but contain
      as many bits as this particular emacs will allow.
    */
-  return make_int (((1L << (VALBITS - 1)) - 1) & tiempo);
+  return make_int (EMACS_INT_MAX & tiempo);
 }
 
 \f
@@ -4469,12 +4564,12 @@ vars_of_event_stream (void)
   Vthis_command_keys = Qnil;
   staticpro (&Vthis_command_keys);
   Vthis_command_keys_tail = Qnil;
-  pdump_wire (&Vthis_command_keys_tail);
+  dump_add_root_object (&Vthis_command_keys_tail);
 
   command_event_queue = Qnil;
   staticpro (&command_event_queue);
   command_event_queue_tail = Qnil;
-  pdump_wire (&command_event_queue_tail);
+  dump_add_root_object (&command_event_queue_tail);
 
   Vlast_selected_frame = Qnil;
   staticpro (&Vlast_selected_frame);
@@ -4809,6 +4904,11 @@ init_event_stream (void)
        init_event_Xt_late ();
       else
 #endif
+#ifdef HAVE_GTK
+      if (!strcmp (display_use, "gtk"))
+       init_event_gtk_late ();
+      else
+#endif
 #ifdef HAVE_MS_WINDOWS
       if (!strcmp (display_use, "mswindows"))
        init_event_mswindows_late ();