1 /* The event_stream interface for tty's.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995 Ben Wing.
6 This file is part of SXEmacs
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 /* Synched up with: Not in FSF. */
27 #include "ui/device.h"
28 #include "console-tty.h"
29 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
30 #include "events/events.h"
38 /* Mask of bits indicating the descriptors that we wait for input on */
39 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
40 extern SELECT_TYPE process_only_mask, tty_only_mask;
42 static struct event_stream *tty_event_stream;
44 /************************************************************************/
46 /************************************************************************/
48 /* The pending timers are stored in an ordered list, where the first timer
49 on the list is the first one to fire. Times recorded here are
51 static struct low_level_timeout *tty_timer_queue;
52 static Lisp_Object dispatch_event_queue;
53 static Lisp_Object SXE_UNUSED(dispatch_event_queue_tail);
54 static int last_quit_check_signal_tick_count;
57 emacs_tty_add_timeout(EMACS_TIME thyme)
59 return add_low_level_timeout(&tty_timer_queue, thyme);
63 emacs_tty_remove_timeout(int id)
65 remove_low_level_timeout(&tty_timer_queue, id);
69 tty_timeout_to_emacs_event(Lisp_Event * emacs_event)
71 emacs_event->event_type = timeout_event;
72 /* timeout events have nil as channel */
73 emacs_event->timestamp = 0; /* #### */
74 emacs_event->event.timeout.interval_id =
75 pop_low_level_timeout(&tty_timer_queue, 0);
76 emacs_event->event.timeout.function = Qnil;
77 emacs_event->event.timeout.object = Qnil;
81 emacs_tty_event_pending_p(int user_p)
89 /* (1) Any pending events in the dispatch queue? */
90 if (!NILP(dispatch_event_queue))
93 /* (2) Any TTY or process input available? */
94 if (poll_fds_for_input (non_fake_input_wait_mask))
97 /* (3) Any timeout input available? */
98 EMACS_GET_TIME(sometime);
99 if (tty_timer_queue &&
100 EMACS_TIME_EQUAL_OR_GREATER(sometime,
101 tty_timer_queue->time))
105 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
107 if (command_event_p (event))
113 tick_val = quit_check_signal_tick_count;
115 if (last_quit_check_signal_tick_count != tick_val)
117 last_quit_check_signal_tick_count = tick_val;
118 /* We need to drain the entire queue now -- if we only drain part of
119 it, we may later on end up with events actually pending but
120 detect_input_pending() returning false because there wasn't
123 event_stream_drain_queue ();
127 return !NILP (dispatch_event_queue);
129 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
131 if (command_event_p (event))
135 return poll_fds_for_input(user_p ? tty_only_mask :
136 non_fake_input_wait_mask);
140 tty_find_console_from_fd(int fd)
144 CONSOLE_LOOP(concons) {
147 c = XCONSOLE(XCAR(concons));
148 if (CONSOLE_TTY_P(c) && CONSOLE_TTY_DATA(c)->infd == fd)
156 emacs_tty_next_event(Lisp_Event * emacs_event)
160 SELECT_TYPE temp_mask;
161 EMACS_TIME time_to_block;
162 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;
167 /* Wait for some event */
169 temp_mask = input_wait_mask;
171 if (!get_low_level_timeout_interval(tty_timer_queue, &time_to_block))
172 /* no timer events; block indefinitely */
175 EMACS_TIME_TO_SELECT_TIME(time_to_block, select_time_to_block);
176 pointer_to_this = &select_time_to_block;
179 ndesc = select(MAXDESC, &temp_mask, 0, 0, pointer_to_this);
181 tty_timeout_to_emacs_event(emacs_event);
183 } else if (ndesc > 0)
187 /* Look for a TTY event */
188 for (i = 0; i < MAXDESC; i++) {
189 /* To avoid race conditions (among other things, an infinite
190 loop when called from Fdiscard_input()), we must return
191 user events ahead of process events. */
192 if (!FD_ISSET(i, &temp_mask) || !FD_ISSET(i, &tty_only_mask))
195 c = tty_find_console_from_fd(i);
197 if (read_event_from_tty_or_stream_desc(emacs_event, c, i))
201 /* Look for a process event */
202 for (i = 0; i < MAXDESC; i++) {
203 if (!FD_ISSET(i, &temp_mask) || !FD_ISSET(i, &process_only_mask))
206 p = get_process_from_usid(FD_TO_USID(i));
209 XSETPROCESS(emacs_event->event.process.process, p);
210 emacs_event->event_type = process_event;
211 /* process events have nil as channel */
212 emacs_event->timestamp = 0; /* #### */
216 /* We might get here when a fake event came through a signal. */
217 /* Return a dummy event, so that a cycle of the command loop will
219 drain_signal_event_pipe();
220 emacs_event->event_type = eval_event;
221 /* eval events have nil as channel */
222 emacs_event->event.eval.function = Qidentity;
223 emacs_event->event.eval.object = Qnil;
227 emacs_tty_handle_magic_event(Lisp_Event * emacs_event)
229 /* Nothing to do currently */
233 emacs_tty_select_process(Lisp_Process * process)
235 event_stream_unixoid_select_process(process);
239 emacs_tty_unselect_process(Lisp_Process * process)
241 event_stream_unixoid_unselect_process(process);
245 emacs_tty_select_console(struct console *con)
247 event_stream_unixoid_select_console(con);
251 emacs_tty_unselect_console(struct console *con)
253 event_stream_unixoid_unselect_console(con);
257 emacs_tty_quit_p(void)
259 /* Nothing to do currently because QUIT is handled through SIGINT.
260 This could change. */
264 emacs_tty_create_stream_pair(void *inhandle, void *outhandle,
265 Lisp_Object * instream, Lisp_Object * outstream,
268 return event_stream_unixoid_create_stream_pair
269 (inhandle, outhandle, instream, outstream, flags);
273 emacs_tty_delete_stream_pair(Lisp_Object instream, Lisp_Object outstream)
275 return event_stream_unixoid_delete_stream_pair(instream, outstream);
278 /************************************************************************/
280 /************************************************************************/
283 reinit_vars_of_event_tty(void)
285 tty_event_stream = xnew(struct event_stream);
287 tty_event_stream->event_pending_p = emacs_tty_event_pending_p;
288 tty_event_stream->force_event_pending = 0;
289 tty_event_stream->next_event_cb = emacs_tty_next_event;
290 tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event;
291 tty_event_stream->add_timeout_cb = emacs_tty_add_timeout;
292 tty_event_stream->remove_timeout_cb = emacs_tty_remove_timeout;
293 tty_event_stream->select_console_cb = emacs_tty_select_console;
294 tty_event_stream->unselect_console_cb = emacs_tty_unselect_console;
295 tty_event_stream->select_process_cb = emacs_tty_select_process;
296 tty_event_stream->unselect_process_cb = emacs_tty_unselect_process;
297 tty_event_stream->quit_p_cb = emacs_tty_quit_p;
298 tty_event_stream->create_stream_pair_cb = emacs_tty_create_stream_pair;
299 tty_event_stream->delete_stream_pair_cb = emacs_tty_delete_stream_pair;
301 last_quit_check_signal_tick_count = 0;
305 vars_of_event_tty(void)
307 reinit_vars_of_event_tty();
309 dispatch_event_queue = Qnil;
310 staticpro(&dispatch_event_queue);
314 init_event_tty_late(void)
316 event_stream = tty_event_stream;