Mercurial > hg > xemacs-beta
annotate src/event-tty.c @ 5580:a0e81357194e
Move macros with shadows in bytecomp.el to the end of the files, cl-macs
lisp/ChangeLog addition:
2011-10-08 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el:
* cl-macs.el (load-time-value):
* cl-macs.el (flet):
* cl-macs.el (labels):
* cl-macs.el (the):
* cl-macs.el (declare):
Move all these macros to the end of the file, since they're in
byte-compile-initial-macro-environment, and we don't want their
definitions to override that for the rest of the file during
byte-compilation. Happens not to matter right now, but avoids
surprises for anyone using the macros elsewhere in cl-macs down
the line.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 08 Oct 2011 12:26:09 +0100 |
parents | 308d34e9f07d |
children |
rev | line source |
---|---|
428 | 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. | |
1268 | 4 Copyright (C) 1995, 2002, 2003 Ben Wing. |
428 | 5 |
6 This file is part of XEmacs. | |
7 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3735
diff
changeset
|
8 XEmacs is free software: you can redistribute it and/or modify it |
428 | 9 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3735
diff
changeset
|
10 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3735
diff
changeset
|
11 option) any later version. |
428 | 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 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3735
diff
changeset
|
19 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 20 |
21 /* Synched up with: Not in FSF. */ | |
22 | |
23 #include <config.h> | |
24 #include "lisp.h" | |
25 | |
26 #include "device.h" | |
872 | 27 #include "console-tty-impl.h" |
428 | 28 #include "events.h" |
29 #include "frame.h" | |
30 #include "process.h" | |
31 | |
32 #include "sysproc.h" | |
33 #include "syswait.h" | |
34 #include "systime.h" | |
35 | |
36 /* Mask of bits indicating the descriptors that we wait for input on */ | |
37 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask; | |
38 extern SELECT_TYPE process_only_mask, tty_only_mask; | |
39 | |
40 static struct event_stream *tty_event_stream; | |
41 | |
1292 | 42 #ifdef WIN32_ANY |
43 extern int mswindows_is_blocking; | |
44 #endif | |
45 | |
3735 | 46 static int last_quit_check_signal_tick_count; |
47 | |
428 | 48 |
49 /************************************************************************/ | |
50 /* timeout events */ | |
51 /************************************************************************/ | |
52 | |
53 /* The pending timers are stored in an ordered list, where the first timer | |
54 on the list is the first one to fire. Times recorded here are | |
55 absolute. */ | |
56 static struct low_level_timeout *tty_timer_queue; | |
57 | |
58 static int | |
59 emacs_tty_add_timeout (EMACS_TIME thyme) | |
60 { | |
61 return add_low_level_timeout (&tty_timer_queue, thyme); | |
62 } | |
63 | |
64 static void | |
65 emacs_tty_remove_timeout (int id) | |
66 { | |
67 remove_low_level_timeout (&tty_timer_queue, id); | |
68 } | |
69 | |
70 static void | |
440 | 71 tty_timeout_to_emacs_event (Lisp_Event *emacs_event) |
428 | 72 { |
934 | 73 /* timeout events have nil as channel */ |
74 SET_EVENT_TYPE (emacs_event, timeout_event); | |
75 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */ | |
1268 | 76 SET_EVENT_TIMEOUT_INTERVAL_ID (emacs_event, |
77 pop_low_level_timeout (&tty_timer_queue, 0)); | |
1204 | 78 SET_EVENT_TIMEOUT_FUNCTION (emacs_event, Qnil); |
79 SET_EVENT_TIMEOUT_OBJECT (emacs_event, Qnil); | |
428 | 80 } |
81 | |
82 | |
83 | |
84 static int | |
1268 | 85 emacs_tty_event_pending_p (int how_many) |
428 | 86 { |
3735 | 87 Lisp_Object event; |
88 int tick_count_val; | |
89 | |
90 /* Cf. the comments on emacs_Xt_event_pending_p in event-xlike-inc.c . */ | |
91 | |
1268 | 92 if (!how_many) |
428 | 93 { |
94 EMACS_TIME sometime; | |
3735 | 95 |
96 /* (1) Any pending events in the dispatch queue? */ | |
97 if (!NILP(dispatch_event_queue)) | |
98 { | |
99 return 1; | |
100 } | |
101 | |
102 /* (2) Any TTY or process input available? */ | |
103 if (poll_fds_for_input (non_fake_input_wait_mask)) | |
104 return 1; | |
105 | |
106 /* (3) Any timeout input available? */ | |
428 | 107 EMACS_GET_TIME (sometime); |
108 if (tty_timer_queue && | |
109 EMACS_TIME_EQUAL_OR_GREATER (sometime, tty_timer_queue->time)) | |
110 return 1; | |
3735 | 111 } |
112 else | |
113 { | |
114 /* HOW_MANY > 0 */ | |
115 EVENT_CHAIN_LOOP (event, dispatch_event_queue) | |
116 { | |
117 if (command_event_p (event)) | |
118 { | |
119 how_many--; | |
120 if (how_many <= 0) | |
121 return 1; | |
122 } | |
123 } | |
1268 | 124 |
428 | 125 } |
126 | |
3735 | 127 tick_count_val = quit_check_signal_tick_count; |
128 | |
129 /* Checking in_modal_loop here is a bit cargo-cultish, since its use is | |
130 specific to builds with a window system. */ | |
131 if (!in_modal_loop && | |
132 (last_quit_check_signal_tick_count != tick_count_val)) | |
133 { | |
134 last_quit_check_signal_tick_count = tick_count_val; | |
135 | |
136 /* We need to drain the entire queue now -- if we only drain part of | |
137 it, we may later on end up with events actually pending but | |
138 detect_input_pending() returning false because there wasn't | |
139 another SIGIO. */ | |
140 event_stream_drain_queue (); | |
141 | |
142 if (!how_many) | |
143 return !NILP (dispatch_event_queue); | |
144 | |
145 EVENT_CHAIN_LOOP (event, dispatch_event_queue) | |
146 { | |
147 if (command_event_p (event)) | |
148 { | |
149 how_many--; | |
150 if (how_many <= 0) | |
151 return 1; | |
152 } | |
153 } | |
154 } | |
155 | |
156 return 0; | |
428 | 157 } |
158 | |
159 static void | |
440 | 160 emacs_tty_next_event (Lisp_Event *emacs_event) |
428 | 161 { |
162 while (1) | |
163 { | |
164 int ndesc; | |
165 int i; | |
166 SELECT_TYPE temp_mask = input_wait_mask; | |
167 EMACS_TIME time_to_block; | |
168 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this; | |
169 | |
3541 | 170 if (!NILP (dispatch_event_queue)) |
171 { | |
172 Lisp_Object event, event2; | |
173 event2 = wrap_event (emacs_event); | |
174 event = dequeue_dispatch_event (); | |
175 Fcopy_event (event, event2); | |
176 Fdeallocate_event (event); | |
177 return; | |
178 } | |
179 | |
428 | 180 if (!get_low_level_timeout_interval (tty_timer_queue, &time_to_block)) |
181 /* no timer events; block indefinitely */ | |
182 pointer_to_this = 0; | |
183 else | |
184 { | |
185 EMACS_TIME_TO_SELECT_TIME (time_to_block, select_time_to_block); | |
186 pointer_to_this = &select_time_to_block; | |
187 } | |
188 | |
1292 | 189 #ifdef WIN32_ANY |
190 mswindows_is_blocking = 1; | |
191 #endif | |
428 | 192 ndesc = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this); |
1292 | 193 #ifdef WIN32_ANY |
194 mswindows_is_blocking = 0; | |
195 #endif | |
428 | 196 if (ndesc > 0) |
197 { | |
198 /* Look for a TTY event */ | |
199 for (i = 0; i < MAXDESC; i++) | |
200 { | |
201 /* To avoid race conditions (among other things, an infinite | |
202 loop when called from Fdiscard_input()), we must return | |
203 user events ahead of process events. */ | |
204 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) | |
205 { | |
1204 | 206 struct console *c = find_tty_or_stream_console_from_fd (i); |
428 | 207 |
208 assert (c); | |
771 | 209 if (read_event_from_tty_or_stream_desc (emacs_event, c)) |
428 | 210 return; |
211 } | |
212 } | |
213 | |
214 /* Look for a process event */ | |
215 for (i = 0; i < MAXDESC; i++) | |
216 { | |
217 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &process_only_mask)) | |
218 { | |
219 Lisp_Object process; | |
440 | 220 Lisp_Process *p = get_process_from_usid (FD_TO_USID(i)); |
428 | 221 |
222 assert (p); | |
793 | 223 process = wrap_process (p); |
934 | 224 set_event_type (emacs_event, process_event); |
225 /* process events have nil as channel */ | |
226 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */ | |
1204 | 227 SET_EVENT_PROCESS_PROCESS (emacs_event, process); |
428 | 228 return; |
229 } | |
230 } | |
231 | |
232 /* We might get here when a fake event came through a signal. */ | |
233 /* Return a dummy event, so that a cycle of the command loop will | |
234 occur. */ | |
235 drain_signal_event_pipe (); | |
934 | 236 set_event_type (emacs_event, eval_event); |
237 /* eval events have nil as channel */ | |
1204 | 238 SET_EVENT_EVAL_FUNCTION (emacs_event, Qidentity); |
239 SET_EVENT_EVAL_OBJECT (emacs_event, Qnil); | |
428 | 240 return; |
241 } | |
242 else if (ndesc == 0) /* timeout fired */ | |
243 { | |
244 tty_timeout_to_emacs_event (emacs_event); | |
245 return; | |
246 } | |
247 } | |
248 } | |
249 | |
250 static void | |
2286 | 251 emacs_tty_format_magic_event (Lisp_Event *UNUSED (emacs_event), |
252 Lisp_Object UNUSED (pstream)) | |
788 | 253 { |
254 /* Nothing to do currently */ | |
255 } | |
256 | |
257 static int | |
2286 | 258 emacs_tty_compare_magic_event (Lisp_Event *UNUSED (e1), |
259 Lisp_Event *UNUSED (e2)) | |
788 | 260 { |
261 return 1; | |
262 } | |
263 | |
264 static Hashcode | |
2286 | 265 emacs_tty_hash_magic_event (Lisp_Event *UNUSED (e)) |
788 | 266 { |
267 return 0; | |
268 } | |
269 | |
270 static void | |
2286 | 271 emacs_tty_handle_magic_event (Lisp_Event *UNUSED (emacs_event)) |
428 | 272 { |
273 /* Nothing to do currently */ | |
274 } | |
275 | |
276 | |
277 static void | |
853 | 278 emacs_tty_select_process (Lisp_Process *process, int doin, int doerr) |
428 | 279 { |
853 | 280 int infd, errfd; |
281 | |
282 event_stream_unixoid_select_process (process, doin, doerr, &infd, &errfd); | |
428 | 283 } |
284 | |
285 static void | |
853 | 286 emacs_tty_unselect_process (Lisp_Process *process, int doin, int doerr) |
428 | 287 { |
853 | 288 int infd, errfd; |
289 | |
290 event_stream_unixoid_unselect_process (process, doin, doerr, &infd, &errfd); | |
428 | 291 } |
292 | |
293 static void | |
294 emacs_tty_select_console (struct console *con) | |
295 { | |
296 event_stream_unixoid_select_console (con); | |
297 } | |
298 | |
299 static void | |
300 emacs_tty_unselect_console (struct console *con) | |
301 { | |
302 event_stream_unixoid_unselect_console (con); | |
303 } | |
304 | |
305 static void | |
1204 | 306 emacs_tty_drain_queue (void) |
428 | 307 { |
1204 | 308 drain_tty_devices (); |
428 | 309 } |
310 | |
853 | 311 static void |
312 emacs_tty_create_io_streams (void* inhandle, void* outhandle, | |
313 void *errhandle, Lisp_Object* instream, | |
314 Lisp_Object* outstream, | |
315 Lisp_Object* errstream, | |
316 USID* in_usid, | |
317 USID* err_usid, | |
318 int flags) | |
428 | 319 { |
853 | 320 event_stream_unixoid_create_io_streams |
321 (inhandle, outhandle, errhandle, instream, outstream, | |
322 errstream, in_usid, err_usid, flags); | |
428 | 323 } |
324 | |
853 | 325 static void |
326 emacs_tty_delete_io_streams (Lisp_Object instream, | |
327 Lisp_Object outstream, | |
328 Lisp_Object errstream, | |
329 USID* in_usid, | |
330 USID* err_usid) | |
428 | 331 { |
853 | 332 event_stream_unixoid_delete_io_streams |
333 (instream, outstream, errstream, in_usid, err_usid); | |
428 | 334 } |
335 | |
336 | |
337 /************************************************************************/ | |
338 /* initialization */ | |
339 /************************************************************************/ | |
340 | |
341 void | |
342 reinit_vars_of_event_tty (void) | |
343 { | |
1204 | 344 tty_event_stream = xnew_and_zero (struct event_stream); |
428 | 345 |
346 tty_event_stream->event_pending_p = emacs_tty_event_pending_p; | |
347 tty_event_stream->next_event_cb = emacs_tty_next_event; | |
348 tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event; | |
788 | 349 tty_event_stream->format_magic_event_cb = emacs_tty_format_magic_event; |
350 tty_event_stream->compare_magic_event_cb= emacs_tty_compare_magic_event; | |
351 tty_event_stream->hash_magic_event_cb = emacs_tty_hash_magic_event; | |
428 | 352 tty_event_stream->add_timeout_cb = emacs_tty_add_timeout; |
353 tty_event_stream->remove_timeout_cb = emacs_tty_remove_timeout; | |
354 tty_event_stream->select_console_cb = emacs_tty_select_console; | |
355 tty_event_stream->unselect_console_cb = emacs_tty_unselect_console; | |
356 tty_event_stream->select_process_cb = emacs_tty_select_process; | |
357 tty_event_stream->unselect_process_cb = emacs_tty_unselect_process; | |
1204 | 358 tty_event_stream->drain_queue_cb = emacs_tty_drain_queue; |
853 | 359 tty_event_stream->create_io_streams_cb = emacs_tty_create_io_streams; |
360 tty_event_stream->delete_io_streams_cb = emacs_tty_delete_io_streams; | |
3735 | 361 |
362 last_quit_check_signal_tick_count = 0; | |
428 | 363 } |
364 | |
365 void | |
366 vars_of_event_tty (void) | |
367 { | |
368 } | |
369 | |
370 void | |
371 init_event_tty_late (void) | |
372 { | |
373 event_stream = tty_event_stream; | |
374 } |