1876ff6feSmrg/* $XFree86: xc/programs/xtrap/xtrapchar.c,v 1.2 2001/11/19 15:33:41 tsi Exp $ */
2876ff6feSmrg/*
3876ff6feSmrg * @DEC_COPYRIGHT@
4876ff6feSmrg */
5876ff6feSmrg/*
6876ff6feSmrg * HISTORY
7876ff6feSmrg * Log: xtrapchar.c,v $
8876ff6feSmrg * Revision 1.1.2.2  1993/12/14  12:37:15  Kenneth_Miller
9876ff6feSmrg * 	ANSI-standardize code and turn client build on
10876ff6feSmrg * 	[1993/12/09  20:15:33  Kenneth_Miller]
11876ff6feSmrg *
12876ff6feSmrg * EndLog$
13876ff6feSmrg */
14876ff6feSmrg#if !defined(lint) && 0
15876ff6feSmrgstatic char *rcsid = "@(#)RCSfile: xtrapchar.c,v $ Revision: 1.1.2.2 $ (DEC) Date: 1993/12/14 12:37:15 $";
16876ff6feSmrg#endif
17876ff6feSmrg/*****************************************************************************
18876ff6feSmrgCopyright 1987, 1988, 1989, 1990, 1991, 1993 by Digital Equipment Corp.,
19876ff6feSmrgMaynard, MA
20876ff6feSmrg
21876ff6feSmrgPermission to use, copy, modify, and distribute this software and its
22876ff6feSmrgdocumentation for any purpose and without fee is hereby granted,
23876ff6feSmrgprovided that the above copyright notice appear in all copies and that
24876ff6feSmrgboth that copyright notice and this permission notice appear in
25876ff6feSmrgsupporting documentation, and that the name of Digital not be
26876ff6feSmrgused in advertising or publicity pertaining to distribution of the
27876ff6feSmrgsoftware without specific, written prior permission.
28876ff6feSmrg
29876ff6feSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
30876ff6feSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
31876ff6feSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
32876ff6feSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33876ff6feSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
34876ff6feSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35876ff6feSmrgSOFTWARE.
36876ff6feSmrg
37876ff6feSmrg*****************************************************************************/
38876ff6feSmrg#define ProgName "xtrapchar"
39876ff6feSmrg/*
40876ff6feSmrg**++
41876ff6feSmrg**  FACILITY:  xtrapchar - Converts ANSI character sequences to X.
42876ff6feSmrg**
43876ff6feSmrg**  MODULE DESCRIPTION:
44876ff6feSmrg**
45876ff6feSmrg**      Parses ANSI character sequences including application program
46876ff6feSmrg**      sequences to synthesize input events to X Window servers
47876ff6feSmrg**      using the XTrap server extension.  Additionally, this main
48876ff6feSmrg**      module is designed to be used with the voice
49876ff6feSmrg**      recognition systems which will allow voice input into X Servers.
50876ff6feSmrg**
51876ff6feSmrg**  AUTHORS:
52876ff6feSmrg**
53876ff6feSmrg**      Kenneth B. Miller
54876ff6feSmrg**
55876ff6feSmrg**  CREATION DATE:  March 23, 1991
56876ff6feSmrg**
57876ff6feSmrg**  DESIGN ISSUES:
58876ff6feSmrg**
59876ff6feSmrg**      Accepts non-buffered Ascii characters as input and
60876ff6feSmrg**      performs a table look-up to determine what the corresponding
61876ff6feSmrg**      X actions are to be performed.
62876ff6feSmrg**
63876ff6feSmrg**      Uses chparse() which was contributed to DECUS C by Roy
64876ff6feSmrg**      Lomicka and later revised by Martin Minow and myself.
65876ff6feSmrg**      Also, getopt() is used to parse the command
66876ff6feSmrg**      line arguments prior to calling XtAppInitialize().
67876ff6feSmrg**      Currently only the -v argument is supported to indicate
68876ff6feSmrg**      echoing of characters received for debugging
69876ff6feSmrg**      purposes.
70876ff6feSmrg**
71876ff6feSmrg**
72876ff6feSmrg**  CAVEAT:
73876ff6feSmrg**
74876ff6feSmrg**      This program has *only* been used with Digital Workstations
75876ff6feSmrg**      using the LK201 compatible keyboard.  Though reasonable
76876ff6feSmrg**      effort was done to maintain portability, no claims are made
77876ff6feSmrg**      as to the current level of portability to non-DEC servers
78876ff6feSmrg**      for this program.
79876ff6feSmrg**--
80876ff6feSmrg*/
81876ff6feSmrg#include <unistd.h>
82876ff6feSmrg#include <stdlib.h>
83876ff6feSmrg#include <ctype.h>
84876ff6feSmrg#include <X11/extensions/xtraplib.h>
85876ff6feSmrg#include <X11/extensions/xtraplibp.h>
86876ff6feSmrg#include <X11/keysym.h>
87876ff6feSmrg
88876ff6feSmrg#include "chparse.h"
89876ff6feSmrg
90876ff6feSmrg#ifndef vaxc
91876ff6feSmrg#define globalref extern
92876ff6feSmrg#endif
93876ff6feSmrg#ifdef Lynx
94876ff6feSmrgextern char *optarg;
95876ff6feSmrgextern int optind;
96876ff6feSmrgextern int opterr;
97876ff6feSmrg#endif
98876ff6feSmrg
99876ff6feSmrg    /* Special private indicators */
100876ff6feSmrg#define BPRESS      '!'
101876ff6feSmrg#define BRELEASE    '"'
102876ff6feSmrg#define BCLICK      '#'
103876ff6feSmrg#define APRESS      '$'
104876ff6feSmrg#define ARELEASE    '%'
105876ff6feSmrg#define CPRESS      '('
106876ff6feSmrg#define CRELEASE    ')'
107876ff6feSmrg#define SPRESS      '+'
108876ff6feSmrg#define SRELEASE    '-'
109876ff6feSmrg#define DPRIVATE    '='
110876ff6feSmrg#define MNOTIFY     '>'
111876ff6feSmrg#define RMNOTIFY    '?'
112876ff6feSmrg
113876ff6feSmrg#define	NPARAM	8
114876ff6feSmrg#define	NINTER	8
115876ff6feSmrg#define	NUL	0x00
116876ff6feSmrg#define	CAN	0x18
117876ff6feSmrg#define	SUB	0x1A
118876ff6feSmrg#define	ESC	0x1B
119876ff6feSmrg#define DEL	0x7F
120876ff6feSmrg#define SS3     0x8f
121876ff6feSmrg#define	DCS	0x90
122876ff6feSmrg#define	CSI	0x9B
123876ff6feSmrg#define	ST	0x9C
124876ff6feSmrg#define	OSC	0x9D
125876ff6feSmrg#define	PM	0x9E
126876ff6feSmrg#define	APC	0x9F
127876ff6feSmrg
128876ff6feSmrgstatic BOOL     verbose_flag = FALSE;
129876ff6feSmrgstatic INT16    column = 0;
130876ff6feSmrgstatic int	state = NUL;	/* Parser state (n.z. if incomplete)	*/
131876ff6feSmrgstatic	Window root;
132876ff6feSmrgstatic BOOL passive_shift; /* Cap's assumed?                       */
133876ff6feSmrgstatic BOOL passive_ctrl;  /* Control key assumed?                 */
134876ff6feSmrgstatic BOOL shift;         /* Cap's on?                            */
135876ff6feSmrgstatic BOOL ctrl;          /* Control key?                         */
136876ff6feSmrgstatic BOOL alt;           /* Alt key?                             */
137d41660beSmrgstatic KeyCode alt_code;
138d41660beSmrgstatic KeyCode ctrl_code;
139d41660beSmrgstatic KeyCode shift_code;
140876ff6feSmrg
141876ff6feSmrg
142876ff6feSmrg
143876ff6feSmrg#define _AdjustCol(length) \
144876ff6feSmrg    if ((column += length) >= 79) \
145876ff6feSmrg    { \
146876ff6feSmrg        printf("\n"); \
147876ff6feSmrg        column = length; \
148876ff6feSmrg    }
149876ff6feSmrg
150876ff6feSmrgstatic void KeyClick(XETC *tc, KeyCode keycode)
151876ff6feSmrg{
152876ff6feSmrg    if (passive_ctrl && !ctrl)
153876ff6feSmrg    {
154876ff6feSmrg        XESimulateXEventRequest(tc, KeyPress, ctrl_code, 0, 0, 0);
155876ff6feSmrg    }
156876ff6feSmrg    if (passive_shift && !shift)
157876ff6feSmrg    {
158876ff6feSmrg        XESimulateXEventRequest(tc, KeyPress, shift_code, 0, 0, 0);
159876ff6feSmrg    }
160876ff6feSmrg    XESimulateXEventRequest(tc, KeyPress, keycode, 0, 0, 0);
161876ff6feSmrg    XESimulateXEventRequest(tc, KeyRelease, keycode, 0, 0, 0);
162876ff6feSmrg    if (passive_shift && !shift)
163876ff6feSmrg    {
164876ff6feSmrg        XESimulateXEventRequest(tc, KeyRelease, shift_code, 0, 0, 0);
165876ff6feSmrg    }
166876ff6feSmrg    if (passive_ctrl && !ctrl)
167876ff6feSmrg    {
168876ff6feSmrg        XESimulateXEventRequest(tc, KeyRelease, ctrl_code, 0, 0, 0);
169876ff6feSmrg    }
170876ff6feSmrg    passive_ctrl = passive_shift = FALSE;   /* Action's been completed */
171876ff6feSmrg}
172876ff6feSmrg
173876ff6feSmrg
174876ff6feSmrg/*
175876ff6feSmrg**
176876ff6feSmrg** FORWARD DECLARATIONS
177876ff6feSmrg**
178876ff6feSmrg*/
179876ff6feSmrgstatic int get_csi_key ( XETC *tc , int private , int param [],
180876ff6feSmrg    int nparam , int inter [], int ninter , int final );
181876ff6feSmrgstatic int get_ss3_key ( XETC *tc , int private , int param [],
182876ff6feSmrg    int nparam , int inter [], int ninter , int final );
183876ff6feSmrgstatic void send_special ( XETC *tc , int private , int param [],
184876ff6feSmrg    int nparam , int inter [], int ninter , int final );
185876ff6feSmrgstatic KeyCode get_typical_char ( XETC *tc , CARD32 keysym);
186876ff6feSmrgstatic KeyCode get_keycode ( XETC *tc , KeySym keysym);
187876ff6feSmrg
188876ff6feSmrg
189876ff6feSmrgint
190876ff6feSmrgmain(int argc, char *argv[])
191876ff6feSmrg{
192876ff6feSmrg    Widget appW;
193876ff6feSmrg    Display *dpy;
194876ff6feSmrg    XETrapGetCurRep   ret_cur;
195876ff6feSmrg    XETC    *tc;
196876ff6feSmrg    XtAppContext app;
197876ff6feSmrg    char *tmp = NULL;
198876ff6feSmrg    INT16 ch;
199876ff6feSmrg    INT16 i;
200876ff6feSmrg    KeyCode keycode;
201876ff6feSmrg    /* ESC & CSI Parsing variables */
202876ff6feSmrg    int	max_delay  = 3;
203876ff6feSmrg    int	rest_delay = 2;
204876ff6feSmrg    int	private;        /* Sequence private char, 'X' if error	*/
205876ff6feSmrg    int	param[NPARAM];	/* numeric param, starting at param[1]	*/
206876ff6feSmrg    int	nparam;	        /* Number of parameters			*/
207876ff6feSmrg    int	inter[NINTER];	/* intermediate char, starting at [1]	*/
208876ff6feSmrg    int	ninter;	        /* Number of intermediates		*/
209876ff6feSmrg    int	final;  	/* Sequence terminator			*/
210876ff6feSmrg    int *popterr;
211876ff6feSmrg#ifndef vms
212876ff6feSmrg    popterr = &opterr;
213876ff6feSmrg#else
214876ff6feSmrg    popterr = XEgetopterr();
215876ff6feSmrg#endif
216876ff6feSmrg    *popterr = 0; /* don't complain about -d for display */
217876ff6feSmrg    while ((ch = getopt(argc, argv, "d:v")) != EOF)
218876ff6feSmrg    {
219876ff6feSmrg        switch(ch)
220876ff6feSmrg        {
221876ff6feSmrg            case 'v':
222876ff6feSmrg                verbose_flag = TRUE;
223876ff6feSmrg                break;
224876ff6feSmrg            case 'd':   /* -display, let's let the toolkit parse it */
225876ff6feSmrg                break;
226876ff6feSmrg            default:
227876ff6feSmrg                break;
228876ff6feSmrg        }
229876ff6feSmrg    }
230876ff6feSmrg    appW = XtAppInitialize(&app,"XTrap",(XrmOptionDescList)NULL,(Cardinal)0L,
231876ff6feSmrg        (int *)&argc, (String *)argv, NULL,(ArgList)&tmp,
232876ff6feSmrg        (Cardinal)0);
233876ff6feSmrg
234876ff6feSmrg    dpy = XtDisplay(appW);
235876ff6feSmrg    if (verbose_flag)
236876ff6feSmrg    {
237876ff6feSmrg        printf("Display:  %s \n", DisplayString(dpy));
238876ff6feSmrg    }
239d41660beSmrg    if ((tc = XECreateTC(dpy,0L, NULL)) == NULL)
240876ff6feSmrg    {
241876ff6feSmrg        fprintf(stderr,"%s: could not initialize XTrap extension\n", ProgName);
242876ff6feSmrg        exit (1L);
243876ff6feSmrg    }
244876ff6feSmrg    root = RootWindow(dpy,DefaultScreen(dpy));
245876ff6feSmrg    (void)XEStartTrapRequest(tc);
246876ff6feSmrg    alt_code   = XKeysymToKeycode(tc->dpy,XK_Alt_L);
247876ff6feSmrg    ctrl_code  = XKeysymToKeycode(tc->dpy,XK_Control_L);
248876ff6feSmrg    shift_code = XKeysymToKeycode(tc->dpy,XK_Shift_L);
249876ff6feSmrg
250876ff6feSmrg
251876ff6feSmrg
252876ff6feSmrg    if (verbose_flag)
253876ff6feSmrg    {
254876ff6feSmrg        (void)XEGetCurrentRequest(tc,&ret_cur);
255876ff6feSmrg        XEPrintCurrent(stderr,&ret_cur);
256876ff6feSmrg    }
257876ff6feSmrg
258876ff6feSmrg    column = 0; /* if displaying char's, don't go beyond 80 columns */
259876ff6feSmrg
260876ff6feSmrg    while ((ch = chparse(max_delay, rest_delay, &state, &private, param,
261876ff6feSmrg        &nparam, inter, &ninter, &final)) != -1)
262876ff6feSmrg    {
263876ff6feSmrg        if (ch == -2)
264876ff6feSmrg        {
265876ff6feSmrg            continue;   /* timeout condition */
266876ff6feSmrg        }
267876ff6feSmrg        if ((!ferror(stdin)) && (!feof(stdin)) && (state == 0))
268876ff6feSmrg        {   /* we got something */
269876ff6feSmrg            switch(ch)
270876ff6feSmrg            {
271876ff6feSmrg                case CSI:   /* Control Sequence */
272876ff6feSmrg                    keycode = get_csi_key(tc, private, param, nparam, inter,
273876ff6feSmrg                        ninter, final);
274876ff6feSmrg                    if (keycode)
275876ff6feSmrg                        KeyClick(tc, keycode);
276876ff6feSmrg                    break;
277876ff6feSmrg                case SS3:   /* Keypad stuff */
278876ff6feSmrg                    keycode = get_ss3_key(tc, private, param, nparam, inter,
279876ff6feSmrg                        ninter, final);
280876ff6feSmrg                    if (keycode)
281876ff6feSmrg                        KeyClick(tc, keycode);
282876ff6feSmrg                    break;
283876ff6feSmrg                case APC:   /* Application Cmd (Button's, Press, Release) */
284876ff6feSmrg                    send_special(tc, private, param, nparam, inter, ninter,
285876ff6feSmrg                        final);
286876ff6feSmrg                    break;
287876ff6feSmrg                case ESC:   /* Escape Sequence */
288876ff6feSmrg                    /* send ESCAPE */
289876ff6feSmrg                    if (!(keycode = XKeysymToKeycode(tc->dpy,XK_Escape)))
290876ff6feSmrg                    {   /* must be an LK201 keyboard */
291876ff6feSmrg                        BOOL orig_ctrl = ctrl;
292876ff6feSmrg                        /*
293876ff6feSmrg                         * the following is kind of strange.  We need to
294876ff6feSmrg                         * have ctrl TRUE for get_typical_char() to
295876ff6feSmrg                         * report the verbose message correctly.  We
296876ff6feSmrg                         * can't use passive_ctrl cause it resets it.
297876ff6feSmrg                         * Then, for KeyClick(), ctrl has to be FALSE
298876ff6feSmrg                         * and passive_ctrl has to be TRUE in order for
299876ff6feSmrg                         * us to get the desired <CTRL>[ to simulate
300876ff6feSmrg                         * an escape key.  Once it's all done, we need
301876ff6feSmrg                         * to return ctrl to whatever it was and clear
302876ff6feSmrg                         * the passive_ctrl.
303876ff6feSmrg                         */
304876ff6feSmrg                        ctrl = TRUE;                /* for get_typical_char */
305876ff6feSmrg                        keycode = get_typical_char(tc, (CARD32)'[');
306876ff6feSmrg                        ctrl         = FALSE;       /* for KeyClick */
307876ff6feSmrg                        passive_ctrl = TRUE;        /* for KeyClick */
308876ff6feSmrg                        KeyClick(tc, keycode);
309876ff6feSmrg                        passive_ctrl  = FALSE;      /* to continue */
310876ff6feSmrg                        ctrl          = orig_ctrl;  /* to continue */
311876ff6feSmrg                    }
312876ff6feSmrg                    else
313876ff6feSmrg                    {
314876ff6feSmrg                        KeyClick(tc, keycode);
315876ff6feSmrg                        if (verbose_flag)
316876ff6feSmrg                        {
317876ff6feSmrg                            _AdjustCol(strlen("<ESC>"));
318876ff6feSmrg                            printf("<ESC>");
319876ff6feSmrg                        }
320876ff6feSmrg                    }
321876ff6feSmrg                    /* send private (if valid) */
322876ff6feSmrg        	    if (private != NUL && private != 'X' &&
323876ff6feSmrg                       (keycode = get_typical_char(tc, (CARD32)private)))
324876ff6feSmrg                        KeyClick(tc, keycode);
325876ff6feSmrg                    /* send addt'l parameters, if any */
326876ff6feSmrg                    for (i = 1; i <= nparam; i++)
327876ff6feSmrg                        if ((keycode = get_typical_char(tc, (CARD32)param[i])))
328876ff6feSmrg                            KeyClick(tc, keycode);
329876ff6feSmrg                    /* send intermediate's, if any */
330876ff6feSmrg                    for (i = 1; i <= ninter; i++)
331876ff6feSmrg                        if ((keycode = get_typical_char(tc, (CARD32)inter[i])))
332876ff6feSmrg                            KeyClick(tc, keycode);
333876ff6feSmrg                    /* send final character */
334876ff6feSmrg                    if ((keycode = get_typical_char(tc, (CARD32)final)))
335876ff6feSmrg                        KeyClick(tc, keycode);
336876ff6feSmrg                    break;
337876ff6feSmrg
338876ff6feSmrg                case DCS:   /* We don't deal with these */
339876ff6feSmrg                case OSC:
340876ff6feSmrg                case PM:
341876ff6feSmrg                    if (verbose_flag)
342876ff6feSmrg                    {
343876ff6feSmrg                        printf("Ignoring the following: ");
344876ff6feSmrg                        dumpsequence(state, ch, private, param, nparam,
345876ff6feSmrg                            inter, ninter, final, &column);
346876ff6feSmrg                    }
347876ff6feSmrg                    break;
348876ff6feSmrg                default:    /* typical character */
349876ff6feSmrg                    keycode = get_typical_char(tc, (CARD32)ch);
350876ff6feSmrg                    if (keycode)
351876ff6feSmrg                        KeyClick(tc, keycode);
352876ff6feSmrg                    break;
353876ff6feSmrg            }
354876ff6feSmrg        }
355876ff6feSmrg        else
356876ff6feSmrg        {   /* error? */
357876ff6feSmrg            if (ferror(stdin) || state != 0)
358876ff6feSmrg            {
359876ff6feSmrg                perror("Error occurred parsing input characters!\n");
360876ff6feSmrg            }
361876ff6feSmrg            break;
362876ff6feSmrg        }
363876ff6feSmrg    }
364876ff6feSmrg    /* Clean things up */
365876ff6feSmrg    XEFreeTC(tc);
366876ff6feSmrg    (void)XCloseDisplay(dpy);
367876ff6feSmrg
368876ff6feSmrg    exit(0L);
369876ff6feSmrg}
370876ff6feSmrg
371d41660beSmrgstatic int get_csi_key(XETC *tc, int private,
372d41660beSmrg		       int param[], int nparam,
373d41660beSmrg		       int inter[], int ninter,
374d41660beSmrg		       int final)
375876ff6feSmrg{
376876ff6feSmrg    KeySym keysym = 0;
377876ff6feSmrg    switch(param[1])
378876ff6feSmrg    {
379876ff6feSmrg        case 0:
380876ff6feSmrg            switch ((char )final)
381876ff6feSmrg            {
382876ff6feSmrg                case 'A':    keysym = XK_Up;         break;
383876ff6feSmrg                case 'B':    keysym = XK_Down;       break;
384876ff6feSmrg                case 'C':    keysym = XK_Right;      break;
385876ff6feSmrg                case 'D':    keysym = XK_Left;       break;
386876ff6feSmrg                default:
387876ff6feSmrg                    dumpsequence(state, CSI, private, param, nparam,
388876ff6feSmrg                        inter, ninter, final, &column);
389876ff6feSmrg                    break;
390876ff6feSmrg            }
391876ff6feSmrg            break;
392876ff6feSmrg        case 1:     keysym = XK_Find;       break;
393876ff6feSmrg        case 2:     keysym = XK_Insert;     break;
394876ff6feSmrg#ifdef DXK_Remove
395876ff6feSmrg        case 3:     keysym = DXK_Remove;    break;
396876ff6feSmrg#endif
397876ff6feSmrg        case 4:     keysym = XK_Select;     break;
398876ff6feSmrg        case 5:     keysym = XK_Prior;      break;
399876ff6feSmrg        case 6:     keysym = XK_Next;       break;
400876ff6feSmrg        case 17:    keysym = XK_F6;         break;
401876ff6feSmrg        case 18:    keysym = XK_F7;         break;
402876ff6feSmrg        case 19:    keysym = XK_F8;         break;
403876ff6feSmrg        case 20:    keysym = XK_F9;         break;
404876ff6feSmrg        case 21:    keysym = XK_F10;        break;
405876ff6feSmrg        case 23:    keysym = XK_F11;        break;
406876ff6feSmrg        case 24:    keysym = XK_F12;        break;
407876ff6feSmrg        case 25:    keysym = XK_F13;        break;
408876ff6feSmrg        case 26:    keysym = XK_F14;        break;
409876ff6feSmrg        case 28:    keysym = XK_Help;       break;
410876ff6feSmrg        case 29:    keysym = XK_Menu;       break;
411876ff6feSmrg        case 31:    keysym = XK_F17;        break;
412876ff6feSmrg        case 32:    keysym = XK_F18;        break;
413876ff6feSmrg        case 33:    keysym = XK_F19;        break;
414876ff6feSmrg        case 34:    keysym = XK_F20;        break;
415876ff6feSmrg        default:
416876ff6feSmrg            dumpsequence(state, CSI, private, param, nparam,
417876ff6feSmrg                inter, ninter, final, &column);
418876ff6feSmrg    }
419876ff6feSmrg
420876ff6feSmrg    return(get_keycode(tc, keysym));
421876ff6feSmrg}
422876ff6feSmrg
423876ff6feSmrg    /*
424876ff6feSmrg     * XTrap special sequences:
425876ff6feSmrg     * ButtonPress:     <APC>=!X        (where 'X' is 'A', 'B', or 'C'
426876ff6feSmrg     *                                  for MB1, MB2, MB3 respectively)
427876ff6feSmrg     * ButtonRelease:   <APC>="X        (where 'X' is 'A', 'B', or 'C'
428876ff6feSmrg     *                                  for MB1, MB2, MB3 respectively)
429876ff6feSmrg     * ButtonClick:     <APC>=#X        (where 'X' is 'A', 'B', or 'C'
430876ff6feSmrg     *                                  for MB1, MB2, MB3 respectively)
431876ff6feSmrg     * AltPress:        <APC>=$~
432876ff6feSmrg     * AltRelease:      <APC>=%~
433876ff6feSmrg     * CtrlPress:       <APC>=(~
434876ff6feSmrg     * CtrlRelease:     <APC>=)~
435876ff6feSmrg     * ShiftPress:      <APC>=+~
436876ff6feSmrg     * ShiftRelease:    <APC>=-~
437876ff6feSmrg     * MotionNotify:    <APC>>;X;Y~     (where 'X' is the X coord and 'Y'
438876ff6feSmrg     *                                  is the Y coord of the desired
439876ff6feSmrg     *                                  pointer position)
440876ff6feSmrg     * Relative MotionNotify:
441876ff6feSmrg     *                  <APC>?;X;Y~     (where 'X' is the X coord and 'Y'
442876ff6feSmrg     *                                  is the Y coord of the desired
443876ff6feSmrg     *                                  pointer position)
444876ff6feSmrg     *
445876ff6feSmrg     */
446d41660beSmrgstatic void send_special(XETC *tc, int private,
447d41660beSmrg			 int param[], int nparam,
448d41660beSmrg			 int inter[], int ninter,
449d41660beSmrg			 int final)
450876ff6feSmrg{
451876ff6feSmrg    switch(private)
452876ff6feSmrg    {
453876ff6feSmrg        case DPRIVATE:   /* default APC */
454876ff6feSmrg            if (ninter != 1)
455876ff6feSmrg            {   /* Not my sequence */
456876ff6feSmrg                dumpsequence(state, APC, private, param, nparam,
457876ff6feSmrg                    inter, ninter, final, &column);
458876ff6feSmrg                return;
459876ff6feSmrg            }
460876ff6feSmrg            else
461876ff6feSmrg            {
462876ff6feSmrg                switch(inter[1])
463876ff6feSmrg                {
464876ff6feSmrg                    Window rid, wid;
465876ff6feSmrg                    int x, y, wx, wy;
466876ff6feSmrg                    unsigned int sm;
467876ff6feSmrg                    CARD8 detail;
468876ff6feSmrg
469876ff6feSmrg                    case BPRESS:
470876ff6feSmrg                        detail = (final - 'A' + 1);
471876ff6feSmrg                        if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
472876ff6feSmrg                            &y,&wx,&wy,&sm) == False)
473876ff6feSmrg                        {
474876ff6feSmrg                            fprintf(stderr, "\nPointer's not on screen 0!\n");
475876ff6feSmrg                        }
476876ff6feSmrg                        else
477876ff6feSmrg                        {
478876ff6feSmrg                            XESimulateXEventRequest(tc, ButtonPress, detail,
479876ff6feSmrg                                x, y, 0);
480876ff6feSmrg                            if (verbose_flag)
481876ff6feSmrg                            {
482876ff6feSmrg                                _AdjustCol(strlen("<MB%d-Press> ")-1);
483876ff6feSmrg                                printf("<MB%d-Press> ", detail);
484876ff6feSmrg                            }
485876ff6feSmrg                        }
486876ff6feSmrg                        break;
487876ff6feSmrg                    case BRELEASE:
488876ff6feSmrg                        detail = (final - 'A' + 1);
489876ff6feSmrg                        if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
490876ff6feSmrg                            &y,&wx,&wy,&sm) == False)
491876ff6feSmrg                        {
492876ff6feSmrg                            fprintf(stderr, "\nPointer's not on screen 0!\n");
493876ff6feSmrg                        }
494876ff6feSmrg                        else
495876ff6feSmrg                        {
496876ff6feSmrg                            XESimulateXEventRequest(tc, ButtonRelease, detail,
497876ff6feSmrg                                x,y,0);
498876ff6feSmrg                            if (verbose_flag)
499876ff6feSmrg                            {
500876ff6feSmrg                                _AdjustCol(strlen("<MB%d-Release> ")-1);
501876ff6feSmrg                                printf("<MB%d-Release> ", detail);
502876ff6feSmrg                            }
503876ff6feSmrg                        }
504876ff6feSmrg                        break;
505876ff6feSmrg                    case BCLICK:
506876ff6feSmrg                        detail = (final - 'A' + 1);
507876ff6feSmrg                        if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,
508876ff6feSmrg                            &wx,&wy,&sm)
509876ff6feSmrg                            == False)
510876ff6feSmrg                        {
511876ff6feSmrg                            fprintf(stderr, "\nPointer's not on screen 0!\n");
512876ff6feSmrg                        }
513876ff6feSmrg                        else
514876ff6feSmrg                        {
515876ff6feSmrg                            XESimulateXEventRequest(tc,ButtonPress,
516876ff6feSmrg                                detail,x,y,0);
517876ff6feSmrg                            XESimulateXEventRequest(tc,ButtonRelease,
518876ff6feSmrg                                detail,x,y,0);
519876ff6feSmrg                            if (verbose_flag)
520876ff6feSmrg                            {
521876ff6feSmrg                                _AdjustCol(strlen("<MB%d> ")-1);
522876ff6feSmrg                                printf("<MB%d> ", detail);
523876ff6feSmrg                            }
524876ff6feSmrg                        }
525876ff6feSmrg                        break;
526876ff6feSmrg                    case APRESS:
527876ff6feSmrg                        alt = TRUE;
528876ff6feSmrg                        XESimulateXEventRequest(tc,KeyPress,alt_code,0,0,0);
529876ff6feSmrg                        break;
530876ff6feSmrg                    case ARELEASE:
531876ff6feSmrg                        alt = FALSE;
532876ff6feSmrg                        XESimulateXEventRequest(tc,KeyRelease,alt_code,0,0,0);
533876ff6feSmrg                        break;
534876ff6feSmrg                    case SPRESS:
535876ff6feSmrg                        shift = TRUE;
536876ff6feSmrg                        XESimulateXEventRequest(tc,KeyPress,shift_code,0,0,0);
537876ff6feSmrg                        break;
538876ff6feSmrg                    case SRELEASE:
539876ff6feSmrg                        shift = FALSE;
540876ff6feSmrg                        XESimulateXEventRequest(tc,KeyRelease,shift_code,
541876ff6feSmrg                            0,0,0);
542876ff6feSmrg                        break;
543876ff6feSmrg                    case CPRESS:
544876ff6feSmrg                        ctrl = TRUE;
545876ff6feSmrg                        XESimulateXEventRequest(tc,KeyPress,ctrl_code,0,0,0);
546876ff6feSmrg                        break;
547876ff6feSmrg                    case CRELEASE:
548876ff6feSmrg                        ctrl = FALSE;
549876ff6feSmrg                        XESimulateXEventRequest(tc,KeyRelease,ctrl_code,0,0,0);
550876ff6feSmrg                        break;
551876ff6feSmrg                    default:
552876ff6feSmrg                        fprintf(stderr, "\nInvalid Sequence!\n");
553876ff6feSmrg                        dumpsequence(state, APC, private, param, nparam,
554876ff6feSmrg                            inter, ninter, final, &column);
555876ff6feSmrg                }
556876ff6feSmrg            }
557876ff6feSmrg            break;
558876ff6feSmrg        case MNOTIFY:
559876ff6feSmrg            if (nparam != 3)
560876ff6feSmrg            {   /* Not my sequence */
561876ff6feSmrg                dumpsequence(state, APC, private, param, nparam,
562876ff6feSmrg                    inter, ninter, final, &column);
563876ff6feSmrg                return;
564876ff6feSmrg            }
565876ff6feSmrg            else
566876ff6feSmrg            {
567876ff6feSmrg                int x, y;
568876ff6feSmrg
569876ff6feSmrg                x = param[2];
570876ff6feSmrg                y = param[3];
571876ff6feSmrg                XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
572876ff6feSmrg                if (verbose_flag)
573876ff6feSmrg                {
574876ff6feSmrg                    _AdjustCol(strlen("<M %d,%d> ")+3);
575876ff6feSmrg                    printf("<M %d,%d> ",x,y);
576876ff6feSmrg                }
577876ff6feSmrg            }
578876ff6feSmrg            break;
579876ff6feSmrg        case RMNOTIFY:
580876ff6feSmrg            if (nparam != 3)
581876ff6feSmrg            {   /* Not my sequence */
582876ff6feSmrg                dumpsequence(state, APC, private, param, nparam,
583876ff6feSmrg                    inter, ninter, final, &column);
584876ff6feSmrg                return;
585876ff6feSmrg            }
586876ff6feSmrg            else
587876ff6feSmrg            {
588876ff6feSmrg                Window rid, wid;
589876ff6feSmrg                int x, y, wx, wy;
590876ff6feSmrg                unsigned int sm;
591876ff6feSmrg
592876ff6feSmrg                if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,&wx,&wy,&sm)
593876ff6feSmrg                    == False)
594876ff6feSmrg                {
595876ff6feSmrg                    fprintf(stderr, "\nPointer's not on screen 0!\n");
596876ff6feSmrg                }
597876ff6feSmrg                else
598876ff6feSmrg                {   /* We're ready to go */
599876ff6feSmrg                    x += param[2];
600876ff6feSmrg                    y += param[3];
601876ff6feSmrg                    XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
602876ff6feSmrg                    if (verbose_flag)
603876ff6feSmrg                    {
604876ff6feSmrg                        _AdjustCol(strlen("<RM ddd+sddd,dddd+sdddd> "));
605876ff6feSmrg                        printf("<RM %d+%d,%d+%d> ",x-param[2],param[3],
606876ff6feSmrg                            y-param[3],param[3]);
607876ff6feSmrg                    }
608876ff6feSmrg                }
609876ff6feSmrg                break;
610876ff6feSmrg            default:
611876ff6feSmrg                dumpsequence(state, APC, private, param, nparam,
612876ff6feSmrg                    inter, ninter, final, &column);
613876ff6feSmrg                break;
614876ff6feSmrg        }
615876ff6feSmrg    }
616876ff6feSmrg}
617876ff6feSmrg
618d41660beSmrgstatic int get_ss3_key(XETC *tc, int private,
619d41660beSmrg		       int param[], int nparam,
620d41660beSmrg		       int inter[], int ninter,
621d41660beSmrg		       int final)
622876ff6feSmrg{
623876ff6feSmrg    KeySym keysym = 0;
624876ff6feSmrg    switch(param[1])
625876ff6feSmrg    {
626876ff6feSmrg        case 0:
627876ff6feSmrg            switch ((char )final)
628876ff6feSmrg            {
629876ff6feSmrg                case 'A':    keysym = XK_Up;            break;
630876ff6feSmrg                case 'B':    keysym = XK_Down;          break;
631876ff6feSmrg                case 'C':    keysym = XK_Right;         break;
632876ff6feSmrg                case 'D':    keysym = XK_Left;          break;
633876ff6feSmrg                case 'p':    keysym = XK_KP_0;          break;
634876ff6feSmrg                case 'q':    keysym = XK_KP_1;          break;
635876ff6feSmrg                case 'r':    keysym = XK_KP_2;          break;
636876ff6feSmrg                case 's':    keysym = XK_KP_3;          break;
637876ff6feSmrg                case 't':    keysym = XK_KP_4;          break;
638876ff6feSmrg                case 'u':    keysym = XK_KP_5;          break;
639876ff6feSmrg                case 'v':    keysym = XK_KP_6;          break;
640876ff6feSmrg                case 'w':    keysym = XK_KP_7;          break;
641876ff6feSmrg                case 'x':    keysym = XK_KP_8;          break;
642876ff6feSmrg                case 'y':    keysym = XK_KP_9;          break;
643876ff6feSmrg                case 'm':    keysym = XK_KP_Subtract;   break;
644876ff6feSmrg                case 'l':    keysym = XK_KP_Separator;  break;
645876ff6feSmrg                case 'n':    keysym = XK_KP_Decimal;    break;
646876ff6feSmrg                case 'M':    keysym = XK_KP_Enter;      break;
647876ff6feSmrg                case 'P':    keysym = XK_KP_F1;         break;
648876ff6feSmrg                case 'Q':    keysym = XK_KP_F2;         break;
649876ff6feSmrg                case 'R':    keysym = XK_KP_F3;         break;
650876ff6feSmrg                case 'S':    keysym = XK_KP_F4;         break;
651876ff6feSmrg                default:
652876ff6feSmrg                    dumpsequence(state, SS3, private, param, nparam,
653876ff6feSmrg                        inter, ninter, final, &column);
654876ff6feSmrg                    break;
655876ff6feSmrg            }
656876ff6feSmrg            break;
657876ff6feSmrg    }
658876ff6feSmrg
659876ff6feSmrg    return(get_keycode(tc, keysym));
660876ff6feSmrg}
661876ff6feSmrg
662d41660beSmrgstatic KeyCode get_typical_char(XETC *tc, CARD32 keysym)
663876ff6feSmrg{
664876ff6feSmrg    if (iscntrl(keysym))
665876ff6feSmrg    {
666876ff6feSmrg        switch(keysym)
667876ff6feSmrg        {
668876ff6feSmrg            case 0x09:  keysym = XK_Tab; break;
669876ff6feSmrg            case 0x0d:  keysym = XK_Return; break;
670876ff6feSmrg            case 0x7f:  keysym = XK_Delete; break;
671876ff6feSmrg            case ESC:   keysym = XK_Escape; break;
672876ff6feSmrg        }
673876ff6feSmrg    }
674876ff6feSmrg    passive_shift = (keysym >= XK_A && keysym <= XK_Z) ? TRUE : FALSE;
675876ff6feSmrg    switch(keysym)
676876ff6feSmrg    {   /* Special case shift's */
677876ff6feSmrg        case '!': case '"': case '@': case '#': case '$':
678876ff6feSmrg        case '%': case '^': case '&': case '*': case '(':
679876ff6feSmrg        case ')': case '_': case '+': case '{': case '}':
680876ff6feSmrg        case '|': case ':': case '>': case '?': case '~':
681876ff6feSmrg            passive_shift = TRUE;
682876ff6feSmrg    }
683876ff6feSmrg
684876ff6feSmrg    if (keysym >= 1 && keysym <= 26)
685876ff6feSmrg    {
686876ff6feSmrg        passive_ctrl  = TRUE;
687876ff6feSmrg        keysym += 'a' - 1;
688876ff6feSmrg    }
689876ff6feSmrg    else
690876ff6feSmrg    {
691876ff6feSmrg        passive_ctrl = FALSE;
692876ff6feSmrg    }
693876ff6feSmrg
694876ff6feSmrg    return(get_keycode(tc, keysym));
695876ff6feSmrg}
696876ff6feSmrg
697876ff6feSmrgstatic KeyCode get_keycode(XETC *tc, KeySym keysym)
698876ff6feSmrg{
699876ff6feSmrg    char *keystr = (char *)XKeysymToString(keysym);
700876ff6feSmrg    KeyCode keycode;
701876ff6feSmrg
702876ff6feSmrg    keystr = (keystr == NULL) ? "unknown" : keystr;
703876ff6feSmrg    if (verbose_flag)
704876ff6feSmrg    {
705876ff6feSmrg        if (shift || passive_shift)
706876ff6feSmrg        {
707876ff6feSmrg            _AdjustCol(strlen("<SHIFT>"));
708876ff6feSmrg            printf("<SHIFT>");
709876ff6feSmrg        }
710876ff6feSmrg        if (alt)
711876ff6feSmrg        {
712876ff6feSmrg            _AdjustCol(strlen("<ALT>"));
713876ff6feSmrg            printf("<ALT>");
714876ff6feSmrg        }
715876ff6feSmrg        if (ctrl || passive_ctrl)
716876ff6feSmrg        {
717876ff6feSmrg            _AdjustCol(strlen("<CTRL>"));
718876ff6feSmrg            printf("<CTRL>");
719876ff6feSmrg        }
720876ff6feSmrg        _AdjustCol(strlen(keystr)+1);
721876ff6feSmrg        printf("%s ", keystr);
722876ff6feSmrg    }
723876ff6feSmrg    if (!(keycode = XKeysymToKeycode(tc->dpy,keysym)))
724876ff6feSmrg    {
725876ff6feSmrg        fprintf(stderr,"\n[%s ('%%0x%04x') returns bad Keycode, ignored]\n",
726876ff6feSmrg            keystr, (unsigned int)keysym);
727876ff6feSmrg        column = 0;
728876ff6feSmrg    }
729876ff6feSmrg
730876ff6feSmrg    return(keycode);
731876ff6feSmrg}
732