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
+ − 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"
872
+ − 29 #include "console-tty-impl.h"
428
+ − 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
1292
+ − 44 #ifdef WIN32_ANY
+ − 45 extern int mswindows_is_blocking;
+ − 46 #endif
+ − 47
3735
+ − 48 static int last_quit_check_signal_tick_count;
+ − 49
428
+ − 50
+ − 51 /************************************************************************/
+ − 52 /* timeout events */
+ − 53 /************************************************************************/
+ − 54
+ − 55 /* The pending timers are stored in an ordered list, where the first timer
+ − 56 on the list is the first one to fire. Times recorded here are
+ − 57 absolute. */
+ − 58 static struct low_level_timeout *tty_timer_queue;
+ − 59
+ − 60 static int
+ − 61 emacs_tty_add_timeout (EMACS_TIME thyme)
+ − 62 {
+ − 63 return add_low_level_timeout (&tty_timer_queue, thyme);
+ − 64 }
+ − 65
+ − 66 static void
+ − 67 emacs_tty_remove_timeout (int id)
+ − 68 {
+ − 69 remove_low_level_timeout (&tty_timer_queue, id);
+ − 70 }
+ − 71
+ − 72 static void
440
+ − 73 tty_timeout_to_emacs_event (Lisp_Event *emacs_event)
428
+ − 74 {
934
+ − 75 /* timeout events have nil as channel */
+ − 76 SET_EVENT_TYPE (emacs_event, timeout_event);
+ − 77 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */
1268
+ − 78 SET_EVENT_TIMEOUT_INTERVAL_ID (emacs_event,
+ − 79 pop_low_level_timeout (&tty_timer_queue, 0));
1204
+ − 80 SET_EVENT_TIMEOUT_FUNCTION (emacs_event, Qnil);
+ − 81 SET_EVENT_TIMEOUT_OBJECT (emacs_event, Qnil);
428
+ − 82 }
+ − 83
+ − 84
+ − 85
+ − 86 static int
1268
+ − 87 emacs_tty_event_pending_p (int how_many)
428
+ − 88 {
3735
+ − 89 Lisp_Object event;
+ − 90 int tick_count_val;
+ − 91
+ − 92 /* Cf. the comments on emacs_Xt_event_pending_p in event-xlike-inc.c . */
+ − 93
1268
+ − 94 if (!how_many)
428
+ − 95 {
+ − 96 EMACS_TIME sometime;
3735
+ − 97
+ − 98 /* (1) Any pending events in the dispatch queue? */
+ − 99 if (!NILP(dispatch_event_queue))
+ − 100 {
+ − 101 return 1;
+ − 102 }
+ − 103
+ − 104 /* (2) Any TTY or process input available? */
+ − 105 if (poll_fds_for_input (non_fake_input_wait_mask))
+ − 106 return 1;
+ − 107
+ − 108 /* (3) Any timeout input available? */
428
+ − 109 EMACS_GET_TIME (sometime);
+ − 110 if (tty_timer_queue &&
+ − 111 EMACS_TIME_EQUAL_OR_GREATER (sometime, tty_timer_queue->time))
+ − 112 return 1;
3735
+ − 113 }
+ − 114 else
+ − 115 {
+ − 116 /* HOW_MANY > 0 */
+ − 117 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
+ − 118 {
+ − 119 if (command_event_p (event))
+ − 120 {
+ − 121 how_many--;
+ − 122 if (how_many <= 0)
+ − 123 return 1;
+ − 124 }
+ − 125 }
1268
+ − 126
428
+ − 127 }
+ − 128
3735
+ − 129 tick_count_val = quit_check_signal_tick_count;
+ − 130
+ − 131 /* Checking in_modal_loop here is a bit cargo-cultish, since its use is
+ − 132 specific to builds with a window system. */
+ − 133 if (!in_modal_loop &&
+ − 134 (last_quit_check_signal_tick_count != tick_count_val))
+ − 135 {
+ − 136 last_quit_check_signal_tick_count = tick_count_val;
+ − 137
+ − 138 /* We need to drain the entire queue now -- if we only drain part of
+ − 139 it, we may later on end up with events actually pending but
+ − 140 detect_input_pending() returning false because there wasn't
+ − 141 another SIGIO. */
+ − 142 event_stream_drain_queue ();
+ − 143
+ − 144 if (!how_many)
+ − 145 return !NILP (dispatch_event_queue);
+ − 146
+ − 147 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
+ − 148 {
+ − 149 if (command_event_p (event))
+ − 150 {
+ − 151 how_many--;
+ − 152 if (how_many <= 0)
+ − 153 return 1;
+ − 154 }
+ − 155 }
+ − 156 }
+ − 157
+ − 158 return 0;
428
+ − 159 }
+ − 160
+ − 161 static void
440
+ − 162 emacs_tty_next_event (Lisp_Event *emacs_event)
428
+ − 163 {
+ − 164 while (1)
+ − 165 {
+ − 166 int ndesc;
+ − 167 int i;
+ − 168 SELECT_TYPE temp_mask = input_wait_mask;
+ − 169 EMACS_TIME time_to_block;
+ − 170 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;
+ − 171
3541
+ − 172 if (!NILP (dispatch_event_queue))
+ − 173 {
+ − 174 Lisp_Object event, event2;
+ − 175 event2 = wrap_event (emacs_event);
+ − 176 event = dequeue_dispatch_event ();
+ − 177 Fcopy_event (event, event2);
+ − 178 Fdeallocate_event (event);
+ − 179 return;
+ − 180 }
+ − 181
428
+ − 182 if (!get_low_level_timeout_interval (tty_timer_queue, &time_to_block))
+ − 183 /* no timer events; block indefinitely */
+ − 184 pointer_to_this = 0;
+ − 185 else
+ − 186 {
+ − 187 EMACS_TIME_TO_SELECT_TIME (time_to_block, select_time_to_block);
+ − 188 pointer_to_this = &select_time_to_block;
+ − 189 }
+ − 190
1292
+ − 191 #ifdef WIN32_ANY
+ − 192 mswindows_is_blocking = 1;
+ − 193 #endif
428
+ − 194 ndesc = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
1292
+ − 195 #ifdef WIN32_ANY
+ − 196 mswindows_is_blocking = 0;
+ − 197 #endif
428
+ − 198 if (ndesc > 0)
+ − 199 {
+ − 200 /* Look for a TTY event */
+ − 201 for (i = 0; i < MAXDESC; i++)
+ − 202 {
+ − 203 /* To avoid race conditions (among other things, an infinite
+ − 204 loop when called from Fdiscard_input()), we must return
+ − 205 user events ahead of process events. */
+ − 206 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
+ − 207 {
1204
+ − 208 struct console *c = find_tty_or_stream_console_from_fd (i);
428
+ − 209
+ − 210 assert (c);
771
+ − 211 if (read_event_from_tty_or_stream_desc (emacs_event, c))
428
+ − 212 return;
+ − 213 }
+ − 214 }
+ − 215
+ − 216 /* Look for a process event */
+ − 217 for (i = 0; i < MAXDESC; i++)
+ − 218 {
+ − 219 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &process_only_mask))
+ − 220 {
+ − 221 Lisp_Object process;
440
+ − 222 Lisp_Process *p = get_process_from_usid (FD_TO_USID(i));
428
+ − 223
+ − 224 assert (p);
793
+ − 225 process = wrap_process (p);
934
+ − 226 set_event_type (emacs_event, process_event);
+ − 227 /* process events have nil as channel */
+ − 228 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */
1204
+ − 229 SET_EVENT_PROCESS_PROCESS (emacs_event, process);
428
+ − 230 return;
+ − 231 }
+ − 232 }
+ − 233
+ − 234 /* We might get here when a fake event came through a signal. */
+ − 235 /* Return a dummy event, so that a cycle of the command loop will
+ − 236 occur. */
+ − 237 drain_signal_event_pipe ();
934
+ − 238 set_event_type (emacs_event, eval_event);
+ − 239 /* eval events have nil as channel */
1204
+ − 240 SET_EVENT_EVAL_FUNCTION (emacs_event, Qidentity);
+ − 241 SET_EVENT_EVAL_OBJECT (emacs_event, Qnil);
428
+ − 242 return;
+ − 243 }
+ − 244 else if (ndesc == 0) /* timeout fired */
+ − 245 {
+ − 246 tty_timeout_to_emacs_event (emacs_event);
+ − 247 return;
+ − 248 }
+ − 249 }
+ − 250 }
+ − 251
+ − 252 static void
2286
+ − 253 emacs_tty_format_magic_event (Lisp_Event *UNUSED (emacs_event),
+ − 254 Lisp_Object UNUSED (pstream))
788
+ − 255 {
+ − 256 /* Nothing to do currently */
+ − 257 }
+ − 258
+ − 259 static int
2286
+ − 260 emacs_tty_compare_magic_event (Lisp_Event *UNUSED (e1),
+ − 261 Lisp_Event *UNUSED (e2))
788
+ − 262 {
+ − 263 return 1;
+ − 264 }
+ − 265
+ − 266 static Hashcode
2286
+ − 267 emacs_tty_hash_magic_event (Lisp_Event *UNUSED (e))
788
+ − 268 {
+ − 269 return 0;
+ − 270 }
+ − 271
+ − 272 static void
2286
+ − 273 emacs_tty_handle_magic_event (Lisp_Event *UNUSED (emacs_event))
428
+ − 274 {
+ − 275 /* Nothing to do currently */
+ − 276 }
+ − 277
+ − 278
+ − 279 static void
853
+ − 280 emacs_tty_select_process (Lisp_Process *process, int doin, int doerr)
428
+ − 281 {
853
+ − 282 int infd, errfd;
+ − 283
+ − 284 event_stream_unixoid_select_process (process, doin, doerr, &infd, &errfd);
428
+ − 285 }
+ − 286
+ − 287 static void
853
+ − 288 emacs_tty_unselect_process (Lisp_Process *process, int doin, int doerr)
428
+ − 289 {
853
+ − 290 int infd, errfd;
+ − 291
+ − 292 event_stream_unixoid_unselect_process (process, doin, doerr, &infd, &errfd);
428
+ − 293 }
+ − 294
+ − 295 static void
+ − 296 emacs_tty_select_console (struct console *con)
+ − 297 {
+ − 298 event_stream_unixoid_select_console (con);
+ − 299 }
+ − 300
+ − 301 static void
+ − 302 emacs_tty_unselect_console (struct console *con)
+ − 303 {
+ − 304 event_stream_unixoid_unselect_console (con);
+ − 305 }
+ − 306
+ − 307 static void
1204
+ − 308 emacs_tty_drain_queue (void)
428
+ − 309 {
1204
+ − 310 drain_tty_devices ();
428
+ − 311 }
+ − 312
853
+ − 313 static void
+ − 314 emacs_tty_create_io_streams (void* inhandle, void* outhandle,
+ − 315 void *errhandle, Lisp_Object* instream,
+ − 316 Lisp_Object* outstream,
+ − 317 Lisp_Object* errstream,
+ − 318 USID* in_usid,
+ − 319 USID* err_usid,
+ − 320 int flags)
428
+ − 321 {
853
+ − 322 event_stream_unixoid_create_io_streams
+ − 323 (inhandle, outhandle, errhandle, instream, outstream,
+ − 324 errstream, in_usid, err_usid, flags);
428
+ − 325 }
+ − 326
853
+ − 327 static void
+ − 328 emacs_tty_delete_io_streams (Lisp_Object instream,
+ − 329 Lisp_Object outstream,
+ − 330 Lisp_Object errstream,
+ − 331 USID* in_usid,
+ − 332 USID* err_usid)
428
+ − 333 {
853
+ − 334 event_stream_unixoid_delete_io_streams
+ − 335 (instream, outstream, errstream, in_usid, err_usid);
428
+ − 336 }
+ − 337
+ − 338
+ − 339 /************************************************************************/
+ − 340 /* initialization */
+ − 341 /************************************************************************/
+ − 342
+ − 343 void
+ − 344 reinit_vars_of_event_tty (void)
+ − 345 {
1204
+ − 346 tty_event_stream = xnew_and_zero (struct event_stream);
428
+ − 347
+ − 348 tty_event_stream->event_pending_p = emacs_tty_event_pending_p;
+ − 349 tty_event_stream->next_event_cb = emacs_tty_next_event;
+ − 350 tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event;
788
+ − 351 tty_event_stream->format_magic_event_cb = emacs_tty_format_magic_event;
+ − 352 tty_event_stream->compare_magic_event_cb= emacs_tty_compare_magic_event;
+ − 353 tty_event_stream->hash_magic_event_cb = emacs_tty_hash_magic_event;
428
+ − 354 tty_event_stream->add_timeout_cb = emacs_tty_add_timeout;
+ − 355 tty_event_stream->remove_timeout_cb = emacs_tty_remove_timeout;
+ − 356 tty_event_stream->select_console_cb = emacs_tty_select_console;
+ − 357 tty_event_stream->unselect_console_cb = emacs_tty_unselect_console;
+ − 358 tty_event_stream->select_process_cb = emacs_tty_select_process;
+ − 359 tty_event_stream->unselect_process_cb = emacs_tty_unselect_process;
1204
+ − 360 tty_event_stream->drain_queue_cb = emacs_tty_drain_queue;
853
+ − 361 tty_event_stream->create_io_streams_cb = emacs_tty_create_io_streams;
+ − 362 tty_event_stream->delete_io_streams_cb = emacs_tty_delete_io_streams;
3735
+ − 363
+ − 364 last_quit_check_signal_tick_count = 0;
428
+ − 365 }
+ − 366
+ − 367 void
+ − 368 vars_of_event_tty (void)
+ − 369 {
+ − 370 }
+ − 371
+ − 372 void
+ − 373 init_event_tty_late (void)
+ − 374 {
+ − 375 event_stream = tty_event_stream;
+ − 376 }