#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
#define ProgName "xtrapchar"
#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
#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;
static Window root;
static BOOL passive_shift;
static BOOL passive_ctrl;
static BOOL shift;
static BOOL ctrl;
static BOOL alt;
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;
}
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;
int max_delay = 3;
int rest_delay = 2;
int private;
int param[NPARAM];
int nparam;
int inter[NINTER];
int ninter;
int final;
int *popterr;
#ifndef vms
popterr = &opterr;
#else
popterr = XEgetopterr();
#endif
*popterr = 0;
while ((ch = getopt(argc, argv, "d:v")) != EOF)
{
switch(ch)
{
case 'v':
verbose_flag = TRUE;
break;
case 'd':
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;
while ((ch = chparse(max_delay, rest_delay, &state, &private, param,
&nparam, inter, &ninter, &final)) != -1)
{
if (ch == -2)
{
continue;
}
if ((!ferror(stdin)) && (!feof(stdin)) && (state == 0))
{
switch(ch)
{
case CSI:
keycode = get_csi_key(tc, private, param, nparam, inter,
ninter, final);
if (keycode)
KeyClick(tc, keycode);
break;
case SS3:
keycode = get_ss3_key(tc, private, param, nparam, inter,
ninter, final);
if (keycode)
KeyClick(tc, keycode);
break;
case APC:
send_special(tc, private, param, nparam, inter, ninter,
final);
break;
case ESC:
if (!(keycode = XKeysymToKeycode(tc->dpy,XK_Escape)))
{
BOOL orig_ctrl = ctrl;
ctrl = TRUE;
keycode = get_typical_char(tc, (CARD32)'[');
ctrl = FALSE;
passive_ctrl = TRUE;
KeyClick(tc, keycode);
passive_ctrl = FALSE;
ctrl = orig_ctrl;
}
else
{
KeyClick(tc, keycode);
if (verbose_flag)
{
_AdjustCol(strlen("<ESC>"));
printf("<ESC>");
}
}
if (private != NUL && private != 'X' &&
(keycode = get_typical_char(tc, (CARD32)private)))
KeyClick(tc, keycode);
for (i = 1; i <= nparam; i++)
if ((keycode = get_typical_char(tc, (CARD32)param[i])))
KeyClick(tc, keycode);
for (i = 1; i <= ninter; i++)
if ((keycode = get_typical_char(tc, (CARD32)inter[i])))
KeyClick(tc, keycode);
if ((keycode = get_typical_char(tc, (CARD32)final)))
KeyClick(tc, keycode);
break;
case DCS:
case OSC:
case PM:
if (verbose_flag)
{
printf("Ignoring the following: ");
dumpsequence(state, ch, private, param, nparam,
inter, ninter, final, &column);
}
break;
default:
keycode = get_typical_char(tc, (CARD32)ch);
if (keycode)
KeyClick(tc, keycode);
break;
}
}
else
{
if (ferror(stdin) || state != 0)
{
perror("Error occurred parsing input characters!\n");
}
break;
}
}
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));
}
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:
if (ninter != 1)
{
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)
{
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)
{
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
{
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)
{
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);
}