diff options
| -rw-r--r-- | dmenu.h | 3 | ||||
| -rw-r--r-- | draw.c | 10 | ||||
| -rw-r--r-- | main.c | 27 | ||||
| -rw-r--r-- | util.c | 5 |
4 files changed, 8 insertions, 37 deletions
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> |
| 2 | * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||
| 3 | * See LICENSE file for license details. | 2 | * See LICENSE file for license details. |
| 4 | */ | 3 | */ |
| 5 | 4 | ||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> |
| 2 | * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||
| 3 | * See LICENSE file for license details. | 2 | * See LICENSE file for license details. |
| 4 | */ | 3 | */ |
| 5 | #include "dmenu.h" | 4 | #include "dmenu.h" |
| @@ -32,21 +31,17 @@ drawtext(const char *text, unsigned long col[ColLast]) { | |||
| 32 | 31 | ||
| 33 | XSetForeground(dpy, dc.gc, col[ColBG]); | 32 | XSetForeground(dpy, dc.gc, col[ColBG]); |
| 34 | XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); | 33 | XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); |
| 35 | |||
| 36 | if(!text) | 34 | if(!text) |
| 37 | return; | 35 | return; |
| 38 | |||
| 39 | w = 0; | 36 | w = 0; |
| 40 | olen = len = strlen(text); | 37 | olen = len = strlen(text); |
| 41 | if(len >= sizeof(buf)) | 38 | if(len >= sizeof(buf)) |
| 42 | len = sizeof(buf) - 1; | 39 | len = sizeof(buf) - 1; |
| 43 | memcpy(buf, text, len); | 40 | memcpy(buf, text, len); |
| 44 | buf[len] = 0; | 41 | buf[len] = 0; |
| 45 | |||
| 46 | h = dc.font.ascent + dc.font.descent; | 42 | h = dc.font.ascent + dc.font.descent; |
| 47 | y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; | 43 | y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; |
| 48 | x = dc.x + (h / 2); | 44 | x = dc.x + (h / 2); |
| 49 | |||
| 50 | /* shorten text if necessary */ | 45 | /* shorten text if necessary */ |
| 51 | while(len && (w = textnw(buf, len)) > dc.w - h) | 46 | while(len && (w = textnw(buf, len)) > dc.w - h) |
| 52 | buf[--len] = 0; | 47 | buf[--len] = 0; |
| @@ -58,10 +53,8 @@ drawtext(const char *text, unsigned long col[ColLast]) { | |||
| 58 | if(len > 3) | 53 | if(len > 3) |
| 59 | buf[len - 3] = '.'; | 54 | buf[len - 3] = '.'; |
| 60 | } | 55 | } |
| 61 | |||
| 62 | if(w > dc.w) | 56 | if(w > dc.w) |
| 63 | return; /* too long */ | 57 | return; /* too long */ |
| 64 | |||
| 65 | gcv.foreground = col[ColFG]; | 58 | gcv.foreground = col[ColFG]; |
| 66 | if(dc.font.set) { | 59 | if(dc.font.set) { |
| 67 | XChangeGC(dpy, dc.gc, GCForeground, &gcv); | 60 | XChangeGC(dpy, dc.gc, GCForeground, &gcv); |
| @@ -106,7 +99,6 @@ setfont(const char *fontstr) { | |||
| 106 | XFontSetExtents *font_extents; | 99 | XFontSetExtents *font_extents; |
| 107 | XFontStruct **xfonts; | 100 | XFontStruct **xfonts; |
| 108 | char **font_names; | 101 | char **font_names; |
| 109 | |||
| 110 | dc.font.ascent = dc.font.descent = 0; | 102 | dc.font.ascent = dc.font.descent = 0; |
| 111 | font_extents = XExtentsOfFontSet(dc.font.set); | 103 | font_extents = XExtentsOfFontSet(dc.font.set); |
| 112 | n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); | 104 | n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); |
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* (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> | 2 | * (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> |
| 4 | * See LICENSE file for license details. | 3 | * See LICENSE file for license details. |
| 5 | */ | 4 | */ |
| @@ -47,7 +46,6 @@ calcoffsets(void) { | |||
| 47 | 46 | ||
| 48 | if(!curr) | 47 | if(!curr) |
| 49 | return; | 48 | return; |
| 50 | |||
| 51 | w = cmdw + 2 * SPACE; | 49 | w = cmdw + 2 * SPACE; |
| 52 | for(next = curr; next; next=next->right) { | 50 | for(next = curr; next; next=next->right) { |
| 53 | tw = textw(next->text); | 51 | tw = textw(next->text); |
| @@ -57,7 +55,6 @@ calcoffsets(void) { | |||
| 57 | if(w > mw) | 55 | if(w > mw) |
| 58 | break; | 56 | break; |
| 59 | } | 57 | } |
| 60 | |||
| 61 | w = cmdw + 2 * SPACE; | 58 | w = cmdw + 2 * SPACE; |
| 62 | for(prev = curr; prev && prev->left; prev=prev->left) { | 59 | for(prev = curr; prev && prev->left; prev=prev->left) { |
| 63 | tw = textw(prev->left->text); | 60 | tw = textw(prev->left->text); |
| @@ -78,18 +75,15 @@ drawmenu(void) { | |||
| 78 | dc.w = mw; | 75 | dc.w = mw; |
| 79 | dc.h = mh; | 76 | dc.h = mh; |
| 80 | drawtext(NULL, dc.norm); | 77 | drawtext(NULL, dc.norm); |
| 81 | |||
| 82 | /* print command */ | 78 | /* print command */ |
| 83 | if(cmdw && item) | 79 | if(cmdw && item) |
| 84 | dc.w = cmdw; | 80 | dc.w = cmdw; |
| 85 | drawtext(text[0] ? text : NULL, dc.norm); | 81 | drawtext(text[0] ? text : NULL, dc.norm); |
| 86 | dc.x += cmdw; | 82 | dc.x += cmdw; |
| 87 | |||
| 88 | if(curr) { | 83 | if(curr) { |
| 89 | dc.w = SPACE; | 84 | dc.w = SPACE; |
| 90 | drawtext((curr && curr->left) ? "<" : NULL, dc.norm); | 85 | drawtext((curr && curr->left) ? "<" : NULL, dc.norm); |
| 91 | dc.x += dc.w; | 86 | dc.x += dc.w; |
| 92 | |||
| 93 | /* determine maximum items */ | 87 | /* determine maximum items */ |
| 94 | for(i = curr; i != next; i=i->right) { | 88 | for(i = curr; i != next; i=i->right) { |
| 95 | dc.w = textw(i->text); | 89 | dc.w = textw(i->text); |
| @@ -98,7 +92,6 @@ drawmenu(void) { | |||
| 98 | drawtext(i->text, (sel == i) ? dc.sel : dc.norm); | 92 | drawtext(i->text, (sel == i) ? dc.sel : dc.norm); |
| 99 | dc.x += dc.w; | 93 | dc.x += dc.w; |
| 100 | } | 94 | } |
| 101 | |||
| 102 | dc.x = mw - SPACE; | 95 | dc.x = mw - SPACE; |
| 103 | dc.w = SPACE; | 96 | dc.w = SPACE; |
| 104 | drawtext(next ? ">" : NULL, dc.norm); | 97 | drawtext(next ? ">" : NULL, dc.norm); |
| @@ -114,11 +107,9 @@ match(char *pattern) { | |||
| 114 | 107 | ||
| 115 | if(!pattern) | 108 | if(!pattern) |
| 116 | return; | 109 | return; |
| 117 | |||
| 118 | plen = strlen(pattern); | 110 | plen = strlen(pattern); |
| 119 | item = j = NULL; | 111 | item = j = NULL; |
| 120 | nitem = 0; | 112 | nitem = 0; |
| 121 | |||
| 122 | for(i = allitems; i; i=i->next) | 113 | for(i = allitems; i; i=i->next) |
| 123 | if(!plen || !strncmp(pattern, i->text, plen)) { | 114 | if(!plen || !strncmp(pattern, i->text, plen)) { |
| 124 | if(!j) | 115 | if(!j) |
| @@ -142,7 +133,6 @@ match(char *pattern) { | |||
| 142 | j = i; | 133 | j = i; |
| 143 | nitem++; | 134 | nitem++; |
| 144 | } | 135 | } |
| 145 | |||
| 146 | curr = prev = next = sel = item; | 136 | curr = prev = next = sel = item; |
| 147 | calcoffsets(); | 137 | calcoffsets(); |
| 148 | } | 138 | } |
| @@ -157,12 +147,10 @@ kpress(XKeyEvent * e) { | |||
| 157 | len = strlen(text); | 147 | len = strlen(text); |
| 158 | buf[0] = 0; | 148 | buf[0] = 0; |
| 159 | num = XLookupString(e, buf, sizeof(buf), &ksym, 0); | 149 | num = XLookupString(e, buf, sizeof(buf), &ksym, 0); |
| 160 | |||
| 161 | if(IsFunctionKey(ksym) || IsKeypadKey(ksym) | 150 | if(IsFunctionKey(ksym) || IsKeypadKey(ksym) |
| 162 | || IsMiscFunctionKey(ksym) || IsPFKey(ksym) | 151 | || IsMiscFunctionKey(ksym) || IsPFKey(ksym) |
| 163 | || IsPrivateKeypadKey(ksym)) | 152 | || IsPrivateKeypadKey(ksym)) |
| 164 | return; | 153 | return; |
| 165 | |||
| 166 | /* first check if a control mask is omitted */ | 154 | /* first check if a control mask is omitted */ |
| 167 | if(e->state & ControlMask) { | 155 | if(e->state & ControlMask) { |
| 168 | switch (ksym) { | 156 | switch (ksym) { |
| @@ -261,7 +249,6 @@ readstdin(void) { | |||
| 261 | maxname = p; | 249 | maxname = p; |
| 262 | max = len; | 250 | max = len; |
| 263 | } | 251 | } |
| 264 | |||
| 265 | new = emalloc(sizeof(Item)); | 252 | new = emalloc(sizeof(Item)); |
| 266 | new->next = new->left = new->right = NULL; | 253 | new->next = new->left = new->right = NULL; |
| 267 | new->text = p; | 254 | new->text = p; |
| @@ -318,7 +305,6 @@ main(int argc, char *argv[]) { | |||
| 318 | } | 305 | } |
| 319 | else | 306 | else |
| 320 | eprint("usage: dmenu [-font <name>] [-{norm,sel}{bg,fg} <color>] [-t <seconds>] [-v]\n", stdout); | 307 | eprint("usage: dmenu [-font <name>] [-{norm,sel}{bg,fg} <color>] [-t <seconds>] [-v]\n", stdout); |
| 321 | |||
| 322 | dpy = XOpenDisplay(0); | 308 | dpy = XOpenDisplay(0); |
| 323 | if(!dpy) | 309 | if(!dpy) |
| 324 | eprint("dmenu: cannot open display\n"); | 310 | eprint("dmenu: cannot open display\n"); |
| @@ -333,44 +319,37 @@ main(int argc, char *argv[]) { | |||
| 333 | while(XGrabKeyboard(dpy, root, True, GrabModeAsync, | 319 | while(XGrabKeyboard(dpy, root, True, GrabModeAsync, |
| 334 | GrabModeAsync, CurrentTime) != GrabSuccess) | 320 | GrabModeAsync, CurrentTime) != GrabSuccess) |
| 335 | usleep(1000); | 321 | usleep(1000); |
| 336 | |||
| 337 | FD_ZERO(&rd); | 322 | FD_ZERO(&rd); |
| 338 | FD_SET(STDIN_FILENO, &rd); | 323 | FD_SET(STDIN_FILENO, &rd); |
| 339 | if(select(ConnectionNumber(dpy) + 1, &rd, NULL, NULL, &timeout) < 1) | 324 | if(select(ConnectionNumber(dpy) + 1, &rd, NULL, NULL, &timeout) < 1) |
| 340 | goto UninitializedEnd; | 325 | goto UninitializedEnd; |
| 341 | maxname = readstdin(); | 326 | maxname = readstdin(); |
| 342 | |||
| 343 | /* style */ | 327 | /* style */ |
| 344 | dc.norm[ColBG] = getcolor(normbg); | 328 | dc.norm[ColBG] = getcolor(normbg); |
| 345 | dc.norm[ColFG] = getcolor(normfg); | 329 | dc.norm[ColFG] = getcolor(normfg); |
| 346 | dc.sel[ColBG] = getcolor(selbg); | 330 | dc.sel[ColBG] = getcolor(selbg); |
| 347 | dc.sel[ColFG] = getcolor(selfg); | 331 | dc.sel[ColFG] = getcolor(selfg); |
| 348 | setfont(font); | 332 | setfont(font); |
| 349 | 333 | /* menu window */ | |
| 350 | wa.override_redirect = 1; | 334 | wa.override_redirect = 1; |
| 351 | wa.background_pixmap = ParentRelative; | 335 | wa.background_pixmap = ParentRelative; |
| 352 | wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask; | 336 | wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask; |
| 353 | |||
| 354 | mx = my = 0; | 337 | mx = my = 0; |
| 355 | mw = DisplayWidth(dpy, screen); | 338 | mw = DisplayWidth(dpy, screen); |
| 356 | mh = dc.font.height + 2; | 339 | mh = dc.font.height + 2; |
| 357 | |||
| 358 | win = XCreateWindow(dpy, root, mx, my, mw, mh, 0, | 340 | win = XCreateWindow(dpy, root, mx, my, mw, mh, 0, |
| 359 | DefaultDepth(dpy, screen), CopyFromParent, | 341 | DefaultDepth(dpy, screen), CopyFromParent, |
| 360 | DefaultVisual(dpy, screen), | 342 | DefaultVisual(dpy, screen), |
| 361 | CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | 343 | CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
| 362 | XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); | 344 | XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); |
| 363 | |||
| 364 | /* pixmap */ | 345 | /* pixmap */ |
| 365 | dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen)); | 346 | dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen)); |
| 366 | dc.gc = XCreateGC(dpy, root, 0, 0); | 347 | dc.gc = XCreateGC(dpy, root, 0, 0); |
| 367 | XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); | 348 | XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
| 368 | |||
| 369 | if(maxname) | 349 | if(maxname) |
| 370 | cmdw = textw(maxname); | 350 | cmdw = textw(maxname); |
| 371 | if(cmdw > mw / 3) | 351 | if(cmdw > mw / 3) |
| 372 | cmdw = mw / 3; | 352 | cmdw = mw / 3; |
| 373 | |||
| 374 | text[0] = 0; | 353 | text[0] = 0; |
| 375 | match(text); | 354 | match(text); |
| 376 | XMapRaised(dpy, win); | 355 | XMapRaised(dpy, win); |
| @@ -392,6 +371,7 @@ main(int argc, char *argv[]) { | |||
| 392 | } | 371 | } |
| 393 | } | 372 | } |
| 394 | 373 | ||
| 374 | /* cleanup */ | ||
| 395 | while(allitems) { | 375 | while(allitems) { |
| 396 | itm = allitems->next; | 376 | itm = allitems->next; |
| 397 | free(allitems->text); | 377 | free(allitems->text); |
| @@ -408,6 +388,5 @@ main(int argc, char *argv[]) { | |||
| 408 | UninitializedEnd: | 388 | UninitializedEnd: |
| 409 | XUngrabKeyboard(dpy, CurrentTime); | 389 | XUngrabKeyboard(dpy, CurrentTime); |
| 410 | XCloseDisplay(dpy); | 390 | XCloseDisplay(dpy); |
| 411 | |||
| 412 | return ret; | 391 | return ret; |
| 413 | } | 392 | } |
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> |
| 2 | * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||
| 3 | * See LICENSE file for license details. | 2 | * See LICENSE file for license details. |
| 4 | */ | 3 | */ |
| 5 | #include "dmenu.h" | 4 | #include "dmenu.h" |
| @@ -22,6 +21,7 @@ badmalloc(unsigned int size) { | |||
| 22 | void * | 21 | void * |
| 23 | emalloc(unsigned int size) { | 22 | emalloc(unsigned int size) { |
| 24 | void *res = malloc(size); | 23 | void *res = malloc(size); |
| 24 | |||
| 25 | if(!res) | 25 | if(!res) |
| 26 | badmalloc(size); | 26 | badmalloc(size); |
| 27 | return res; | 27 | return res; |
| @@ -40,6 +40,7 @@ eprint(const char *errstr, ...) { | |||
| 40 | char * | 40 | char * |
| 41 | estrdup(const char *str) { | 41 | estrdup(const char *str) { |
| 42 | void *res = strdup(str); | 42 | void *res = strdup(str); |
| 43 | |||
| 43 | if(!res) | 44 | if(!res) |
| 44 | badmalloc(strlen(str)); | 45 | badmalloc(strlen(str)); |
| 45 | return res; | 46 | return res; |
