Mercurial > hg > xemacs-beta
comparison src/event-tty.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 8de8e3f6228a |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
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. | |
5 | |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 #include <config.h> | |
26 #include "lisp.h" | |
27 | |
28 #include "device.h" | |
29 #include "console-tty.h" | |
30 #include "events.h" | |
31 #include "frame.h" | |
32 #include "process.h" | |
33 | |
34 #include "sysproc.h" | |
35 #include "syswait.h" | |
36 #include "systime.h" | |
37 | |
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; | |
41 | |
42 static struct event_stream *tty_event_stream; | |
43 | |
44 | |
45 /************************************************************************/ | |
46 /* timeout events */ | |
47 /************************************************************************/ | |
48 | |
49 /* The pending timers are stored in an ordered list, where the first timer | |
50 on the list is the first one to fire. Times recorded here are | |
51 absolute. */ | |
52 static struct low_level_timeout *tty_timer_queue; | |
53 | |
54 static int | |
55 emacs_tty_add_timeout (EMACS_TIME thyme) | |
56 { | |
57 return add_low_level_timeout (&tty_timer_queue, thyme); | |
58 } | |
59 | |
60 static void | |
61 emacs_tty_remove_timeout (int id) | |
62 { | |
63 remove_low_level_timeout (&tty_timer_queue, id); | |
64 } | |
65 | |
66 static void | |
67 tty_timeout_to_emacs_event (struct Lisp_Event *emacs_event) | |
68 { | |
69 emacs_event->event_type = timeout_event; | |
70 /* timeout events have nil as channel */ | |
71 emacs_event->timestamp = 0; /* #### */ | |
72 emacs_event->event.timeout.interval_id = | |
73 pop_low_level_timeout (&tty_timer_queue, 0); | |
74 emacs_event->event.timeout.function = Qnil; | |
75 emacs_event->event.timeout.object = Qnil; | |
76 } | |
77 | |
78 | |
79 | |
80 static int | |
81 emacs_tty_event_pending_p (int user_p) | |
82 { | |
83 if (!user_p) | |
84 { | |
85 EMACS_TIME sometime; | |
86 /* see if there's a pending timeout. */ | |
87 EMACS_GET_TIME (sometime); | |
88 if (tty_timer_queue && | |
89 EMACS_TIME_EQUAL_OR_GREATER (sometime, tty_timer_queue->time)) | |
90 return 1; | |
91 } | |
92 | |
93 return poll_fds_for_input (user_p ? tty_only_mask : | |
94 non_fake_input_wait_mask); | |
95 } | |
96 | |
97 struct console * | |
98 tty_find_console_from_fd (int fd) | |
99 { | |
100 Lisp_Object concons; | |
101 | |
102 CONSOLE_LOOP (concons) | |
103 { | |
104 struct console *c; | |
105 | |
106 c = XCONSOLE (XCAR (concons)); | |
107 if (CONSOLE_TTY_P (c) && CONSOLE_TTY_DATA (c)->infd == fd) | |
108 return c; | |
109 } | |
110 | |
111 return 0; | |
112 } | |
113 | |
114 static void | |
115 emacs_tty_next_event (struct Lisp_Event *emacs_event) | |
116 { | |
117 while (1) | |
118 { | |
119 int ndesc; | |
120 int i; | |
121 SELECT_TYPE temp_mask = input_wait_mask; | |
122 EMACS_TIME time_to_block; | |
123 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this; | |
124 | |
125 if (!get_low_level_timeout_interval (tty_timer_queue, &time_to_block)) | |
126 /* no timer events; block indefinitely */ | |
127 pointer_to_this = 0; | |
128 else | |
129 { | |
130 EMACS_TIME_TO_SELECT_TIME (time_to_block, select_time_to_block); | |
131 pointer_to_this = &select_time_to_block; | |
132 } | |
133 | |
134 ndesc = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this); | |
135 if (ndesc > 0) | |
136 { | |
137 /* Look for a TTY event */ | |
138 for (i = 0; i < MAXDESC; i++) | |
139 { | |
140 /* To avoid race conditions (among other things, an infinite | |
141 loop when called from Fdiscard_input()), we must return | |
142 user events ahead of process events. */ | |
143 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) | |
144 { | |
145 struct console *c = tty_find_console_from_fd (i); | |
146 | |
147 assert (c); | |
148 if (read_event_from_tty_or_stream_desc (emacs_event, c, i)) | |
149 return; | |
150 } | |
151 } | |
152 | |
153 /* Look for a process event */ | |
154 for (i = 0; i < MAXDESC; i++) | |
155 { | |
156 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &process_only_mask)) | |
157 { | |
158 Lisp_Object process; | |
159 struct Lisp_Process *p = | |
160 get_process_from_usid (FD_TO_USID(i)); | |
161 | |
162 assert (p); | |
163 XSETPROCESS (process, p); | |
164 emacs_event->event_type = process_event; | |
165 /* process events have nil as channel */ | |
166 emacs_event->timestamp = 0; /* #### */ | |
167 emacs_event->event.process.process = process; | |
168 return; | |
169 } | |
170 } | |
171 | |
172 /* We might get here when a fake event came through a signal. */ | |
173 /* Return a dummy event, so that a cycle of the command loop will | |
174 occur. */ | |
175 drain_signal_event_pipe (); | |
176 emacs_event->event_type = eval_event; | |
177 /* eval events have nil as channel */ | |
178 emacs_event->event.eval.function = Qidentity; | |
179 emacs_event->event.eval.object = Qnil; | |
180 return; | |
181 } | |
182 else if (ndesc == 0) /* timeout fired */ | |
183 { | |
184 tty_timeout_to_emacs_event (emacs_event); | |
185 return; | |
186 } | |
187 } | |
188 } | |
189 | |
190 static void | |
191 emacs_tty_handle_magic_event (struct Lisp_Event *emacs_event) | |
192 { | |
193 /* Nothing to do currently */ | |
194 } | |
195 | |
196 | |
197 static void | |
198 emacs_tty_select_process (struct Lisp_Process *process) | |
199 { | |
200 event_stream_unixoid_select_process (process); | |
201 } | |
202 | |
203 static void | |
204 emacs_tty_unselect_process (struct Lisp_Process *process) | |
205 { | |
206 event_stream_unixoid_unselect_process (process); | |
207 } | |
208 | |
209 static void | |
210 emacs_tty_select_console (struct console *con) | |
211 { | |
212 event_stream_unixoid_select_console (con); | |
213 } | |
214 | |
215 static void | |
216 emacs_tty_unselect_console (struct console *con) | |
217 { | |
218 event_stream_unixoid_unselect_console (con); | |
219 } | |
220 | |
221 static void | |
222 emacs_tty_quit_p (void) | |
223 { | |
224 /* Nothing to do currently because QUIT is handled through SIGINT. | |
225 This could change. */ | |
226 } | |
227 | |
228 static USID | |
229 emacs_tty_create_stream_pair (void* inhandle, void* outhandle, | |
230 Lisp_Object* instream, Lisp_Object* outstream, int flags) | |
231 { | |
232 return event_stream_unixoid_create_stream_pair | |
233 (inhandle, outhandle, instream, outstream, flags); | |
234 } | |
235 | |
236 static USID | |
237 emacs_tty_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream) | |
238 { | |
239 return event_stream_unixoid_delete_stream_pair (instream, outstream); | |
240 } | |
241 | |
242 | |
243 /************************************************************************/ | |
244 /* initialization */ | |
245 /************************************************************************/ | |
246 | |
247 void | |
248 reinit_vars_of_event_tty (void) | |
249 { | |
250 tty_event_stream = xnew (struct event_stream); | |
251 | |
252 tty_event_stream->event_pending_p = emacs_tty_event_pending_p; | |
253 tty_event_stream->next_event_cb = emacs_tty_next_event; | |
254 tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event; | |
255 tty_event_stream->add_timeout_cb = emacs_tty_add_timeout; | |
256 tty_event_stream->remove_timeout_cb = emacs_tty_remove_timeout; | |
257 tty_event_stream->select_console_cb = emacs_tty_select_console; | |
258 tty_event_stream->unselect_console_cb = emacs_tty_unselect_console; | |
259 tty_event_stream->select_process_cb = emacs_tty_select_process; | |
260 tty_event_stream->unselect_process_cb = emacs_tty_unselect_process; | |
261 tty_event_stream->quit_p_cb = emacs_tty_quit_p; | |
262 tty_event_stream->create_stream_pair_cb = emacs_tty_create_stream_pair; | |
263 tty_event_stream->delete_stream_pair_cb = emacs_tty_delete_stream_pair; | |
264 } | |
265 | |
266 void | |
267 vars_of_event_tty (void) | |
268 { | |
269 reinit_vars_of_event_tty (); | |
270 } | |
271 | |
272 void | |
273 init_event_tty_late (void) | |
274 { | |
275 event_stream = tty_event_stream; | |
276 } |