wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit e9f604795df43ffe1441d69a577ae6aed4ff3d7e
parent be8a984d73237606db239c36612afee07ea76199
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Sun, 12 Feb 2006 03:16:42 +0100

simplified wmiimenu


Diffstat:
cmd/wmiimenu.c | 459++++++++++++++++++++++++++-----------------------------------------------------
1 file changed, 152 insertions(+), 307 deletions(-)

diff --git a/cmd/wmiimenu.c b/cmd/wmiimenu.c @@ -13,54 +13,39 @@ #include <time.h> #include <unistd.h> #include <X11/Xlib.h> -#include <X11/Xatom.h> #include <X11/cursorfont.h> -#include <X11/Xproto.h> #include <X11/Xutil.h> #include <X11/keysym.h> #include "blitz.h" - -enum { - OFF_NEXT, OFF_PREV, OFF_CURR, OFF_LAST -}; - -typedef struct Item Item; -struct Item { - char *name; - Item *next; - Item *prev; -}; - -static char *command = 0; -static Item *allitems = nil; -static char *fontstr = 0; -static char *normcolstr = 0; -static char *selcolstr = 0; -static int done = 0; -static int retvalue = 0; +static Bool done = False; +static int ret = 0; +static char text[4096]; +static Color selcolor; +static Color normcolor; static Display *dpy; -static GC gc; static Window win; -static XRectangle rect; static XRectangle mrect; static int screen; -static size_t nitems = 0; -static Item *sel = nil; -static Item *items = nil; -static Item *offset[OFF_LAST]; +static char **allitem = nil; +static size_t nallitem = 0; +static size_t allitemsz = 0; +static char **item = nil; +static size_t itemsz = 0; +static size_t nitem = 0; +static int sel = -1; +static size_t nextoff = 0; +static size_t prevoff = 0; +static size_t curroff = 0; static unsigned int cmdw = 0; -static Pixmap pmap; +static Draw draw = { 0 }; static const int seek = 30; /* 30px */ -static XFontStruct *font; static void check_event(void); static void draw_menu(void); static void handle_kpress(XKeyEvent * e); -static void set_text(char *text); -static size_t update_items(char *prefix); static char version[] = "wmiimenu - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n"; @@ -72,210 +57,110 @@ usage() } static void -return_item(char *cmd) -{ - char *rc = cmd; - - if(!cmd || cmd[0] == 0) - return; - - if(sel && strlen(sel->name)) - rc = cmd = sel->name; - - fprintf(stdout, "%s", rc); - done = 1; -} - -static void -show() -{ - set_text(0); - XMapRaised(dpy, win); - XSync(dpy, False); - update_items(command); - draw_menu(); - while(XGrabKeyboard - (dpy, RootWindow(dpy, screen), True, GrabModeAsync, - GrabModeAsync, CurrentTime) != GrabSuccess) - usleep(1000); - -} - -static void -hide() -{ - XUngrabKeyboard(dpy, CurrentTime); - XUnmapWindow(dpy, win); - XSync(dpy, False); -} - -void -set_text(char *text) -{ - if(command) { - free(command); - command = 0; - } - if(text && strlen(text)) { - command = strdup(text); - } -} - -static void update_offsets() { - Item *i; + size_t i; unsigned int w = cmdw + 2 * seek; - if(!items) + if(!nitem) return; - /* calc next offset */ - for(i = offset[OFF_CURR]; i; i = i->next) { - w += XTextWidth(font, i->name, - strlen(i->name)) + mrect.height; + for(i = curroff; i < nitem; i++) { + w += XTextWidth(draw.font, item[i], strlen(item[i])) + mrect.height; if(w > mrect.width) break; } - offset[OFF_NEXT] = i; + nextoff = i; w = cmdw + 2 * seek; - for(i = offset[OFF_CURR]->prev; i && i->prev; i = i->prev) { - w += XTextWidth(font, i->name, - strlen(i->name)) + mrect.height; + for(i = curroff; i > 0; i--) { + w += XTextWidth(draw.font, item[i], strlen(item[i])) + mrect.height; if(w > mrect.width) break; } - offset[OFF_PREV] = i; + prevoff = i; } -static size_t +static size_t update_items(char *pattern) { - size_t plen = pattern ? strlen(pattern) : 0, len, max = 0; - int matched = pattern ? plen == 0 : 1; - Item *i, *new, *p, *maxitem = 0; + size_t plen = strlen(pattern); + int i, matched = pattern ? plen == 0 : 1; cmdw = 0; - offset[OFF_CURR] = offset[OFF_PREV] = offset[OFF_NEXT] = nil; - - while((i = items)) { - items = items->next; - free(i); - } - sel = items = nil; - nitems = 0; - - /* build new items */ - for(p = allitems; p; p = p->next) { - len = strlen(p->name); - if(max < len) { - maxitem = p; - max = len; - } - } - - if(maxitem) - cmdw = XTextWidth(font, maxitem->name, max) + mrect.height; - - for(p = allitems; p; p = p->next) { - if(matched || !strncmp(pattern, p->name, plen)) { - new = cext_emallocz(sizeof(Item)); - new->name = strdup(p->name); - new->next=0; - new->prev=0; - nitems++; - if(!items) - offset[OFF_CURR] = sel = items = i = new; - else { - i->next = new; - new->prev = i; - i = new; - } - } + curroff = prevoff = nextoff = 0; + sel = -1; + + for(i = 0; i < nitem; i++) + item[i] = nil; /* faster than cext_array_detach */ + nitem = 0; + + for(i = 0; i < nallitem; i++) { + if(matched|| !strncmp(pattern, allitem[i], plen) + || (pattern && strstr(allitem[i], pattern))) + { + item = (char **)cext_array_attach((void **)item, allitem[i], + sizeof(char *), &itemsz); + nitem++; + } } - for(p = allitems; p; p = p->next) { - if(pattern && strstr(p->name, pattern)) { - new = cext_emallocz(sizeof(Item)); - new->name = strdup(p->name); - new->next=0; - new->prev=0; - nitems++; - if(!items) - offset[OFF_CURR] = sel = items = i = new; - else { - if(strncmp(pattern, p->name, plen)) { /* yuck... */ - i->next = new; - new->prev = i; - i = new; - } - } - } - } - update_offsets(); - return nitems; + return nitem++; } /* creates draw structs for menu mode drawing */ static void draw_menu() { - Draw d = { 0 }; - unsigned int offx = 0; - Item *i = sel; - - d.gc = gc; - d.font = font; - d.drawable = pmap; - d.rect = mrect; - d.rect.x = 0; - d.rect.y = 0; - blitz_loadcolor(dpy, screen, normcolstr, &(d.color)); - blitz_drawlabelnoborder(dpy, &d); + unsigned int i, offx = 0; + + draw.rect = mrect; + draw.rect.x = 0; + draw.rect.y = 0; + draw.color = normcolor; + blitz_drawlabelnoborder(dpy, &draw); /* print command */ - d.align = WEST; - d.font = font; - d.data = command; - if(cmdw && sel) - d.rect.width = cmdw; - offx += d.rect.width; - blitz_drawlabelnoborder(dpy, &d); - - d.align = CENTER; - if(sel) { - blitz_loadcolor(dpy, screen, normcolstr, &(d.color)); - d.data = offset[OFF_PREV] ? "<" : nil; - d.rect.x = offx; - d.rect.width = seek; - offx += d.rect.width; - blitz_drawlabelnoborder(dpy, &d); + draw.align = WEST; + draw.data = text; + if(cmdw && sel >= 0) + draw.rect.width = cmdw; + offx += draw.rect.width; + blitz_drawlabelnoborder(dpy, &draw); + + draw.align = CENTER; + if(sel >= 0) { + draw.color = normcolor; + draw.data = prevoff < curroff ? "<" : nil; + draw.rect.x = offx; + draw.rect.width = seek; + offx += draw.rect.width; + blitz_drawlabelnoborder(dpy, &draw); /* determine maximum items */ - for(i = offset[OFF_CURR]; i && i != offset[OFF_NEXT]; i = i->next) { - d.data = i->name; - d.rect.x = offx; - d.rect.width = - XTextWidth(d.font, d.data, strlen(d.data)) + mrect.height; - offx += d.rect.width; + for(i = curroff; i < nextoff; i++) { + draw.data = item[i]; + draw.rect.x = offx; + draw.rect.width = + XTextWidth(draw.font, draw.data, strlen(draw.data)) + mrect.height; + offx += draw.rect.width; if(sel == i) { - blitz_loadcolor(dpy, screen, selcolstr, &(d.color)); - blitz_drawlabel(dpy, &d); + draw.color = selcolor; + blitz_drawlabel(dpy, &draw); } else { - blitz_loadcolor(dpy, screen, normcolstr, &(d.color)); - blitz_drawlabelnoborder(dpy, &d); + draw.color = normcolor; + blitz_drawlabelnoborder(dpy, &draw); } } - blitz_loadcolor(dpy, screen, normcolstr, &(d.color)); - d.data = offset[OFF_NEXT] ? ">" : nil; - d.rect.x = mrect.width - seek; - d.rect.width = seek; - blitz_drawlabelnoborder(dpy, &d); + draw.color = normcolor; + draw.data = nitem > nextoff ? ">" : nil; + draw.rect.x = mrect.width - seek; + draw.rect.width = seek; + blitz_drawlabelnoborder(dpy, &draw); } - XCopyArea(dpy, pmap, win, gc, 0, 0, mrect.width, mrect.height, 0, 0); + XCopyArea(dpy, draw.drawable, win, draw.gc, 0, 0, mrect.width, mrect.height, 0, 0); XSync(dpy, False); } @@ -285,14 +170,8 @@ handle_kpress(XKeyEvent * e) KeySym ksym; char buf[32]; int num; - static char text[4096]; - size_t len = 0; + size_t len = strlen(text); - text[0] = 0; - if(command) { - cext_strlcpy(text, command, sizeof(text)); - len = strlen(text); - } buf[0] = 0; num = XLookupString(e, buf, sizeof(buf), &ksym, 0); @@ -321,7 +200,7 @@ handle_kpress(XKeyEvent * e) break; case XK_U: case XK_u: - set_text(0); + text[0] = 0; update_items(0); draw_menu(); return; @@ -333,48 +212,43 @@ handle_kpress(XKeyEvent * e) } switch (ksym) { case XK_Left: - if(!sel) - return; - if(sel->prev) { - sel = sel->prev; - } else + if(sel <= 0) return; + sel--; break; case XK_Tab: - if(!sel) + if(sel < 0) return; - set_text(sel->name); - update_items(command); + cext_strlcpy(text, item[sel], sizeof(text)); + update_items(text); break; case XK_Right: - if(!sel) - return; - if(sel->next) { - sel = sel->next; - } else + if(sel < 0 || (sel + 1 == nitem)) return; + sel++; break; case XK_Return: - if(sel) - return_item(sel->name); + if(sel >= 0) + fprintf(stdout, "%s", item[sel]); else if(text) - return_item(text); - break; + fprintf(stdout, "%s", text); + fflush(stdout); + done = True; + break; case XK_Escape: - retvalue = 1; - done = 1; + ret = 1; + done = True; break; case XK_BackSpace: if(len) { size_t i = len; if(i) { - int prev_nitems; + int prev_nitem; do text[--i] = 0; - while((prev_nitems = nitems) && i && prev_nitems == update_items(text)); + while((prev_nitem = nitem) && i && prev_nitem == update_items(text)); } - set_text(text); - update_items(command); + update_items(text); } break; default: @@ -384,18 +258,15 @@ handle_kpress(XKeyEvent * e) cext_strlcat(text, buf, sizeof(text)); else cext_strlcpy(text, buf, sizeof(text)); - set_text(text); - update_items(command); + update_items(text); } } - if(sel) { - if(sel == offset[OFF_CURR]->prev) { - offset[OFF_CURR] = offset[OFF_PREV]; + if(sel >= 0) { + if(sel == curroff - 1) { + sel = prevoff; update_offsets(); - } else if(sel == offset[OFF_NEXT]) { - offset[OFF_CURR] = offset[OFF_NEXT]; + } else if(sel == nextoff) update_offsets(); - } } draw_menu(); } @@ -422,51 +293,26 @@ check_event() } } -static void -update_geometry() -{ - mrect = rect; - mrect.height = font->ascent + font->descent + 4; - mrect.y = rect.height - mrect.height; - XMoveResizeWindow(dpy, win, mrect.x, mrect.y, mrect.width, - mrect.height); - XSync(dpy, False); - XFreePixmap(dpy, pmap); - pmap = - XCreatePixmap(dpy, win, mrect.width, mrect.height, - DefaultDepth(dpy, screen)); - XSync(dpy, False); -} - void -init_allitems() +read_allitems() { - char text[4096]; - allitems = cext_emallocz(sizeof(Item)); - allitems->prev = 0; - Item *curitem = allitems; - char ch; - int i = 0; - while ((ch = (char)fgetc(stdin)) != EOF) { - if (!iscntrl(ch) && i<4095) { - text[i]=ch; - i++; - } else { - text[i] = 0; - if (strlen(text)) { - curitem->name = strdup(text); - curitem->next = cext_emallocz(sizeof(Item)); - curitem->next->prev = curitem; - curitem = curitem->next; - } - i=0; + char *maxname = 0, *p, buf[1024]; + size_t len = 0, max = 0; + + while(fgets(buf, sizeof(buf), stdin)) { + p = strdup(buf); + len = strlen(p); + if(max < len) { + maxname = p; + max = len; } - } - if (curitem == allitems) - allitems = 0; - if (curitem->prev) - curitem->prev->next = 0; - free(curitem); + allitem = (char **)cext_array_attach((void **)allitem, p, + sizeof(char *), &allitemsz); + nallitem++; + } + + if(maxname) + cmdw = XTextWidth(draw.font, maxname, max) + mrect.height; } int @@ -474,7 +320,7 @@ main(int argc, char *argv[]) { int i; XSetWindowAttributes wa; - XGCValues gcv; + char *fontstr, *selcolstr, *normcolstr; /* command line args */ for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { @@ -500,64 +346,63 @@ main(int argc, char *argv[]) fontstr = getenv("WMII_FONT"); if (!fontstr) fontstr = strdup(BLITZ_FONT); - font = blitz_getfont(dpy, fontstr); + draw.font = blitz_getfont(dpy, fontstr); normcolstr = getenv("WMII_NORMCOLORS"); if (!normcolstr || strlen(normcolstr) != 23) normcolstr = strdup(BLITZ_NORMCOLORS); + blitz_loadcolor(dpy, screen, normcolstr, &normcolor); selcolstr = getenv("WMII_SELCOLORS"); if (!selcolstr || strlen(selcolstr) != 23) selcolstr = strdup(BLITZ_SELCOLORS); + blitz_loadcolor(dpy, screen, selcolstr, &selcolor); - /* init */ wa.override_redirect = 1; wa.background_pixmap = ParentRelative; wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask | SubstructureRedirectMask | SubstructureNotifyMask; - rect.x = rect.y = 0; - rect.width = DisplayWidth(dpy, screen); - rect.height = DisplayHeight(dpy, screen); - mrect = rect; - mrect.height = font->ascent + font->descent + 4; - mrect.y = rect.height - mrect.height; + mrect.width = DisplayWidth(dpy, screen); + mrect.height = draw.font->ascent + draw.font->descent + 4; + mrect.y = DisplayHeight(dpy, screen) - mrect.height; + mrect.x = 0; win = XCreateWindow(dpy, RootWindow(dpy, screen), mrect.x, mrect.y, - mrect.width, mrect.height, 0, DefaultDepth(dpy, - screen), + mrect.width, mrect.height, 0, DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); XSync(dpy, False); - /* window pixmap */ - gcv.function = GXcopy; - gcv.graphics_exposures = False; + /* pixmap */ + draw.gc = XCreateGC(dpy, win, 0, 0); + draw.drawable = XCreatePixmap(dpy, win, mrect.width, mrect.height, + DefaultDepth(dpy, screen)); - gc = XCreateGC(dpy, win, 0, 0); - pmap = - XCreatePixmap(dpy, win, mrect.width, mrect.height, - DefaultDepth(dpy, screen)); + XSync(dpy, False); + read_allitems(); - /* initialize some more stuff */ - update_geometry(); - init_allitems(); - if(!allitems) { - fprintf(stderr, "%s", "wmiimenu: feed me newline-separated items on stdin please.\n"); - exit(1); - } + text[0] = 0; + XMapRaised(dpy, win); + XSync(dpy, False); + update_items(text); + draw_menu(); + + while(XGrabKeyboard + (dpy, RootWindow(dpy, screen), True, GrabModeAsync, + GrabModeAsync, CurrentTime) != GrabSuccess) + usleep(1000); /* main event loop */ - show(); while (!done) { check_event(); usleep(1000); } - hide(); - XFreePixmap(dpy, pmap); - XFreeGC(dpy, gc); + XFreePixmap(dpy, draw.drawable); + XFreeGC(dpy, draw.gc); + XDestroyWindow(dpy, win); XCloseDisplay(dpy); - return retvalue; + return ret; }