aewl
changeset 4:991bd8b0771e
renamed gridmenu.c into menu.c
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Mon, 10 Jul 2006 19:47:35 +0200 |
parents | e969f3575b7a |
children | e5018cae273f |
files | Makefile menu.c |
diffstat | 3 files changed, 466 insertions(+), 466 deletions(-) [+] |
line diff
1.1 --- a/Makefile Mon Jul 10 19:46:24 2006 +0200 1.2 +++ b/Makefile Mon Jul 10 19:47:35 2006 +0200 1.3 @@ -5,7 +5,7 @@ 1.4 1.5 WMSRC = wm.c draw.c util.c 1.6 WMOBJ = ${WMSRC:.c=.o} 1.7 -MENSRC = gridmenu.c draw.c util.c 1.8 +MENSRC = menu.c draw.c util.c 1.9 MENOBJ = ${MENSRC:.c=.o} 1.10 MAN = gridwm.1 1.11 BIN = gridwm gridmenu
2.1 --- a/gridmenu.c Mon Jul 10 19:46:24 2006 +0200 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,465 +0,0 @@ 2.4 -/* 2.5 - * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 2.6 - * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> 2.7 - * See LICENSE file for license details. 2.8 - */ 2.9 - 2.10 -#include "config.h" 2.11 -#include "draw.h" 2.12 -#include "util.h" 2.13 - 2.14 -#include <ctype.h> 2.15 -#include <stdlib.h> 2.16 -#include <stdio.h> 2.17 -#include <string.h> 2.18 -#include <sys/stat.h> 2.19 -#include <sys/wait.h> 2.20 -#include <time.h> 2.21 -#include <unistd.h> 2.22 -#include <X11/cursorfont.h> 2.23 -#include <X11/Xutil.h> 2.24 -#include <X11/keysym.h> 2.25 - 2.26 -typedef struct Item Item; 2.27 - 2.28 -struct Item { 2.29 - Item *next; /* traverses all items */ 2.30 - Item *left, *right; /* traverses items matching current search pattern */ 2.31 - char *text; 2.32 -}; 2.33 - 2.34 -static Display *dpy; 2.35 -static Window root; 2.36 -static Window win; 2.37 -static XRectangle rect; 2.38 -static Bool done = False; 2.39 - 2.40 -static Item *allitem = 0; /* first of all items */ 2.41 -static Item *item = 0; /* first of pattern matching items */ 2.42 -static Item *sel = 0; 2.43 -static Item *nextoff = 0; 2.44 -static Item *prevoff = 0; 2.45 -static Item *curroff = 0; 2.46 - 2.47 -static int screen; 2.48 -static char *title = 0; 2.49 -static char text[4096]; 2.50 -static int ret = 0; 2.51 -static int nitem = 0; 2.52 -static unsigned int cmdw = 0; 2.53 -static unsigned int twidth = 0; 2.54 -static unsigned int cwidth = 0; 2.55 -static const int seek = 30; /* 30px */ 2.56 - 2.57 -static Brush brush = {0}; 2.58 - 2.59 -static void draw_menu(void); 2.60 -static void kpress(XKeyEvent * e); 2.61 - 2.62 -static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; 2.63 - 2.64 -static void 2.65 -usage() 2.66 -{ 2.67 - fprintf(stderr, "%s", "usage: gridmenu [-v] [-t <title>]\n"); 2.68 - exit(1); 2.69 -} 2.70 - 2.71 -static void 2.72 -update_offsets() 2.73 -{ 2.74 - unsigned int tw, w = cmdw + 2 * seek; 2.75 - 2.76 - if(!curroff) 2.77 - return; 2.78 - 2.79 - for(nextoff = curroff; nextoff; nextoff=nextoff->right) { 2.80 - tw = textwidth(&brush.font, nextoff->text); 2.81 - if(tw > rect.width / 3) 2.82 - tw = rect.width / 3; 2.83 - w += tw + brush.font.height; 2.84 - if(w > rect.width) 2.85 - break; 2.86 - } 2.87 - 2.88 - w = cmdw + 2 * seek; 2.89 - for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { 2.90 - tw = textwidth(&brush.font, prevoff->left->text); 2.91 - if(tw > rect.width / 3) 2.92 - tw = rect.width / 3; 2.93 - w += tw + brush.font.height; 2.94 - if(w > rect.width) 2.95 - break; 2.96 - } 2.97 -} 2.98 - 2.99 -static void 2.100 -update_items(char *pattern) 2.101 -{ 2.102 - unsigned int plen = strlen(pattern); 2.103 - Item *i, *j; 2.104 - 2.105 - if(!pattern) 2.106 - return; 2.107 - 2.108 - if(!title || *pattern) 2.109 - cmdw = cwidth; 2.110 - else 2.111 - cmdw = twidth; 2.112 - 2.113 - item = j = 0; 2.114 - nitem = 0; 2.115 - 2.116 - for(i = allitem; i; i=i->next) 2.117 - if(!plen || !strncmp(pattern, i->text, plen)) { 2.118 - if(!j) 2.119 - item = i; 2.120 - else 2.121 - j->right = i; 2.122 - i->left = j; 2.123 - i->right = 0; 2.124 - j = i; 2.125 - nitem++; 2.126 - } 2.127 - for(i = allitem; i; i=i->next) 2.128 - if(plen && strncmp(pattern, i->text, plen) 2.129 - && strstr(i->text, pattern)) { 2.130 - if(!j) 2.131 - item = i; 2.132 - else 2.133 - j->right = i; 2.134 - i->left = j; 2.135 - i->right = 0; 2.136 - j = i; 2.137 - nitem++; 2.138 - } 2.139 - 2.140 - curroff = prevoff = nextoff = sel = item; 2.141 - 2.142 - update_offsets(); 2.143 -} 2.144 - 2.145 -/* creates brush structs for brush mode drawing */ 2.146 -static void 2.147 -draw_menu() 2.148 -{ 2.149 - unsigned int offx = 0; 2.150 - Item *i; 2.151 - 2.152 - brush.rect = rect; 2.153 - brush.rect.x = 0; 2.154 - brush.rect.y = 0; 2.155 - draw(dpy, &brush, False, 0); 2.156 - 2.157 - /* print command */ 2.158 - if(!title || text[0]) { 2.159 - cmdw = cwidth; 2.160 - if(cmdw && item) 2.161 - brush.rect.width = cmdw; 2.162 - draw(dpy, &brush, False, text); 2.163 - } 2.164 - else { 2.165 - cmdw = twidth; 2.166 - brush.rect.width = cmdw; 2.167 - draw(dpy, &brush, False, title); 2.168 - } 2.169 - offx += brush.rect.width; 2.170 - 2.171 - if(curroff) { 2.172 - brush.rect.x = offx; 2.173 - brush.rect.width = seek; 2.174 - offx += brush.rect.width; 2.175 - draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0); 2.176 - 2.177 - /* determine maximum items */ 2.178 - for(i = curroff; i != nextoff; i=i->right) { 2.179 - brush.border = False; 2.180 - brush.rect.x = offx; 2.181 - brush.rect.width = textwidth(&brush.font, i->text); 2.182 - if(brush.rect.width > rect.width / 3) 2.183 - brush.rect.width = rect.width / 3; 2.184 - brush.rect.width += brush.font.height; 2.185 - if(sel == i) { 2.186 - swap((void **)&brush.fg, (void **)&brush.bg); 2.187 - draw(dpy, &brush, True, i->text); 2.188 - swap((void **)&brush.fg, (void **)&brush.bg); 2.189 - } 2.190 - else 2.191 - draw(dpy, &brush, False, i->text); 2.192 - offx += brush.rect.width; 2.193 - } 2.194 - 2.195 - brush.rect.x = rect.width - seek; 2.196 - brush.rect.width = seek; 2.197 - draw(dpy, &brush, False, nextoff ? ">" : 0); 2.198 - } 2.199 - XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, rect.width, 2.200 - rect.height, 0, 0); 2.201 - XFlush(dpy); 2.202 -} 2.203 - 2.204 -static void 2.205 -kpress(XKeyEvent * e) 2.206 -{ 2.207 - KeySym ksym; 2.208 - char buf[32]; 2.209 - int num, prev_nitem; 2.210 - unsigned int i, len = strlen(text); 2.211 - 2.212 - buf[0] = 0; 2.213 - num = XLookupString(e, buf, sizeof(buf), &ksym, 0); 2.214 - 2.215 - if(IsFunctionKey(ksym) || IsKeypadKey(ksym) 2.216 - || IsMiscFunctionKey(ksym) || IsPFKey(ksym) 2.217 - || IsPrivateKeypadKey(ksym)) 2.218 - return; 2.219 - 2.220 - /* first check if a control mask is omitted */ 2.221 - if(e->state & ControlMask) { 2.222 - switch (ksym) { 2.223 - case XK_H: 2.224 - case XK_h: 2.225 - ksym = XK_BackSpace; 2.226 - break; 2.227 - case XK_I: 2.228 - case XK_i: 2.229 - ksym = XK_Tab; 2.230 - break; 2.231 - case XK_J: 2.232 - case XK_j: 2.233 - ksym = XK_Return; 2.234 - break; 2.235 - case XK_N: 2.236 - case XK_n: 2.237 - ksym = XK_Right; 2.238 - break; 2.239 - case XK_P: 2.240 - case XK_p: 2.241 - ksym = XK_Left; 2.242 - break; 2.243 - case XK_U: 2.244 - case XK_u: 2.245 - text[0] = 0; 2.246 - update_items(text); 2.247 - draw_menu(); 2.248 - return; 2.249 - break; 2.250 - case XK_bracketleft: 2.251 - ksym = XK_Escape; 2.252 - break; 2.253 - default: /* ignore other control sequences */ 2.254 - return; 2.255 - break; 2.256 - } 2.257 - } 2.258 - switch (ksym) { 2.259 - case XK_Left: 2.260 - if(!(sel && sel->left)) 2.261 - return; 2.262 - sel=sel->left; 2.263 - if(sel->right == curroff) { 2.264 - curroff = prevoff; 2.265 - update_offsets(); 2.266 - } 2.267 - break; 2.268 - case XK_Tab: 2.269 - if(!sel) 2.270 - return; 2.271 - strncpy(text, sel->text, sizeof(text)); 2.272 - update_items(text); 2.273 - break; 2.274 - case XK_Right: 2.275 - if(!(sel && sel->right)) 2.276 - return; 2.277 - sel=sel->right; 2.278 - if(sel == nextoff) { 2.279 - curroff = nextoff; 2.280 - update_offsets(); 2.281 - } 2.282 - break; 2.283 - case XK_Return: 2.284 - if(e->state & ShiftMask) { 2.285 - if(text) 2.286 - fprintf(stdout, "%s", text); 2.287 - } 2.288 - else if(sel) 2.289 - fprintf(stdout, "%s", sel->text); 2.290 - else if(text) 2.291 - fprintf(stdout, "%s", text); 2.292 - fflush(stdout); 2.293 - done = True; 2.294 - break; 2.295 - case XK_Escape: 2.296 - ret = 1; 2.297 - done = True; 2.298 - break; 2.299 - case XK_BackSpace: 2.300 - if((i = len)) { 2.301 - prev_nitem = nitem; 2.302 - do { 2.303 - text[--i] = 0; 2.304 - update_items(text); 2.305 - } while(i && nitem && prev_nitem == nitem); 2.306 - update_items(text); 2.307 - } 2.308 - break; 2.309 - default: 2.310 - if((num == 1) && !iscntrl((int) buf[0])) { 2.311 - buf[num] = 0; 2.312 - if(len > 0) 2.313 - strncat(text, buf, sizeof(text)); 2.314 - else 2.315 - strncpy(text, buf, sizeof(text)); 2.316 - update_items(text); 2.317 - } 2.318 - } 2.319 - draw_menu(); 2.320 -} 2.321 - 2.322 -static char * 2.323 -read_allitems() 2.324 -{ 2.325 - static char *maxname = 0; 2.326 - char *p, buf[1024]; 2.327 - unsigned int len = 0, max = 0; 2.328 - Item *i, *new; 2.329 - 2.330 - i = 0; 2.331 - while(fgets(buf, sizeof(buf), stdin)) { 2.332 - len = strlen(buf); 2.333 - if (buf[len - 1] == '\n') 2.334 - buf[len - 1] = 0; 2.335 - p = estrdup(buf); 2.336 - if(max < len) { 2.337 - maxname = p; 2.338 - max = len; 2.339 - } 2.340 - 2.341 - new = emalloc(sizeof(Item)); 2.342 - new->next = new->left = new->right = 0; 2.343 - new->text = p; 2.344 - if(!i) 2.345 - allitem = new; 2.346 - else 2.347 - i->next = new; 2.348 - i = new; 2.349 - } 2.350 - 2.351 - return maxname; 2.352 -} 2.353 - 2.354 -int 2.355 -main(int argc, char *argv[]) 2.356 -{ 2.357 - int i; 2.358 - XSetWindowAttributes wa; 2.359 - char *maxname; 2.360 - XEvent ev; 2.361 - 2.362 - /* command line args */ 2.363 - for(i = 1; i < argc; i++) { 2.364 - if (argv[i][0] == '-') 2.365 - switch (argv[i][1]) { 2.366 - case 'v': 2.367 - fprintf(stdout, "%s", version); 2.368 - exit(0); 2.369 - break; 2.370 - case 't': 2.371 - if(++i < argc) 2.372 - title = argv[i]; 2.373 - else 2.374 - usage(); 2.375 - break; 2.376 - default: 2.377 - usage(); 2.378 - break; 2.379 - } 2.380 - else 2.381 - usage(); 2.382 - } 2.383 - 2.384 - dpy = XOpenDisplay(0); 2.385 - if(!dpy) 2.386 - error("gridmenu: cannot open dpy\n"); 2.387 - screen = DefaultScreen(dpy); 2.388 - root = RootWindow(dpy, screen); 2.389 - 2.390 - maxname = read_allitems(); 2.391 - 2.392 - /* grab as early as possible, but after reading all items!!! */ 2.393 - while(XGrabKeyboard(dpy, root, True, GrabModeAsync, 2.394 - GrabModeAsync, CurrentTime) != GrabSuccess) 2.395 - usleep(1000); 2.396 - 2.397 - /* style */ 2.398 - loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR); 2.399 - loadfont(dpy, &brush.font, FONT); 2.400 - 2.401 - wa.override_redirect = 1; 2.402 - wa.background_pixmap = ParentRelative; 2.403 - wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask 2.404 - | SubstructureRedirectMask | SubstructureNotifyMask; 2.405 - 2.406 - rect.width = DisplayWidth(dpy, screen); 2.407 - rect.height = brush.font.height + 4; 2.408 - rect.y = DisplayHeight(dpy, screen) - rect.height; 2.409 - rect.x = 0; 2.410 - 2.411 - win = XCreateWindow(dpy, root, rect.x, rect.y, 2.412 - rect.width, rect.height, 0, DefaultDepth(dpy, screen), 2.413 - CopyFromParent, DefaultVisual(dpy, screen), 2.414 - CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 2.415 - XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); 2.416 - XFlush(dpy); 2.417 - 2.418 - /* pixmap */ 2.419 - brush.gc = XCreateGC(dpy, win, 0, 0); 2.420 - brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height, 2.421 - DefaultDepth(dpy, screen)); 2.422 - XFlush(dpy); 2.423 - 2.424 - if(maxname) 2.425 - cwidth = textwidth(&brush.font, maxname) + brush.font.height; 2.426 - if(cwidth > rect.width / 3) 2.427 - cwidth = rect.width / 3; 2.428 - 2.429 - if(title) { 2.430 - twidth = textwidth(&brush.font, title) + brush.font.height; 2.431 - if(twidth > rect.width / 3) 2.432 - twidth = rect.width / 3; 2.433 - } 2.434 - 2.435 - cmdw = title ? twidth : cwidth; 2.436 - 2.437 - text[0] = 0; 2.438 - update_items(text); 2.439 - XMapRaised(dpy, win); 2.440 - draw_menu(); 2.441 - XFlush(dpy); 2.442 - 2.443 - /* main event loop */ 2.444 - while(!XNextEvent(dpy, &ev)) { 2.445 - switch (ev.type) { 2.446 - case KeyPress: 2.447 - kpress(&ev.xkey); 2.448 - break; 2.449 - case Expose: 2.450 - if(ev.xexpose.count == 0) { 2.451 - draw_menu(); 2.452 - } 2.453 - break; 2.454 - default: 2.455 - break; 2.456 - } 2.457 - if(done) 2.458 - break; 2.459 - } 2.460 - 2.461 - XUngrabKeyboard(dpy, CurrentTime); 2.462 - XFreePixmap(dpy, brush.drawable); 2.463 - XFreeGC(dpy, brush.gc); 2.464 - XDestroyWindow(dpy, win); 2.465 - XCloseDisplay(dpy); 2.466 - 2.467 - return ret; 2.468 -}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/menu.c Mon Jul 10 19:47:35 2006 +0200 3.3 @@ -0,0 +1,465 @@ 3.4 +/* 3.5 + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 3.6 + * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> 3.7 + * See LICENSE file for license details. 3.8 + */ 3.9 + 3.10 +#include "config.h" 3.11 +#include "draw.h" 3.12 +#include "util.h" 3.13 + 3.14 +#include <ctype.h> 3.15 +#include <stdlib.h> 3.16 +#include <stdio.h> 3.17 +#include <string.h> 3.18 +#include <sys/stat.h> 3.19 +#include <sys/wait.h> 3.20 +#include <time.h> 3.21 +#include <unistd.h> 3.22 +#include <X11/cursorfont.h> 3.23 +#include <X11/Xutil.h> 3.24 +#include <X11/keysym.h> 3.25 + 3.26 +typedef struct Item Item; 3.27 + 3.28 +struct Item { 3.29 + Item *next; /* traverses all items */ 3.30 + Item *left, *right; /* traverses items matching current search pattern */ 3.31 + char *text; 3.32 +}; 3.33 + 3.34 +static Display *dpy; 3.35 +static Window root; 3.36 +static Window win; 3.37 +static XRectangle rect; 3.38 +static Bool done = False; 3.39 + 3.40 +static Item *allitem = 0; /* first of all items */ 3.41 +static Item *item = 0; /* first of pattern matching items */ 3.42 +static Item *sel = 0; 3.43 +static Item *nextoff = 0; 3.44 +static Item *prevoff = 0; 3.45 +static Item *curroff = 0; 3.46 + 3.47 +static int screen; 3.48 +static char *title = 0; 3.49 +static char text[4096]; 3.50 +static int ret = 0; 3.51 +static int nitem = 0; 3.52 +static unsigned int cmdw = 0; 3.53 +static unsigned int twidth = 0; 3.54 +static unsigned int cwidth = 0; 3.55 +static const int seek = 30; /* 30px */ 3.56 + 3.57 +static Brush brush = {0}; 3.58 + 3.59 +static void draw_menu(void); 3.60 +static void kpress(XKeyEvent * e); 3.61 + 3.62 +static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; 3.63 + 3.64 +static void 3.65 +usage() 3.66 +{ 3.67 + fprintf(stderr, "%s", "usage: gridmenu [-v] [-t <title>]\n"); 3.68 + exit(1); 3.69 +} 3.70 + 3.71 +static void 3.72 +update_offsets() 3.73 +{ 3.74 + unsigned int tw, w = cmdw + 2 * seek; 3.75 + 3.76 + if(!curroff) 3.77 + return; 3.78 + 3.79 + for(nextoff = curroff; nextoff; nextoff=nextoff->right) { 3.80 + tw = textwidth(&brush.font, nextoff->text); 3.81 + if(tw > rect.width / 3) 3.82 + tw = rect.width / 3; 3.83 + w += tw + brush.font.height; 3.84 + if(w > rect.width) 3.85 + break; 3.86 + } 3.87 + 3.88 + w = cmdw + 2 * seek; 3.89 + for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { 3.90 + tw = textwidth(&brush.font, prevoff->left->text); 3.91 + if(tw > rect.width / 3) 3.92 + tw = rect.width / 3; 3.93 + w += tw + brush.font.height; 3.94 + if(w > rect.width) 3.95 + break; 3.96 + } 3.97 +} 3.98 + 3.99 +static void 3.100 +update_items(char *pattern) 3.101 +{ 3.102 + unsigned int plen = strlen(pattern); 3.103 + Item *i, *j; 3.104 + 3.105 + if(!pattern) 3.106 + return; 3.107 + 3.108 + if(!title || *pattern) 3.109 + cmdw = cwidth; 3.110 + else 3.111 + cmdw = twidth; 3.112 + 3.113 + item = j = 0; 3.114 + nitem = 0; 3.115 + 3.116 + for(i = allitem; i; i=i->next) 3.117 + if(!plen || !strncmp(pattern, i->text, plen)) { 3.118 + if(!j) 3.119 + item = i; 3.120 + else 3.121 + j->right = i; 3.122 + i->left = j; 3.123 + i->right = 0; 3.124 + j = i; 3.125 + nitem++; 3.126 + } 3.127 + for(i = allitem; i; i=i->next) 3.128 + if(plen && strncmp(pattern, i->text, plen) 3.129 + && strstr(i->text, pattern)) { 3.130 + if(!j) 3.131 + item = i; 3.132 + else 3.133 + j->right = i; 3.134 + i->left = j; 3.135 + i->right = 0; 3.136 + j = i; 3.137 + nitem++; 3.138 + } 3.139 + 3.140 + curroff = prevoff = nextoff = sel = item; 3.141 + 3.142 + update_offsets(); 3.143 +} 3.144 + 3.145 +/* creates brush structs for brush mode drawing */ 3.146 +static void 3.147 +draw_menu() 3.148 +{ 3.149 + unsigned int offx = 0; 3.150 + Item *i; 3.151 + 3.152 + brush.rect = rect; 3.153 + brush.rect.x = 0; 3.154 + brush.rect.y = 0; 3.155 + draw(dpy, &brush, False, 0); 3.156 + 3.157 + /* print command */ 3.158 + if(!title || text[0]) { 3.159 + cmdw = cwidth; 3.160 + if(cmdw && item) 3.161 + brush.rect.width = cmdw; 3.162 + draw(dpy, &brush, False, text); 3.163 + } 3.164 + else { 3.165 + cmdw = twidth; 3.166 + brush.rect.width = cmdw; 3.167 + draw(dpy, &brush, False, title); 3.168 + } 3.169 + offx += brush.rect.width; 3.170 + 3.171 + if(curroff) { 3.172 + brush.rect.x = offx; 3.173 + brush.rect.width = seek; 3.174 + offx += brush.rect.width; 3.175 + draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0); 3.176 + 3.177 + /* determine maximum items */ 3.178 + for(i = curroff; i != nextoff; i=i->right) { 3.179 + brush.border = False; 3.180 + brush.rect.x = offx; 3.181 + brush.rect.width = textwidth(&brush.font, i->text); 3.182 + if(brush.rect.width > rect.width / 3) 3.183 + brush.rect.width = rect.width / 3; 3.184 + brush.rect.width += brush.font.height; 3.185 + if(sel == i) { 3.186 + swap((void **)&brush.fg, (void **)&brush.bg); 3.187 + draw(dpy, &brush, True, i->text); 3.188 + swap((void **)&brush.fg, (void **)&brush.bg); 3.189 + } 3.190 + else 3.191 + draw(dpy, &brush, False, i->text); 3.192 + offx += brush.rect.width; 3.193 + } 3.194 + 3.195 + brush.rect.x = rect.width - seek; 3.196 + brush.rect.width = seek; 3.197 + draw(dpy, &brush, False, nextoff ? ">" : 0); 3.198 + } 3.199 + XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, rect.width, 3.200 + rect.height, 0, 0); 3.201 + XFlush(dpy); 3.202 +} 3.203 + 3.204 +static void 3.205 +kpress(XKeyEvent * e) 3.206 +{ 3.207 + KeySym ksym; 3.208 + char buf[32]; 3.209 + int num, prev_nitem; 3.210 + unsigned int i, len = strlen(text); 3.211 + 3.212 + buf[0] = 0; 3.213 + num = XLookupString(e, buf, sizeof(buf), &ksym, 0); 3.214 + 3.215 + if(IsFunctionKey(ksym) || IsKeypadKey(ksym) 3.216 + || IsMiscFunctionKey(ksym) || IsPFKey(ksym) 3.217 + || IsPrivateKeypadKey(ksym)) 3.218 + return; 3.219 + 3.220 + /* first check if a control mask is omitted */ 3.221 + if(e->state & ControlMask) { 3.222 + switch (ksym) { 3.223 + case XK_H: 3.224 + case XK_h: 3.225 + ksym = XK_BackSpace; 3.226 + break; 3.227 + case XK_I: 3.228 + case XK_i: 3.229 + ksym = XK_Tab; 3.230 + break; 3.231 + case XK_J: 3.232 + case XK_j: 3.233 + ksym = XK_Return; 3.234 + break; 3.235 + case XK_N: 3.236 + case XK_n: 3.237 + ksym = XK_Right; 3.238 + break; 3.239 + case XK_P: 3.240 + case XK_p: 3.241 + ksym = XK_Left; 3.242 + break; 3.243 + case XK_U: 3.244 + case XK_u: 3.245 + text[0] = 0; 3.246 + update_items(text); 3.247 + draw_menu(); 3.248 + return; 3.249 + break; 3.250 + case XK_bracketleft: 3.251 + ksym = XK_Escape; 3.252 + break; 3.253 + default: /* ignore other control sequences */ 3.254 + return; 3.255 + break; 3.256 + } 3.257 + } 3.258 + switch (ksym) { 3.259 + case XK_Left: 3.260 + if(!(sel && sel->left)) 3.261 + return; 3.262 + sel=sel->left; 3.263 + if(sel->right == curroff) { 3.264 + curroff = prevoff; 3.265 + update_offsets(); 3.266 + } 3.267 + break; 3.268 + case XK_Tab: 3.269 + if(!sel) 3.270 + return; 3.271 + strncpy(text, sel->text, sizeof(text)); 3.272 + update_items(text); 3.273 + break; 3.274 + case XK_Right: 3.275 + if(!(sel && sel->right)) 3.276 + return; 3.277 + sel=sel->right; 3.278 + if(sel == nextoff) { 3.279 + curroff = nextoff; 3.280 + update_offsets(); 3.281 + } 3.282 + break; 3.283 + case XK_Return: 3.284 + if(e->state & ShiftMask) { 3.285 + if(text) 3.286 + fprintf(stdout, "%s", text); 3.287 + } 3.288 + else if(sel) 3.289 + fprintf(stdout, "%s", sel->text); 3.290 + else if(text) 3.291 + fprintf(stdout, "%s", text); 3.292 + fflush(stdout); 3.293 + done = True; 3.294 + break; 3.295 + case XK_Escape: 3.296 + ret = 1; 3.297 + done = True; 3.298 + break; 3.299 + case XK_BackSpace: 3.300 + if((i = len)) { 3.301 + prev_nitem = nitem; 3.302 + do { 3.303 + text[--i] = 0; 3.304 + update_items(text); 3.305 + } while(i && nitem && prev_nitem == nitem); 3.306 + update_items(text); 3.307 + } 3.308 + break; 3.309 + default: 3.310 + if((num == 1) && !iscntrl((int) buf[0])) { 3.311 + buf[num] = 0; 3.312 + if(len > 0) 3.313 + strncat(text, buf, sizeof(text)); 3.314 + else 3.315 + strncpy(text, buf, sizeof(text)); 3.316 + update_items(text); 3.317 + } 3.318 + } 3.319 + draw_menu(); 3.320 +} 3.321 + 3.322 +static char * 3.323 +read_allitems() 3.324 +{ 3.325 + static char *maxname = 0; 3.326 + char *p, buf[1024]; 3.327 + unsigned int len = 0, max = 0; 3.328 + Item *i, *new; 3.329 + 3.330 + i = 0; 3.331 + while(fgets(buf, sizeof(buf), stdin)) { 3.332 + len = strlen(buf); 3.333 + if (buf[len - 1] == '\n') 3.334 + buf[len - 1] = 0; 3.335 + p = estrdup(buf); 3.336 + if(max < len) { 3.337 + maxname = p; 3.338 + max = len; 3.339 + } 3.340 + 3.341 + new = emalloc(sizeof(Item)); 3.342 + new->next = new->left = new->right = 0; 3.343 + new->text = p; 3.344 + if(!i) 3.345 + allitem = new; 3.346 + else 3.347 + i->next = new; 3.348 + i = new; 3.349 + } 3.350 + 3.351 + return maxname; 3.352 +} 3.353 + 3.354 +int 3.355 +main(int argc, char *argv[]) 3.356 +{ 3.357 + int i; 3.358 + XSetWindowAttributes wa; 3.359 + char *maxname; 3.360 + XEvent ev; 3.361 + 3.362 + /* command line args */ 3.363 + for(i = 1; i < argc; i++) { 3.364 + if (argv[i][0] == '-') 3.365 + switch (argv[i][1]) { 3.366 + case 'v': 3.367 + fprintf(stdout, "%s", version); 3.368 + exit(0); 3.369 + break; 3.370 + case 't': 3.371 + if(++i < argc) 3.372 + title = argv[i]; 3.373 + else 3.374 + usage(); 3.375 + break; 3.376 + default: 3.377 + usage(); 3.378 + break; 3.379 + } 3.380 + else 3.381 + usage(); 3.382 + } 3.383 + 3.384 + dpy = XOpenDisplay(0); 3.385 + if(!dpy) 3.386 + error("gridmenu: cannot open dpy\n"); 3.387 + screen = DefaultScreen(dpy); 3.388 + root = RootWindow(dpy, screen); 3.389 + 3.390 + maxname = read_allitems(); 3.391 + 3.392 + /* grab as early as possible, but after reading all items!!! */ 3.393 + while(XGrabKeyboard(dpy, root, True, GrabModeAsync, 3.394 + GrabModeAsync, CurrentTime) != GrabSuccess) 3.395 + usleep(1000); 3.396 + 3.397 + /* style */ 3.398 + loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR); 3.399 + loadfont(dpy, &brush.font, FONT); 3.400 + 3.401 + wa.override_redirect = 1; 3.402 + wa.background_pixmap = ParentRelative; 3.403 + wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask 3.404 + | SubstructureRedirectMask | SubstructureNotifyMask; 3.405 + 3.406 + rect.width = DisplayWidth(dpy, screen); 3.407 + rect.height = brush.font.height + 4; 3.408 + rect.y = DisplayHeight(dpy, screen) - rect.height; 3.409 + rect.x = 0; 3.410 + 3.411 + win = XCreateWindow(dpy, root, rect.x, rect.y, 3.412 + rect.width, rect.height, 0, DefaultDepth(dpy, screen), 3.413 + CopyFromParent, DefaultVisual(dpy, screen), 3.414 + CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); 3.415 + XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); 3.416 + XFlush(dpy); 3.417 + 3.418 + /* pixmap */ 3.419 + brush.gc = XCreateGC(dpy, win, 0, 0); 3.420 + brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height, 3.421 + DefaultDepth(dpy, screen)); 3.422 + XFlush(dpy); 3.423 + 3.424 + if(maxname) 3.425 + cwidth = textwidth(&brush.font, maxname) + brush.font.height; 3.426 + if(cwidth > rect.width / 3) 3.427 + cwidth = rect.width / 3; 3.428 + 3.429 + if(title) { 3.430 + twidth = textwidth(&brush.font, title) + brush.font.height; 3.431 + if(twidth > rect.width / 3) 3.432 + twidth = rect.width / 3; 3.433 + } 3.434 + 3.435 + cmdw = title ? twidth : cwidth; 3.436 + 3.437 + text[0] = 0; 3.438 + update_items(text); 3.439 + XMapRaised(dpy, win); 3.440 + draw_menu(); 3.441 + XFlush(dpy); 3.442 + 3.443 + /* main event loop */ 3.444 + while(!XNextEvent(dpy, &ev)) { 3.445 + switch (ev.type) { 3.446 + case KeyPress: 3.447 + kpress(&ev.xkey); 3.448 + break; 3.449 + case Expose: 3.450 + if(ev.xexpose.count == 0) { 3.451 + draw_menu(); 3.452 + } 3.453 + break; 3.454 + default: 3.455 + break; 3.456 + } 3.457 + if(done) 3.458 + break; 3.459 + } 3.460 + 3.461 + XUngrabKeyboard(dpy, CurrentTime); 3.462 + XFreePixmap(dpy, brush.drawable); 3.463 + XFreeGC(dpy, brush.gc); 3.464 + XDestroyWindow(dpy, win); 3.465 + XCloseDisplay(dpy); 3.466 + 3.467 + return ret; 3.468 +}