1
/* $XFree86: xc/programs/xtrap/xtrapchar.c,v 1.2 2001/11/19 15:33:41 tsi Exp $ */
8
* Revision 1.1.2.2 1993/12/14 12:37:15 Kenneth_Miller
9
* ANSI-standardize code and turn client build on
10
* [1993/12/09 20:15:33 Kenneth_Miller]
14
#if !defined(lint) && 0
15
static char *rcsid = "@(#)RCSfile: xtrapchar.c,v $ Revision: 1.1.2.2 $ (DEC) Date: 1993/12/14 12:37:15 $";
17
/*****************************************************************************
18
Copyright 1987, 1988, 1989, 1990, 1991, 1993 by Digital Equipment Corp.,
21
Permission to use, copy, modify, and distribute this software and its
22
documentation for any purpose and without fee is hereby granted,
23
provided that the above copyright notice appear in all copies and that
24
both that copyright notice and this permission notice appear in
25
supporting documentation, and that the name of Digital not be
26
used in advertising or publicity pertaining to distribution of the
27
software without specific, written prior permission.
29
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
30
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
31
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
32
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
34
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37
*****************************************************************************/
38
#define ProgName "xtrapchar"
41
** FACILITY: xtrapchar - Converts ANSI character sequences to X.
43
** MODULE DESCRIPTION:
45
** Parses ANSI character sequences including application program
46
** sequences to synthesize input events to X Window servers
47
** using the XTrap server extension. Additionally, this main
48
** module is designed to be used with the voice
49
** recognition systems which will allow voice input into X Servers.
55
** CREATION DATE: March 23, 1991
59
** Accepts non-buffered Ascii characters as input and
60
** performs a table look-up to determine what the corresponding
61
** X actions are to be performed.
63
** Uses chparse() which was contributed to DECUS C by Roy
64
** Lomicka and later revised by Martin Minow and myself.
65
** Also, getopt() is used to parse the command
66
** line arguments prior to calling XtAppInitialize().
67
** Currently only the -v argument is supported to indicate
68
** echoing of characters received for debugging
74
** This program has *only* been used with Digital Workstations
75
** using the LK201 compatible keyboard. Though reasonable
76
** effort was done to maintain portability, no claims are made
77
** as to the current level of portability to non-DEC servers
84
#include <X11/extensions/xtraplib.h>
85
#include <X11/extensions/xtraplibp.h>
86
#include <X11/keysym.h>
91
#define globalref extern
99
/* Special private indicators */
128
static BOOL verbose_flag = FALSE;
129
static INT16 column = 0;
130
static int state = NUL; /* Parser state (n.z. if incomplete) */
132
static BOOL passive_shift; /* Cap's assumed? */
133
static BOOL passive_ctrl; /* Control key assumed? */
134
static BOOL shift; /* Cap's on? */
135
static BOOL ctrl; /* Control key? */
136
static BOOL alt; /* Alt key? */
143
#define _AdjustCol(length) \
144
if ((column += length) >= 79) \
150
static void KeyClick(XETC *tc, KeyCode keycode)
152
if (passive_ctrl && !ctrl)
154
XESimulateXEventRequest(tc, KeyPress, ctrl_code, 0, 0, 0);
156
if (passive_shift && !shift)
158
XESimulateXEventRequest(tc, KeyPress, shift_code, 0, 0, 0);
160
XESimulateXEventRequest(tc, KeyPress, keycode, 0, 0, 0);
161
XESimulateXEventRequest(tc, KeyRelease, keycode, 0, 0, 0);
162
if (passive_shift && !shift)
164
XESimulateXEventRequest(tc, KeyRelease, shift_code, 0, 0, 0);
166
if (passive_ctrl && !ctrl)
168
XESimulateXEventRequest(tc, KeyRelease, ctrl_code, 0, 0, 0);
170
passive_ctrl = passive_shift = FALSE; /* Action's been completed */
176
** FORWARD DECLARATIONS
179
static int get_csi_key ( XETC *tc , int private , int param [],
180
int nparam , int inter [], int ninter , int final );
181
static int get_ss3_key ( XETC *tc , int private , int param [],
182
int nparam , int inter [], int ninter , int final );
183
static void send_special ( XETC *tc , int private , int param [],
184
int nparam , int inter [], int ninter , int final );
185
static KeyCode get_typical_char ( XETC *tc , CARD32 keysym);
186
static KeyCode get_keycode ( XETC *tc , KeySym keysym);
190
main(int argc, char *argv[])
194
XETrapGetCurRep ret_cur;
201
/* ESC & CSI Parsing variables */
204
int private; /* Sequence private char, 'X' if error */
205
int param[NPARAM]; /* numeric param, starting at param[1] */
206
int nparam; /* Number of parameters */
207
int inter[NINTER]; /* intermediate char, starting at [1] */
208
int ninter; /* Number of intermediates */
209
int final; /* Sequence terminator */
214
popterr = XEgetopterr();
216
*popterr = 0; /* don't complain about -d for display */
217
while ((ch = getopt(argc, argv, "d:v")) != EOF)
224
case 'd': /* -display, let's let the toolkit parse it */
230
appW = XtAppInitialize(&app,"XTrap",(XrmOptionDescList)NULL,(Cardinal)0L,
231
(int *)&argc, (String *)argv, NULL,(ArgList)&tmp,
234
dpy = XtDisplay(appW);
237
printf("Display: %s \n", DisplayString(dpy));
239
if ((tc = XECreateTC(dpy,0L, NULL)) == False)
241
fprintf(stderr,"%s: could not initialize XTrap extension\n", ProgName);
244
root = RootWindow(dpy,DefaultScreen(dpy));
245
(void)XEStartTrapRequest(tc);
246
alt_code = XKeysymToKeycode(tc->dpy,XK_Alt_L);
247
ctrl_code = XKeysymToKeycode(tc->dpy,XK_Control_L);
248
shift_code = XKeysymToKeycode(tc->dpy,XK_Shift_L);
254
(void)XEGetCurrentRequest(tc,&ret_cur);
255
XEPrintCurrent(stderr,&ret_cur);
258
column = 0; /* if displaying char's, don't go beyond 80 columns */
260
while ((ch = chparse(max_delay, rest_delay, &state, &private, param,
261
&nparam, inter, &ninter, &final)) != -1)
265
continue; /* timeout condition */
267
if ((!ferror(stdin)) && (!feof(stdin)) && (state == 0))
268
{ /* we got something */
271
case CSI: /* Control Sequence */
272
keycode = get_csi_key(tc, private, param, nparam, inter,
275
KeyClick(tc, keycode);
277
case SS3: /* Keypad stuff */
278
keycode = get_ss3_key(tc, private, param, nparam, inter,
281
KeyClick(tc, keycode);
283
case APC: /* Application Cmd (Button's, Press, Release) */
284
send_special(tc, private, param, nparam, inter, ninter,
287
case ESC: /* Escape Sequence */
289
if (!(keycode = XKeysymToKeycode(tc->dpy,XK_Escape)))
290
{ /* must be an LK201 keyboard */
291
BOOL orig_ctrl = ctrl;
293
* the following is kind of strange. We need to
294
* have ctrl TRUE for get_typical_char() to
295
* report the verbose message correctly. We
296
* can't use passive_ctrl cause it resets it.
297
* Then, for KeyClick(), ctrl has to be FALSE
298
* and passive_ctrl has to be TRUE in order for
299
* us to get the desired <CTRL>[ to simulate
300
* an escape key. Once it's all done, we need
301
* to return ctrl to whatever it was and clear
304
ctrl = TRUE; /* for get_typical_char */
305
keycode = get_typical_char(tc, (CARD32)'[');
306
ctrl = FALSE; /* for KeyClick */
307
passive_ctrl = TRUE; /* for KeyClick */
308
KeyClick(tc, keycode);
309
passive_ctrl = FALSE; /* to continue */
310
ctrl = orig_ctrl; /* to continue */
314
KeyClick(tc, keycode);
317
_AdjustCol(strlen("<ESC>"));
321
/* send private (if valid) */
322
if (private != NUL && private != 'X' &&
323
(keycode = get_typical_char(tc, (CARD32)private)))
324
KeyClick(tc, keycode);
325
/* send addt'l parameters, if any */
326
for (i = 1; i <= nparam; i++)
327
if ((keycode = get_typical_char(tc, (CARD32)param[i])))
328
KeyClick(tc, keycode);
329
/* send intermediate's, if any */
330
for (i = 1; i <= ninter; i++)
331
if ((keycode = get_typical_char(tc, (CARD32)inter[i])))
332
KeyClick(tc, keycode);
333
/* send final character */
334
if ((keycode = get_typical_char(tc, (CARD32)final)))
335
KeyClick(tc, keycode);
338
case DCS: /* We don't deal with these */
343
printf("Ignoring the following: ");
344
dumpsequence(state, ch, private, param, nparam,
345
inter, ninter, final, &column);
348
default: /* typical character */
349
keycode = get_typical_char(tc, (CARD32)ch);
351
KeyClick(tc, keycode);
357
if (ferror(stdin) || state != 0)
359
perror("Error occurred parsing input characters!\n");
364
/* Clean things up */
366
(void)XCloseDisplay(dpy);
371
static int get_csi_key(tc, private, param, nparam, inter, ninter, final)
382
switch ((char )final)
384
case 'A': keysym = XK_Up; break;
385
case 'B': keysym = XK_Down; break;
386
case 'C': keysym = XK_Right; break;
387
case 'D': keysym = XK_Left; break;
389
dumpsequence(state, CSI, private, param, nparam,
390
inter, ninter, final, &column);
394
case 1: keysym = XK_Find; break;
395
case 2: keysym = XK_Insert; break;
397
case 3: keysym = DXK_Remove; break;
399
case 4: keysym = XK_Select; break;
400
case 5: keysym = XK_Prior; break;
401
case 6: keysym = XK_Next; break;
402
case 17: keysym = XK_F6; break;
403
case 18: keysym = XK_F7; break;
404
case 19: keysym = XK_F8; break;
405
case 20: keysym = XK_F9; break;
406
case 21: keysym = XK_F10; break;
407
case 23: keysym = XK_F11; break;
408
case 24: keysym = XK_F12; break;
409
case 25: keysym = XK_F13; break;
410
case 26: keysym = XK_F14; break;
411
case 28: keysym = XK_Help; break;
412
case 29: keysym = XK_Menu; break;
413
case 31: keysym = XK_F17; break;
414
case 32: keysym = XK_F18; break;
415
case 33: keysym = XK_F19; break;
416
case 34: keysym = XK_F20; break;
418
dumpsequence(state, CSI, private, param, nparam,
419
inter, ninter, final, &column);
422
return(get_keycode(tc, keysym));
426
* XTrap special sequences:
427
* ButtonPress: <APC>=!X (where 'X' is 'A', 'B', or 'C'
428
* for MB1, MB2, MB3 respectively)
429
* ButtonRelease: <APC>="X (where 'X' is 'A', 'B', or 'C'
430
* for MB1, MB2, MB3 respectively)
431
* ButtonClick: <APC>=#X (where 'X' is 'A', 'B', or 'C'
432
* for MB1, MB2, MB3 respectively)
434
* AltRelease: <APC>=%~
435
* CtrlPress: <APC>=(~
436
* CtrlRelease: <APC>=)~
437
* ShiftPress: <APC>=+~
438
* ShiftRelease: <APC>=-~
439
* MotionNotify: <APC>>;X;Y~ (where 'X' is the X coord and 'Y'
440
* is the Y coord of the desired
442
* Relative MotionNotify:
443
* <APC>?;X;Y~ (where 'X' is the X coord and 'Y'
444
* is the Y coord of the desired
448
static void send_special(tc, private, param, nparam, inter, ninter, final)
457
case DPRIVATE: /* default APC */
459
{ /* Not my sequence */
460
dumpsequence(state, APC, private, param, nparam,
461
inter, ninter, final, &column);
474
detail = (final - 'A' + 1);
475
if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
476
&y,&wx,&wy,&sm) == False)
478
fprintf(stderr, "\nPointer's not on screen 0!\n");
482
XESimulateXEventRequest(tc, ButtonPress, detail,
486
_AdjustCol(strlen("<MB%d-Press> ")-1);
487
printf("<MB%d-Press> ", detail);
492
detail = (final - 'A' + 1);
493
if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
494
&y,&wx,&wy,&sm) == False)
496
fprintf(stderr, "\nPointer's not on screen 0!\n");
500
XESimulateXEventRequest(tc, ButtonRelease, detail,
504
_AdjustCol(strlen("<MB%d-Release> ")-1);
505
printf("<MB%d-Release> ", detail);
510
detail = (final - 'A' + 1);
511
if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,
515
fprintf(stderr, "\nPointer's not on screen 0!\n");
519
XESimulateXEventRequest(tc,ButtonPress,
521
XESimulateXEventRequest(tc,ButtonRelease,
525
_AdjustCol(strlen("<MB%d> ")-1);
526
printf("<MB%d> ", detail);
532
XESimulateXEventRequest(tc,KeyPress,alt_code,0,0,0);
536
XESimulateXEventRequest(tc,KeyRelease,alt_code,0,0,0);
540
XESimulateXEventRequest(tc,KeyPress,shift_code,0,0,0);
544
XESimulateXEventRequest(tc,KeyRelease,shift_code,
549
XESimulateXEventRequest(tc,KeyPress,ctrl_code,0,0,0);
553
XESimulateXEventRequest(tc,KeyRelease,ctrl_code,0,0,0);
556
fprintf(stderr, "\nInvalid Sequence!\n");
557
dumpsequence(state, APC, private, param, nparam,
558
inter, ninter, final, &column);
564
{ /* Not my sequence */
565
dumpsequence(state, APC, private, param, nparam,
566
inter, ninter, final, &column);
575
XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
578
_AdjustCol(strlen("<M %d,%d> ")+3);
579
printf("<M %d,%d> ",x,y);
585
{ /* Not my sequence */
586
dumpsequence(state, APC, private, param, nparam,
587
inter, ninter, final, &column);
596
if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,&wx,&wy,&sm)
599
fprintf(stderr, "\nPointer's not on screen 0!\n");
602
{ /* We're ready to go */
605
XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
608
_AdjustCol(strlen("<RM ddd+sddd,dddd+sdddd> "));
609
printf("<RM %d+%d,%d+%d> ",x-param[2],param[3],
610
y-param[3],param[3]);
615
dumpsequence(state, APC, private, param, nparam,
616
inter, ninter, final, &column);
622
static int get_ss3_key(tc, private, param, nparam, inter, ninter, final)
633
switch ((char )final)
635
case 'A': keysym = XK_Up; break;
636
case 'B': keysym = XK_Down; break;
637
case 'C': keysym = XK_Right; break;
638
case 'D': keysym = XK_Left; break;
639
case 'p': keysym = XK_KP_0; break;
640
case 'q': keysym = XK_KP_1; break;
641
case 'r': keysym = XK_KP_2; break;
642
case 's': keysym = XK_KP_3; break;
643
case 't': keysym = XK_KP_4; break;
644
case 'u': keysym = XK_KP_5; break;
645
case 'v': keysym = XK_KP_6; break;
646
case 'w': keysym = XK_KP_7; break;
647
case 'x': keysym = XK_KP_8; break;
648
case 'y': keysym = XK_KP_9; break;
649
case 'm': keysym = XK_KP_Subtract; break;
650
case 'l': keysym = XK_KP_Separator; break;
651
case 'n': keysym = XK_KP_Decimal; break;
652
case 'M': keysym = XK_KP_Enter; break;
653
case 'P': keysym = XK_KP_F1; break;
654
case 'Q': keysym = XK_KP_F2; break;
655
case 'R': keysym = XK_KP_F3; break;
656
case 'S': keysym = XK_KP_F4; break;
658
dumpsequence(state, SS3, private, param, nparam,
659
inter, ninter, final, &column);
665
return(get_keycode(tc, keysym));
668
static KeyCode get_typical_char(tc, keysym)
676
case 0x09: keysym = XK_Tab; break;
677
case 0x0d: keysym = XK_Return; break;
678
case 0x7f: keysym = XK_Delete; break;
679
case ESC: keysym = XK_Escape; break;
682
passive_shift = (keysym >= XK_A && keysym <= XK_Z) ? TRUE : FALSE;
684
{ /* Special case shift's */
685
case '!': case '"': case '@': case '#': case '$':
686
case '%': case '^': case '&': case '*': case '(':
687
case ')': case '_': case '+': case '{': case '}':
688
case '|': case ':': case '>': case '?': case '~':
689
passive_shift = TRUE;
692
if (keysym >= 1 && keysym <= 26)
699
passive_ctrl = FALSE;
702
return(get_keycode(tc, keysym));
705
static KeyCode get_keycode(XETC *tc, KeySym keysym)
707
char *keystr = (char *)XKeysymToString(keysym);
710
keystr = (keystr == NULL) ? "unknown" : keystr;
713
if (shift || passive_shift)
715
_AdjustCol(strlen("<SHIFT>"));
720
_AdjustCol(strlen("<ALT>"));
723
if (ctrl || passive_ctrl)
725
_AdjustCol(strlen("<CTRL>"));
728
_AdjustCol(strlen(keystr)+1);
729
printf("%s ", keystr);
731
if (!(keycode = XKeysymToKeycode(tc->dpy,keysym)))
733
fprintf(stderr,"\n[%s ('%%0x%04x') returns bad Keycode, ignored]\n",
734
keystr, (unsigned int)keysym);