/
sample.c
145 lines (118 loc) · 3.47 KB
/
sample.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* A little experiment with auto-spellchecking in X11 */
/* (c) Andrew Yourtchenko ayourtch@gmail.com, MIT license */
typedef struct tuple_t {
char *search;
char *replace;
} tuple_t;
tuple_t xlate[] = {
{ "int tnu", "\b\b\btun" },
{ NULL, 0 },
};
char txtbuf[16] = { };
int txtidx = sizeof(txtbuf)-1; // Leave space for the string terminator
/* Send Fake Key Event */
static void SendKey (Display * disp, KeySym keysym, KeySym modsym)
{
KeyCode keycode = 0, modcode = 0;
keycode = XKeysymToKeycode (disp, keysym);
if (keycode == 0) return;
XTestGrabControl (disp, True);
/* Generate modkey press */
if (modsym != 0)
{
modcode = XKeysymToKeycode(disp, modsym);
XTestFakeKeyEvent (disp, modcode, True, 0);
}
/* Generate regular key press and release */
XTestFakeKeyEvent (disp, keycode, True, 0);
XTestFakeKeyEvent (disp, keycode, False, 0);
/* Generate modkey release */
if (modsym != 0)
XTestFakeKeyEvent (disp, modcode, False, 0);
XSync (disp, False);
XTestGrabControl (disp, False);
}
void InjectKey(Display *d, KeySym key) {
XUngrabKeyboard(d, CurrentTime);
SendKey (d, key, 0);
XGrabKeyboard(d, DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync, CurrentTime);
}
void TrySpellcheck(Display *d, KeySym key) {
int i = 0;
char *match;
char *buf;
printf("TrySpellCheck\n");
XUngrabKeyboard(d, CurrentTime);
SendKey (d, key, 0);
while(xlate[i].search) {
printf("Matching: '%s', '%s'\n", &txtbuf[txtidx], xlate[i].search);
match = xlate[i].search + strlen(xlate[i].search);
buf = &txtbuf[txtidx] + strlen(&txtbuf[txtidx]);
while((buf >= &txtbuf[txtidx]) && (match >= xlate[i].search) && (*buf == *match)) {
buf--; match--;
}
if(match < xlate[i].search) {
int k = 0;
printf("Matched %s!\n", xlate[i].search);
while(xlate[i].replace[k]) {
if (xlate[i].replace[k] == '\b') {
SendKey (d, XK_BackSpace, 0);
} else {
SendKey (d, xlate[i].replace[k], 0);
}
k++;
}
}
i++;
}
XGrabKeyboard(d, DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync, CurrentTime);
}
int main(void) {
Display *d;
Window w;
XEvent e;
KeySym key;
int s;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 200, 1,
BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask);
XMapWindow(d, w);
XGrabKeyboard(d, DefaultRootWindow(d), True, GrabModeAsync, GrabModeAsync, CurrentTime);
while (1) {
XNextEvent(d, &e);
if (e.type == KeyPress) {
key = XKeycodeToKeysym(d, e.xkey.keycode, 0);
} else if (e.type == KeyRelease) {
key = XKeycodeToKeysym(d, e.xkey.keycode, 0);
printf("Release: %c\n", key);
// This is really a hack since it does not correctly handle non-alnum keys.
if(txtidx > 0) {
txtidx--;
}
memmove(txtbuf, txtbuf+1, sizeof(txtbuf)-2);
txtbuf[sizeof(txtbuf)-2] = (char)key;
TrySpellcheck(d, key);
}
if (e.type == KeyPress) {
key = XKeycodeToKeysym(d, e.xkey.keycode, 0);
if (key == XK_Alt_L) {
// Exit on pressing Alt
break;
}
}
}
XUngrabKeyboard(d, CurrentTime);
XCloseDisplay(d);
return 0;
}