/* Keyboard and mouse input; editor command loop.
- Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03
+ Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03,04
Free Software Foundation, Inc.
This file is part of GNU Emacs.
static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
-/* Vector to GCPRO the Lisp objects referenced from kbd_buffer.
-
- The interrupt-level event handlers will never enqueue an event on a
- frame which is not in Vframe_list, and once an event is dequeued,
- internal_last_event_frame or the event itself points to the frame.
- So that's all fine.
-
- But while the event is sitting in the queue, it's completely
- unprotected. Suppose the user types one command which will run for
- a while and then delete a frame, and then types another event at
- the frame that will be deleted, before the command gets around to
- it. Suppose there are no references to this frame elsewhere in
- Emacs, and a GC occurs before the second event is dequeued. Now we
- have an event referring to a freed frame, which will crash Emacs
- when it is dequeued.
-
- Similar things happen when an event on a scroll bar is enqueued; the
- window may be deleted while the event is in the queue.
-
- So, we use this vector to protect the Lisp_Objects in the event
- queue. That way, they'll be dequeued as dead frames or windows,
- but still valid Lisp objects.
-
- If kbd_buffer[i].kind != NO_EVENT, then
-
- AREF (kbd_buffer_gcpro, 2 * i) == kbd_buffer[i].frame_or_window.
- AREF (kbd_buffer_gcpro, 2 * i + 1) == kbd_buffer[i].arg. */
-
-static Lisp_Object kbd_buffer_gcpro;
-
/* Pointer to next available character in kbd_buffer.
If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the
Discard the event if it would fill the last slot. */
if (kbd_fetch_ptr - 1 != kbd_store_ptr)
{
- int idx;
#if 0 /* The SELECTION_REQUEST_EVENT case looks bogus, and it's error
prone to assign individual members for other events, in case
*kbd_store_ptr = *event;
#endif
- idx = 2 * (kbd_store_ptr - kbd_buffer);
- ASET (kbd_buffer_gcpro, idx, event->frame_or_window);
- ASET (kbd_buffer_gcpro, idx + 1, event->arg);
++kbd_store_ptr;
}
}
clear_event (event)
struct input_event *event;
{
- int idx = 2 * (event - kbd_buffer);
- ASET (kbd_buffer_gcpro, idx, Qnil);
- ASET (kbd_buffer_gcpro, idx + 1, Qnil);
event->kind = NO_EVENT;
}
for (i = 0; i < KBD_BUFFER_SIZE; i++)
EVENT_INIT (buf[i]);
- for (d = display_list; d; d = d->next_display)
+ d = display_list;
+ while (d)
{
+ struct display *next = d->next_display;
+
if (d->read_socket_hook)
/* No need for FIONREAD or fcntl; just say don't wait. */
nread = (*d->read_socket_hook) (d, buf, KBD_BUFFER_SIZE, expected);
- if (nread > 0)
- break;
+ if (nread == -2)
+ {
+ /* The display device terminated; it should be closed. */
+
+ /* Kill Emacs if this was our last display. */
+ if (! display_list->next_display)
+ kill (getpid (), SIGHUP);
+
+ /* XXX Is calling delete_display safe here? It calls Fdelete_frame. */
+ if (d->delete_display_hook)
+ (*d->delete_display_hook) (d);
+ else
+ delete_display (d);
+ }
+ else if (nread > 0)
+ {
+ /* We've got input. */
+ break;
+ }
+
+ d = next;
}
/* Scan the chars for C-g and store them in kbd_buffer. */
Note that each terminal device has its own `struct display' object,
and so this function is called once for each individual termcap
display. The first parameter indicates which device to read from. */
+
int
tty_read_avail_input (struct display *display,
struct input_event *buf,
if (ioctl (fileno (TTY_INPUT (tty)), FIONREAD, &n_to_read) < 0)
{
if (! noninteractive)
- {
- delete_tty (tty); /* XXX I wonder if this is safe here. */
-
- /* Formerly simply reported no input, but that sometimes led to
- a failure of Emacs to terminate.
- SIGHUP seems appropriate if we can't reach the terminal. */
- /* ??? Is it really right to send the signal just to this process
- rather than to the whole process group?
- Perhaps on systems with FIONREAD Emacs is alone in its group. */
- /* It appears to be the case, see narrow_foreground_group. */
- if (! tty_list->next)
- kill (getpid (), SIGHUP); /* This was the last terminal. */
- }
+ return -2; /* Close this display. */
else
- {
- n_to_read = 0;
- }
+ n_to_read = 0;
}
if (n_to_read == 0)
return 0;
Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
if (nread == -1 && errno == EIO)
{
- if (! tty_list->next)
- kill (0, SIGHUP); /* This was the last terminal. */
- else
- delete_tty (tty); /* XXX I wonder if this is safe here. */
+ return -2; /* Close this display. */
}
#if defined (AIX) && (! defined (aix386) && defined (_BSD))
/* The kernel sometimes fails to deliver SIGHUP for ptys.
and that causes a value other than 0 when there is no input. */
if (nread == 0)
{
- if (! tty_list->next)
- kill (0, SIGHUP); /* This was the last terminal. */
- else
- delete_tty (tty); /* XXX I wonder if this is safe here. */
+ return -2; /* Close this display. */
}
#endif
}
#endif /* not VMS */
\f
+void
+handle_async_input ()
+{
+#ifdef BSD4_1
+ extern int select_alarmed;
+#endif
+ interrupt_input_pending = 0;
+
+ while (1)
+ {
+ int nread;
+ nread = read_avail_input (1);
+ /* -1 means it's not ok to read the input now.
+ UNBLOCK_INPUT will read it later; now, avoid infinite loop.
+ 0 means there was no keyboard input available. */
+ if (nread <= 0)
+ break;
+
+#ifdef BSD4_1
+ select_alarmed = 1; /* Force the select emulator back to life */
+#endif
+ }
+}
+
#ifdef SIGIO /* for entire page */
/* Note SIGIO has been undef'd if FIONREAD is missing. */
{
/* Must preserve main program's value of errno. */
int old_errno = errno;
-#ifdef BSD4_1
- extern int select_alarmed;
-#endif
#if defined (USG) && !defined (POSIX_SIGNALS)
/* USG systems forget handlers when they are used;
if (input_available_clear_time)
EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
- while (1)
- {
- int nread;
- nread = read_avail_input (1);
- /* -1 means it's not ok to read the input now.
- UNBLOCK_INPUT will read it later; now, avoid infinite loop.
- 0 means there was no keyboard input available. */
- if (nread <= 0)
- break;
-
-#ifdef BSD4_1
- select_alarmed = 1; /* Force the select emulator back to life */
+#ifdef SYNC_INPUT
+ interrupt_input_pending = 1;
+#else
+ handle_async_input ();
#endif
- }
#ifdef BSD4_1
sigfree ();
reinvoke_input_signal ()
{
#ifdef SIGIO
- kill (getpid (), SIGIO);
+ handle_async_input ();
#endif
}
discard_tty_input ();
kbd_fetch_ptr = kbd_store_ptr;
- Ffillarray (kbd_buffer_gcpro, Qnil);
input_pending = 0;
return Qnil;
Should we ignore anything that was typed in at the "wrong" kboard? */
for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
{
- int idx;
if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
kbd_fetch_ptr = kbd_buffer;
if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT)
stuff_char (kbd_fetch_ptr->code);
- kbd_fetch_ptr->kind = NO_EVENT;
- idx = 2 * (kbd_fetch_ptr - kbd_buffer);
- ASET (kbd_buffer_gcpro, idx, Qnil);
- ASET (kbd_buffer_gcpro, idx + 1, Qnil);
+ clear_event (kbd_fetch_ptr);
}
input_pending = 0;
input_available_clear_time = 0;
}
-/* This routine is called at interrupt level in response to C-g.
-
- If interrupt_input, this is the handler for SIGINT. Otherwise, it
- is called from kbd_buffer_store_event, in handling SIGIO or
- SIGTINT.
-
- If `waiting_for_input' is non zero, then unless `echoing' is
- nonzero, immediately throw back to read_char.
-
- Otherwise it sets the Lisp variable quit-flag not-nil. This causes
- eval to throw, when it gets a chance. If quit-flag is already
- non-nil, it stops the job right away.
+/* The SIGINT handler.
- XXX This comment needs to be updated. */
+ If we have a frame on the controlling tty, the SIGINT was generated
+ by C-g, so we call handle_interrupt. Otherwise, the handler kills
+ Emacs. */
static SIGTYPE
interrupt_signal (signalnum) /* If we don't have an argument, */
internal_last_event_frame = display->display_info.tty->top_frame;
handle_interrupt ();
-
}
errno = old_errno;
}
-/* C-g processing, signal independent code.
+/* This routine is called at interrupt level in response to C-g.
+
+ It is called from the SIGINT handler or kbd_buffer_store_event.
+
+ If `waiting_for_input' is non zero, then unless `echoing' is
+ nonzero, immediately throw back to read_char.
+
+ Otherwise it sets the Lisp variable quit-flag not-nil. This causes
+ eval to throw, when it gets a chance. If quit-flag is already
+ non-nil, it stops the job right away. */
- XXX Expand this comment. */
static void
handle_interrupt ()
{
recent_keys_index = 0;
kbd_fetch_ptr = kbd_buffer;
kbd_store_ptr = kbd_buffer;
- kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
#ifdef HAVE_MOUSE
do_mouse_tracking = Qnil;
#endif
Fset (Qextended_command_history, Qnil);
staticpro (&Qextended_command_history);
- kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
- staticpro (&kbd_buffer_gcpro);
-
accent_key_syms = Qnil;
staticpro (&accent_key_syms);