X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=main.c;h=e4c490336814ef8c8b7153320a67bc5eef1fd4dc;hb=aa2f73fc88ef3e6946e75bab54a3c0f83f887b3b;hp=08406436540ff9927b6079a7bb5cc14ebf46a122;hpb=665488a6eedeecf743e44bd9624105c8b47c4f97;p=dmenu.git diff --git a/main.c b/main.c index 0840643..e4c4903 100644 --- a/main.c +++ b/main.c @@ -1,17 +1,13 @@ -/* (C)opyright MMVI-MMVII Anselm R. Garbe - * (C)opyright MMVI-MMVII Sander van Dijk - * See LICENSE file for license details. - */ +/* © 2006-2007 Anselm R. Garbe + * © 2006-2007 Sander van Dijk + * See LICENSE file for license details. */ #include "dmenu.h" - #include #include #include #include #include #include -#include -#include #include #include @@ -44,22 +40,6 @@ static Item *curr = NULL; static Window root; static Window win; -static unsigned int -textnw(const char *text, unsigned int len) { - XRectangle r; - - if(dc.font.set) { - XmbTextExtents(dc.font.set, text, len, NULL, &r); - return r.width; - } - return XTextWidth(dc.font.xfont, text, len); -} - -static unsigned int -textw(const char *text) { - return textnw(text, strlen(text)) + dc.font.height; -} - static void calcoffsets(void) { unsigned int tw, w; @@ -86,53 +66,6 @@ calcoffsets(void) { } } -static void -drawtext(const char *text, unsigned long col[ColLast]) { - int x, y, w, h; - static char buf[256]; - unsigned int len, olen; - XGCValues gcv; - XRectangle r = { dc.x, dc.y, dc.w, dc.h }; - - XSetForeground(dpy, dc.gc, col[ColBG]); - XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); - if(!text) - return; - w = 0; - olen = len = strlen(text); - if(len >= sizeof buf) - len = sizeof buf - 1; - memcpy(buf, text, len); - buf[len] = 0; - h = dc.font.ascent + dc.font.descent; - y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; - x = dc.x + (h / 2); - /* shorten text if necessary */ - while(len && (w = textnw(buf, len)) > dc.w - h) - buf[--len] = 0; - if(len < olen) { - if(len > 1) - buf[len - 1] = '.'; - if(len > 2) - buf[len - 2] = '.'; - if(len > 3) - buf[len - 3] = '.'; - } - if(w > dc.w) - return; /* too long */ - gcv.foreground = col[ColFG]; - if(dc.font.set) { - XChangeGC(dpy, dc.gc, GCForeground, &gcv); - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, - x, y, buf, len); - } - else { - gcv.font = dc.font.xfont->fid; - XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv); - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); - } -} - static void drawmenu(void) { Item *i; @@ -174,8 +107,21 @@ drawmenu(void) { XFlush(dpy); } +static Bool +grabkeyboard(void) { + unsigned int len; + + for(len = 1000; len; len--) { + if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) + == GrabSuccess) + break; + usleep(1000); + } + return len > 0; +} + static unsigned long -getcolor(const char *colstr) { +initcolor(const char *colstr) { Colormap cmap = DefaultColormap(dpy, screen); XColor color; @@ -185,10 +131,12 @@ getcolor(const char *colstr) { } static void -setfont(const char *fontstr) { +initfont(const char *fontstr) { char *def, **missing; int i, n; + if(!fontstr || fontstr[0] == '\0') + eprint("error, cannot load font: '%s'\n", fontstr); missing = NULL; if(dc.font.set) XFreeFontSet(dpy, dc.font.set); @@ -262,13 +210,20 @@ match(char *pattern) { static void kpress(XKeyEvent * e) { char buf[32]; - int i, num, prev_nitem; + int i, num; unsigned int len; KeySym ksym; len = strlen(text); buf[0] = 0; num = XLookupString(e, buf, sizeof buf, &ksym, 0); + if(IsKeypadKey(ksym)) { + if(ksym == XK_KP_Enter) { + ksym = XK_Return; + } else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) { + ksym = (ksym - XK_KP_0) + XK_0; + } + } if(IsFunctionKey(ksym) || IsKeypadKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsPrivateKeypadKey(ksym)) @@ -348,12 +303,8 @@ kpress(XKeyEvent * e) { } break; case XK_BackSpace: - if((i = len)) { - prev_nitem = nitem; - do { - text[--i] = 0; - match(text); - } while(i && nitem && prev_nitem == nitem); + if(len) { + text[--len] = 0; match(text); } break; @@ -457,6 +408,12 @@ readstdin(void) { return maxname; } +static void +usage(void) { + eprint("usage: dmenu [-b] [-fn ] [-nb ] [-nf ]\n" + " [-p ] [-sb ] [-sf ] [-v]\n"); +} + /* extern */ int screen; @@ -472,16 +429,12 @@ main(int argc, char *argv[]) { char *normfg = NORMFGCOLOR; char *selbg = SELBGCOLOR; char *selfg = SELFGCOLOR; - fd_set rd; int i, j; - struct timeval timeout; Item *itm; XEvent ev; XModifierKeymap *modmap; XSetWindowAttributes wa; - timeout.tv_usec = 0; - timeout.tv_sec = 3; /* command line args */ for(i = 1; i < argc; i++) if(!strncmp(argv[i], "-b", 3)) { @@ -505,51 +458,40 @@ main(int argc, char *argv[]) { else if(!strncmp(argv[i], "-sf", 4)) { if(++i < argc) selfg = argv[i]; } - else if(!strncmp(argv[i], "-t", 3)) { - if(++i < argc) timeout.tv_sec = atoi(argv[i]); - } - else if(!strncmp(argv[i], "-v", 3)) { - fputs("dmenu-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n", stdout); - exit(EXIT_SUCCESS); - } + else if(!strncmp(argv[i], "-v", 3)) + eprint("dmenu-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk\n"); else - eprint("usage: dmenu [-b] [-fn ] [-nb ] [-nf ] [-p ]\n" - " [-sb ] [-sf ] [-t ] [-v]\n", stdout); + usage(); setlocale(LC_CTYPE, ""); dpy = XOpenDisplay(0); if(!dpy) eprint("dmenu: cannot open display\n"); screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); - - /* Note, the select() construction allows to grab all keypresses as - * early as possible, to not loose them. But if there is no standard - * input supplied, we will make sure to exit after MAX_WAIT_STDIN - * seconds. This is convenience behavior for rapid typers. - */ - while(XGrabKeyboard(dpy, root, True, GrabModeAsync, - GrabModeAsync, CurrentTime) != GrabSuccess) - usleep(1000); - FD_ZERO(&rd); - FD_SET(STDIN_FILENO, &rd); - if(select(ConnectionNumber(dpy) + 1, &rd, NULL, NULL, &timeout) < 1) - goto UninitializedEnd; - maxname = readstdin(); + if(isatty(STDIN_FILENO)) { + maxname = readstdin(); + running = grabkeyboard(); + } + else { /* prevent keypress loss */ + running = grabkeyboard(); + maxname = readstdin(); + } /* init modifier map */ modmap = XGetModifierMapping(dpy); for (i = 0; i < 8; i++) { for (j = 0; j < modmap->max_keypermod; j++) { - if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) + if(modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) numlockmask = (1 << i); } } XFreeModifiermap(modmap); /* style */ - dc.norm[ColBG] = getcolor(normbg); - dc.norm[ColFG] = getcolor(normfg); - dc.sel[ColBG] = getcolor(selbg); - dc.sel[ColFG] = getcolor(selfg); - setfont(font); + dc.norm[ColBG] = initcolor(normbg); + dc.norm[ColFG] = initcolor(normfg); + dc.sel[ColBG] = initcolor(selbg); + dc.sel[ColFG] = initcolor(selfg); + initfont(font); /* menu window */ wa.override_redirect = 1; wa.background_pixmap = ParentRelative; @@ -565,6 +507,8 @@ main(int argc, char *argv[]) { dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen)); dc.gc = XCreateGC(dpy, root, 0, 0); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); + if(!dc.font.set) + XSetFont(dpy, dc.gc, dc.font.xfont->fid); if(maxname) cmdw = textw(maxname); if(cmdw > mw / 3) @@ -607,7 +551,6 @@ main(int argc, char *argv[]) { XFreePixmap(dpy, dc.drawable); XFreeGC(dpy, dc.gc); XDestroyWindow(dpy, win); -UninitializedEnd: XUngrabKeyboard(dpy, CurrentTime); XCloseDisplay(dpy); return ret;