Mercurial > hg > xemacs-beta
annotate src/event-tty.c @ 5925:08cfc8f77fb6 cygwin
make space for long ptr, and store as such, for frame in WINDOW data,
add a bit more debugging to debug-mswindow,
Vin Shelton patch to fix M-x shell
| author | Henry Thompson <ht@markup.co.uk> |
|---|---|
| date | Fri, 27 Feb 2015 17:41:20 +0000 |
| 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 } |
