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.
788
+ − 4 Copyright (C) 1995, 2002 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
+ − 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
440
+ − 67 tty_timeout_to_emacs_event (Lisp_Event *emacs_event)
428
+ − 68 {
934
+ − 69 /* timeout events have nil as channel */
+ − 70 #ifdef USE_KKCC
+ − 71 SET_EVENT_TYPE (emacs_event, timeout_event);
+ − 72 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */
+ − 73 XSET_TIMEOUT_DATA_INTERVAL_ID (EVENT_DATA (emacs_event), pop_low_level_timeout (&tty_timer_queue, 0));
+ − 74 XSET_TIMEOUT_DATA_FUNCTION (EVENT_DATA (emacs_event), Qnil);
+ − 75 XSET_TIMEOUT_DATA_OBJECT (EVENT_DATA (emacs_event), Qnil);
+ − 76 #else /* not USE_KKCC */
428
+ − 77 emacs_event->event_type = timeout_event;
+ − 78 emacs_event->timestamp = 0; /* #### */
+ − 79 emacs_event->event.timeout.interval_id =
+ − 80 pop_low_level_timeout (&tty_timer_queue, 0);
+ − 81 emacs_event->event.timeout.function = Qnil;
+ − 82 emacs_event->event.timeout.object = Qnil;
934
+ − 83 #endif /* not USE_KKCC */
428
+ − 84 }
+ − 85
+ − 86
+ − 87
+ − 88 static int
+ − 89 emacs_tty_event_pending_p (int user_p)
+ − 90 {
+ − 91 if (!user_p)
+ − 92 {
+ − 93 EMACS_TIME sometime;
+ − 94 /* see if there's a pending timeout. */
+ − 95 EMACS_GET_TIME (sometime);
+ − 96 if (tty_timer_queue &&
+ − 97 EMACS_TIME_EQUAL_OR_GREATER (sometime, tty_timer_queue->time))
+ − 98 return 1;
+ − 99 }
+ − 100
+ − 101 return poll_fds_for_input (user_p ? tty_only_mask :
+ − 102 non_fake_input_wait_mask);
+ − 103 }
+ − 104
+ − 105 struct console *
+ − 106 tty_find_console_from_fd (int fd)
+ − 107 {
+ − 108 Lisp_Object concons;
+ − 109
+ − 110 CONSOLE_LOOP (concons)
+ − 111 {
+ − 112 struct console *c;
+ − 113
+ − 114 c = XCONSOLE (XCAR (concons));
+ − 115 if (CONSOLE_TTY_P (c) && CONSOLE_TTY_DATA (c)->infd == fd)
+ − 116 return c;
+ − 117 }
+ − 118
+ − 119 return 0;
+ − 120 }
+ − 121
+ − 122 static void
440
+ − 123 emacs_tty_next_event (Lisp_Event *emacs_event)
428
+ − 124 {
+ − 125 while (1)
+ − 126 {
+ − 127 int ndesc;
+ − 128 int i;
+ − 129 SELECT_TYPE temp_mask = input_wait_mask;
+ − 130 EMACS_TIME time_to_block;
+ − 131 EMACS_SELECT_TIME select_time_to_block, *pointer_to_this;
+ − 132
+ − 133 if (!get_low_level_timeout_interval (tty_timer_queue, &time_to_block))
+ − 134 /* no timer events; block indefinitely */
+ − 135 pointer_to_this = 0;
+ − 136 else
+ − 137 {
+ − 138 EMACS_TIME_TO_SELECT_TIME (time_to_block, select_time_to_block);
+ − 139 pointer_to_this = &select_time_to_block;
+ − 140 }
+ − 141
+ − 142 ndesc = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
+ − 143 if (ndesc > 0)
+ − 144 {
+ − 145 /* Look for a TTY event */
+ − 146 for (i = 0; i < MAXDESC; i++)
+ − 147 {
+ − 148 /* To avoid race conditions (among other things, an infinite
+ − 149 loop when called from Fdiscard_input()), we must return
+ − 150 user events ahead of process events. */
+ − 151 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
+ − 152 {
+ − 153 struct console *c = tty_find_console_from_fd (i);
+ − 154
+ − 155 assert (c);
771
+ − 156 if (read_event_from_tty_or_stream_desc (emacs_event, c))
428
+ − 157 return;
+ − 158 }
+ − 159 }
+ − 160
+ − 161 /* Look for a process event */
+ − 162 for (i = 0; i < MAXDESC; i++)
+ − 163 {
+ − 164 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &process_only_mask))
+ − 165 {
+ − 166 Lisp_Object process;
440
+ − 167 Lisp_Process *p = get_process_from_usid (FD_TO_USID(i));
428
+ − 168
+ − 169 assert (p);
793
+ − 170 process = wrap_process (p);
934
+ − 171 #ifdef USE_KKCC
+ − 172 set_event_type (emacs_event, process_event);
+ − 173 /* process events have nil as channel */
+ − 174 SET_EVENT_TIMESTAMP_ZERO (emacs_event); /* #### */
+ − 175 XSET_PROCESS_DATA_PROCESS (EVENT_DATA (emacs_event), process);
+ − 176 #else /* not USE_KKCC */
428
+ − 177 emacs_event->event_type = process_event;
+ − 178 /* process events have nil as channel */
+ − 179 emacs_event->timestamp = 0; /* #### */
+ − 180 emacs_event->event.process.process = process;
934
+ − 181 #endif /* not USE_KKCC */
428
+ − 182 return;
+ − 183 }
+ − 184 }
+ − 185
+ − 186 /* We might get here when a fake event came through a signal. */
+ − 187 /* Return a dummy event, so that a cycle of the command loop will
+ − 188 occur. */
+ − 189 drain_signal_event_pipe ();
934
+ − 190 #ifdef USE_KKCC
+ − 191 set_event_type (emacs_event, eval_event);
+ − 192 /* eval events have nil as channel */
+ − 193 XSET_EVAL_DATA_FUNCTION (EVENT_DATA (emacs_event), Qidentity);
+ − 194 XSET_EVAL_DATA_OBJECT (EVENT_DATA (emacs_event), Qnil);
+ − 195 #else /* not USE_KKCC */
428
+ − 196 emacs_event->event_type = eval_event;
+ − 197 /* eval events have nil as channel */
+ − 198 emacs_event->event.eval.function = Qidentity;
+ − 199 emacs_event->event.eval.object = Qnil;
934
+ − 200 #endif /* not USE_KKCC */
428
+ − 201 return;
+ − 202 }
+ − 203 else if (ndesc == 0) /* timeout fired */
+ − 204 {
+ − 205 tty_timeout_to_emacs_event (emacs_event);
+ − 206 return;
+ − 207 }
+ − 208 }
+ − 209 }
+ − 210
+ − 211 static void
788
+ − 212 emacs_tty_format_magic_event (Lisp_Event *emacs_event, Lisp_Object pstream)
+ − 213 {
+ − 214 /* Nothing to do currently */
+ − 215 }
+ − 216
+ − 217 static int
+ − 218 emacs_tty_compare_magic_event (Lisp_Event *e1, Lisp_Event *e2)
+ − 219 {
+ − 220 return 1;
+ − 221 }
+ − 222
+ − 223 static Hashcode
+ − 224 emacs_tty_hash_magic_event (Lisp_Event *e)
+ − 225 {
+ − 226 return 0;
+ − 227 }
+ − 228
+ − 229 static void
440
+ − 230 emacs_tty_handle_magic_event (Lisp_Event *emacs_event)
428
+ − 231 {
+ − 232 /* Nothing to do currently */
+ − 233 }
+ − 234
+ − 235
+ − 236 static void
853
+ − 237 emacs_tty_select_process (Lisp_Process *process, int doin, int doerr)
428
+ − 238 {
853
+ − 239 int infd, errfd;
+ − 240
+ − 241 event_stream_unixoid_select_process (process, doin, doerr, &infd, &errfd);
428
+ − 242 }
+ − 243
+ − 244 static void
853
+ − 245 emacs_tty_unselect_process (Lisp_Process *process, int doin, int doerr)
428
+ − 246 {
853
+ − 247 int infd, errfd;
+ − 248
+ − 249 event_stream_unixoid_unselect_process (process, doin, doerr, &infd, &errfd);
428
+ − 250 }
+ − 251
+ − 252 static void
+ − 253 emacs_tty_select_console (struct console *con)
+ − 254 {
+ − 255 event_stream_unixoid_select_console (con);
+ − 256 }
+ − 257
+ − 258 static void
+ − 259 emacs_tty_unselect_console (struct console *con)
+ − 260 {
+ − 261 event_stream_unixoid_unselect_console (con);
+ − 262 }
+ − 263
+ − 264 static void
+ − 265 emacs_tty_quit_p (void)
+ − 266 {
+ − 267 /* Nothing to do currently because QUIT is handled through SIGINT.
+ − 268 This could change. */
+ − 269 }
+ − 270
853
+ − 271 static void
+ − 272 emacs_tty_create_io_streams (void* inhandle, void* outhandle,
+ − 273 void *errhandle, Lisp_Object* instream,
+ − 274 Lisp_Object* outstream,
+ − 275 Lisp_Object* errstream,
+ − 276 USID* in_usid,
+ − 277 USID* err_usid,
+ − 278 int flags)
428
+ − 279 {
853
+ − 280 event_stream_unixoid_create_io_streams
+ − 281 (inhandle, outhandle, errhandle, instream, outstream,
+ − 282 errstream, in_usid, err_usid, flags);
428
+ − 283 }
+ − 284
853
+ − 285 static void
+ − 286 emacs_tty_delete_io_streams (Lisp_Object instream,
+ − 287 Lisp_Object outstream,
+ − 288 Lisp_Object errstream,
+ − 289 USID* in_usid,
+ − 290 USID* err_usid)
428
+ − 291 {
853
+ − 292 event_stream_unixoid_delete_io_streams
+ − 293 (instream, outstream, errstream, in_usid, err_usid);
428
+ − 294 }
+ − 295
+ − 296
+ − 297 /************************************************************************/
+ − 298 /* initialization */
+ − 299 /************************************************************************/
+ − 300
+ − 301 void
+ − 302 reinit_vars_of_event_tty (void)
+ − 303 {
+ − 304 tty_event_stream = xnew (struct event_stream);
+ − 305
+ − 306 tty_event_stream->event_pending_p = emacs_tty_event_pending_p;
442
+ − 307 tty_event_stream->force_event_pending = 0;
428
+ − 308 tty_event_stream->next_event_cb = emacs_tty_next_event;
+ − 309 tty_event_stream->handle_magic_event_cb = emacs_tty_handle_magic_event;
788
+ − 310 tty_event_stream->format_magic_event_cb = emacs_tty_format_magic_event;
+ − 311 tty_event_stream->compare_magic_event_cb= emacs_tty_compare_magic_event;
+ − 312 tty_event_stream->hash_magic_event_cb = emacs_tty_hash_magic_event;
428
+ − 313 tty_event_stream->add_timeout_cb = emacs_tty_add_timeout;
+ − 314 tty_event_stream->remove_timeout_cb = emacs_tty_remove_timeout;
+ − 315 tty_event_stream->select_console_cb = emacs_tty_select_console;
+ − 316 tty_event_stream->unselect_console_cb = emacs_tty_unselect_console;
+ − 317 tty_event_stream->select_process_cb = emacs_tty_select_process;
+ − 318 tty_event_stream->unselect_process_cb = emacs_tty_unselect_process;
+ − 319 tty_event_stream->quit_p_cb = emacs_tty_quit_p;
853
+ − 320 tty_event_stream->create_io_streams_cb = emacs_tty_create_io_streams;
+ − 321 tty_event_stream->delete_io_streams_cb = emacs_tty_delete_io_streams;
428
+ − 322 }
+ − 323
+ − 324 void
+ − 325 vars_of_event_tty (void)
+ − 326 {
+ − 327 reinit_vars_of_event_tty ();
+ − 328 }
+ − 329
+ − 330 void
+ − 331 init_event_tty_late (void)
+ − 332 {
+ − 333 event_stream = tty_event_stream;
+ − 334 }