Mercurial > dwm-meillo
comparison gridmenu.c @ 3:e969f3575b7a
several new changes, made gridmenu working
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Mon, 10 Jul 2006 19:46:24 +0200 |
parents | f10194d4b76d |
children |
comparison
equal
deleted
inserted
replaced
2:a79188fe4a40 | 3:e969f3575b7a |
---|---|
1 /* | 1 /* |
2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | 2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> |
3 * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> | 3 * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> |
4 * See LICENSE file for license details. | 4 * See LICENSE file for license details. |
5 */ | 5 */ |
6 | |
7 #include "config.h" | |
8 #include "draw.h" | |
9 #include "util.h" | |
6 | 10 |
7 #include <ctype.h> | 11 #include <ctype.h> |
8 #include <stdlib.h> | 12 #include <stdlib.h> |
9 #include <stdio.h> | 13 #include <stdio.h> |
10 #include <string.h> | 14 #include <string.h> |
11 #include <sys/stat.h> | 15 #include <sys/stat.h> |
12 #include <sys/wait.h> | 16 #include <sys/wait.h> |
13 #include <time.h> | 17 #include <time.h> |
14 #include <unistd.h> | 18 #include <unistd.h> |
15 #include <X11/Xlib.h> | |
16 #include <X11/cursorfont.h> | 19 #include <X11/cursorfont.h> |
17 #include <X11/Xutil.h> | 20 #include <X11/Xutil.h> |
18 #include <X11/keysym.h> | 21 #include <X11/keysym.h> |
19 | |
20 #include <blitz.h> | |
21 #include <cext.h> | |
22 | 22 |
23 typedef struct Item Item; | 23 typedef struct Item Item; |
24 | 24 |
25 struct Item { | 25 struct Item { |
26 Item *next; /* traverses all items */ | 26 Item *next; /* traverses all items */ |
27 Item *left, *right; /* traverses items matching current search pattern */ | 27 Item *left, *right; /* traverses items matching current search pattern */ |
28 char *text; | 28 char *text; |
29 }; | 29 }; |
30 | 30 |
31 static char *title = nil; | 31 static Display *dpy; |
32 static Window root; | |
33 static Window win; | |
34 static XRectangle rect; | |
32 static Bool done = False; | 35 static Bool done = False; |
36 | |
37 static Item *allitem = 0; /* first of all items */ | |
38 static Item *item = 0; /* first of pattern matching items */ | |
39 static Item *sel = 0; | |
40 static Item *nextoff = 0; | |
41 static Item *prevoff = 0; | |
42 static Item *curroff = 0; | |
43 | |
44 static int screen; | |
45 static char *title = 0; | |
46 static char text[4096]; | |
33 static int ret = 0; | 47 static int ret = 0; |
34 static char text[4096]; | |
35 static BlitzColor selcolor; | |
36 static BlitzColor normcolor; | |
37 static Window win; | |
38 static XRectangle mrect; | |
39 static Item *allitem = nil; /* first of all items */ | |
40 static Item *item = nil; /* first of pattern matching items */ | |
41 static Item *sel = nil; | |
42 static Item *nextoff = nil; | |
43 static Item *prevoff = nil; | |
44 static Item *curroff = nil; | |
45 static int nitem = 0; | 48 static int nitem = 0; |
46 static unsigned int cmdw = 0; | 49 static unsigned int cmdw = 0; |
47 static unsigned int twidth = 0; | 50 static unsigned int twidth = 0; |
48 static unsigned int cwidth = 0; | 51 static unsigned int cwidth = 0; |
49 static Blitz blz = {0}; | |
50 static BlitzBrush brush = {0}; | |
51 static const int seek = 30; /* 30px */ | 52 static const int seek = 30; /* 30px */ |
52 | 53 |
54 static Brush brush = {0}; | |
55 | |
53 static void draw_menu(void); | 56 static void draw_menu(void); |
54 static void handle_kpress(XKeyEvent * e); | 57 static void kpress(XKeyEvent * e); |
55 | 58 |
56 static char version[] = "wmiimenu - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n"; | 59 static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; |
57 | 60 |
58 static void | 61 static void |
59 usage() | 62 usage() |
60 { | 63 { |
61 fprintf(stderr, "%s", "usage: wmiimenu [-v] [-t <title>]\n"); | 64 fprintf(stderr, "%s", "usage: gridmenu [-v] [-t <title>]\n"); |
62 exit(1); | 65 exit(1); |
63 } | 66 } |
64 | 67 |
65 static void | 68 static void |
66 update_offsets() | 69 update_offsets() |
69 | 72 |
70 if(!curroff) | 73 if(!curroff) |
71 return; | 74 return; |
72 | 75 |
73 for(nextoff = curroff; nextoff; nextoff=nextoff->right) { | 76 for(nextoff = curroff; nextoff; nextoff=nextoff->right) { |
74 tw = blitz_textwidth(brush.font, nextoff->text); | 77 tw = textwidth(&brush.font, nextoff->text); |
75 if(tw > mrect.width / 3) | 78 if(tw > rect.width / 3) |
76 tw = mrect.width / 3; | 79 tw = rect.width / 3; |
77 w += tw + mrect.height; | 80 w += tw + brush.font.height; |
78 if(w > mrect.width) | 81 if(w > rect.width) |
79 break; | 82 break; |
80 } | 83 } |
81 | 84 |
82 w = cmdw + 2 * seek; | 85 w = cmdw + 2 * seek; |
83 for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { | 86 for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { |
84 tw = blitz_textwidth(brush.font, prevoff->left->text); | 87 tw = textwidth(&brush.font, prevoff->left->text); |
85 if(tw > mrect.width / 3) | 88 if(tw > rect.width / 3) |
86 tw = mrect.width / 3; | 89 tw = rect.width / 3; |
87 w += tw + mrect.height; | 90 w += tw + brush.font.height; |
88 if(w > mrect.width) | 91 if(w > rect.width) |
89 break; | 92 break; |
90 } | 93 } |
91 } | 94 } |
92 | 95 |
93 static void | 96 static void |
102 if(!title || *pattern) | 105 if(!title || *pattern) |
103 cmdw = cwidth; | 106 cmdw = cwidth; |
104 else | 107 else |
105 cmdw = twidth; | 108 cmdw = twidth; |
106 | 109 |
107 item = j = nil; | 110 item = j = 0; |
108 nitem = 0; | 111 nitem = 0; |
109 | 112 |
110 for(i = allitem; i; i=i->next) | 113 for(i = allitem; i; i=i->next) |
111 if(!plen || !strncmp(pattern, i->text, plen)) { | 114 if(!plen || !strncmp(pattern, i->text, plen)) { |
112 if(!j) | 115 if(!j) |
113 item = i; | 116 item = i; |
114 else | 117 else |
115 j->right = i; | 118 j->right = i; |
116 i->left = j; | 119 i->left = j; |
117 i->right = nil; | 120 i->right = 0; |
118 j = i; | 121 j = i; |
119 nitem++; | 122 nitem++; |
120 } | 123 } |
121 for(i = allitem; i; i=i->next) | 124 for(i = allitem; i; i=i->next) |
122 if(plen && strncmp(pattern, i->text, plen) | 125 if(plen && strncmp(pattern, i->text, plen) |
124 if(!j) | 127 if(!j) |
125 item = i; | 128 item = i; |
126 else | 129 else |
127 j->right = i; | 130 j->right = i; |
128 i->left = j; | 131 i->left = j; |
129 i->right = nil; | 132 i->right = 0; |
130 j = i; | 133 j = i; |
131 nitem++; | 134 nitem++; |
132 } | 135 } |
133 | 136 |
134 curroff = prevoff = nextoff = sel = item; | 137 curroff = prevoff = nextoff = sel = item; |
139 /* creates brush structs for brush mode drawing */ | 142 /* creates brush structs for brush mode drawing */ |
140 static void | 143 static void |
141 draw_menu() | 144 draw_menu() |
142 { | 145 { |
143 unsigned int offx = 0; | 146 unsigned int offx = 0; |
144 | |
145 Item *i; | 147 Item *i; |
146 | 148 |
147 brush.align = WEST; | 149 brush.rect = rect; |
148 | |
149 brush.rect = mrect; | |
150 brush.rect.x = 0; | 150 brush.rect.x = 0; |
151 brush.rect.y = 0; | 151 brush.rect.y = 0; |
152 brush.color = normcolor; | 152 draw(dpy, &brush, False, 0); |
153 brush.border = False; | |
154 blitz_draw_tile(&brush); | |
155 | 153 |
156 /* print command */ | 154 /* print command */ |
157 if(!title || text[0]) { | 155 if(!title || text[0]) { |
158 brush.color = normcolor; | |
159 cmdw = cwidth; | 156 cmdw = cwidth; |
160 if(cmdw && item) | 157 if(cmdw && item) |
161 brush.rect.width = cmdw; | 158 brush.rect.width = cmdw; |
162 blitz_draw_label(&brush, text); | 159 draw(dpy, &brush, False, text); |
163 } | 160 } |
164 else { | 161 else { |
165 cmdw = twidth; | 162 cmdw = twidth; |
166 brush.color = selcolor; | |
167 brush.rect.width = cmdw; | 163 brush.rect.width = cmdw; |
168 blitz_draw_label(&brush, title); | 164 draw(dpy, &brush, False, title); |
169 } | 165 } |
170 offx += brush.rect.width; | 166 offx += brush.rect.width; |
171 | 167 |
172 brush.align = CENTER; | |
173 if(curroff) { | 168 if(curroff) { |
174 brush.color = normcolor; | |
175 brush.rect.x = offx; | 169 brush.rect.x = offx; |
176 brush.rect.width = seek; | 170 brush.rect.width = seek; |
177 offx += brush.rect.width; | 171 offx += brush.rect.width; |
178 blitz_draw_label(&brush, (curroff && curroff->left) ? "<" : nil); | 172 draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0); |
179 | 173 |
180 /* determine maximum items */ | 174 /* determine maximum items */ |
181 for(i = curroff; i != nextoff; i=i->right) { | 175 for(i = curroff; i != nextoff; i=i->right) { |
182 brush.color = normcolor; | |
183 brush.border = False; | 176 brush.border = False; |
184 brush.rect.x = offx; | 177 brush.rect.x = offx; |
185 brush.rect.width = blitz_textwidth(brush.font, i->text); | 178 brush.rect.width = textwidth(&brush.font, i->text); |
186 if(brush.rect.width > mrect.width / 3) | 179 if(brush.rect.width > rect.width / 3) |
187 brush.rect.width = mrect.width / 3; | 180 brush.rect.width = rect.width / 3; |
188 brush.rect.width += mrect.height; | 181 brush.rect.width += brush.font.height; |
189 if(sel == i) { | 182 if(sel == i) { |
190 brush.color = selcolor; | 183 swap((void **)&brush.fg, (void **)&brush.bg); |
191 brush.border = True; | 184 draw(dpy, &brush, True, i->text); |
185 swap((void **)&brush.fg, (void **)&brush.bg); | |
192 } | 186 } |
193 blitz_draw_label(&brush, i->text); | 187 else |
188 draw(dpy, &brush, False, i->text); | |
194 offx += brush.rect.width; | 189 offx += brush.rect.width; |
195 } | 190 } |
196 | 191 |
197 brush.color = normcolor; | 192 brush.rect.x = rect.width - seek; |
198 brush.border = False; | |
199 brush.rect.x = mrect.width - seek; | |
200 brush.rect.width = seek; | 193 brush.rect.width = seek; |
201 blitz_draw_label(&brush, nextoff ? ">" : nil); | 194 draw(dpy, &brush, False, nextoff ? ">" : 0); |
202 } | 195 } |
203 XCopyArea(blz.dpy, brush.drawable, win, brush.gc, 0, 0, mrect.width, | 196 XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, rect.width, |
204 mrect.height, 0, 0); | 197 rect.height, 0, 0); |
205 XSync(blz.dpy, False); | 198 XFlush(dpy); |
206 } | 199 } |
207 | 200 |
208 static void | 201 static void |
209 handle_kpress(XKeyEvent * e) | 202 kpress(XKeyEvent * e) |
210 { | 203 { |
211 KeySym ksym; | 204 KeySym ksym; |
212 char buf[32]; | 205 char buf[32]; |
213 int num, prev_nitem; | 206 int num, prev_nitem; |
214 unsigned int i, len = strlen(text); | 207 unsigned int i, len = strlen(text); |
270 } | 263 } |
271 break; | 264 break; |
272 case XK_Tab: | 265 case XK_Tab: |
273 if(!sel) | 266 if(!sel) |
274 return; | 267 return; |
275 cext_strlcpy(text, sel->text, sizeof(text)); | 268 strncpy(text, sel->text, sizeof(text)); |
276 update_items(text); | 269 update_items(text); |
277 break; | 270 break; |
278 case XK_Right: | 271 case XK_Right: |
279 if(!(sel && sel->right)) | 272 if(!(sel && sel->right)) |
280 return; | 273 return; |
312 break; | 305 break; |
313 default: | 306 default: |
314 if((num == 1) && !iscntrl((int) buf[0])) { | 307 if((num == 1) && !iscntrl((int) buf[0])) { |
315 buf[num] = 0; | 308 buf[num] = 0; |
316 if(len > 0) | 309 if(len > 0) |
317 cext_strlcat(text, buf, sizeof(text)); | 310 strncat(text, buf, sizeof(text)); |
318 else | 311 else |
319 cext_strlcpy(text, buf, sizeof(text)); | 312 strncpy(text, buf, sizeof(text)); |
320 update_items(text); | 313 update_items(text); |
321 } | 314 } |
322 } | 315 } |
323 draw_menu(); | 316 draw_menu(); |
324 } | 317 } |
325 | 318 |
326 static char * | 319 static char * |
327 read_allitems() | 320 read_allitems() |
328 { | 321 { |
329 static char *maxname = nil; | 322 static char *maxname = 0; |
330 char *p, buf[1024]; | 323 char *p, buf[1024]; |
331 unsigned int len = 0, max = 0; | 324 unsigned int len = 0, max = 0; |
332 Item *i, *new; | 325 Item *i, *new; |
333 | 326 |
334 i = nil; | 327 i = 0; |
335 while(fgets(buf, sizeof(buf), stdin)) { | 328 while(fgets(buf, sizeof(buf), stdin)) { |
336 len = strlen(buf); | 329 len = strlen(buf); |
337 if (buf[len - 1] == '\n') | 330 if (buf[len - 1] == '\n') |
338 buf[len - 1] = 0; | 331 buf[len - 1] = 0; |
339 p = cext_estrdup(buf); | 332 p = estrdup(buf); |
340 if(max < len) { | 333 if(max < len) { |
341 maxname = p; | 334 maxname = p; |
342 max = len; | 335 max = len; |
343 } | 336 } |
344 | 337 |
345 new = cext_emalloc(sizeof(Item)); | 338 new = emalloc(sizeof(Item)); |
346 new->next = new->left = new->right = nil; | 339 new->next = new->left = new->right = 0; |
347 new->text = p; | 340 new->text = p; |
348 if(!i) | 341 if(!i) |
349 allitem = new; | 342 allitem = new; |
350 else | 343 else |
351 i->next = new; | 344 i->next = new; |
358 int | 351 int |
359 main(int argc, char *argv[]) | 352 main(int argc, char *argv[]) |
360 { | 353 { |
361 int i; | 354 int i; |
362 XSetWindowAttributes wa; | 355 XSetWindowAttributes wa; |
363 char *maxname, *p; | 356 char *maxname; |
364 BlitzFont font = {0}; | |
365 GC gc; | |
366 Drawable pmap; | |
367 XEvent ev; | 357 XEvent ev; |
368 | 358 |
369 /* command line args */ | 359 /* command line args */ |
370 for(i = 1; i < argc; i++) { | 360 for(i = 1; i < argc; i++) { |
371 if (argv[i][0] == '-') | 361 if (argv[i][0] == '-') |
386 } | 376 } |
387 else | 377 else |
388 usage(); | 378 usage(); |
389 } | 379 } |
390 | 380 |
391 blz.dpy = XOpenDisplay(0); | 381 dpy = XOpenDisplay(0); |
392 if(!blz.dpy) { | 382 if(!dpy) |
393 fprintf(stderr, "%s", "wmiimenu: cannot open dpy\n"); | 383 error("gridmenu: cannot open dpy\n"); |
394 exit(1); | 384 screen = DefaultScreen(dpy); |
395 } | 385 root = RootWindow(dpy, screen); |
396 blz.screen = DefaultScreen(blz.dpy); | |
397 blz.root = RootWindow(blz.dpy, blz.screen); | |
398 | 386 |
399 maxname = read_allitems(); | 387 maxname = read_allitems(); |
400 | 388 |
401 /* grab as early as possible, but after reading all items!!! */ | 389 /* grab as early as possible, but after reading all items!!! */ |
402 while(XGrabKeyboard | 390 while(XGrabKeyboard(dpy, root, True, GrabModeAsync, |
403 (blz.dpy, blz.root, True, GrabModeAsync, | |
404 GrabModeAsync, CurrentTime) != GrabSuccess) | 391 GrabModeAsync, CurrentTime) != GrabSuccess) |
405 usleep(1000); | 392 usleep(1000); |
406 | 393 |
407 font.fontstr = getenv("WMII_FONT"); | 394 /* style */ |
408 if (!font.fontstr) | 395 loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR); |
409 font.fontstr = cext_estrdup(BLITZ_FONT); | 396 loadfont(dpy, &brush.font, FONT); |
410 blitz_loadfont(&blz, &font); | |
411 | |
412 if((p = getenv("WMII_NORMCOLORS"))) | |
413 cext_strlcpy(normcolor.colstr, p, sizeof(normcolor.colstr)); | |
414 if(strlen(normcolor.colstr) != 23) | |
415 cext_strlcpy(normcolor.colstr, BLITZ_NORMCOLORS, sizeof(normcolor.colstr)); | |
416 blitz_loadcolor(&blz, &normcolor); | |
417 | |
418 if((p = getenv("WMII_SELCOLORS"))) | |
419 cext_strlcpy(selcolor.colstr, p, sizeof(selcolor.colstr)); | |
420 if(strlen(selcolor.colstr) != 23) | |
421 cext_strlcpy(selcolor.colstr, BLITZ_SELCOLORS, sizeof(selcolor.colstr)); | |
422 blitz_loadcolor(&blz, &selcolor); | |
423 | 397 |
424 wa.override_redirect = 1; | 398 wa.override_redirect = 1; |
425 wa.background_pixmap = ParentRelative; | 399 wa.background_pixmap = ParentRelative; |
426 wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask | 400 wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask |
427 | SubstructureRedirectMask | SubstructureNotifyMask; | 401 | SubstructureRedirectMask | SubstructureNotifyMask; |
428 | 402 |
429 mrect.width = DisplayWidth(blz.dpy, blz.screen); | 403 rect.width = DisplayWidth(dpy, screen); |
430 mrect.height = font.ascent + font.descent + 4; | 404 rect.height = brush.font.height + 4; |
431 mrect.y = DisplayHeight(blz.dpy, blz.screen) - mrect.height; | 405 rect.y = DisplayHeight(dpy, screen) - rect.height; |
432 mrect.x = 0; | 406 rect.x = 0; |
433 | 407 |
434 win = XCreateWindow(blz.dpy, blz.root, mrect.x, mrect.y, | 408 win = XCreateWindow(dpy, root, rect.x, rect.y, |
435 mrect.width, mrect.height, 0, DefaultDepth(blz.dpy, blz.screen), | 409 rect.width, rect.height, 0, DefaultDepth(dpy, screen), |
436 CopyFromParent, DefaultVisual(blz.dpy, blz.screen), | 410 CopyFromParent, DefaultVisual(dpy, screen), |
437 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | 411 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
438 XDefineCursor(blz.dpy, win, XCreateFontCursor(blz.dpy, XC_xterm)); | 412 XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); |
439 XSync(blz.dpy, False); | 413 XFlush(dpy); |
440 | 414 |
441 /* pixmap */ | 415 /* pixmap */ |
442 gc = XCreateGC(blz.dpy, win, 0, 0); | 416 brush.gc = XCreateGC(dpy, win, 0, 0); |
443 pmap = XCreatePixmap(blz.dpy, win, mrect.width, mrect.height, | 417 brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height, |
444 DefaultDepth(blz.dpy, blz.screen)); | 418 DefaultDepth(dpy, screen)); |
445 | 419 XFlush(dpy); |
446 XSync(blz.dpy, False); | |
447 | |
448 brush.blitz = &blz; | |
449 brush.color = normcolor; | |
450 brush.drawable = pmap; | |
451 brush.gc = gc; | |
452 brush.font = &font; | |
453 | 420 |
454 if(maxname) | 421 if(maxname) |
455 cwidth = blitz_textwidth(brush.font, maxname) + mrect.height; | 422 cwidth = textwidth(&brush.font, maxname) + brush.font.height; |
456 if(cwidth > mrect.width / 3) | 423 if(cwidth > rect.width / 3) |
457 cwidth = mrect.width / 3; | 424 cwidth = rect.width / 3; |
458 | 425 |
459 if(title) { | 426 if(title) { |
460 twidth = blitz_textwidth(brush.font, title) + mrect.height; | 427 twidth = textwidth(&brush.font, title) + brush.font.height; |
461 if(twidth > mrect.width / 3) | 428 if(twidth > rect.width / 3) |
462 twidth = mrect.width / 3; | 429 twidth = rect.width / 3; |
463 } | 430 } |
464 | 431 |
465 cmdw = title ? twidth : cwidth; | 432 cmdw = title ? twidth : cwidth; |
466 | 433 |
467 text[0] = 0; | 434 text[0] = 0; |
468 update_items(text); | 435 update_items(text); |
469 XMapRaised(blz.dpy, win); | 436 XMapRaised(dpy, win); |
470 draw_menu(); | 437 draw_menu(); |
471 XSync(blz.dpy, False); | 438 XFlush(dpy); |
472 | 439 |
473 /* main event loop */ | 440 /* main event loop */ |
474 while(!XNextEvent(blz.dpy, &ev)) { | 441 while(!XNextEvent(dpy, &ev)) { |
475 switch (ev.type) { | 442 switch (ev.type) { |
476 case KeyPress: | 443 case KeyPress: |
477 handle_kpress(&ev.xkey); | 444 kpress(&ev.xkey); |
478 break; | 445 break; |
479 case Expose: | 446 case Expose: |
480 if(ev.xexpose.count == 0) { | 447 if(ev.xexpose.count == 0) { |
481 draw_menu(); | 448 draw_menu(); |
482 } | 449 } |
486 } | 453 } |
487 if(done) | 454 if(done) |
488 break; | 455 break; |
489 } | 456 } |
490 | 457 |
491 XUngrabKeyboard(blz.dpy, CurrentTime); | 458 XUngrabKeyboard(dpy, CurrentTime); |
492 XFreePixmap(blz.dpy, pmap); | 459 XFreePixmap(dpy, brush.drawable); |
493 XFreeGC(blz.dpy, gc); | 460 XFreeGC(dpy, brush.gc); |
494 XDestroyWindow(blz.dpy, win); | 461 XDestroyWindow(dpy, win); |
495 XCloseDisplay(blz.dpy); | 462 XCloseDisplay(dpy); |
496 | 463 |
497 return ret; | 464 return ret; |
498 } | 465 } |