If kbd_buffer is becoming full, stop reading until it drains (Bug#6571).

* keyboard.c (input_available_signal): Declare.
(kbd_buffer_nr_stored): New function.
(kbd_buffer_store_event_hold): If kbd_buffer_nr_stored returns
more than KBD_BUFFER_SIZE/2, stop reding input (Bug#6571).
(kbd_buffer_get_event): If input is suspended and kbd_buffer_nr_stored
returns less than KBD_BUFFER_SIZE/4, resume reding input (Bug#6571).
(tty_read_avail_input): If input is on hold, return.
Don't read more that free slots in kbd_buffer (Bug#6571).

* process.h (hold_keyboard_input, unhold_keyboard_input)
(kbd_on_hold_p): Declare.

* process.c (kbd_is_on_hold): New variable.
(hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): New
functions.
(wait_reading_process_output): If kbd_on_hold_p returns non-zero,
select on empty input mask.
(init_process): Initialize kbd_is_on_hold to 0.
This commit is contained in:
Jan D 2010-07-07 19:39:49 +02:00
parent 3a8ce82256
commit cb768704a4
4 changed files with 105 additions and 2 deletions

View file

@ -1,3 +1,24 @@
2010-07-07 Jan Djärv <jan.h.d@swipnet.se>
* process.c (kbd_is_on_hold): New variable.
(hold_keyboard_input, unhold_keyboard_input, kbd_on_hold_p): New
functions.
(wait_reading_process_output): If kbd_on_hold_p returns non-zero,
select on empty input mask.
(init_process): Initialize kbd_is_on_hold to 0.
* process.h (hold_keyboard_input, unhold_keyboard_input)
(kbd_on_hold_p): Declare.
* keyboard.c (input_available_signal): Declare.
(kbd_buffer_nr_stored): New function.
(kbd_buffer_store_event_hold): If kbd_buffer_nr_stored returns
more than KBD_BUFFER_SIZE/2, stop reding input (Bug#6571).
(kbd_buffer_get_event): If input is suspended and kbd_buffer_nr_stored
returns less than KBD_BUFFER_SIZE/4, resume reding input (Bug#6571).
(tty_read_avail_input): If input is on hold, return.
Don't read more that free slots in kbd_buffer (Bug#6571).
2010-07-07 Eli Zaretskii <eliz@gnu.org>
* msdos.h:

View file

@ -635,6 +635,7 @@ static Lisp_Object apply_modifiers (int, Lisp_Object);
static void clear_event (struct input_event *);
static Lisp_Object restore_kboard_configuration (Lisp_Object);
static SIGTYPE interrupt_signal (int signalnum);
static SIGTYPE input_available_signal (int signo);
static void handle_interrupt (void);
static void timer_start_idle (void);
static void timer_stop_idle (void);
@ -3590,6 +3591,18 @@ event_to_kboard (struct input_event *event)
return FRAME_KBOARD (XFRAME (frame));
}
/* Return the number of slots occupied in kbd_buffer. */
static int
kbd_buffer_nr_stored ()
{
return kbd_fetch_ptr == kbd_store_ptr
? 0
: (kbd_fetch_ptr < kbd_store_ptr
? kbd_store_ptr - kbd_fetch_ptr
: ((kbd_buffer + KBD_BUFFER_SIZE) - kbd_fetch_ptr
+ (kbd_store_ptr - kbd_buffer)));
}
Lisp_Object Vthrow_on_input;
@ -3711,6 +3724,17 @@ kbd_buffer_store_event_hold (register struct input_event *event,
{
*kbd_store_ptr = *event;
++kbd_store_ptr;
if (kbd_buffer_nr_stored () > KBD_BUFFER_SIZE/2 && ! kbd_on_hold_p ())
{
/* Don't read keyboard input until we have processed kbd_buffer.
This happens when pasting text longer than KBD_BUFFER_SIZE/2. */
hold_keyboard_input ();
#ifdef SIGIO
if (!noninteractive)
signal (SIGIO, SIG_IGN);
#endif
stop_polling ();
}
}
/* If we're inside while-no-input, and this event qualifies
@ -3866,10 +3890,24 @@ clear_event (struct input_event *event)
We always read and discard one event. */
static Lisp_Object
kbd_buffer_get_event (KBOARD **kbp, int *used_mouse_menu, struct timeval *end_time)
kbd_buffer_get_event (KBOARD **kbp,
int *used_mouse_menu,
struct timeval *end_time)
{
register int c;
Lisp_Object obj;
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE/4)
{
/* Start reading input again, we have processed enough so we can
accept new events again. */
unhold_keyboard_input ();
#ifdef SIGIO
if (!noninteractive)
signal (SIGIO, input_available_signal);
#endif /* SIGIO */
start_polling ();
}
if (noninteractive
/* In case we are running as a daemon, only do this before
@ -7039,6 +7077,10 @@ tty_read_avail_input (struct terminal *terminal,
int n_to_read, i;
struct tty_display_info *tty = terminal->display_info.tty;
int nread = 0;
int buffer_free = KBD_BUFFER_SIZE - kbd_buffer_nr_stored () - 1;
if (kbd_on_hold_p () || buffer_free <= 0)
return 0;
if (!terminal->name) /* Don't read from a dead terminal. */
return 0;
@ -7120,6 +7162,10 @@ tty_read_avail_input (struct terminal *terminal,
#endif
#endif
/* Don't read more than we can store. */
if (n_to_read > buffer_free)
n_to_read = buffer_free;
/* Now read; for one reason or another, this will not block.
NREAD is set to the number of chars read. */
do

View file

@ -306,6 +306,10 @@ extern int timers_run;
static SELECT_TYPE input_wait_mask;
/* Non-zero if keyboard input is on hold, zero otherwise. */
static int kbd_is_on_hold;
/* Mask that excludes keyboard input descriptor(s). */
static SELECT_TYPE non_keyboard_wait_mask;
@ -4731,7 +4735,10 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
SELECT_TYPE Ctemp;
#endif
Atemp = input_wait_mask;
if (kbd_on_hold_p ())
FD_ZERO (&Atemp);
else
Atemp = input_wait_mask;
IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
EMACS_SET_SECS_USECS (timeout, 0, 0);
@ -7010,6 +7017,30 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p,
/* Stop reading input from keyboard sources. */
void
hold_keyboard_input (void)
{
kbd_is_on_hold = 1;
}
/* Resume reading input from keyboard sources. */
void
unhold_keyboard_input (void)
{
kbd_is_on_hold = 0;
}
/* Return non-zero if keyboard input is on hold, zero otherwise. */
int
kbd_on_hold_p (void)
{
return kbd_is_on_hold;
}
/* Add DESC to the set of keyboard input descriptors. */
void
@ -7901,6 +7932,7 @@ integer or floating point values.
void
init_process ()
{
kbd_is_on_hold = 0;
}
void

View file

@ -170,5 +170,9 @@ extern Lisp_Object Qtime, Qctime;
extern Lisp_Object list_system_processes (void);
extern Lisp_Object system_process_attributes (Lisp_Object);
extern void hold_keyboard_input (void);
extern void unhold_keyboard_input (void);
extern int kbd_on_hold_p (void);
/* arch-tag: dffedfc4-d7bc-4b58-a26f-c16155449c72
(do not change this comment) */