]> git.armaanb.net Git - dmenu.git/blobdiff - dmenu.c
applied Connor's next nice patch, thanks a lot!
[dmenu.git] / dmenu.c
diff --git a/dmenu.c b/dmenu.c
index 1f7abca95b37d5bf1e3f99e1db3a48437ae3fb25..61779066b76307e9c045c748690549e2471aea4e 100644 (file)
--- a/dmenu.c
+++ b/dmenu.c
@@ -52,6 +52,8 @@ 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);
 static void drawtext(const char *text, unsigned long col[ColLast]);
@@ -95,7 +97,6 @@ static char *(*fstrstr)(const char *, const char *) = strstr;
 static Bool vlist = False;
 static unsigned int lines = 5;
 static void (*calcoffsets)(void) = calcoffsetsh;
-static void (*drawmenu)(void) = drawmenuh;
 
 void
 appenditem(Item *i, Item **list, Item **last) {
@@ -200,7 +201,7 @@ cleanup(void) {
 
 void
 drawcursor(void) {
-       XRectangle r = { dc.x, dc.y + 2, 1, dc.h - 4 };
+       XRectangle r = { dc.x, dc.y + 2, 1, dc.font.height - 2 };
 
        r.x += textnw(text, cursor) + dc.font.height / 2;
 
@@ -209,9 +210,7 @@ drawcursor(void) {
 }
 
 void
-drawmenuh(void) {
-       Item *i;
-
+drawmenu(void) {
        dc.x = 0;
        dc.y = 0;
        dc.w = mw;
@@ -231,56 +230,46 @@ drawmenuh(void) {
        drawcursor();
        dc.x += cmdw;
        if(curr) {
-               dc.w = spaceitem;
-               drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
-               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;
-                       drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
-                       dc.x += dc.w;
-               }
-               dc.x = mw - spaceitem;
-               dc.w = spaceitem;
-               drawtext(next ? ">" : NULL, dc.norm);
+               if(vlist)
+                       drawmenuv();
+               else
+                       drawmenuh();
        }
        XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
        XFlush(dpy);
 }
 
+void
+drawmenuh(void) {
+       Item *i;
+
+       dc.w = spaceitem;
+       drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
+       dc.x += dc.w;
+       /* determine maximum items */
+       for(i = curr; i != next; i=i->right) {
+               dc.w = MIN(textw(i->text), mw / 3);
+               drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
+               dc.x += dc.w;
+       }
+       dc.x = mw - spaceitem;
+       dc.w = spaceitem;
+       drawtext(next ? ">" : NULL, dc.norm);
+}
+
 void
 drawmenuv(void) {
        Item *i;
 
        dc.x = 0;
-       dc.y = 0;
        dc.w = mw;
-       dc.h = mh;
-       drawtext(NULL, dc.norm);
-       /* print prompt? */
-       if(promptw) {
-               dc.w = promptw;
-               drawtext(prompt, dc.sel);
-       }
-       dc.x += promptw;
-       dc.w = mw - promptw;
-       /* print command */
-       drawtext(text[0] ? text : NULL, dc.norm);
-       if(curr) {
-               dc.x = 0;
-               dc.w = mw;
+       dc.y += dc.font.height + 2;
+       /* determine maximum items */
+       for(i = curr; i != next; i=i->right) {
+               drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
                dc.y += dc.font.height + 2;
-               /* determine maximum items */
-               for(i = curr; i != next; i=i->right) {
-                       drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
-                       dc.y += dc.font.height + 2;
-               }
-               drawtext(NULL, dc.norm);
        }
-       XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
-       XFlush(dpy);
+       drawtext(NULL, dc.norm);
 }
 
 void
@@ -382,7 +371,7 @@ initfont(const char *fontstr) {
 
 void
 kpress(XKeyEvent * e) {
-       char buf[32];
+       char buf[sizeof text];
        int i, num;
        unsigned int len;
        KeySym ksym;
@@ -405,7 +394,8 @@ kpress(XKeyEvent * e) {
                switch (ksym) {
                default:        /* ignore other control sequences */
                        return;
-               case XK_bracketleft:
+               case XK_c:
+               case XK_C:
                        ksym = XK_Escape;
                        break;
                case XK_h:
@@ -424,18 +414,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);
+                               cursor = i + 1;
                                match(text);
-                               drawmenu();
                        }
                        break;
                }
@@ -467,39 +455,43 @@ kpress(XKeyEvent * e) {
                                char *c;
                                if(!(fp = (FILE*)popen("sselp", "r")))
                                        eprint("dmenu: Could not popen sselp\n");
-                               c = fgets(text + len, sizeof(text) - len, fp);
+                               c = fgets(buf, sizeof buf, fp);
                                pclose(fp);
                                if(c == 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();
@@ -512,8 +504,10 @@ kpress(XKeyEvent * e) {
                running = False;
                break;
        case XK_Home:
-               if(!item)
-                       return;
+               if(sel == item) {
+                       cursor = 0;
+                       break;
+               }
                sel = curr = item;
                calcoffsets();
                break;
@@ -544,12 +538,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;
@@ -575,9 +567,6 @@ kpress(XKeyEvent * e) {
                match(text);
                break;
        }
-       len = strlen(text);
-       cursor = MIN(cursor, len);
-       cursor = MAX(cursor, 0);
        drawmenu();
 }
 
@@ -628,13 +617,13 @@ readstdin(void) {
        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;
@@ -742,13 +731,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);
@@ -786,8 +771,7 @@ main(int argc, char *argv[]) {
                else if(!strcmp(argv[i], "-l")) {
                        vlist = True;
                        calcoffsets = calcoffsetsv;
-                       drawmenu = drawmenuv;
-                       if(++i < argc) lines += atoi(argv[i]);
+                       if(++i < argc) lines = atoi(argv[i]);
                }
                else if(!strcmp(argv[i], "-fn")) {
                        if(++i < argc) font = argv[i];
@@ -808,7 +792,7 @@ 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 <lines>] [-fn <font>] [-nb <color>] [-nf <color>]\n"
                               "             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");