Compare commits

...

13 Commits
1.5 ... 1.7

6 changed files with 98 additions and 54 deletions

View File

@ -12,3 +12,5 @@ e8c1e9733752db12f2dbd1fa93c46f5806242ba9 1.1
bee7fe6d1189174d0204ca3195b83cdc1bb4f82e 1.2 bee7fe6d1189174d0204ca3195b83cdc1bb4f82e 1.2
2eb9997be51cb1b11a8900728ccc0904f9371157 1.3 2eb9997be51cb1b11a8900728ccc0904f9371157 1.3
df3fbb050004c544d14e43c36f6a94cca6ed4a69 1.4 df3fbb050004c544d14e43c36f6a94cca6ed4a69 1.4
e071fb045bd9e8574947acff7196360bc0270e68 1.5
dcc5427f99f51a978386a0dd770467cd911ac84b 1.6

View File

@ -1,5 +1,5 @@
# dmenu version # dmenu version
VERSION = 1.5 VERSION = 1.7
# Customize below to fit your system # Customize below to fit your system

12
dmenu.1
View File

@ -8,6 +8,7 @@ dmenu \- dynamic menu
.RB [ \-normfg " <color>"] .RB [ \-normfg " <color>"]
.RB [ \-selbg " <color>"] .RB [ \-selbg " <color>"]
.RB [ \-selfg " <color>"] .RB [ \-selfg " <color>"]
.RB [ \-p " <prompt>"]
.RB [ \-t " <seconds>"] .RB [ \-t " <seconds>"]
.RB [ \-v ] .RB [ \-v ]
.SH DESCRIPTION .SH DESCRIPTION
@ -33,6 +34,9 @@ defines the selected background color (#RGB, #RRGGBB, and color names are suppor
.B \-selfg <color> .B \-selfg <color>
defines the selected foreground color (#RGB, #RRGGBB, and color names are supported). defines the selected foreground color (#RGB, #RRGGBB, and color names are supported).
.TP .TP
.B \-p <prompt>
defines a prompt to be displayed before the input area.
.TP
.B \-t <seconds> .B \-t <seconds>
defines the seconds to wait for standard input, before exiting (default is 3). defines the seconds to wait for standard input, before exiting (default is 3).
.TP .TP
@ -40,7 +44,7 @@ defines the seconds to wait for standard input, before exiting (default is 3).
prints version information to standard output, then exits. prints version information to standard output, then exits.
.SH USAGE .SH USAGE
dmenu reads a list of newline-separated items from standard input and creates a dmenu reads a list of newline-separated items from standard input and creates a
menu. When the user selects an item or enters any text and presses Return, his menu. When the user selects an item or enters any text and presses Return, his/her
choice is printed to standard output and dmenu terminates. choice is printed to standard output and dmenu terminates.
.P .P
dmenu is completely controlled by the keyboard. The following keys are recognized: dmenu is completely controlled by the keyboard. The following keys are recognized:
@ -52,6 +56,12 @@ only items containing this text will be displayed.
.B Left/Right .B Left/Right
Select the previous/next item. Select the previous/next item.
.TP .TP
.B PageUp/PageDown
Select the first item of the previous/next 'page' of items.
.TP
.B Home/End
Select the first/last item.
.TP
.B Tab .B Tab
Copy the selected item to the input field. Copy the selected item to the input field.
.TP .TP

View File

@ -3,14 +3,13 @@
*/ */
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xlocale.h>
#define FONT "fixed" #define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
#define NORMBGCOLOR "#333366" #define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc" #define NORMFGCOLOR "#cccccc"
#define SELBGCOLOR "#666699" #define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee" #define SELFGCOLOR "#eeeeee"
#define SPACE 30 /* px */ #define SPACE 30 /* px */
/* color */ /* color */
enum { ColFG, ColBG, ColLast }; enum { ColFG, ColBG, ColLast };

18
draw.c
View File

@ -4,7 +4,6 @@
#include "dmenu.h" #include "dmenu.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <X11/Xlocale.h>
/* static */ /* static */
@ -80,21 +79,15 @@ getcolor(const char *colstr) {
void void
setfont(const char *fontstr) { setfont(const char *fontstr) {
char **missing, *def; char *def, **missing;
int i, n; int i, n;
missing = NULL; missing = NULL;
setlocale(LC_ALL, "");
if(dc.font.set) if(dc.font.set)
XFreeFontSet(dpy, dc.font.set); XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) { if(missing)
XFreeStringList(missing); XFreeStringList(missing);
if(dc.font.set) {
XFreeFontSet(dpy, dc.font.set);
dc.font.set = NULL;
}
}
if(dc.font.set) { if(dc.font.set) {
XFontSetExtents *font_extents; XFontSetExtents *font_extents;
XFontStruct **xfonts; XFontStruct **xfonts;
@ -114,11 +107,8 @@ setfont(const char *fontstr) {
if(dc.font.xfont) if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont); XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL; dc.font.xfont = NULL;
dc.font.xfont = XLoadQueryFont(dpy, fontstr); if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
if (!dc.font.xfont) eprint("error, cannot load font: '%s'\n", fontstr);
dc.font.xfont = XLoadQueryFont(dpy, "fixed");
if (!dc.font.xfont)
eprint("error, cannot init 'fixed' font\n");
dc.font.ascent = dc.font.xfont->ascent; dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent; dc.font.descent = dc.font.xfont->descent;
} }

113
main.c
View File

@ -5,6 +5,7 @@
#include "dmenu.h" #include "dmenu.h"
#include <ctype.h> #include <ctype.h>
#include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -24,10 +25,12 @@ struct Item {
/* static */ /* static */
static char text[4096]; static char text[4096];
static char *prompt = NULL;
static int mx, my, mw, mh; static int mx, my, mw, mh;
static int ret = 0; static int ret = 0;
static int nitem = 0; static int nitem = 0;
static unsigned int cmdw = 0; static unsigned int cmdw = 0;
static unsigned int promptw = 0;
static Bool running = True; static Bool running = True;
static Item *allitems = NULL; /* first of all items */ static Item *allitems = NULL; /* first of all items */
static Item *item = NULL; /* first of pattern matching items */ static Item *item = NULL; /* first of pattern matching items */
@ -44,7 +47,7 @@ calcoffsets(void) {
if(!curr) if(!curr)
return; return;
w = cmdw + 2 * SPACE; w = promptw + cmdw + 2 * SPACE;
for(next = curr; next; next=next->right) { for(next = curr; next; next=next->right) {
tw = textw(next->text); tw = textw(next->text);
if(tw > mw / 3) if(tw > mw / 3)
@ -53,7 +56,7 @@ calcoffsets(void) {
if(w > mw) if(w > mw)
break; break;
} }
w = cmdw + 2 * SPACE; w = promptw + cmdw + 2 * SPACE;
for(prev = curr; prev && prev->left; prev=prev->left) { for(prev = curr; prev && prev->left; prev=prev->left) {
tw = textw(prev->left->text); tw = textw(prev->left->text);
if(tw > mw / 3) if(tw > mw / 3)
@ -73,6 +76,13 @@ drawmenu(void) {
dc.w = mw; dc.w = mw;
dc.h = mh; dc.h = mh;
drawtext(NULL, dc.norm); drawtext(NULL, dc.norm);
/* print prompt? */
if(promptw) {
dc.w = promptw;
drawtext(prompt, dc.sel);
}
dc.x += promptw;
dc.w = mw - promptw;
/* print command */ /* print command */
if(cmdw && item) if(cmdw && item)
dc.w = cmdw; dc.w = cmdw;
@ -169,6 +179,42 @@ kpress(XKeyEvent * e) {
} }
} }
switch(ksym) { switch(ksym) {
default:
if(num && !iscntrl((int) buf[0])) {
buf[num] = 0;
if(len > 0)
strncat(text, buf, sizeof text);
else
strncpy(text, buf, sizeof text);
match(text);
}
break;
case XK_BackSpace:
if((i = len)) {
prev_nitem = nitem;
do {
text[--i] = 0;
match(text);
} while(i && nitem && prev_nitem == nitem);
match(text);
}
break;
case XK_End:
while(next) {
sel = curr = next;
calcoffsets();
}
while(sel->right)
sel = sel->right;
break;
case XK_Escape:
ret = 1;
running = False;
break;
case XK_Home:
sel = curr = item;
calcoffsets();
break;
case XK_Left: case XK_Left:
if(!(sel && sel->left)) if(!(sel && sel->left))
return; return;
@ -178,18 +224,15 @@ kpress(XKeyEvent * e) {
calcoffsets(); calcoffsets();
} }
break; break;
case XK_Tab: case XK_Next:
if(!sel) if(next) {
return; sel = curr = next;
strncpy(text, sel->text, sizeof text); calcoffsets();
match(text); }
break; break;
case XK_Right: case XK_Prior:
if(!(sel && sel->right)) if(prev) {
return; sel = curr = prev;
sel=sel->right;
if(sel == next) {
curr = next;
calcoffsets(); calcoffsets();
} }
break; break;
@ -203,29 +246,21 @@ kpress(XKeyEvent * e) {
fflush(stdout); fflush(stdout);
running = False; running = False;
break; break;
case XK_Escape: case XK_Right:
ret = 1; if(!(sel && sel->right))
running = False; return;
break; sel=sel->right;
case XK_BackSpace: if(sel == next) {
if((i = len)) { curr = next;
prev_nitem = nitem; calcoffsets();
do {
text[--i] = 0;
match(text);
} while(i && nitem && prev_nitem == nitem);
match(text);
} }
break; break;
default: case XK_Tab:
if(num && !iscntrl((int) buf[0])) { if(!sel)
buf[num] = 0; return;
if(len > 0) strncpy(text, sel->text, sizeof text);
strncat(text, buf, sizeof text); match(text);
else break;
strncpy(text, buf, sizeof text);
match(text);
}
} }
drawmenu(); drawmenu();
} }
@ -300,6 +335,9 @@ main(int argc, char *argv[]) {
else if(!strncmp(argv[i], "-selfg", 7)) { else if(!strncmp(argv[i], "-selfg", 7)) {
if(++i < argc) selfg = argv[i]; if(++i < argc) selfg = argv[i];
} }
else if(!strncmp(argv[i], "-p", 3)) {
if(++i < argc) prompt = argv[i];
}
else if(!strncmp(argv[i], "-t", 3)) { else if(!strncmp(argv[i], "-t", 3)) {
if(++i < argc) timeout.tv_sec = atoi(argv[i]); if(++i < argc) timeout.tv_sec = atoi(argv[i]);
} }
@ -308,7 +346,8 @@ main(int argc, char *argv[]) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
else else
eprint("usage: dmenu [-font <name>] [-{norm,sel}{bg,fg} <color>] [-t <seconds>] [-v]\n", stdout); eprint("usage: dmenu [-font <name>] [-{norm,sel}{bg,fg} <color>] [-p <prompt>] [-t <seconds>] [-v]\n", stdout);
setlocale(LC_CTYPE, "");
dpy = XOpenDisplay(0); dpy = XOpenDisplay(0);
if(!dpy) if(!dpy)
eprint("dmenu: cannot open display\n"); eprint("dmenu: cannot open display\n");
@ -353,6 +392,10 @@ main(int argc, char *argv[]) {
cmdw = textw(maxname); cmdw = textw(maxname);
if(cmdw > mw / 3) if(cmdw > mw / 3)
cmdw = mw / 3; cmdw = mw / 3;
if(prompt)
promptw = textw(prompt);
if(promptw > mw / 5)
promptw = mw / 5;
text[0] = 0; text[0] = 0;
match(text); match(text);
XMapRaised(dpy, win); XMapRaised(dpy, win);