Hi,
I wrote two patches for displaying a vertical list and adjusting width/height/offsets
of a dmenu-window.
This is how it looks like
http://img246.imageshack.us/my.php?image=dmenuvd1.png
The first patch just adds the vertical list and a counter option. This counter option
is used to display the number off items in the item-list after applying a filter.
[-l <#items>] activates vertical list mode, window will be adjusted for displaying #items
[-c] displays a counter in vlist mode (hits on applied filter)
The second patch adds the options for chaning width/height/offsets. It also adds an
option for aligning the window to the right side.
[-r] align right
[-w <width>] window width. be careful ;(
[-h <height>] window height. you can breath a wish here, [-h] has higher priority then [-l]
but it gets recalculated internally ( simplified: #items = height / font.height )
[-bo <width>] border width; not a real border but the distance to the edges of the screen.
the distance can be also chosen independently:
[-x <xoffset>] distance to left or right side of the screen, depends on [-r]
[-y <yoffset>] distance to top or bottom of the screen, depends on [-b]
[-bo],[-x] and [-y] can be mixed.
[-r] and [-b] should work with all of those width/height/offset options.
For now it is not checked, if given values for width/offsets are appropriate.
Let me know if you have suggestions or comments
Frederik
--- dmenu-3.8.orig/dmenu.c 2008-08-25 15:34:19.000000000 +0200
+++ dmenu-3.8-vlist/dmenu.c 2008-08-25 16:44:51.000000000 +0200
@@ -47,10 +47,13 @@
/* 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 updatemenuv(Bool);
static void drawtext(const char *text, unsigned long col[ColLast]);
static void eprint(const char *errstr, ...);
static unsigned long getcolor(const char *colstr);
@@ -60,7 +63,7 @@
static void match(char *pattern);
static void readstdin(void);
static void run(void);
-static void setup(Bool topbar);
+static void setup(void);
static int textnw(const char *text, unsigned int len);
static int textw(const char *text);
@@ -70,13 +73,19 @@
static char *maxname = NULL;
static char *prompt = NULL;
static char text[4096];
+static char hitstxt[16] = {0};
static int cmdw = 0;
static int promptw = 0;
static int ret = 0;
static int screen;
static unsigned int mw, mh;
static unsigned int numlockmask = 0;
+static unsigned int hits = 0;
+static unsigned int lines = 3;
static Bool running = True;
+static Bool topbar = True;
+static Bool vlist = False;
+static Bool hitcounter = False;
static Display *dpy;
static DC dc = {0};
static Item *allitems = NULL; /* first of all items */
@@ -88,6 +97,8 @@
static Window root, win;
static int (*fstrncmp)(const char *, const char *, size_t n) = strncmp;
static char *(*fstrstr)(const char *, const char *) = strstr;
+static void (*calcoffsets)(void) = calcoffsetsh;
+static void (*drawmenu)(void) = drawmenuh;
void
appenditem(Item *i, Item **list, Item **last) {
@@ -98,12 +109,13 @@
i->left = *last;
i->right = NULL;
*last = i;
+ ++hits;
}
void
-calcoffsets(void) {
- int tw;
- unsigned int w;
+calcoffsetsh(void) {
+ static int tw;
+ static unsigned int w;
if(!curr)
return;
@@ -127,6 +139,26 @@
}
}
+void
+calcoffsetsv(void) {
+ static unsigned int w;
+
+ if(!curr)
+ return;
+ w = (dc.font.height + 2) * (lines - 2);
+ for(next = curr; next; next=next->right) {
+ w -= dc.font.height + 2;
+ if (w <= 0)
+ break;
+ }
+ w = (dc.font.height + 2) * (lines - 2);
+ 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,8 +203,8 @@
}
void
-drawmenu(void) {
- Item *i;
+drawmenuh(void) {
+ static Item *i;
dc.x = 0;
dc.y = 0;
@@ -212,6 +244,79 @@
}
void
+drawmenuv(void) {
+ static Item *i;
+
+ dc.x = 0;
+ dc.y = 0;
+ 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 - (hitcounter ? textnw(hitstxt, strlen(hitstxt)) : 0);
+
+ drawtext(text[0] ? text : NULL, dc.norm);
+ if(curr) {
+ if (hitcounter) {
+ dc.w = textw(hitstxt);
+ dc.x = mw - textw(hitstxt);
+ drawtext(hitstxt, dc.norm);
+ }
+ dc.x = 0;
+ dc.y = dc.font.height + 2;
+ dc.w = mw;
+ drawtext((curr && curr->left) ? "^" : NULL, 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(next ? "v" : NULL, dc.norm);
+ } else {
+ if (hitcounter) {
+ dc.w = textw(hitstxt);
+ dc.x = mw - textw(hitstxt);
+ dc.y = 0;
+ drawtext(hitstxt, dc.norm);
+ }
+ dc.x = 0;
+ dc.w = mw;
+ dc.h = mh;
+ 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
+updatemenuv(Bool updown) {
+ static Item *i;
+
+ if(curr) {
+ dc.x = 0;
+ dc.y = (dc.font.height + 2) * 2;
+ dc.w = mw;
+ dc.h = mh;
+ for(i = curr; i != next; i=i->right) {
+ if (((i==sel->left) && !updown) || (i==sel)
+ || ((i==sel->right) && updown)) {
+ drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
+ XCopyArea(dpy, dc.drawable, win, dc.gc, dc.x, dc.y,
+ dc.w, (dc.font.height) + 2, dc.x, dc.y);
+ }
+ dc.y += dc.font.height + 2;
+ }
+ }
+ XFlush(dpy);
+}
+
+void
drawtext(const char *text, unsigned long col[ColLast]) {
int x, y, w, h;
static char buf[256];
@@ -228,8 +333,8 @@
len = sizeof buf - 1;
memcpy(buf, text, len);
buf[len] = 0;
- 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 */
while(len && (w = textnw(buf, len)) > dc.w - h)
@@ -446,12 +551,18 @@
calcoffsets();
break;
case XK_Left:
+ case XK_Up:
if(!(sel && sel->left))
return;
sel=sel->left;
if(sel->right == curr) {
curr = prev;
calcoffsets();
+ } else {
+ if (vlist) {
+ updatemenuv(True);
+ return;
+ }
}
break;
case XK_Next:
@@ -477,12 +588,18 @@
running = False;
break;
case XK_Right:
+ case XK_Down:
if(!(sel && sel->right))
return;
sel=sel->right;
if(sel == next) {
curr = next;
calcoffsets();
+ } else {
+ if (vlist) {
+ updatemenuv(False);
+ return;
+ }
}
break;
case XK_Tab:
@@ -534,6 +651,8 @@
}
curr = prev = next = sel = item;
calcoffsets();
+ snprintf(hitstxt, sizeof(hitstxt), "(%d)", hits);
+ hits = 0;
}
void
@@ -585,7 +704,7 @@
}
void
-setup(Bool topbar) {
+setup(void) {
int i, j, x, y;
#if XINERAMA
int n;
@@ -643,6 +762,11 @@
mw = DisplayWidth(dpy, screen);
}
+ /* update menu window geometry */
+
+ mh = vlist ? (dc.font.height + 2) * lines : mh;
+ y = topbar ? y : y - mh + (dc.font.height + 2);
+
win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen),
@@ -686,7 +810,6 @@
int
main(int argc, char *argv[]) {
unsigned int i;
- Bool topbar = True;
/* command line args */
for(i = 1; i < argc; i++)
@@ -696,6 +819,14 @@
}
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], "-c"))
+ hitcounter = True;
else if(!strcmp(argv[i], "-fn")) {
if(++i < argc) font = argv[i];
}
@@ -717,8 +848,8 @@
else if(!strcmp(argv[i], "-v"))
eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
else
- eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
- " [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
+ eprint("usage: dmenu [-i] [-b] [-l <#items>] [-c] [-fn <font>] [-nb <color>]\n"
+ "[-nf <color>] [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fprintf(stderr, "warning: no locale support\n");
if(!(dpy = XOpenDisplay(0)))
@@ -735,7 +866,7 @@
readstdin();
}
- setup(topbar);
+ setup();
drawmenu();
XSync(dpy, False);
run();
-- Frederik Schiewek <fs_AT_schiewek.net>Received on Mon Aug 25 2008 - 18:57:19 UTC
This archive was generated by hypermail 2.2.0 : Mon Aug 25 2008 - 19:12:04 UTC