1 /* Copyright 1992, 1993 John Bovey, University of Kent at Canterbury.
2 *
3 * Redistribution and use in source code and/or executable forms, with
4 * or without modification, are permitted provided that the following
5 * condition is met:
6 *
7 * Any redistribution must retain the above copyright notice, this
8 * condition and the following disclaimer, either as part of the
9 * program source code included in the redistribution or in human-
10 * readable materials provided with the redistribution.
11 *
12 * THIS SOFTWARE IS PROVIDED "AS IS". Any express or implied
13 * warranties concerning this software are disclaimed by the copyright
14 * holder to the fullest extent permitted by applicable law. In no
15 * event shall the copyright-holder be liable for any damages of any
16 * kind, however caused and on any theory of liability, arising in any
17 * way out of the use of, or inability to use, this software.
18 *
19 * -------------------------------------------------------------------
20 *
21 * In other words, do not misrepresent my work as your own work, and
22 * do not sue me if it causes problems. Feel free to do anything else
23 * you wish with it.
24 */
25
26 char xvt_command_c_sccsid[] = "@(#)command.c 1.3 9/12/93 (UKC)";
27
28 #ifdef __STDC__
29 #include <stdarg.h>
30 #else
31 #include <varargs.h>
32 #endif
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/keysym.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <sys/time.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <string.h>
46 #include "rvt.h"
47 #include "token.h"
48 #include "command.h"
49 #include "ttyinit.h"
50 #include "screen.h"
51 #include "xsetup.h"
52
53 #ifdef AIX3
54 #include <sys/select.h>
55 #endif /* AIX3 */
56
57 #define NLMAX 15 /* max number of lines to scroll */
58
59 #define KBUFSIZE 256 /* size of keyboard mapping buffer */
60 #define COM_BUF_SIZE 2048 /* size of buffer used to read from the command */
61 #define COM_PUSH_MAX 20 /* max number of characters that can be pushed
62 back into the input queue */
63 #define MP_INTERVAL 500 /* multi-press interval in milliseconds */
64
65 /* Special character returned by get_com_char().
66 */
67 #define GCC_NULL 0x100 /* Input buffer is empty */
68 #define ESC 033
69
70 /* Flags used to control get_com_char();
71 */
72 #define BUF_ONLY 1
73 #define GET_XEVENTS 2
74
75 /* Global variables that are set up at the beginning and then not changed
76 */
77 extern Display *display;
78 extern Window vt_win;
79 extern Window sb_win;
80 extern Window main_win;
81
82 int comm_fd = -1; /* file descriptor connected to the command */
83 int fd_width; /* width of file descriptors being used */
84
85 static int x_fd; /* file descriptor of the X server connection */
86 static int app_cur_keys = 0;/* flag to say cursor keys are in application mode */
87 static int app_kp_keys = 0; /* flag to set application keypad keys */
88 static int sun_function_keys = 0; /* flag set to use Sun function key mapping */
89 static Atom wm_del_win;
90
91 static unsigned char *send_buf = NULL; /* characters waiting to be sent to the command */
92 static unsigned char *send_nxt = NULL; /* next character to be sent */
93 static int send_count = 0; /* number of characters waiting to be sent */
94
95 /* Static variables used to record interesting X events.
96 */
97 /* Small X event structure used to queue interesting X events that need to
98 * be converted into tokens.
99 */
100 struct xeventst {
101 int xe_type;
102 int xe_button;
103 int xe_state;
104 int xe_x;
105 int xe_y;
106 int xe_width;
107 int xe_height;
108 int xe_detail;
109 unsigned long xe_time;
110 Window xe_window;
111 Atom xe_property; /* for selection requests */
112 Atom xe_target;
113 Window xe_requestor; /* ditto */
114 struct xeventst *xe_next;
115 struct xeventst *xe_prev;
116 };
117
118 static struct xeventst *xevent_start = NULL;
119 static struct xeventst *xevent_last = NULL; /* start and end of queue */
120
121 /* Variables used for buffered command input.
122 */
123 static unsigned char com_buf[COM_BUF_SIZE];
124 static unsigned char *com_buf_next, *com_buf_top;
125 static unsigned char com_stack[COM_PUSH_MAX]; /* stack of pushed back characters */
126 static unsigned char *com_stack_top;
127
128 /* Thanks to Rob McMullen for the following function key mapping tables
129 * and code.
130 */
131 /* Structure used to describe the string generated by a function key,
132 * keypad key, etc.
133 */
134 struct keystringst {
135 char ks_type; /* the way to generate the string (see below) */
136 unsigned char ks_value; /* value used in creating the string */
137 };
138
139 /* Different values for ks_type which determine how the value is used to
140 * generate the string.
141 */
142 #define KS_TYPE_NONE (char)0 /* No output */
143 #define KS_TYPE_CHAR (char)1 /* as printf("%c",ks_value) */
144 #define KS_TYPE_XTERM (char)2 /* as printf("\033[%d",ks_value) */
145 #define KS_TYPE_SUN (char)3 /* as printf("\033[%dz",ks_value) */
146 #define KS_TYPE_APPKEY (char)4 /* as printf("\033O%c",ks_value) */
147 #define KS_TYPE_NONAPP (char)5 /* as printf("\033[%c",ks_value) */
148 /* Added by cpbs for Debian, 1999/12/7: this is only used for the Delete key */
149 #define KS_TYPE_VT220 (char)6 /* as printf("\033[%d~",ks_value) */
150
151 /* Structure used to map a keysym to a string.
152 */
153 struct keymapst {
154 KeySym km_keysym;
155 struct keystringst km_normal; /* The usual string */
156 struct keystringst km_alt; /* The alternative string */
157 };
158
159 /* Table of function key mappings
160 */
161 static struct keymapst func_key_table[] = {
162 {XK_F1, {KS_TYPE_XTERM,11}, {KS_TYPE_SUN,224}},
163 {XK_F2, {KS_TYPE_XTERM,12}, {KS_TYPE_SUN,225}},
164 {XK_F3, {KS_TYPE_XTERM,13}, {KS_TYPE_SUN,226}},
165 {XK_F4, {KS_TYPE_XTERM,14}, {KS_TYPE_SUN,227}},
166 {XK_F5, {KS_TYPE_XTERM,15}, {KS_TYPE_SUN,228}},
167 {XK_F6, {KS_TYPE_XTERM,17}, {KS_TYPE_SUN,229}},
168 {XK_F7, {KS_TYPE_XTERM,18}, {KS_TYPE_SUN,230}},
169 {XK_F8, {KS_TYPE_XTERM,19}, {KS_TYPE_SUN,231}},
170 {XK_F9, {KS_TYPE_XTERM,20}, {KS_TYPE_SUN,232}},
171 {XK_F10, {KS_TYPE_XTERM,21}, {KS_TYPE_SUN,233}},
172 {XK_F11, {KS_TYPE_XTERM,23}, {KS_TYPE_SUN,192}},
173 {XK_F12, {KS_TYPE_XTERM,24}, {KS_TYPE_SUN,193}},
174 {XK_F13, {KS_TYPE_XTERM,25}, {KS_TYPE_SUN,194}},
175 {XK_F14, {KS_TYPE_XTERM,26}, {KS_TYPE_SUN,195}},
176 {XK_F15, {KS_TYPE_XTERM,28}, {KS_TYPE_SUN,196}},
177 {XK_F16, {KS_TYPE_XTERM,29}, {KS_TYPE_SUN,197}},
178 {XK_F17, {KS_TYPE_XTERM,31}, {KS_TYPE_SUN,198}},
179 {XK_F18, {KS_TYPE_XTERM,32}, {KS_TYPE_SUN,199}},
180 {XK_F19, {KS_TYPE_XTERM,33}, {KS_TYPE_SUN,200}},
181 {XK_F20, {KS_TYPE_XTERM,34}, {KS_TYPE_SUN,201}},
182 {XK_F21, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,208}},
183 {XK_F22, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,209}},
184 {XK_F23, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,210}},
185 {XK_F24, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,211}},
186 {XK_F25, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,212}},
187 {XK_F26, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,213}},
188 {XK_F27, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,214}},
189 {XK_F28, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,215}},
190 {XK_F29, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,216}},
191 {XK_F30, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,217}},
192 {XK_F31, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,218}},
193 {XK_F32, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,219}},
194 {XK_F33, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,220}},
195 {XK_F34, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,221}},
196 {XK_F35, {KS_TYPE_NONE,0}, {KS_TYPE_SUN,222}},
197 {XK_Find, {KS_TYPE_XTERM,1}, {KS_TYPE_SUN,1}},
198 {XK_Insert, {KS_TYPE_XTERM,2}, {KS_TYPE_SUN,2}},
199 {XK_Delete, {KS_TYPE_VT220,3}, {KS_TYPE_SUN,3}},
200 {XK_BackSpace, {KS_TYPE_CHAR,127}, {KS_TYPE_SUN,3}},
201 {XK_Select, {KS_TYPE_XTERM,4}, {KS_TYPE_SUN,4}},
202 {XK_Prior, {KS_TYPE_XTERM,5}, {KS_TYPE_SUN,5}},
203 {XK_Next, {KS_TYPE_XTERM,6}, {KS_TYPE_SUN,6}},
204 {XK_Help, {KS_TYPE_XTERM,28}, {KS_TYPE_SUN,196}},
205 {XK_Menu, {KS_TYPE_XTERM,29}, {KS_TYPE_SUN,197}},
206 {0, {KS_TYPE_NONE,0}, {KS_TYPE_NONE,0}}
207 };
208
209 /* PC keys and VT100 keypad function keys
210 */
211 static struct keymapst other_key_table[]={
212 { XK_Up, {KS_TYPE_NONAPP,'A'}, {KS_TYPE_APPKEY,'A'}},
213 { XK_Down, {KS_TYPE_NONAPP,'B'}, {KS_TYPE_APPKEY,'B'}},
214 { XK_Right, {KS_TYPE_NONAPP,'C'}, {KS_TYPE_APPKEY,'C'}},
215 { XK_Left, {KS_TYPE_NONAPP,'D'}, {KS_TYPE_APPKEY,'D'}},
216 { XK_Home, {KS_TYPE_NONAPP,'h'}, {KS_TYPE_APPKEY,'h'}},
217 { XK_End, {KS_TYPE_NONAPP,'\0'}, {KS_TYPE_APPKEY,'\0'}},
218 { XK_KP_F1, {KS_TYPE_APPKEY,'P'}, {KS_TYPE_APPKEY,'P'}},
219 { XK_KP_F2, {KS_TYPE_APPKEY,'Q'}, {KS_TYPE_APPKEY,'Q'}},
220 { XK_KP_F3, {KS_TYPE_APPKEY,'R'}, {KS_TYPE_APPKEY,'R'}},
221 { XK_KP_F4, {KS_TYPE_APPKEY,'S'}, {KS_TYPE_APPKEY,'S'}},
222 {0, {KS_TYPE_NONE,0}, {KS_TYPE_NONE,0}}
223 };
224
225 /* VT100 numeric keypad keys
226 */
227 static struct keymapst kp_key_table[]={
228 { XK_KP_0, {KS_TYPE_CHAR,'0'}, {KS_TYPE_APPKEY,'p'}},
229 { XK_KP_1, {KS_TYPE_CHAR,'1'}, {KS_TYPE_APPKEY,'q'}},
230 { XK_KP_2, {KS_TYPE_CHAR,'2'}, {KS_TYPE_APPKEY,'r'}},
231 { XK_KP_3, {KS_TYPE_CHAR,'3'}, {KS_TYPE_APPKEY,'s'}},
232 { XK_KP_4, {KS_TYPE_CHAR,'4'}, {KS_TYPE_APPKEY,'t'}},
233 { XK_KP_5, {KS_TYPE_CHAR,'5'}, {KS_TYPE_APPKEY,'u'}},
234 { XK_KP_6, {KS_TYPE_CHAR,'6'}, {KS_TYPE_APPKEY,'v'}},
235 { XK_KP_7, {KS_TYPE_CHAR,'7'}, {KS_TYPE_APPKEY,'w'}},
236 { XK_KP_8, {KS_TYPE_CHAR,'8'}, {KS_TYPE_APPKEY,'x'}},
237 { XK_KP_9, {KS_TYPE_CHAR,'9'}, {KS_TYPE_APPKEY,'y'}},
238 { XK_KP_Add, {KS_TYPE_CHAR,'+'}, {KS_TYPE_APPKEY,'k'}},
239 { XK_KP_Subtract,{KS_TYPE_CHAR,'-'}, {KS_TYPE_APPKEY,'m'}},
240 { XK_KP_Multiply,{KS_TYPE_CHAR,'*'}, {KS_TYPE_APPKEY,'j'}},
241 { XK_KP_Divide, {KS_TYPE_CHAR,'/'}, {KS_TYPE_APPKEY,'o'}},
242 { XK_KP_Separator,{KS_TYPE_CHAR,','}, {KS_TYPE_APPKEY,'l'}},
243 { XK_KP_Decimal,{KS_TYPE_CHAR,'.'}, {KS_TYPE_APPKEY,'n'}},
244 { XK_KP_Enter, {KS_TYPE_CHAR,'\r'}, {KS_TYPE_APPKEY,'M'}},
245 { XK_KP_Space, {KS_TYPE_CHAR,' '}, {KS_TYPE_APPKEY,' '}},
246 { XK_KP_Tab, {KS_TYPE_CHAR,'\t'}, {KS_TYPE_APPKEY,'I'}},
247 {0, {KS_TYPE_NONE,0}, {KS_TYPE_NONE,0}}
248 };
249
250 #ifdef __STDC__
251 static void push_xevent(struct xeventst *);
252 static struct xeventst *pop_xevent(void);
253 static unsigned char * get_keycode_value(struct keymapst *,KeySym,unsigned char *,int);
254 static unsigned char *lookup_key(XEvent *,int *);
255 static int get_com_char(int);
256 static void push_com_char(int);
257 #ifdef DEBUG
258 static void show_token_args(struct tokenst *);
259 static void show_hex_token_args(struct tokenst *);
260 #endif /* DEBUG */
261 #else /* __STDC__ */
262 static void push_xevent();
263 static struct xeventst *pop_xevent();
264 static unsigned char * get_keycode_value();
265 static unsigned char *lookup_key();
266 static int get_com_char();
267 static void push_com_char();
268 #ifdef DEBUG
269 static void show_token_args();
270 static void show_hex_token_args();
271 #endif /* DEBUG */
272 #endif /* __STDC__ */
273
274 /* Push a mini X event onto the queue
275 */
276 static void
push_xevent(xe)277 push_xevent(xe)
278 struct xeventst *xe;
279 {
280 xe->xe_next = xevent_start;
281 xe->xe_prev = NULL;
282 if (xe->xe_next != NULL)
283 xe->xe_next->xe_prev = xe;
284 else
285 xevent_last = xe;
286 }
287
288 static struct xeventst *
pop_xevent()289 pop_xevent()
290 {
291 struct xeventst *xe;
292
293 if (xevent_last == NULL)
294 return(NULL);
295
296 xe = xevent_last;
297 xevent_last = xe->xe_prev;
298 if (xevent_last != NULL)
299 xevent_last->xe_next = NULL;
300 else
301 xevent_start = NULL;
302 return(xe);
303 }
304
305 /* Initialise the command connection. This should be called after the X
306 * server connection is established.
307 */
308 void
init_command(char * command,char ** argv)309 init_command(char *command, char **argv)
310 {
311 /* Enable the delete window protocol.
312 */
313 wm_del_win = XInternAtom(display, "WM_DELETE_WINDOW", False);
314 XSetWMProtocols(display, main_win, &wm_del_win, 1);
315
316 if ((comm_fd = run_command(command, argv)) < 0) {
317 error("Quitting");
318 quit(1);
319 }
320 x_fd = XConnectionNumber(display);
321 com_buf_next = com_buf_top = com_buf;
322 com_stack_top = com_stack;
323 }
324
325 /* Set the current cursor keys mode.
326 */
327 void
set_cur_keys(mode)328 set_cur_keys(mode)
329 int mode;
330 {
331 app_cur_keys = (mode == HIGH);
332 }
333
334 /* Set the current keypad keys mode.
335 */
336 void
set_kp_keys(mode)337 set_kp_keys(mode)
338 int mode;
339 {
340 app_kp_keys = (mode == HIGH);
341 }
342
343 /* Enable or disable the use of Sun function key mapping.
344 */
345 void
set_sun_function_keys(value)346 set_sun_function_keys(value)
347 int value;
348 {
349 sun_function_keys = value;
350 }
351
352 /* Look up function key keycode
353 */
354 static unsigned char *
get_keycode_value(keymaptable,keysym,buf,use_alternate)355 get_keycode_value(keymaptable,keysym,buf,use_alternate)
356 struct keymapst *keymaptable;
357 KeySym keysym;
358 unsigned char *buf;
359 int use_alternate;
360 {
361 struct keymapst *km;
362 struct keystringst *ks;
363
364 for (km = keymaptable; km->km_keysym != 0; km++) {
365 if (km->km_keysym == keysym) {
366 ks = use_alternate ? &km->km_alt : &km->km_normal;
367 switch (ks->ks_type) {
368 case KS_TYPE_NONE:
369 return NULL;
370 case KS_TYPE_CHAR:
371 sprintf((char *)buf,"%c",ks->ks_value);
372 return buf;
373 case KS_TYPE_XTERM:
374 sprintf((char *)buf,"\033[%d~",ks->ks_value);
375 return buf;
376 case KS_TYPE_SUN:
377 sprintf((char *)buf,"\033[%dz",ks->ks_value);
378 return buf;
379 case KS_TYPE_APPKEY:
380 sprintf((char *)buf,"\033O%c",ks->ks_value);
381 return buf;
382 case KS_TYPE_NONAPP:
383 sprintf((char *)buf,"\033[%c",ks->ks_value);
384 return buf;
385 case KS_TYPE_VT220:
386 sprintf((char *)buf,"\033[%d~",ks->ks_value);
387 return buf;
388 }
389 }
390 }
391 return NULL;
392 }
393
394 /* Convert the keypress event into a string.
395 */
396 static unsigned char *
lookup_key(ev,pcount)397 lookup_key(ev,pcount)
398 int *pcount;
399 XEvent *ev;
400 {
401 KeySym keysym;
402 int count;
403 static unsigned char kbuf[KBUFSIZE];
404 unsigned char *s;
405 unsigned char *str;
406
407 count = XLookupString(&ev->xkey,kbuf,KBUFSIZE,&keysym,NULL);
408 s = NULL;
409
410 if (IsFunctionKey(keysym) || IsMiscFunctionKey(keysym)
411 || keysym == XK_Next || keysym == XK_Prior
412 || keysym == XK_Delete || keysym == XK_BackSpace)
413 s = get_keycode_value(func_key_table,keysym,kbuf,sun_function_keys);
414 else if (IsCursorKey(keysym) || IsPFKey(keysym))
415 s = get_keycode_value(other_key_table,keysym,kbuf,app_cur_keys);
416 else
417 s = get_keycode_value(kp_key_table,keysym,kbuf,app_kp_keys);
418
419 if (s != NULL) {
420 *pcount = strlen((char *)s);
421 str = s;
422 } else {
423 str = kbuf;
424 if ((ev->xkey.state & Mod1Mask) && (count == 1)) {
425 if (is_eightbit()) {
426 kbuf[0] |= 0200;
427 *pcount = 1;
428 } else {
429 kbuf[1] = kbuf[0];
430 kbuf[0] = '\033';
431 *pcount = 2;
432 }
433 } else
434 *pcount = count;
435 }
436 return (str);
437 }
438
439 /* Return the next input character after first passing any keyboard input
440 * to the command. If flags & BUF_ONLY is true then only buffered characters are
441 * returned and once the buffer is empty the special value GCC_NULL is
442 * returned. If flags and GET_XEVENTS is true then GCC_NULL is returned
443 * when an X event arrives.
444 */
445 static int
get_com_char(flags)446 get_com_char(flags)
447 int flags;
448 {
449 XEvent event;
450 struct xeventst *xe;
451 fd_set in_fdset, out_fdset;
452 unsigned char *s;
453 int count, sv;
454 unsigned char mask = is_eightbit() ? 0xff : 0x7f;
455 extern int errno;
456
457 if (com_stack_top > com_stack)
458 return(*--com_stack_top);
459
460 if (com_buf_next < com_buf_top)
461 return(*com_buf_next++ & mask);
462 else if (flags & BUF_ONLY)
463 return(GCC_NULL);
464
465 for (;;) {
466 FD_ZERO(&in_fdset);
467 while (XPending(display) == 0) {
468 if (FD_ISSET(x_fd,&in_fdset))
469 /* If we get to this point something is wrong
470 * because there is X input available but no
471 * events. Exit the program to avoid looping
472 * forever.
473 */
474 quit(0);
475 FD_SET(comm_fd,&in_fdset);
476 FD_SET(x_fd,&in_fdset);
477 FD_ZERO(&out_fdset);
478 if (send_count > 0)
479 FD_SET(comm_fd,&out_fdset);
480 do
481 sv = select(fd_width,&in_fdset,&out_fdset,NULL,NULL);
482 while (sv < 0 && errno == EINTR);
483 if (sv < 0) {
484 error("select failed");
485 quit(-1);
486 }
487
488 if (FD_ISSET(comm_fd,&out_fdset)) {
489 count = send_count < 100 ? send_count : 100;
490 count = write(comm_fd,send_nxt,count);
491 if (count < 0) {
492 error("failed to write to command");
493 quit(-1);
494 }
495 send_count -= count;
496 send_nxt += count;
497 }
498
499 if (FD_ISSET(comm_fd,&in_fdset))
500 break;
501 }
502 if (FD_ISSET(comm_fd,&in_fdset))
503 break;
504 XNextEvent(display,&event);
505 if (event.type == KeyPress) {
506 s = lookup_key(&event,&count);
507 if (count != 0)
508 send_string(s,count);
509 } else if (event.type == ClientMessage) {
510 if (event.xclient.format == 32 && event.xclient.data.l[0] == wm_del_win)
511 quit(0);
512 } else if (event.type == MappingNotify) {
513 XRefreshKeyboardMapping(&event.xmapping);
514 } else if (event.type == SelectionRequest) {
515 xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
516 xe->xe_type = event.type;
517 xe->xe_window = event.xselectionrequest.owner;
518 xe->xe_time = event.xselectionrequest.time;
519 xe->xe_requestor = event.xselectionrequest.requestor;
520 xe->xe_target = event.xselectionrequest.target;
521 xe->xe_property = event.xselectionrequest.property;
522 push_xevent(xe);
523 if (flags & GET_XEVENTS)
524 return(GCC_NULL);
525 } else if (event.type == SelectionNotify) {
526 xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
527 xe->xe_type = event.type;
528 xe->xe_time = event.xselection.time;
529 xe->xe_requestor = event.xselection.requestor;
530 xe->xe_property = event.xselection.property;
531 push_xevent(xe);
532 if (flags & GET_XEVENTS)
533 return(GCC_NULL);
534 } else if (event.type == FocusIn || event.type == FocusOut) {
535 if (event.xfocus.mode != NotifyNormal)
536 continue;
537 switch (event.xfocus.detail) {
538 case NotifyAncestor :
539 case NotifyInferior :
540 case NotifyNonlinear :
541 break;
542 default :
543 continue;
544 }
545 xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
546 xe->xe_type = event.type;
547 xe->xe_time = event.xselection.time;
548 xe->xe_detail = event.xfocus.detail;
549 push_xevent(xe);
550 if (flags & GET_XEVENTS)
551 return(GCC_NULL);
552 } else {
553 xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
554 xe->xe_type = event.type;
555 xe->xe_window = event.xany.window;
556 if (event.type == Expose || event.type == GraphicsExpose) {
557 xe->xe_x = event.xexpose.x;
558 xe->xe_y = event.xexpose.y;
559 xe->xe_width = event.xexpose.width;
560 xe->xe_height = event.xexpose.height;
561 } else {
562 xe->xe_time = event.xbutton.time;
563 xe->xe_x = event.xbutton.x;
564 xe->xe_y = event.xbutton.y;
565 xe->xe_state = event.xbutton.state;
566 xe->xe_button = event.xbutton.button;
567 }
568 push_xevent(xe);
569 if (flags & GET_XEVENTS)
570 return(GCC_NULL);
571 }
572 }
573
574 count = read(comm_fd,com_buf,COM_BUF_SIZE);
575 if (count <= 0) {
576 if (errno == EWOULDBLOCK) {
577 return(GCC_NULL);
578 } else {
579 return(EOF);
580 }
581 }
582 com_buf_next = com_buf;
583 com_buf_top = com_buf + count;
584 return(*com_buf_next++ & mask);
585 }
586
587 /* Push an input character back into the input queue.
588 */
589 static void
push_com_char(c)590 push_com_char(c)
591 int c;
592 {
593 if (com_stack_top < com_stack + COM_PUSH_MAX)
594 *com_stack_top++ = c;
595 }
596
597 /* Send count characters directly to the command.
598 */
599 void
send_string(buf,count)600 send_string(buf,count)
601 unsigned char *buf;
602 int count;
603 {
604 unsigned char *s;
605 register unsigned char *s1, *s2;
606 register int i;
607
608 if (count == 0)
609 return;
610
611 if (send_count == 0) {
612 if (send_buf != NULL) {
613 free(send_buf);
614 send_buf = NULL;
615 }
616 send_buf = (unsigned char *)cmalloc(count);
617 s2 = send_buf;
618 s1 = buf;
619 for (i = 0; i < count; i++, s1++, s2++)
620 *s2 = *s1;
621 send_nxt = send_buf;
622 send_count = count;
623 } else {
624 s = (unsigned char *)cmalloc(send_count + count);
625 memcpy(s,send_nxt,send_count);
626 s2 = s + send_count;
627 s1 = buf;
628 for (i = 0; i < count; i++, s1++, s2++)
629 *s2 = *s1;
630 free(send_buf);
631 send_buf = send_nxt = s;
632 send_count += count;
633 }
634 }
635
636 /* Send printf formatted output to the command. Only used for small ammounts
637 * of data.
638 */
639 /*VARARGS1*/
640 void
641 #ifdef __STDC__
cprintf(char * fmt,...)642 cprintf(char *fmt,...)
643 {
644 va_list args;
645 static unsigned char buf[1024];
646
647 va_start(args,fmt);
648 #else
649 cprintf(va_alist)
650 va_dcl
651 {
652 char *fmt;
653 va_list args;
654 static unsigned char buf[1024];
655
656 va_start(args);
657 fmt = va_arg(args,char *);
658 #endif
659
660 vsprintf((char *)buf,fmt,args);
661 va_end(args);
662 send_string(buf,strlen((char *)buf));
663 }
664
665 /* Return an input token
666 */
667 void
668 get_token(tk)
669 struct tokenst *tk;
670 {
671 int c, i, n;
672 struct xeventst *xe;
673 static unsigned int time1 = 0, time2 = 0;
674
675 tk->tk_private = 0;
676 tk->tk_type = TK_NULL;
677
678 if ((xe = pop_xevent()) != NULL) {
679 if (xe->xe_window == vt_win)
680 tk->tk_region = SCREEN;
681 else if (xe->xe_window == sb_win)
682 tk->tk_region = SCROLLBAR;
683 else if (xe->xe_window == main_win)
684 tk->tk_region = MAINWIN;
685 else
686 tk->tk_region = -1;
687 switch (xe->xe_type) {
688 case EnterNotify :
689 tk->tk_type = TK_ENTRY;
690 tk->tk_arg[0] = 1;
691 tk->tk_nargs = 1;
692 break;
693 case LeaveNotify :
694 tk->tk_type = TK_ENTRY;
695 tk->tk_arg[0] = 0;
696 tk->tk_nargs = 1;
697 break;
698 case FocusIn :
699 tk->tk_type = TK_FOCUS;
700 tk->tk_arg[0] = 1;
701 tk->tk_arg[1] = xe->xe_detail;
702 tk->tk_nargs = 2;
703 break;
704 case FocusOut :
705 tk->tk_type = TK_FOCUS;
706 tk->tk_arg[0] = 0;
707 tk->tk_arg[1] = xe->xe_detail;
708 tk->tk_nargs = 2;
709 break;
710 case Expose :
711 tk->tk_type = TK_EXPOSE;
712 tk->tk_arg[0] = xe->xe_x;
713 tk->tk_arg[1] = xe->xe_y;
714 tk->tk_arg[2] = xe->xe_width;
715 tk->tk_arg[3] = xe->xe_height;
716 tk->tk_nargs = 4;
717 break;
718 case ConfigureNotify :
719 tk->tk_type = TK_RESIZE;
720 tk->tk_nargs = 0;
721 break;
722 case SelectionClear :
723 tk->tk_type = TK_SELCLEAR;
724 tk->tk_arg[0] = xe->xe_time;
725 tk->tk_nargs = 1;
726 break;
727 case SelectionNotify :
728 tk->tk_type = TK_SELNOTIFY;
729 tk->tk_arg[0] = xe->xe_time;
730 tk->tk_arg[1] = xe->xe_requestor;
731 tk->tk_arg[2] = xe->xe_property;
732 tk->tk_nargs = 3;
733 break;
734 case SelectionRequest :
735 tk->tk_type = TK_SELREQUEST;
736 tk->tk_arg[0] = xe->xe_time;
737 tk->tk_arg[1] = xe->xe_requestor;
738 tk->tk_arg[2] = xe->xe_target;
739 tk->tk_arg[3] = xe->xe_property;
740 tk->tk_nargs = 4;
741 break;
742 case ButtonPress :
743 /* Deal with a SendEvent */
744 if (xe->xe_window != vt_win &&
745 xe->xe_window != sb_win &&
746 xe->xe_window != main_win)
747 xe->xe_window = vt_win;
748 if (xe->xe_window == vt_win && xe->xe_state == ControlMask) {
749 tk->tk_type = TK_SBSWITCH;
750 tk->tk_nargs = 0;
751 break;
752 }
753 if (xe->xe_window == vt_win && (xe->xe_state & ControlMask) == 0) {
754 switch (xe->xe_button) {
755 case Button1 :
756 if (xe->xe_time - time2 < MP_INTERVAL) {
757 time1 = 0;
758 time2 = 0;
759 tk->tk_type = TK_SELLINE;
760 } else if (xe->xe_time - time1 < MP_INTERVAL) {
761 time2 = xe->xe_time;
762 tk->tk_type = TK_SELWORD;
763 } else {
764 time1 = xe->xe_time;
765 tk->tk_type = TK_SELSTART;
766 }
767 break;
768 case Button2 :
769 tk->tk_type = TK_NULL;
770 break;
771 case Button3 :
772 tk->tk_type = TK_SELEXTND;
773 break;
774 }
775 tk->tk_arg[0] = xe->xe_x;
776 tk->tk_arg[1] = xe->xe_y;
777 tk->tk_nargs = 2;
778 break;
779 }
780 if (xe->xe_window == sb_win) {
781 if (xe->xe_button == Button2) {
782 tk->tk_type = TK_SBGOTO;
783 tk->tk_arg[0] = xe->xe_y;
784 tk->tk_nargs = 1;
785 }
786 }
787 break;
788 case ButtonRelease :
789 /* Deal with a SendEvent */
790 if (xe->xe_window != vt_win &&
791 xe->xe_window != main_win &&
792 xe->xe_window != sb_win) {
793 switch (xe->xe_button) {
794 case Button1:
795 case Button3:
796 xe->xe_window = sb_win;
797 break;
798 case Button2:
799 xe->xe_window = vt_win;
800 break;
801 }
802 }
803 if (xe->xe_window == sb_win) {
804 switch (xe->xe_button) {
805 case Button1 :
806 tk->tk_type = TK_SBUP;
807 tk->tk_arg[0] = xe->xe_y;
808 tk->tk_nargs = 1;
809 break;
810 case Button3 :
811 tk->tk_type = TK_SBDOWN;
812 tk->tk_arg[0] = xe->xe_y;
813 tk->tk_nargs = 1;
814 break;
815 }
816 } else if (xe->xe_window == vt_win &&
817 (xe->xe_state & ControlMask) == 0) {
818 switch (xe->xe_button) {
819 case Button1 :
820 case Button3 :
821 tk->tk_type = TK_SELECT;
822 tk->tk_arg[0] = xe->xe_time;
823 tk->tk_nargs = 1;
824 break;
825 case Button2 :
826 tk->tk_type = TK_SELINSRT;
827 tk->tk_arg[0] = xe->xe_time;
828 tk->tk_arg[1] = xe->xe_x;
829 tk->tk_arg[2] = xe->xe_y;
830 tk->tk_nargs = 3;
831 break;
832 }
833 }
834 break;
835 case MotionNotify :
836 if (xe->xe_window == sb_win && (xe->xe_state & Button2Mask)) {
837 Window root, child;
838 int root_x, root_y, x, y;
839 unsigned int mods;
840
841 XQueryPointer(display,sb_win,&root,&child,
842 &root_x,&root_y,&x,&y,&mods);
843 if (mods & Button2Mask) {
844 tk->tk_type = TK_SBGOTO;
845 tk->tk_arg[0] = y;
846 tk->tk_nargs = 1;
847 }
848 break;
849 }
850 if (xe->xe_window == vt_win && (xe->xe_state & Button1Mask) &&
851 !(xe->xe_state & ControlMask)) {
852 tk->tk_type = TK_SELDRAG;
853 tk->tk_arg[0] = xe->xe_x;
854 tk->tk_arg[1] = xe->xe_y;
855 tk->tk_nargs = 2;
856 break;
857 }
858 break;
859
860 }
861 free((void *)xe);
862 return;
863 }
864 if ((c = get_com_char(GET_XEVENTS)) == GCC_NULL) {
865 tk->tk_type = TK_NULL;
866 return;
867 }
868
869 if (c == EOF) {
870 tk->tk_type = TK_EOF;
871 return;
872 }
873 if (is_string_char(c)) {
874 i = 0;
875 tk->tk_nlcount = 0;
876 do {
877 tk->tk_string[i++] = c;
878 c = get_com_char(1);
879 if (c == '\n' && ++tk->tk_nlcount >= NLMAX) {
880 tk->tk_nlcount--;
881 break;
882 }
883 } while (is_string_char(c) && i < TKS_MAX);
884 tk->tk_length = i;
885 tk->tk_string[i] = 0;
886 tk->tk_type = TK_STRING;
887 if (c != GCC_NULL)
888 push_com_char(c);
889 } else if (c == ESC) {
890 c = get_com_char(0);
891 if (c == '[') {
892 c = get_com_char(0);
893 if (c >= '<' && c <= '?') {
894 tk->tk_private = c;
895 c = get_com_char(0);
896 }
897
898 /* read any numerical arguments
899 */
900 i = 0;
901 do {
902 n = 0;
903 while (c >= '0' && c <= '9') {
904 n = n * 10 + c - '0';
905 c = get_com_char(0);
906 }
907 if (i < TK_MAX_ARGS)
908 tk->tk_arg[i++] = n;
909 if (c == ESC)
910 push_com_char(c);
911 if (c < ' ')
912 return;
913 if (c < '@')
914 c = get_com_char(0);
915 } while (c < '@' && c >= ' ');
916 if (c == ESC)
917 push_com_char(c);
918 if (c < ' ')
919 return;
920 tk->tk_nargs = i;
921 tk->tk_type = c;
922 } else if (c == ']') {
923 c = get_com_char(0);
924 n = 0;
925 while (c >= '0' && c <= '9') {
926 n = n * 10 + c - '0';
927 c = get_com_char(0);
928 }
929 tk->tk_arg[0] = n;
930 tk->tk_nargs = 1;
931 c = get_com_char(0);
932 i = 0;
933 while ((c & 0177) >= ' ' && i < TKS_MAX) {
934 if (c >= ' ')
935 tk->tk_string[i++] = c;
936 c = get_com_char(0);
937 }
938 tk->tk_length = i;
939 tk->tk_string[i] = 0;
940 tk->tk_type = TK_TXTPAR;
941 } else if (c == '#' || c == '(' || c == ')') {
942 tk->tk_type = c;
943 c = get_com_char(0);
944 tk->tk_arg[0] = c;
945 tk->tk_nargs = 1;
946 } else if (c == '7' || c == '8' || c == '=' || c == '>') {
947 tk->tk_type = c;
948 tk->tk_nargs = 0;
949 } else {
950 switch (c) {
951 case 'D' :
952 tk->tk_type = TK_IND;
953 break;
954 case 'E' :
955 tk->tk_type = TK_NEL;
956 break;
957 case 'H' :
958 tk->tk_type = TK_HTS;
959 break;
960 case 'M' :
961 tk->tk_type = TK_RI;
962 break;
963 case 'N' :
964 tk->tk_type = TK_SS2;
965 break;
966 case 'O' :
967 tk->tk_type = TK_SS3;
968 break;
969 case 'Z' :
970 tk->tk_type = TK_DECID;
971 break;
972 default :
973 return;
974 }
975 }
976 } else {
977 tk->tk_type = TK_CHAR;
978 tk->tk_char = c;
979 }
980 }
981
982 #ifdef DEBUG
983 /* Print out a token's numerical arguments. Just used by show_token()
984 */
985 static void
986 show_token_args(tk)
987 struct tokenst *tk;
988 {
989 int i;
990
991 for (i = 0; i < tk->tk_nargs; i++) {
992 if (i == 0)
993 printf(" (%d",tk->tk_arg[i]);
994 else
995 printf(",%d",tk->tk_arg[i]);
996 }
997 if (tk->tk_nargs > 0)
998 printf(")");
999 if (tk->tk_private !=0)
1000 putchar(tk->tk_private);
1001 }
1002
1003 /* Print out a token's numerical arguments in hex. Just used by show_token()
1004 */
1005 static void
1006 show_hex_token_args(tk)
1007 struct tokenst *tk;
1008 {
1009 int i;
1010
1011 for (i = 0; i < tk->tk_nargs; i++) {
1012 if (i == 0)
1013 printf(" (0x%x",tk->tk_arg[i]);
1014 else
1015 printf(",0x%x",tk->tk_arg[i]);
1016 }
1017 if (tk->tk_nargs > 0)
1018 printf(")");
1019 if (tk->tk_private !=0)
1020 putchar(tk->tk_private);
1021 }
1022
1023 /* Print out the contents of an input token - used for debugging.
1024 */
1025 void
1026 show_token(tk)
1027 struct tokenst *tk;
1028 {
1029
1030 /* Screen out token types that are not currently of interest.
1031 */
1032 switch (tk->tk_type) {
1033 case TK_SELDRAG :
1034 return;
1035 }
1036
1037 switch (tk->tk_type) {
1038 case TK_STRING :
1039 printf("token(TK_STRING)");
1040 printf(" \"%s\"",tk->tk_string);
1041 break;
1042 case TK_TXTPAR :
1043 printf("token(TK_TXTPAR)");
1044 printf(" (%d) \"%s\"",tk->tk_arg[0],tk->tk_string);
1045 break;
1046 case TK_CHAR :
1047 printf("token(TK_CHAR)");
1048 printf(" <%o>",tk->tk_char);
1049 break;
1050 case TK_EOF :
1051 printf("token(TK_EOF)");
1052 show_token_args(tk);
1053 break;
1054 case TK_FOCUS :
1055 printf("token(TK_FOCUS)");
1056 printf(" <%d>",tk->tk_region);
1057 show_token_args(tk);
1058 break;
1059 case TK_ENTRY :
1060 printf("token(TK_ENTRY)");
1061 printf(" <%d>",tk->tk_region);
1062 show_token_args(tk);
1063 break;
1064 case TK_SBSWITCH :
1065 printf("token(TK_SBSWITCH)");
1066 show_token_args(tk);
1067 break;
1068 case TK_SBGOTO :
1069 printf("token(TK_SBGOTO)");
1070 show_token_args(tk);
1071 break;
1072 case TK_SBUP :
1073 printf("token(TK_SBUP)");
1074 show_token_args(tk);
1075 break;
1076 case TK_SBDOWN :
1077 printf("token(TK_SBDOWN)");
1078 show_token_args(tk);
1079 break;
1080 case TK_EXPOSE :
1081 printf("token(TK_EXPOSE)");
1082 printf("(%d)",tk->tk_region);
1083 show_token_args(tk);
1084 break;
1085 case TK_RESIZE :
1086 printf("token(TK_RESIZE)");
1087 show_token_args(tk);
1088 break;
1089 case TK_SELSTART :
1090 printf("token(TK_SELSTART)");
1091 show_token_args(tk);
1092 break;
1093 case TK_SELEXTND :
1094 printf("token(TK_SELEXTND)");
1095 show_token_args(tk);
1096 break;
1097 case TK_SELDRAG :
1098 printf("token(TK_SELDRAG)");
1099 show_token_args(tk);
1100 break;
1101 case TK_SELINSRT :
1102 printf("token(TK_SELINSRT)");
1103 show_token_args(tk);
1104 break;
1105 case TK_SELECT :
1106 printf("token(TK_SELECT)");
1107 show_token_args(tk);
1108 break;
1109 case TK_SELWORD :
1110 printf("token(TK_SELWORD)");
1111 show_token_args(tk);
1112 break;
1113 case TK_SELLINE :
1114 printf("token(TK_SELLINE)");
1115 show_token_args(tk);
1116 break;
1117 case TK_SELCLEAR :
1118 printf("token(TK_SELCLEAR)");
1119 show_token_args(tk);
1120 break;
1121 case TK_SELNOTIFY :
1122 printf("token(TK_SELNOTIFY)");
1123 show_hex_token_args(tk);
1124 break;
1125 case TK_SELREQUEST :
1126 printf("token(TK_SELREQUEST)");
1127 show_hex_token_args(tk);
1128 break;
1129 case TK_CUU :
1130 printf("token(TK_CUU)");
1131 show_token_args(tk);
1132 break;
1133 case TK_CUD :
1134 printf("token(TK_CUD)");
1135 show_token_args(tk);
1136 break;
1137 case TK_CUF :
1138 printf("token(TK_CUF)");
1139 show_token_args(tk);
1140 break;
1141 case TK_CUB :
1142 printf("token(TK_CUB)");
1143 show_token_args(tk);
1144 break;
1145 case TK_CUP :
1146 printf("token(TK_CUP)");
1147 show_token_args(tk);
1148 break;
1149 case TK_ED :
1150 printf("token(TK_ED)");
1151 show_token_args(tk);
1152 break;
1153 case TK_EL :
1154 printf("token(TK_EL)");
1155 show_token_args(tk);
1156 break;
1157 case TK_IL :
1158 printf("token(TK_IL)");
1159 show_token_args(tk);
1160 break;
1161 case TK_DL :
1162 printf("token(TK_DL)");
1163 show_token_args(tk);
1164 break;
1165 case TK_DCH :
1166 printf("token(TK_DCH)");
1167 show_token_args(tk);
1168 break;
1169 case TK_ICH :
1170 printf("token(TK_ICH)");
1171 show_token_args(tk);
1172 break;
1173 case TK_DA :
1174 printf("token(TK_DA)");
1175 show_token_args(tk);
1176 break;
1177 case TK_HVP :
1178 printf("token(TK_HVP)");
1179 show_token_args(tk);
1180 break;
1181 case TK_TBC :
1182 printf("token(TK_TBC)");
1183 show_token_args(tk);
1184 break;
1185 case TK_SET :
1186 printf("token(TK_SET)");
1187 show_token_args(tk);
1188 break;
1189 case TK_RESET :
1190 printf("token(TK_RESET)");
1191 show_token_args(tk);
1192 break;
1193 case TK_SGR :
1194 printf("token(TK_SGR)");
1195 show_token_args(tk);
1196 break;
1197 case TK_DSR :
1198 printf("token(TK_DSR)");
1199 show_token_args(tk);
1200 break;
1201 case TK_DECSTBM :
1202 printf("token(TK_DECSTBM)");
1203 show_token_args(tk);
1204 break;
1205 case TK_DECSWH :
1206 printf("token(TK_DECSWH)");
1207 show_token_args(tk);
1208 break;
1209 case TK_SCS0 :
1210 printf("token(TK_SCS0)");
1211 show_token_args(tk);
1212 break;
1213 case TK_SCS1 :
1214 printf("token(TK_SCS1)");
1215 show_token_args(tk);
1216 break;
1217 case TK_DECSC :
1218 printf("token(TK_DECSC)");
1219 show_token_args(tk);
1220 break;
1221 case TK_DECRC :
1222 printf("token(TK_DECRC)");
1223 show_token_args(tk);
1224 break;
1225 case TK_DECPAM :
1226 printf("token(TK_DECPAM)");
1227 show_token_args(tk);
1228 break;
1229 case TK_DECPNM :
1230 printf("token(TK_DECPNM)");
1231 show_token_args(tk);
1232 break;
1233 case TK_IND :
1234 printf("token(TK_IND)");
1235 show_token_args(tk);
1236 break;
1237 case TK_NEL :
1238 printf("token(TK_NEL)");
1239 show_token_args(tk);
1240 break;
1241 case TK_HTS :
1242 printf("token(TK_HTS)");
1243 show_token_args(tk);
1244 break;
1245 case TK_RI :
1246 printf("token(TK_RI)");
1247 show_token_args(tk);
1248 break;
1249 case TK_SS2 :
1250 printf("token(TK_SS2)");
1251 show_token_args(tk);
1252 break;
1253 case TK_SS3 :
1254 printf("token(TK_SS3)");
1255 show_token_args(tk);
1256 break;
1257 case TK_DECID :
1258 printf("token(TK_DECID)");
1259 show_token_args(tk);
1260 break;
1261 case TK_NULL :
1262 return;
1263 default :
1264 printf("unknown token <%o>",tk->tk_type);
1265 show_token_args(tk);
1266 break;
1267 }
1268 printf("\n");
1269 }
1270 #endif /* DEBUG */
1271