summaryrefslogtreecommitdiff
path: root/xtrapchar.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:24 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:49:24 +0000
commit721055e48fa8964d8895f551292dc845a5724c36 (patch)
treed9d8ccc8ab5a56f81a5ae722ee286ec801285d52 /xtrapchar.c
Initial revisionXORG-STABLE
Diffstat (limited to 'xtrapchar.c')
-rw-r--r--xtrapchar.c733
1 files changed, 733 insertions, 0 deletions
diff --git a/xtrapchar.c b/xtrapchar.c
new file mode 100644
index 0000000..3f632d6
--- /dev/null
+++ b/xtrapchar.c
@@ -0,0 +1,733 @@
+/* $XFree86: xc/programs/xtrap/xtrapchar.c,v 1.3 2001/12/12 00:43:50 dawes Exp $ */
+/*
+ * @DEC_COPYRIGHT@
+ */
+/*
+ * HISTORY
+ * Log: xtrapchar.c,v $
+ * Revision 1.1.2.2 1993/12/14 12:37:15 Kenneth_Miller
+ * ANSI-standardize code and turn client build on
+ * [1993/12/09 20:15:33 Kenneth_Miller]
+ *
+ * EndLog$
+ */
+#if !defined(lint) && 0
+static char *rcsid = "@(#)RCSfile: xtrapchar.c,v $ Revision: 1.1.2.2 $ (DEC) Date: 1993/12/14 12:37:15 $";
+#endif
+/*****************************************************************************
+Copyright 1987, 1988, 1989, 1990, 1991, 1993 by Digital Equipment Corp.,
+Maynard, MA
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+*****************************************************************************/
+#define ProgName "xtrapchar"
+/*
+**++
+** FACILITY: xtrapchar - Converts ANSI character sequences to X.
+**
+** MODULE DESCRIPTION:
+**
+** Parses ANSI character sequences including application program
+** sequences to synthesize input events to X Window servers
+** using the XTrap server extension. Additionally, this main
+** module is designed to be used with the voice
+** recognition systems which will allow voice input into X Servers.
+**
+** AUTHORS:
+**
+** Kenneth B. Miller
+**
+** CREATION DATE: March 23, 1991
+**
+** DESIGN ISSUES:
+**
+** Accepts non-buffered Ascii characters as input and
+** performs a table look-up to determine what the corresponding
+** X actions are to be performed.
+**
+** Uses chparse() which was contributed to DECUS C by Roy
+** Lomicka and later revised by Martin Minow and myself.
+** Also, getopt() is used to parse the command
+** line arguments prior to calling XtAppInitialize().
+** Currently only the -v argument is supported to indicate
+** echoing of characters received for debugging
+** purposes.
+**
+**
+** CAVEAT:
+**
+** This program has *only* been used with Digital Workstations
+** using the LK201 compatible keyboard. Though reasonable
+** effort was done to maintain portability, no claims are made
+** as to the current level of portability to non-DEC servers
+** for this program.
+**--
+*/
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <X11/extensions/xtraplib.h>
+#include <X11/extensions/xtraplibp.h>
+#include <X11/keysym.h>
+
+#include "chparse.h"
+
+#ifndef vaxc
+#define globalref extern
+#endif
+ /* Special private indicators */
+#define BPRESS '!'
+#define BRELEASE '"'
+#define BCLICK '#'
+#define APRESS '$'
+#define ARELEASE '%'
+#define CPRESS '('
+#define CRELEASE ')'
+#define SPRESS '+'
+#define SRELEASE '-'
+#define DPRIVATE '='
+#define MNOTIFY '>'
+#define RMNOTIFY '?'
+
+#define NPARAM 8
+#define NINTER 8
+#define NUL 0x00
+#define CAN 0x18
+#define SUB 0x1A
+#define ESC 0x1B
+#define DEL 0x7F
+#define SS3 0x8f
+#define DCS 0x90
+#define CSI 0x9B
+#define ST 0x9C
+#define OSC 0x9D
+#define PM 0x9E
+#define APC 0x9F
+
+static BOOL verbose_flag = FALSE;
+static INT16 column = 0;
+static int state = NUL; /* Parser state (n.z. if incomplete) */
+static Window root;
+static BOOL passive_shift; /* Cap's assumed? */
+static BOOL passive_ctrl; /* Control key assumed? */
+static BOOL shift; /* Cap's on? */
+static BOOL ctrl; /* Control key? */
+static BOOL alt; /* Alt key? */
+KeyCode alt_code;
+KeyCode ctrl_code;
+KeyCode shift_code;
+
+
+
+#define _AdjustCol(length) \
+ if ((column += length) >= 79) \
+ { \
+ printf("\n"); \
+ column = length; \
+ }
+
+static void KeyClick(XETC *tc, KeyCode keycode)
+{
+ if (passive_ctrl && !ctrl)
+ {
+ XESimulateXEventRequest(tc, KeyPress, ctrl_code, 0, 0, 0);
+ }
+ if (passive_shift && !shift)
+ {
+ XESimulateXEventRequest(tc, KeyPress, shift_code, 0, 0, 0);
+ }
+ XESimulateXEventRequest(tc, KeyPress, keycode, 0, 0, 0);
+ XESimulateXEventRequest(tc, KeyRelease, keycode, 0, 0, 0);
+ if (passive_shift && !shift)
+ {
+ XESimulateXEventRequest(tc, KeyRelease, shift_code, 0, 0, 0);
+ }
+ if (passive_ctrl && !ctrl)
+ {
+ XESimulateXEventRequest(tc, KeyRelease, ctrl_code, 0, 0, 0);
+ }
+ passive_ctrl = passive_shift = FALSE; /* Action's been completed */
+}
+
+
+/*
+**
+** FORWARD DECLARATIONS
+**
+*/
+static int get_csi_key ( XETC *tc , int private , int param [],
+ int nparam , int inter [], int ninter , int final );
+static int get_ss3_key ( XETC *tc , int private , int param [],
+ int nparam , int inter [], int ninter , int final );
+static void send_special ( XETC *tc , int private , int param [],
+ int nparam , int inter [], int ninter , int final );
+static KeyCode get_typical_char ( XETC *tc , CARD32 keysym);
+static KeyCode get_keycode ( XETC *tc , KeySym keysym);
+
+
+int
+main(int argc, char *argv[])
+{
+ Widget appW;
+ Display *dpy;
+ XETrapGetCurRep ret_cur;
+ XETC *tc;
+ XtAppContext app;
+ char *tmp = NULL;
+ INT16 ch;
+ INT16 i;
+ KeyCode keycode;
+ /* ESC & CSI Parsing variables */
+ int max_delay = 3;
+ int rest_delay = 2;
+ int private; /* Sequence private char, 'X' if error */
+ int param[NPARAM]; /* numeric param, starting at param[1] */
+ int nparam; /* Number of parameters */
+ int inter[NINTER]; /* intermediate char, starting at [1] */
+ int ninter; /* Number of intermediates */
+ int final; /* Sequence terminator */
+ int *popterr;
+#ifndef vms
+ popterr = &opterr;
+#else
+ popterr = XEgetopterr();
+#endif
+ *popterr = 0; /* don't complain about -d for display */
+ while ((ch = getopt(argc, argv, "d:v")) != EOF)
+ {
+ switch(ch)
+ {
+ case 'v':
+ verbose_flag = TRUE;
+ break;
+ case 'd': /* -display, let's let the toolkit parse it */
+ break;
+ default:
+ break;
+ }
+ }
+ appW = XtAppInitialize(&app,"XTrap",(XrmOptionDescList)NULL,(Cardinal)0L,
+ (int *)&argc, (String *)argv, NULL,(ArgList)&tmp,
+ (Cardinal)0);
+
+ dpy = XtDisplay(appW);
+ if (verbose_flag)
+ {
+ printf("Display: %s \n", DisplayString(dpy));
+ }
+ if ((tc = XECreateTC(dpy,0L, NULL)) == False)
+ {
+ fprintf(stderr,"%s: could not initialize XTrap extension\n", ProgName);
+ exit (1L);
+ }
+ root = RootWindow(dpy,DefaultScreen(dpy));
+ (void)XEStartTrapRequest(tc);
+ alt_code = XKeysymToKeycode(tc->dpy,XK_Alt_L);
+ ctrl_code = XKeysymToKeycode(tc->dpy,XK_Control_L);
+ shift_code = XKeysymToKeycode(tc->dpy,XK_Shift_L);
+
+
+
+ if (verbose_flag)
+ {
+ (void)XEGetCurrentRequest(tc,&ret_cur);
+ XEPrintCurrent(stderr,&ret_cur);
+ }
+
+ column = 0; /* if displaying char's, don't go beyond 80 columns */
+
+ while ((ch = chparse(max_delay, rest_delay, &state, &private, param,
+ &nparam, inter, &ninter, &final)) != -1)
+ {
+ if (ch == -2)
+ {
+ continue; /* timeout condition */
+ }
+ if ((!ferror(stdin)) && (!feof(stdin)) && (state == 0))
+ { /* we got something */
+ switch(ch)
+ {
+ case CSI: /* Control Sequence */
+ keycode = get_csi_key(tc, private, param, nparam, inter,
+ ninter, final);
+ if (keycode)
+ KeyClick(tc, keycode);
+ break;
+ case SS3: /* Keypad stuff */
+ keycode = get_ss3_key(tc, private, param, nparam, inter,
+ ninter, final);
+ if (keycode)
+ KeyClick(tc, keycode);
+ break;
+ case APC: /* Application Cmd (Button's, Press, Release) */
+ send_special(tc, private, param, nparam, inter, ninter,
+ final);
+ break;
+ case ESC: /* Escape Sequence */
+ /* send ESCAPE */
+ if (!(keycode = XKeysymToKeycode(tc->dpy,XK_Escape)))
+ { /* must be an LK201 keyboard */
+ BOOL orig_ctrl = ctrl;
+ /*
+ * the following is kind of strange. We need to
+ * have ctrl TRUE for get_typical_char() to
+ * report the verbose message correctly. We
+ * can't use passive_ctrl cause it resets it.
+ * Then, for KeyClick(), ctrl has to be FALSE
+ * and passive_ctrl has to be TRUE in order for
+ * us to get the desired <CTRL>[ to simulate
+ * an escape key. Once it's all done, we need
+ * to return ctrl to whatever it was and clear
+ * the passive_ctrl.
+ */
+ ctrl = TRUE; /* for get_typical_char */
+ keycode = get_typical_char(tc, (CARD32)'[');
+ ctrl = FALSE; /* for KeyClick */
+ passive_ctrl = TRUE; /* for KeyClick */
+ KeyClick(tc, keycode);
+ passive_ctrl = FALSE; /* to continue */
+ ctrl = orig_ctrl; /* to continue */
+ }
+ else
+ {
+ KeyClick(tc, keycode);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<ESC>"));
+ printf("<ESC>");
+ }
+ }
+ /* send private (if valid) */
+ if (private != NUL && private != 'X' &&
+ (keycode = get_typical_char(tc, (CARD32)private)))
+ KeyClick(tc, keycode);
+ /* send addt'l parameters, if any */
+ for (i = 1; i <= nparam; i++)
+ if ((keycode = get_typical_char(tc, (CARD32)param[i])))
+ KeyClick(tc, keycode);
+ /* send intermediate's, if any */
+ for (i = 1; i <= ninter; i++)
+ if ((keycode = get_typical_char(tc, (CARD32)inter[i])))
+ KeyClick(tc, keycode);
+ /* send final character */
+ if ((keycode = get_typical_char(tc, (CARD32)final)))
+ KeyClick(tc, keycode);
+ break;
+
+ case DCS: /* We don't deal with these */
+ case OSC:
+ case PM:
+ if (verbose_flag)
+ {
+ printf("Ignoring the following: ");
+ dumpsequence(state, ch, private, param, nparam,
+ inter, ninter, final, &column);
+ }
+ break;
+ default: /* typical character */
+ keycode = get_typical_char(tc, (CARD32)ch);
+ if (keycode)
+ KeyClick(tc, keycode);
+ break;
+ }
+ }
+ else
+ { /* error? */
+ if (ferror(stdin) || state != 0)
+ {
+ perror("Error occurred parsing input characters!\n");
+ }
+ break;
+ }
+ }
+ /* Clean things up */
+ XEFreeTC(tc);
+ (void)XCloseDisplay(dpy);
+
+ exit(0L);
+}
+
+static int get_csi_key(tc, private, param, nparam, inter, ninter, final)
+ XETC *tc;
+ int private;
+ int param[], nparam;
+ int inter[], ninter;
+ int final;
+{
+ KeySym keysym = 0;
+ switch(param[1])
+ {
+ case 0:
+ switch ((char )final)
+ {
+ case 'A': keysym = XK_Up; break;
+ case 'B': keysym = XK_Down; break;
+ case 'C': keysym = XK_Right; break;
+ case 'D': keysym = XK_Left; break;
+ default:
+ dumpsequence(state, CSI, private, param, nparam,
+ inter, ninter, final, &column);
+ break;
+ }
+ break;
+ case 1: keysym = XK_Find; break;
+ case 2: keysym = XK_Insert; break;
+#ifdef DXK_Remove
+ case 3: keysym = DXK_Remove; break;
+#endif
+ case 4: keysym = XK_Select; break;
+ case 5: keysym = XK_Prior; break;
+ case 6: keysym = XK_Next; break;
+ case 17: keysym = XK_F6; break;
+ case 18: keysym = XK_F7; break;
+ case 19: keysym = XK_F8; break;
+ case 20: keysym = XK_F9; break;
+ case 21: keysym = XK_F10; break;
+ case 23: keysym = XK_F11; break;
+ case 24: keysym = XK_F12; break;
+ case 25: keysym = XK_F13; break;
+ case 26: keysym = XK_F14; break;
+ case 28: keysym = XK_Help; break;
+ case 29: keysym = XK_Menu; break;
+ case 31: keysym = XK_F17; break;
+ case 32: keysym = XK_F18; break;
+ case 33: keysym = XK_F19; break;
+ case 34: keysym = XK_F20; break;
+ default:
+ dumpsequence(state, CSI, private, param, nparam,
+ inter, ninter, final, &column);
+ }
+
+ return(get_keycode(tc, keysym));
+}
+
+ /*
+ * XTrap special sequences:
+ * ButtonPress: <APC>=!X (where 'X' is 'A', 'B', or 'C'
+ * for MB1, MB2, MB3 respectively)
+ * ButtonRelease: <APC>="X (where 'X' is 'A', 'B', or 'C'
+ * for MB1, MB2, MB3 respectively)
+ * ButtonClick: <APC>=#X (where 'X' is 'A', 'B', or 'C'
+ * for MB1, MB2, MB3 respectively)
+ * AltPress: <APC>=$~
+ * AltRelease: <APC>=%~
+ * CtrlPress: <APC>=(~
+ * CtrlRelease: <APC>=)~
+ * ShiftPress: <APC>=+~
+ * ShiftRelease: <APC>=-~
+ * MotionNotify: <APC>>;X;Y~ (where 'X' is the X coord and 'Y'
+ * is the Y coord of the desired
+ * pointer position)
+ * Relative MotionNotify:
+ * <APC>?;X;Y~ (where 'X' is the X coord and 'Y'
+ * is the Y coord of the desired
+ * pointer position)
+ *
+ */
+static void send_special(tc, private, param, nparam, inter, ninter, final)
+ XETC *tc;
+ int private;
+ int param[], nparam;
+ int inter[], ninter;
+ int final;
+{
+ switch(private)
+ {
+ case DPRIVATE: /* default APC */
+ if (ninter != 1)
+ { /* Not my sequence */
+ dumpsequence(state, APC, private, param, nparam,
+ inter, ninter, final, &column);
+ return;
+ }
+ else
+ {
+ switch(inter[1])
+ {
+ Window rid, wid;
+ int x, y, wx, wy;
+ unsigned int sm;
+ CARD8 detail;
+
+ case BPRESS:
+ detail = (final - 'A' + 1);
+ if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
+ &y,&wx,&wy,&sm) == False)
+ {
+ fprintf(stderr, "\nPointer's not on screen 0!\n");
+ }
+ else
+ {
+ XESimulateXEventRequest(tc, ButtonPress, detail,
+ x, y, 0);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<MB%d-Press> ")-1);
+ printf("<MB%d-Press> ", detail);
+ }
+ }
+ break;
+ case BRELEASE:
+ detail = (final - 'A' + 1);
+ if ((Bool)XQueryPointer(tc->dpy,root,&rid,&wid,&x,
+ &y,&wx,&wy,&sm) == False)
+ {
+ fprintf(stderr, "\nPointer's not on screen 0!\n");
+ }
+ else
+ {
+ XESimulateXEventRequest(tc, ButtonRelease, detail,
+ x,y,0);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<MB%d-Release> ")-1);
+ printf("<MB%d-Release> ", detail);
+ }
+ }
+ break;
+ case BCLICK:
+ detail = (final - 'A' + 1);
+ if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,
+ &wx,&wy,&sm)
+ == False)
+ {
+ fprintf(stderr, "\nPointer's not on screen 0!\n");
+ }
+ else
+ {
+ XESimulateXEventRequest(tc,ButtonPress,
+ detail,x,y,0);
+ XESimulateXEventRequest(tc,ButtonRelease,
+ detail,x,y,0);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<MB%d> ")-1);
+ printf("<MB%d> ", detail);
+ }
+ }
+ break;
+ case APRESS:
+ alt = TRUE;
+ XESimulateXEventRequest(tc,KeyPress,alt_code,0,0,0);
+ break;
+ case ARELEASE:
+ alt = FALSE;
+ XESimulateXEventRequest(tc,KeyRelease,alt_code,0,0,0);
+ break;
+ case SPRESS:
+ shift = TRUE;
+ XESimulateXEventRequest(tc,KeyPress,shift_code,0,0,0);
+ break;
+ case SRELEASE:
+ shift = FALSE;
+ XESimulateXEventRequest(tc,KeyRelease,shift_code,
+ 0,0,0);
+ break;
+ case CPRESS:
+ ctrl = TRUE;
+ XESimulateXEventRequest(tc,KeyPress,ctrl_code,0,0,0);
+ break;
+ case CRELEASE:
+ ctrl = FALSE;
+ XESimulateXEventRequest(tc,KeyRelease,ctrl_code,0,0,0);
+ break;
+ default:
+ fprintf(stderr, "\nInvalid Sequence!\n");
+ dumpsequence(state, APC, private, param, nparam,
+ inter, ninter, final, &column);
+ }
+ }
+ break;
+ case MNOTIFY:
+ if (nparam != 3)
+ { /* Not my sequence */
+ dumpsequence(state, APC, private, param, nparam,
+ inter, ninter, final, &column);
+ return;
+ }
+ else
+ {
+ int x, y;
+
+ x = param[2];
+ y = param[3];
+ XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<M %d,%d> ")+3);
+ printf("<M %d,%d> ",x,y);
+ }
+ }
+ break;
+ case RMNOTIFY:
+ if (nparam != 3)
+ { /* Not my sequence */
+ dumpsequence(state, APC, private, param, nparam,
+ inter, ninter, final, &column);
+ return;
+ }
+ else
+ {
+ Window rid, wid;
+ int x, y, wx, wy;
+ unsigned int sm;
+
+ if (XQueryPointer(tc->dpy,root,&rid,&wid,&x,&y,&wx,&wy,&sm)
+ == False)
+ {
+ fprintf(stderr, "\nPointer's not on screen 0!\n");
+ }
+ else
+ { /* We're ready to go */
+ x += param[2];
+ y += param[3];
+ XESimulateXEventRequest(tc,MotionNotify,0,x,y,0);
+ if (verbose_flag)
+ {
+ _AdjustCol(strlen("<RM ddd+sddd,dddd+sdddd> "));
+ printf("<RM %d+%d,%d+%d> ",x-param[2],param[3],
+ y-param[3],param[3]);
+ }
+ }
+ break;
+ default:
+ dumpsequence(state, APC, private, param, nparam,
+ inter, ninter, final, &column);
+ break;
+ }
+ }
+}
+
+static int get_ss3_key(tc, private, param, nparam, inter, ninter, final)
+ XETC *tc;
+ int private;
+ int param[], nparam;
+ int inter[], ninter;
+ int final;
+{
+ KeySym keysym = 0;
+ switch(param[1])
+ {
+ case 0:
+ switch ((char )final)
+ {
+ case 'A': keysym = XK_Up; break;
+ case 'B': keysym = XK_Down; break;
+ case 'C': keysym = XK_Right; break;
+ case 'D': keysym = XK_Left; break;
+ case 'p': keysym = XK_KP_0; break;
+ case 'q': keysym = XK_KP_1; break;
+ case 'r': keysym = XK_KP_2; break;
+ case 's': keysym = XK_KP_3; break;
+ case 't': keysym = XK_KP_4; break;
+ case 'u': keysym = XK_KP_5; break;
+ case 'v': keysym = XK_KP_6; break;
+ case 'w': keysym = XK_KP_7; break;
+ case 'x': keysym = XK_KP_8; break;
+ case 'y': keysym = XK_KP_9; break;
+ case 'm': keysym = XK_KP_Subtract; break;
+ case 'l': keysym = XK_KP_Separator; break;
+ case 'n': keysym = XK_KP_Decimal; break;
+ case 'M': keysym = XK_KP_Enter; break;
+ case 'P': keysym = XK_KP_F1; break;
+ case 'Q': keysym = XK_KP_F2; break;
+ case 'R': keysym = XK_KP_F3; break;
+ case 'S': keysym = XK_KP_F4; break;
+ default:
+ dumpsequence(state, SS3, private, param, nparam,
+ inter, ninter, final, &column);
+ break;
+ }
+ break;
+ }
+
+ return(get_keycode(tc, keysym));
+}
+
+static KeyCode get_typical_char(tc, keysym)
+ XETC *tc;
+ CARD32 keysym;
+{
+ if (iscntrl(keysym))
+ {
+ switch(keysym)
+ {
+ case 0x09: keysym = XK_Tab; break;
+ case 0x0d: keysym = XK_Return; break;
+ case 0x7f: keysym = XK_Delete; break;
+ case ESC: keysym = XK_Escape; break;
+ }
+ }
+ passive_shift = (keysym >= XK_A && keysym <= XK_Z) ? TRUE : FALSE;
+ switch(keysym)
+ { /* Special case shift's */
+ case '!': case '"': case '@': case '#': case '$':
+ case '%': case '^': case '&': case '*': case '(':
+ case ')': case '_': case '+': case '{': case '}':
+ case '|': case ':': case '>': case '?': case '~':
+ passive_shift = TRUE;
+ }
+
+ if (keysym >= 1 && keysym <= 26)
+ {
+ passive_ctrl = TRUE;
+ keysym += 'a' - 1;
+ }
+ else
+ {
+ passive_ctrl = FALSE;
+ }
+
+ return(get_keycode(tc, keysym));
+}
+
+static KeyCode get_keycode(XETC *tc, KeySym keysym)
+{
+ char *keystr = (char *)XKeysymToString(keysym);
+ KeyCode keycode;
+
+ keystr = (keystr == NULL) ? "unknown" : keystr;
+ if (verbose_flag)
+ {
+ if (shift || passive_shift)
+ {
+ _AdjustCol(strlen("<SHIFT>"));
+ printf("<SHIFT>");
+ }
+ if (alt)
+ {
+ _AdjustCol(strlen("<ALT>"));
+ printf("<ALT>");
+ }
+ if (ctrl || passive_ctrl)
+ {
+ _AdjustCol(strlen("<CTRL>"));
+ printf("<CTRL>");
+ }
+ _AdjustCol(strlen(keystr)+1);
+ printf("%s ", keystr);
+ }
+ if (!(keycode = XKeysymToKeycode(tc->dpy,keysym)))
+ {
+ fprintf(stderr,"\n[%s ('%%0x%04x') returns bad Keycode, ignored]\n",
+ keystr, (unsigned int)keysym);
+ column = 0;
+ }
+
+ return(keycode);
+}