summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Anselm R Garbe 2009-11-28 12:28:15 +0000
committerGravatar Anselm R Garbe 2009-11-28 12:28:15 +0000
commit569a1f925a7cf351e6ec3e38529f46a1d9becf3f (patch)
tree38e61a5eda145b5449636143ebbbc1ea13c34465
parentAdded tag 4.0 for changeset 78f9f72cc9c6 (diff)
applied cursor, vertical and paste patches for upcoming 4.1 dmenu version (due to the fact that surf is using dmenu as well)
Diffstat (limited to '')
-rw-r--r--LICENSE5
-rw-r--r--config.mk2
-rw-r--r--dmenu.17
-rw-r--r--dmenu.c163
4 files changed, 149 insertions, 28 deletions
diff --git a/LICENSE b/LICENSE
index 8f13918..1f2db9b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,9 @@
MIT/X Consortium License
-© 2006-2008 Anselm R. Garbe <garbeam at gmail dot com>
+© 2006-2009 Anselm R. Garbe <anselm@garbe.us>
+© 2009 Gottox <gottox@s01.de>
+© 2009 Markus Schnalke <meillo@marmaro.de>
+© 2009 Evan Gates <evan.gates@gmail.com>
© 2006-2008 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Michał Janeczek <janeczek at gmail dot com>
diff --git a/config.mk b/config.mk
index f6a3652..75c6abe 100644
--- a/config.mk
+++ b/config.mk
@@ -1,5 +1,5 @@
# dmenu version
-VERSION = 4.0
+VERSION = 4.1
# Customize below to fit your system
diff --git a/dmenu.1 b/dmenu.1
index a072883..24ee38b 100644
--- a/dmenu.1
+++ b/dmenu.1
@@ -5,6 +5,7 @@ dmenu \- dynamic menu
.B dmenu
.RB [ \-i ]
.RB [ \-b ]
+.RB [ \-l " <lines>"]
.RB [ \-fn " <font>"]
.RB [ \-nb " <color>"]
.RB [ \-nf " <color>"]
@@ -26,6 +27,10 @@ makes dmenu match menu entries case insensitively.
.B \-b
defines that dmenu appears at the bottom.
.TP
+.B \-l <lines>
+activates vertical list mode.
+The given number of lines will be displayed. Window height will get adjusted.
+.TP
.B \-fn <font>
defines the font.
.TP
@@ -57,7 +62,7 @@ dmenu is completely controlled by the keyboard. The following keys are recognize
Appends the character to the text in the input field. This works as a filter:
only items containing this text will be displayed.
.TP
-.B Left/Right (Mod1\-h/Mod1\-l)
+.B Left/Right (Up/Down) (Mod1\-h/Mod1\-l)
Select the previous/next item.
.TP
.B PageUp/PageDown (Mod1\-k/Mod1\-j)
diff --git a/dmenu.c b/dmenu.c
index 0f95af6..be9b41b 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -18,6 +18,7 @@
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
/* enums */
enum { ColFG, ColBG, ColLast };
@@ -47,10 +48,12 @@ struct Item {
/* forward declarations */
static void appenditem(Item *i, Item **list, Item **last);
-static void calcoffsets(void);
+static void calcoffsetsh(void);
+static void calcoffsetsv(void);
static char *cistrstr(const char *s, const char *sub);
static void cleanup(void);
-static void drawmenu(void);
+static void drawmenuh(void);
+static void drawmenuv(void);
static void drawtext(const char *text, unsigned long col[ColLast]);
static void eprint(const char *errstr, ...);
static unsigned long getcolor(const char *colstr);
@@ -73,6 +76,7 @@ static char text[4096];
static int cmdw = 0;
static int promptw = 0;
static int ret = 0;
+static int cursor = 0;
static int screen;
static unsigned int mw, mh;
static unsigned int numlockmask = 0;
@@ -88,6 +92,10 @@ static Item *curr = NULL;
static Window root, win;
static int (*fstrncmp)(const char *, const char *, size_t n) = strncmp;
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) {
@@ -101,7 +109,7 @@ appenditem(Item *i, Item **list, Item **last) {
}
void
-calcoffsets(void) {
+calcoffsetsh(void) {
int tw;
unsigned int w;
@@ -127,6 +135,26 @@ calcoffsets(void) {
}
}
+void
+calcoffsetsv(void) {
+ static unsigned int w;
+
+ if(!curr)
+ return;
+ w = (dc.font.height + 2) * (lines + 1);
+ for(next = curr; next; next=next->right) {
+ w -= dc.font.height + 2;
+ if(w <= 0)
+ break;
+ }
+ w = (dc.font.height + 2) * (lines + 1);
+ for(prev = curr; prev && prev->left; prev=prev->left) {
+ w -= dc.font.height + 2;
+ if(w <= 0)
+ break;
+ }
+}
+
char *
cistrstr(const char *s, const char *sub) {
int c, csub;
@@ -171,7 +199,17 @@ cleanup(void) {
}
void
-drawmenu(void) {
+drawcursor(void) {
+ XRectangle r = { dc.x, dc.y + 2, 1, dc.h - 4 };
+
+ r.x += textnw(text, cursor) + dc.font.height / 2;
+
+ XSetForeground(dpy, dc.gc, dc.norm[ColFG]);
+ XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
+}
+
+void
+drawmenuh(void) {
Item *i;
dc.x = 0;
@@ -190,6 +228,7 @@ drawmenu(void) {
if(cmdw && item)
dc.w = cmdw;
drawtext(text[0] ? text : NULL, dc.norm);
+ drawcursor();
dc.x += cmdw;
if(curr) {
dc.w = spaceitem;
@@ -212,6 +251,39 @@ drawmenu(void) {
}
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;
+ }
+ drawtext(NULL, dc.norm);
+ }
+ XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
+ XFlush(dpy);
+}
+
+void
drawtext(const char *text, unsigned long col[ColLast]) {
char buf[256];
int i, x, y, h, len, olen;
@@ -222,8 +294,8 @@ drawtext(const char *text, unsigned long col[ColLast]) {
if(!text)
return;
olen = strlen(text);
- h = dc.font.ascent + dc.font.descent;
- y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
+ h = dc.font.height;
+ y = dc.y + ((h+2) / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2);
/* shorten text if necessary */
for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
@@ -353,7 +425,7 @@ kpress(XKeyEvent * e) {
text[0] = 0;
match(text);
drawmenu();
- return;
+ break;
case XK_w:
case XK_W:
if(len) {
@@ -365,7 +437,7 @@ kpress(XKeyEvent * e) {
match(text);
drawmenu();
}
- return;
+ break;
}
}
if(CLEANMASK(e->state) & Mod1Mask) {
@@ -389,19 +461,39 @@ kpress(XKeyEvent * e) {
case XK_G:
ksym = XK_End;
break;
+ case XK_p:
+ {
+ FILE *fp;
+ char *c;
+ if(!(fp = (FILE*)popen("sselp", "r")))
+ fprintf(stderr, "dmenu: Could not popen sselp\n");
+ c = fgets(text + len, sizeof(text) - len, fp);
+ pclose(fp);
+ if(c == NULL)
+ return;
+ }
+ len = strlen(text);
+ if(len && text[len-1] == '\n')
+ text[--len] = '\0';
+ match(text);
+ drawmenu();
+ return;
}
}
switch(ksym) {
default:
if(num && !iscntrl((int) buf[0])) {
buf[num] = 0;
- strncpy(text + len, buf, sizeof text - len);
+ memmove(text + cursor + num, text + cursor, sizeof text - cursor);
+ strncpy(text + cursor, buf, sizeof text - cursor);
+ cursor+=num;
match(text);
}
break;
case XK_BackSpace:
- if(len) {
- text[--len] = 0;
+ if(cursor > 0) {
+ memmove(text + cursor + -1, text + cursor, sizeof text - cursor);
+ cursor--;
match(text);
}
break;
@@ -426,13 +518,18 @@ kpress(XKeyEvent * e) {
calcoffsets();
break;
case XK_Left:
- if(!(sel && sel->left))
- return;
- sel=sel->left;
- if(sel->right == curr) {
- curr = prev;
- calcoffsets();
+ case XK_Up:
+ if(sel && sel->left){
+ sel=sel->left;
+ if(sel->right == curr) {
+ curr = prev;
+ calcoffsets();
+ }
}
+ else if(cursor > 0)
+ cursor--;
+ else
+ return;
break;
case XK_Next:
if(!next)
@@ -457,21 +554,30 @@ kpress(XKeyEvent * e) {
running = False;
break;
case XK_Right:
- if(!(sel && sel->right))
- return;
- sel=sel->right;
- if(sel == next) {
- curr = next;
- calcoffsets();
+ case XK_Down:
+ if(cursor < len)
+ cursor++;
+ else if(sel && sel->right) {
+ sel=sel->right;
+ if(sel == next) {
+ curr = next;
+ calcoffsets();
+ }
}
+ else
+ return;
break;
case XK_Tab:
if(!sel)
return;
strncpy(text, sel->text, sizeof text);
+ cursor = strlen(text);
match(text);
break;
}
+ len = strlen(text);
+ cursor = MIN(cursor, len);
+ cursor = MAX(cursor, 0);
drawmenu();
}
@@ -598,6 +704,7 @@ setup(Bool topbar) {
/* menu window geometry */
mh = dc.font.height + 2;
+ mh = vlist ? mh * (lines+1) : mh;
#if XINERAMA
if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
i = 0;
@@ -676,6 +783,12 @@ main(int argc, char *argv[]) {
}
else if(!strcmp(argv[i], "-b"))
topbar = False;
+ else if(!strcmp(argv[i], "-l")) {
+ vlist = True;
+ calcoffsets = calcoffsetsv;
+ drawmenu = drawmenuv;
+ if(++i < argc) lines += atoi(argv[i]);
+ }
else if(!strcmp(argv[i], "-fn")) {
if(++i < argc) font = argv[i];
}
@@ -695,9 +808,9 @@ main(int argc, char *argv[]) {
if(++i < argc) selfgcolor = argv[i];
}
else if(!strcmp(argv[i], "-v"))
- eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
+ eprint("dmenu-"VERSION", © 2006-2009 dmenu engineers, see LICENSE for details\n");
else
- eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
+ eprint("usage: dmenu [-i] [-b] [-l <lines>] [-fn <font>] [-nb <color>] [-nf <color>]\n"
" [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fprintf(stderr, "warning: no locale support\n");