Xinqi Bao's Git

updated to libdraw tip
[dmenu.git] / dinput.c
1 /* See LICENSE file for copyright and license details. */
2 #include <ctype.h>
3 #include <locale.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <X11/keysym.h>
8 #include <X11/Xlib.h>
9 #include <X11/Xutil.h>
10 #include "dmenu.h"
11
12 /* forward declarations */
13 static void cleanup(void);
14
15 /* variables */
16 static size_t cursor = 0;
17
18 void
19 cleanup(void) {
20 cleanupdraw(&dc);
21 XDestroyWindow(dpy, win);
22 XUngrabKeyboard(dpy, CurrentTime);
23 XCloseDisplay(dpy);
24 }
25
26 void
27 drawbar(void)
28 {
29 dc.x = 0;
30 dc.y = 0;
31 dc.w = mw;
32 dc.h = mh;
33 drawbox(&dc, normcol);
34 /* print prompt? */
35 if(prompt) {
36 dc.w = promptw;
37 drawtext(&dc, prompt, selcol);
38 dc.x += dc.w;
39 }
40 dc.w = mw - dc.x;
41 drawtext(&dc, text, normcol);
42 drawcursor(&dc, text, cursor, normcol);
43 commitdraw(&dc, win);
44 }
45
46 void
47 kpress(XKeyEvent *e) {
48 char buf[sizeof text];
49 int num;
50 unsigned int i, len;
51 KeySym ksym;
52
53 len = strlen(text);
54 num = XLookupString(e, buf, sizeof buf, &ksym, NULL);
55 if(ksym == XK_KP_Enter)
56 ksym = XK_Return;
57 else if(ksym >= XK_KP_0 && ksym <= XK_KP_9)
58 ksym = (ksym - XK_KP_0) + XK_0;
59 else if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
60 || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
61 || IsPrivateKeypadKey(ksym))
62 return;
63 /* first check if a control mask is omitted */
64 if(e->state & ControlMask) {
65 switch(tolower(ksym)) {
66 default:
67 return;
68 case XK_a:
69 ksym = XK_Home;
70 break;
71 case XK_b:
72 ksym = XK_Left;
73 break;
74 case XK_c:
75 ksym = XK_Escape;
76 break;
77 case XK_e:
78 ksym = XK_End;
79 break;
80 case XK_f:
81 ksym = XK_Right;
82 break;
83 case XK_h:
84 ksym = XK_BackSpace;
85 break;
86 case XK_j:
87 case XK_m:
88 ksym = XK_Return;
89 break;
90 case XK_k:
91 text[cursor] = '\0';
92 break;
93 case XK_u:
94 memmove(text, text + cursor, sizeof text - cursor + 1);
95 cursor = 0;
96 break;
97 case XK_w:
98 if(cursor > 0) {
99 i = cursor;
100 while(i-- > 0 && text[i] == ' ');
101 while(i-- > 0 && text[i] != ' ');
102 memmove(text + i + 1, text + cursor, sizeof text - cursor + 1);
103 cursor = i + 1;
104 }
105 break;
106 case XK_y:
107 {
108 FILE *fp;
109 char *s;
110 if(!(fp = popen("sselp", "r")))
111 eprint("cannot popen sselp\n");
112 s = fgets(buf, sizeof buf, fp);
113 pclose(fp);
114 if(s == NULL)
115 return;
116 }
117 num = strlen(buf);
118 if(num && buf[num-1] == '\n')
119 buf[--num] = '\0';
120 break;
121 }
122 }
123 switch(ksym) {
124 default:
125 num = MIN(num, sizeof text - cursor);
126 if(num && !iscntrl((int) buf[0])) {
127 memmove(text + cursor + num, text + cursor, sizeof text - cursor - num);
128 memcpy(text + cursor, buf, num);
129 cursor += num;
130 }
131 break;
132 case XK_BackSpace:
133 if(cursor == 0)
134 return;
135 for(i = 1; cursor - i > 0 && !IS_UTF8_1ST_CHAR(text[cursor - i]); i++);
136 memmove(text + cursor - i, text + cursor, sizeof text - cursor + i);
137 cursor -= i;
138 break;
139 case XK_Delete:
140 if(cursor == len)
141 return;
142 for(i = 1; cursor + i < len && !IS_UTF8_1ST_CHAR(text[cursor + i]); i++);
143 memmove(text + cursor, text + cursor + i, sizeof text - cursor);
144 break;
145 case XK_End:
146 cursor = len;
147 break;
148 case XK_Escape:
149 exit(EXIT_FAILURE);
150 case XK_Home:
151 cursor = 0;
152 break;
153 case XK_Left:
154 if(cursor == 0)
155 return;
156 while(cursor-- > 0 && !IS_UTF8_1ST_CHAR(text[cursor]));
157 break;
158 case XK_Return:
159 fprintf(stdout, "%s", text);
160 fflush(stdout);
161 exit(EXIT_SUCCESS);
162 case XK_Right:
163 if(cursor == len)
164 return;
165 while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor]));
166 break;
167 }
168 drawbar();
169 }
170
171 int
172 main(int argc, char *argv[]) {
173 unsigned int i;
174
175 /* command line args */
176 progname = "dinput";
177 for(i = 1; i < argc; i++)
178 if(!strcmp(argv[i], "-i"))
179 ; /* ignore flag */
180 else if(!strcmp(argv[i], "-b"))
181 topbar = False;
182 else if(!strcmp(argv[i], "-l"))
183 i++; /* ignore flag */
184 else if(!strcmp(argv[i], "-fn")) {
185 if(++i < argc) font = argv[i];
186 }
187 else if(!strcmp(argv[i], "-nb")) {
188 if(++i < argc) normbgcolor = argv[i];
189 }
190 else if(!strcmp(argv[i], "-nf")) {
191 if(++i < argc) normfgcolor = argv[i];
192 }
193 else if(!strcmp(argv[i], "-p")) {
194 if(++i < argc) prompt = argv[i];
195 }
196 else if(!strcmp(argv[i], "-sb")) {
197 if(++i < argc) selbgcolor = argv[i];
198 }
199 else if(!strcmp(argv[i], "-sf")) {
200 if(++i < argc) selfgcolor = argv[i];
201 }
202 else if(!strcmp(argv[i], "-v")) {
203 printf("dinput-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n");
204 exit(EXIT_SUCCESS);
205 }
206 else if(!*text) {
207 strncpy(text, argv[i], sizeof text);
208 cursor = strlen(text);
209 }
210 else {
211 fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
212 " [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr);
213 exit(EXIT_FAILURE);
214 }
215 if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
216 fprintf(stderr, "dinput: warning: no locale support\n");
217 if(!(dpy = XOpenDisplay(NULL)))
218 eprint("cannot open display\n");
219 if(atexit(&cleanup) != 0)
220 eprint("cannot register cleanup\n");
221 screen = DefaultScreen(dpy);
222 root = RootWindow(dpy, screen);
223
224 grabkeyboard();
225 setup(0);
226 run();
227 return 0;
228 }