X-Git-Url: https://git.xinqibao.xyz/dmenu.git/blobdiff_plain/37236f8840624d5e9d590e7be9ba365bc61913a6..ebeb4e4752e33e9a87cbe0725f65595cba0037fa:/dmenu.c diff --git a/dmenu.c b/dmenu.c index aef8ae5..97014cc 100644 --- a/dmenu.c +++ b/dmenu.c @@ -52,6 +52,7 @@ static void calcoffsetsh(void); static void calcoffsetsv(void); static char *cistrstr(const char *s, const char *sub); static void cleanup(void); +static void drawcursor(void); static void drawmenu(void); static void drawmenuh(void); static void drawmenuv(void); @@ -117,18 +118,14 @@ calcoffsetsh(void) { return; w = promptw + cmdw + 2 * spaceitem; for(next = curr; next; next=next->right) { - tw = textw(next->text); - if(tw > mw / 3) - tw = mw / 3; + tw = MIN(textw(next->text), mw / 3); w += tw; if(w > mw) break; } w = promptw + cmdw + 2 * spaceitem; for(prev = curr; prev && prev->left; prev=prev->left) { - tw = textw(prev->left->text); - if(tw > mw / 3) - tw = mw / 3; + tw = MIN(textw(prev->left->text), mw / 3); w += tw; if(w > mw) break; @@ -137,20 +134,20 @@ calcoffsetsh(void) { void calcoffsetsv(void) { - static unsigned int w; + static unsigned int h; if(!curr) return; - w = (dc.font.height + 2) * (lines + 1); + h = (dc.font.height + 2) * (lines + 1); for(next = curr; next; next=next->right) { - w -= dc.font.height + 2; - if(w <= 0) + h -= dc.font.height + 2; + if(h <= 0) break; } - w = (dc.font.height + 2) * (lines + 1); + h = (dc.font.height + 2) * (lines + 1); for(prev = curr; prev && prev->left; prev=prev->left) { - w -= dc.font.height + 2; - if(w <= 0) + h -= dc.font.height + 2; + if(h <= 0) break; } } @@ -247,9 +244,7 @@ drawmenuh(void) { dc.x += dc.w; /* determine maximum items */ for(i = curr; i != next; i=i->right) { - dc.w = textw(i->text); - if(dc.w > mw / 3) - dc.w = mw / 3; + dc.w = MIN(textw(i->text), mw / 3); drawtext(i->text, (sel == i) ? dc.sel : dc.norm); dc.x += dc.w; } @@ -353,10 +348,8 @@ initfont(const char *fontstr) { font_extents = XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { - if(dc.font.ascent < (*xfonts)->ascent) - dc.font.ascent = (*xfonts)->ascent; - if(dc.font.descent < (*xfonts)->descent) - dc.font.descent = (*xfonts)->descent; + dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); + dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent); xfonts++; } } @@ -372,7 +365,7 @@ initfont(const char *fontstr) { void kpress(XKeyEvent * e) { - char buf[32]; + char buf[sizeof text]; int i, num; unsigned int len; KeySym ksym; @@ -395,9 +388,18 @@ kpress(XKeyEvent * e) { switch (ksym) { default: /* ignore other control sequences */ return; - case XK_bracketleft: + case XK_a: + case XK_A: + ksym = XK_Home; + break; + case XK_c: + case XK_C: ksym = XK_Escape; break; + case XK_e: + case XK_E: + ksym = XK_End; + break; case XK_h: case XK_H: ksym = XK_BackSpace; @@ -414,18 +416,16 @@ kpress(XKeyEvent * e) { case XK_U: text[0] = 0; match(text); - drawmenu(); break; case XK_w: case XK_W: - if(len) { - i = len - 1; - while(i >= 0 && text[i] == ' ') - text[i--] = 0; - while(i >= 0 && text[i] != ' ') - text[i--] = 0; + if(cursor > 0) { + i = cursor; + while(i-- > 0 && text[i] == ' '); + while(i-- > 0 && text[i] != ' '); + memmove(text + i + 1, text + cursor, sizeof text - cursor + 1); + cursor = i + 1; match(text); - drawmenu(); } break; } @@ -454,42 +454,46 @@ kpress(XKeyEvent * e) { case XK_p: { FILE *fp; - char *c; + char *s; if(!(fp = (FILE*)popen("sselp", "r"))) eprint("dmenu: Could not popen sselp\n"); - c = fgets(text + len, sizeof(text) - len, fp); + s = fgets(buf, sizeof buf, fp); pclose(fp); - if(c == NULL) + if(s == NULL) return; } - len = strlen(text); - if(len && text[len-1] == '\n') - text[--len] = '\0'; - match(text); - drawmenu(); - return; + num = strlen(buf); + if(num && buf[num-1] == '\n') + buf[--num] = '\0'; + break; } } switch(ksym) { default: + num = MIN(num, sizeof text - cursor); if(num && !iscntrl((int) buf[0])) { - buf[num] = 0; - memmove(text + cursor + num, text + cursor, sizeof text - cursor); - strncpy(text + cursor, buf, sizeof text - cursor); + memmove(text + cursor + num, text + cursor, sizeof text - cursor - num); + memcpy(text + cursor, buf, num); cursor+=num; match(text); } break; case XK_BackSpace: if(cursor > 0) { - memmove(text + cursor + -1, text + cursor, sizeof text - cursor); + memmove(text + cursor - 1, text + cursor, sizeof text - cursor + 1); cursor--; match(text); } break; + case XK_Delete: + memmove(text + cursor, text + cursor + 1, sizeof text - cursor); + match(text); + break; case XK_End: - if(!item) - return; + if(cursor < len) { + cursor = len; + break; + } while(next) { sel = curr = next; calcoffsets(); @@ -502,8 +506,10 @@ kpress(XKeyEvent * e) { running = False; break; case XK_Home: - if(!item) - return; + if(sel == item) { + cursor = 0; + break; + } sel = curr = item; calcoffsets(); break; @@ -534,12 +540,10 @@ kpress(XKeyEvent * e) { calcoffsets(); break; case XK_Return: - if((e->state & ShiftMask) && *text) + if((e->state & ShiftMask) || !sel) fprintf(stdout, "%s", text); - else if(sel) + else fprintf(stdout, "%s", sel->text); - else if(*text) - fprintf(stdout, "%s", text); fflush(stdout); running = False; break; @@ -565,9 +569,6 @@ kpress(XKeyEvent * e) { match(text); break; } - len = strlen(text); - cursor = MIN(cursor, len); - cursor = MAX(cursor, 0); drawmenu(); } @@ -614,17 +615,17 @@ match(char *pattern) { void readstdin(void) { - char *p, buf[1024]; + char *p, buf[sizeof text]; unsigned int len = 0, max = 0; Item *i, *new; - i = 0; + i = NULL; while(fgets(buf, sizeof buf, stdin)) { len = strlen(buf); - if (buf[len - 1] == '\n') - buf[len - 1] = 0; + if(buf[len-1] == '\n') + buf[--len] = '\0'; if(!(p = strdup(buf))) - eprint("fatal: could not strdup() %u bytes\n", strlen(buf)); + eprint("fatal: could not strdup() %u bytes\n", len); if(max < len) { maxname = p; max = len; @@ -732,13 +733,9 @@ setup(Bool topbar) { if(!dc.font.set) XSetFont(dpy, dc.gc, dc.font.xfont->fid); if(maxname) - cmdw = textw(maxname); - if(cmdw > mw / 3) - cmdw = mw / 3; + cmdw = MIN(textw(maxname), mw / 3); if(prompt) - promptw = textw(prompt); - if(promptw > mw / 5) - promptw = mw / 5; + promptw = MIN(textw(prompt), mw / 5); text[0] = 0; match(text); XMapRaised(dpy, win); @@ -773,6 +770,9 @@ main(int argc, char *argv[]) { } else if(!strcmp(argv[i], "-b")) topbar = False; + else if(!strcmp(argv[i], "-e")) { + if(++i < argc) root = atoi(argv[i]); + } else if(!strcmp(argv[i], "-l")) { vlist = True; calcoffsets = calcoffsetsv; @@ -797,25 +797,20 @@ main(int argc, char *argv[]) { if(++i < argc) selfgcolor = argv[i]; } else if(!strcmp(argv[i], "-v")) - eprint("dmenu-"VERSION", © 2006-2009 dmenu engineers, see LICENSE for details\n"); + eprint("dmenu-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n"); else - eprint("usage: dmenu [-i] [-b] [-l ] [-fn ] [-nb ] [-nf ]\n" - " [-p ] [-sb ] [-sf ] [-v]\n"); + eprint("usage: dmenu [-i] [-b] [-e ] [-l ] [-fn ] [-nb ]\n" + " [-nf ] [-p ] [-sb ] [-sf ] [-v]\n"); if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fprintf(stderr, "warning: no locale support\n"); if(!(dpy = XOpenDisplay(NULL))) eprint("dmenu: cannot open display\n"); screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); + if(!root) + root = RootWindow(dpy, screen); - if(isatty(STDIN_FILENO)) { - readstdin(); - running = grabkeyboard(); - } - else { /* prevent keypress loss */ - running = grabkeyboard(); - readstdin(); - } + readstdin(); + running = grabkeyboard(); setup(topbar); drawmenu();