@@ -3,7 +3,7 @@ | |||||
include config.mk | include config.mk | ||||
SRC = dinput.c dmenu.c | |||||
SRC = dinput.c dmenu.c common.c | |||||
OBJ = ${SRC:.c=.o} | OBJ = ${SRC:.c=.o} | ||||
all: options dinput dmenu | all: options dinput dmenu | ||||
@@ -24,9 +24,13 @@ config.h: | |||||
@echo creating $@ from config.def.h | @echo creating $@ from config.def.h | ||||
@cp config.def.h $@ | @cp config.def.h $@ | ||||
.o: | |||||
dinput: dinput.o common.o | |||||
@echo CC -o $@ | @echo CC -o $@ | ||||
@${CC} -o $@ $< ${LDFLAGS} | |||||
@${CC} -o $@ $+ ${LDFLAGS} | |||||
dmenu: dmenu.o common.o | |||||
@echo CC -o $@ | |||||
@${CC} -o $@ $+ ${LDFLAGS} | |||||
clean: | clean: | ||||
@echo cleaning | @echo cleaning | ||||
@@ -0,0 +1,129 @@ | |||||
/* See LICENSE file for copyright and license details. */ | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <unistd.h> | |||||
#include <X11/keysym.h> | |||||
#ifdef XINERAMA | |||||
#include <X11/extensions/Xinerama.h> | |||||
#endif | |||||
#include "dmenu.h" | |||||
/* variables */ | |||||
char *prompt = NULL; | |||||
char text[4096] = ""; | |||||
int promptw = 0; | |||||
int screen; | |||||
unsigned int numlockmask = 0; | |||||
unsigned int mw, mh; | |||||
unsigned long normcol[ColLast]; | |||||
unsigned long selcol[ColLast]; | |||||
Bool topbar = True; | |||||
DC dc; | |||||
Display *dpy; | |||||
Window win, root; | |||||
void | |||||
grabkeyboard(void) { | |||||
unsigned int len; | |||||
for(len = 1000; len; len--) { | |||||
if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | |||||
== GrabSuccess) | |||||
return; | |||||
usleep(1000); | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | |||||
run(void) { | |||||
XEvent ev; | |||||
/* main event loop */ | |||||
XSync(dpy, False); | |||||
while(!XNextEvent(dpy, &ev)) | |||||
switch(ev.type) { | |||||
case KeyPress: | |||||
kpress(&ev.xkey); | |||||
break; | |||||
case Expose: | |||||
if(ev.xexpose.count == 0) | |||||
drawbar(); | |||||
break; | |||||
case VisibilityNotify: | |||||
if(ev.xvisibility.state != VisibilityUnobscured) | |||||
XRaiseWindow(dpy, win); | |||||
break; | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | |||||
setup(unsigned int lines) { | |||||
int i, j, x, y; | |||||
#if XINERAMA | |||||
int n; | |||||
XineramaScreenInfo *info = NULL; | |||||
#endif | |||||
XModifierKeymap *modmap; | |||||
XSetWindowAttributes wa; | |||||
/* init modifier map */ | |||||
modmap = XGetModifierMapping(dpy); | |||||
for(i = 0; i < 8; i++) | |||||
for(j = 0; j < modmap->max_keypermod; j++) { | |||||
if(modmap->modifiermap[i * modmap->max_keypermod + j] | |||||
== XKeysymToKeycode(dpy, XK_Num_Lock)) | |||||
numlockmask = (1 << i); | |||||
} | |||||
XFreeModifiermap(modmap); | |||||
dc.dpy = dpy; | |||||
normcol[ColBG] = getcolor(&dc, normbgcolor); | |||||
normcol[ColFG] = getcolor(&dc, normfgcolor); | |||||
selcol[ColBG] = getcolor(&dc, selbgcolor); | |||||
selcol[ColFG] = getcolor(&dc, selfgcolor); | |||||
initfont(&dc, font); | |||||
/* input window */ | |||||
wa.override_redirect = True; | |||||
wa.background_pixmap = ParentRelative; | |||||
wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; | |||||
/* input window geometry */ | |||||
mh = (dc.font.height + 2) * (lines + 1); | |||||
#if XINERAMA | |||||
if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { | |||||
i = 0; | |||||
if(n > 1) { | |||||
int di; | |||||
unsigned int dui; | |||||
Window dummy; | |||||
if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) | |||||
for(i = 0; i < n; i++) | |||||
if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) | |||||
break; | |||||
} | |||||
x = info[i].x_org; | |||||
y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh; | |||||
mw = info[i].width; | |||||
XFree(info); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
x = 0; | |||||
y = topbar ? 0 : DisplayHeight(dpy, screen) - mh; | |||||
mw = DisplayWidth(dpy, screen); | |||||
} | |||||
win = XCreateWindow(dpy, root, x, y, mw, mh, 0, | |||||
DefaultDepth(dpy, screen), CopyFromParent, | |||||
DefaultVisual(dpy, screen), | |||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | |||||
setupdraw(&dc, win); | |||||
if(prompt) | |||||
promptw = MIN(textw(&dc, prompt), mw / 5); | |||||
XMapRaised(dpy, win); | |||||
} |
@@ -1,9 +1,8 @@ | |||||
/* See LICENSE file for copyright and license details. */ | /* See LICENSE file for copyright and license details. */ | ||||
/* appearance */ | /* appearance */ | ||||
const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"; | |||||
const char *normbgcolor = "#cccccc"; | |||||
const char *normfgcolor = "#000000"; | |||||
const char *selbgcolor = "#0066ff"; | |||||
const char *selfgcolor = "#ffffff"; | |||||
unsigned int spaceitem = 30; /* px between menu items */ | |||||
static const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"; | |||||
static const char *normbgcolor = "#cccccc"; | |||||
static const char *normfgcolor = "#000000"; | |||||
static const char *selbgcolor = "#0066ff"; | |||||
static const char *selfgcolor = "#ffffff"; |
@@ -4,45 +4,16 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | |||||
#include <X11/keysym.h> | #include <X11/keysym.h> | ||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
#ifdef XINERAMA | |||||
#include <X11/extensions/Xinerama.h> | |||||
#endif | |||||
#include <draw.h> | |||||
/* macros */ | |||||
#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)) | |||||
#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80)) | |||||
#include "dmenu.h" | |||||
/* forward declarations */ | /* forward declarations */ | ||||
static void cleanup(void); | static void cleanup(void); | ||||
static void drawinput(void); | |||||
static void grabkeyboard(void); | |||||
static void kpress(XKeyEvent *e); | |||||
static void run(void); | |||||
static void setup(void); | |||||
#include "config.h" | |||||
/* variables */ | /* variables */ | ||||
static char *prompt = NULL; | |||||
static char text[4096]; | |||||
static int promptw = 0; | |||||
static int screen; | |||||
static size_t cursor = 0; | static size_t cursor = 0; | ||||
static unsigned int numlockmask = 0; | |||||
static unsigned int mw, mh; | |||||
static unsigned long normcol[ColLast]; | |||||
static unsigned long selcol[ColLast]; | |||||
static Bool topbar = True; | |||||
static DC dc; | |||||
static Display *dpy; | |||||
static Window win, root; | |||||
void | void | ||||
cleanup(void) { | cleanup(void) { | ||||
@@ -53,7 +24,7 @@ cleanup(void) { | |||||
} | } | ||||
void | void | ||||
drawinput(void) | |||||
drawbar(void) | |||||
{ | { | ||||
dc.x = 0; | dc.x = 0; | ||||
dc.y = 0; | dc.y = 0; | ||||
@@ -72,19 +43,6 @@ drawinput(void) | |||||
commitdraw(&dc, win); | commitdraw(&dc, win); | ||||
} | } | ||||
void | |||||
grabkeyboard(void) { | |||||
unsigned int len; | |||||
for(len = 1000; len; len--) { | |||||
if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | |||||
== GrabSuccess) | |||||
return; | |||||
usleep(1000); | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | void | ||||
kpress(XKeyEvent *e) { | kpress(XKeyEvent *e) { | ||||
char buf[sizeof text]; | char buf[sizeof text]; | ||||
@@ -207,101 +165,7 @@ kpress(XKeyEvent *e) { | |||||
while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor])); | while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor])); | ||||
break; | break; | ||||
} | } | ||||
drawinput(); | |||||
} | |||||
void | |||||
run(void) { | |||||
XEvent ev; | |||||
/* main event loop */ | |||||
XSync(dpy, False); | |||||
while(!XNextEvent(dpy, &ev)) | |||||
switch(ev.type) { | |||||
case KeyPress: | |||||
kpress(&ev.xkey); | |||||
break; | |||||
case Expose: | |||||
if(ev.xexpose.count == 0) | |||||
drawinput(); | |||||
break; | |||||
case VisibilityNotify: | |||||
if(ev.xvisibility.state != VisibilityUnobscured) | |||||
XRaiseWindow(dpy, win); | |||||
break; | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | |||||
setup(void) { | |||||
int i, j, x, y; | |||||
#if XINERAMA | |||||
int n; | |||||
XineramaScreenInfo *info = NULL; | |||||
#endif | |||||
XModifierKeymap *modmap; | |||||
XSetWindowAttributes wa; | |||||
/* init modifier map */ | |||||
modmap = XGetModifierMapping(dpy); | |||||
for(i = 0; i < 8; i++) | |||||
for(j = 0; j < modmap->max_keypermod; j++) { | |||||
if(modmap->modifiermap[i * modmap->max_keypermod + j] | |||||
== XKeysymToKeycode(dpy, XK_Num_Lock)) | |||||
numlockmask = (1 << i); | |||||
} | |||||
XFreeModifiermap(modmap); | |||||
dc.dpy = dpy; | |||||
normcol[ColBG] = getcolor(&dc, normbgcolor); | |||||
normcol[ColFG] = getcolor(&dc, normfgcolor); | |||||
selcol[ColBG] = getcolor(&dc, selbgcolor); | |||||
selcol[ColFG] = getcolor(&dc, selfgcolor); | |||||
initfont(&dc, font); | |||||
/* input window */ | |||||
wa.override_redirect = True; | |||||
wa.background_pixmap = ParentRelative; | |||||
wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; | |||||
/* input window geometry */ | |||||
mh = dc.font.height + 2; | |||||
#if XINERAMA | |||||
if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { | |||||
i = 0; | |||||
if(n > 1) { | |||||
int di; | |||||
unsigned int dui; | |||||
Window dummy; | |||||
if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) | |||||
for(i = 0; i < n; i++) | |||||
if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) | |||||
break; | |||||
} | |||||
x = info[i].x_org; | |||||
y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh; | |||||
mw = info[i].width; | |||||
XFree(info); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
x = 0; | |||||
y = topbar ? 0 : DisplayHeight(dpy, screen) - mh; | |||||
mw = DisplayWidth(dpy, screen); | |||||
} | |||||
win = XCreateWindow(dpy, root, x, y, mw, mh, 0, | |||||
DefaultDepth(dpy, screen), CopyFromParent, | |||||
DefaultVisual(dpy, screen), | |||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | |||||
setupdraw(&dc, win); | |||||
if(prompt) | |||||
promptw = MIN(textw(&dc, prompt), mw / 5); | |||||
cursor = strlen(text); | |||||
XMapRaised(dpy, win); | |||||
drawbar(); | |||||
} | } | ||||
int | int | ||||
@@ -336,11 +200,13 @@ main(int argc, char *argv[]) { | |||||
if(++i < argc) selfgcolor = argv[i]; | if(++i < argc) selfgcolor = argv[i]; | ||||
} | } | ||||
else if(!strcmp(argv[i], "-v")) { | else if(!strcmp(argv[i], "-v")) { | ||||
printf("dinput-"VERSION", © 2006-2010 dinput engineers, see LICENSE for details\n"); | |||||
printf("dinput-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n"); | |||||
exit(EXIT_SUCCESS); | exit(EXIT_SUCCESS); | ||||
} | } | ||||
else if(!*text) | |||||
else if(!*text) { | |||||
strncpy(text, argv[i], sizeof text); | strncpy(text, argv[i], sizeof text); | ||||
cursor = strlen(text); | |||||
} | |||||
else { | else { | ||||
fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n" | fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n" | ||||
" [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr); | " [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr); | ||||
@@ -356,7 +222,7 @@ main(int argc, char *argv[]) { | |||||
root = RootWindow(dpy, screen); | root = RootWindow(dpy, screen); | ||||
grabkeyboard(); | grabkeyboard(); | ||||
setup(); | |||||
setup(0); | |||||
run(); | run(); | ||||
return 0; | return 0; | ||||
} | } |
@@ -8,16 +8,7 @@ | |||||
#include <X11/keysym.h> | #include <X11/keysym.h> | ||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <X11/Xutil.h> | #include <X11/Xutil.h> | ||||
#ifdef XINERAMA | |||||
#include <X11/extensions/Xinerama.h> | |||||
#endif | |||||
#include <draw.h> | |||||
/* macros */ | |||||
#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)) | |||||
#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80)) | |||||
#include "dmenu.h" | |||||
typedef struct Item Item; | typedef struct Item Item; | ||||
struct Item { | struct Item { | ||||
@@ -33,41 +24,22 @@ static void calcoffsetsv(void); | |||||
static char *cistrstr(const char *s, const char *sub); | static char *cistrstr(const char *s, const char *sub); | ||||
static void cleanup(void); | static void cleanup(void); | ||||
static void dinput(void); | static void dinput(void); | ||||
static void drawmenu(void); | |||||
static void drawmenuh(void); | static void drawmenuh(void); | ||||
static void drawmenuv(void); | static void drawmenuv(void); | ||||
static void grabkeyboard(void); | |||||
static void kpress(XKeyEvent *e); | |||||
static void match(char *pattern); | |||||
static void match(void); | |||||
static void readstdin(void); | static void readstdin(void); | ||||
static void run(void); | |||||
static void setup(void); | |||||
#include "config.h" | |||||
/* variables */ | /* variables */ | ||||
static char **argp = NULL; | static char **argp = NULL; | ||||
static char *maxname = NULL; | static char *maxname = NULL; | ||||
static char *prompt = NULL; | |||||
static char text[4096]; | |||||
static int cmdw = 0; | |||||
static int promptw = 0; | |||||
static int screen; | |||||
static unsigned int cmdw = 0; | |||||
static unsigned int lines = 0; | static unsigned int lines = 0; | ||||
static unsigned int numlockmask = 0; | |||||
static unsigned int mw, mh; | |||||
static unsigned long normcol[ColLast]; | |||||
static unsigned long selcol[ColLast]; | |||||
static Bool topbar = True; | |||||
static DC dc; | |||||
static Display *dpy; | |||||
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 */ | ||||
static Item *sel = NULL; | static Item *sel = NULL; | ||||
static Item *next = NULL; | static Item *next = NULL; | ||||
static Item *prev = NULL; | static Item *prev = NULL; | ||||
static Item *curr = NULL; | static Item *curr = NULL; | ||||
static Window win, root; | |||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; | static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; | ||||
static char *(*fstrstr)(const char *, const char *) = strstr; | static char *(*fstrstr)(const char *, const char *) = strstr; | ||||
static void (*calcoffsets)(void) = calcoffsetsh; | static void (*calcoffsets)(void) = calcoffsetsh; | ||||
@@ -85,14 +57,13 @@ appenditem(Item *i, Item **list, Item **last) { | |||||
void | void | ||||
calcoffsetsh(void) { | calcoffsetsh(void) { | ||||
unsigned int x; | |||||
unsigned int w, x; | |||||
x = promptw + cmdw + (2 * spaceitem); | |||||
for(next = curr; next; next = next->right) | |||||
w = promptw + cmdw + textw(&dc, "<") + textw(&dc, ">"); | |||||
for(x = w, next = curr; next; next = next->right) | |||||
if((x += MIN(textw(&dc, next->text), mw / 3)) > mw) | if((x += MIN(textw(&dc, next->text), mw / 3)) > mw) | ||||
break; | break; | ||||
x = promptw + cmdw + (2 * spaceitem); | |||||
for(prev = curr; prev && prev->left; prev = prev->left) | |||||
for(x = w, prev = curr; prev && prev->left; prev = prev->left) | |||||
if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw) | if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw) | ||||
break; | break; | ||||
} | } | ||||
@@ -157,7 +128,7 @@ dinput(void) { | |||||
} | } | ||||
void | void | ||||
drawmenu(void) { | |||||
drawbar(void) { | |||||
dc.x = 0; | dc.x = 0; | ||||
dc.y = 0; | dc.y = 0; | ||||
dc.w = mw; | dc.w = mw; | ||||
@@ -188,7 +159,7 @@ drawmenuh(void) { | |||||
Item *i; | Item *i; | ||||
dc.x += cmdw; | dc.x += cmdw; | ||||
dc.w = spaceitem; | |||||
dc.w = textw(&dc, "<"); | |||||
drawtext(&dc, curr->left ? "<" : NULL, normcol); | drawtext(&dc, curr->left ? "<" : NULL, normcol); | ||||
dc.x += dc.w; | dc.x += dc.w; | ||||
for(i = curr; i != next; i = i->right) { | for(i = curr; i != next; i = i->right) { | ||||
@@ -196,7 +167,7 @@ drawmenuh(void) { | |||||
drawtext(&dc, i->text, (sel == i) ? selcol : normcol); | drawtext(&dc, i->text, (sel == i) ? selcol : normcol); | ||||
dc.x += dc.w; | dc.x += dc.w; | ||||
} | } | ||||
dc.w = spaceitem; | |||||
dc.w = textw(&dc, ">"); | |||||
dc.x = mw - dc.w; | dc.x = mw - dc.w; | ||||
drawtext(&dc, next ? ">" : NULL, normcol); | drawtext(&dc, next ? ">" : NULL, normcol); | ||||
} | } | ||||
@@ -217,19 +188,6 @@ drawmenuv(void) { | |||||
XMoveResizeWindow(dpy, win, wa.x, wa.y + (topbar ? 0 : wa.height - mh), mw, mh); | XMoveResizeWindow(dpy, win, wa.x, wa.y + (topbar ? 0 : wa.height - mh), mw, mh); | ||||
} | } | ||||
void | |||||
grabkeyboard(void) { | |||||
unsigned int len; | |||||
for(len = 1000; len; len--) { | |||||
if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | |||||
== GrabSuccess) | |||||
return; | |||||
usleep(1000); | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | void | ||||
kpress(XKeyEvent *e) { | kpress(XKeyEvent *e) { | ||||
char buf[sizeof text]; | char buf[sizeof text]; | ||||
@@ -285,7 +243,7 @@ kpress(XKeyEvent *e) { | |||||
break; | break; | ||||
case XK_u: | case XK_u: | ||||
text[0] = '\0'; | text[0] = '\0'; | ||||
match(text); | |||||
match(); | |||||
break; | break; | ||||
case XK_w: | case XK_w: | ||||
if(len == 0) | if(len == 0) | ||||
@@ -294,7 +252,7 @@ kpress(XKeyEvent *e) { | |||||
while(i-- > 0 && text[i] == ' '); | while(i-- > 0 && text[i] == ' '); | ||||
while(i-- > 0 && text[i] != ' '); | while(i-- > 0 && text[i] != ' '); | ||||
text[++i] = '\0'; | text[++i] = '\0'; | ||||
match(text); | |||||
match(); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -304,7 +262,7 @@ kpress(XKeyEvent *e) { | |||||
if(num && !iscntrl((int) buf[0])) { | if(num && !iscntrl((int) buf[0])) { | ||||
memcpy(text + len, buf, num + 1); | memcpy(text + len, buf, num + 1); | ||||
len += num; | len += num; | ||||
match(text); | |||||
match(); | |||||
} | } | ||||
break; | break; | ||||
case XK_BackSpace: | case XK_BackSpace: | ||||
@@ -313,7 +271,7 @@ kpress(XKeyEvent *e) { | |||||
for(i = 1; len - i > 0 && !IS_UTF8_1ST_CHAR(text[len - i]); i++); | for(i = 1; len - i > 0 && !IS_UTF8_1ST_CHAR(text[len - i]); i++); | ||||
len -= i; | len -= i; | ||||
text[len] = '\0'; | text[len] = '\0'; | ||||
match(text); | |||||
match(); | |||||
break; | break; | ||||
case XK_End: | case XK_End: | ||||
while(next) { | while(next) { | ||||
@@ -373,24 +331,22 @@ kpress(XKeyEvent *e) { | |||||
dinput(); | dinput(); | ||||
break; | break; | ||||
} | } | ||||
drawmenu(); | |||||
drawbar(); | |||||
} | } | ||||
void | void | ||||
match(char *pattern) { | |||||
unsigned int plen; | |||||
match(void) { | |||||
unsigned int len; | |||||
Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend; | Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend; | ||||
if(!pattern) | |||||
return; | |||||
plen = strlen(pattern); | |||||
len = strlen(text); | |||||
item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL; | item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL; | ||||
for(i = allitems; i; i = i->next) | for(i = allitems; i; i = i->next) | ||||
if(!fstrncmp(pattern, i->text, plen + 1)) | |||||
if(!fstrncmp(text, i->text, len + 1)) | |||||
appenditem(i, &lexact, &exactend); | appenditem(i, &lexact, &exactend); | ||||
else if(!fstrncmp(pattern, i->text, plen)) | |||||
else if(!fstrncmp(text, i->text, len)) | |||||
appenditem(i, &lprefix, &prefixend); | appenditem(i, &lprefix, &prefixend); | ||||
else if(fstrstr(i->text, pattern)) | |||||
else if(fstrstr(i->text, text)) | |||||
appenditem(i, &lsubstr, &substrend); | appenditem(i, &lsubstr, &substrend); | ||||
if(lexact) { | if(lexact) { | ||||
item = lexact; | item = lexact; | ||||
@@ -444,103 +400,6 @@ readstdin(void) { | |||||
} | } | ||||
} | } | ||||
void | |||||
run(void) { | |||||
XEvent ev; | |||||
/* main event loop */ | |||||
XSync(dpy, False); | |||||
while(!XNextEvent(dpy, &ev)) | |||||
switch(ev.type) { | |||||
case KeyPress: | |||||
kpress(&ev.xkey); | |||||
break; | |||||
case Expose: | |||||
if(ev.xexpose.count == 0) | |||||
drawmenu(); | |||||
break; | |||||
case VisibilityNotify: | |||||
if(ev.xvisibility.state != VisibilityUnobscured) | |||||
XRaiseWindow(dpy, win); | |||||
break; | |||||
} | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
void | |||||
setup(void) { | |||||
int i, j, x, y; | |||||
#if XINERAMA | |||||
int n; | |||||
XineramaScreenInfo *info = NULL; | |||||
#endif | |||||
XModifierKeymap *modmap; | |||||
XSetWindowAttributes wa; | |||||
/* init modifier map */ | |||||
modmap = XGetModifierMapping(dpy); | |||||
for(i = 0; i < 8; i++) | |||||
for(j = 0; j < modmap->max_keypermod; j++) { | |||||
if(modmap->modifiermap[i * modmap->max_keypermod + j] | |||||
== XKeysymToKeycode(dpy, XK_Num_Lock)) | |||||
numlockmask = (1 << i); | |||||
} | |||||
XFreeModifiermap(modmap); | |||||
dc.dpy = dpy; | |||||
normcol[ColBG] = getcolor(&dc, normbgcolor); | |||||
normcol[ColFG] = getcolor(&dc, normfgcolor); | |||||
selcol[ColBG] = getcolor(&dc, selbgcolor); | |||||
selcol[ColFG] = getcolor(&dc, selfgcolor); | |||||
initfont(&dc, font); | |||||
/* menu window */ | |||||
wa.override_redirect = True; | |||||
wa.background_pixmap = ParentRelative; | |||||
wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; | |||||
/* menu window geometry */ | |||||
mh = (dc.font.height + 2) * (lines + 1); | |||||
#if XINERAMA | |||||
if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) { | |||||
i = 0; | |||||
if(n > 1) { | |||||
int di; | |||||
unsigned int dui; | |||||
Window dummy; | |||||
if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui)) | |||||
for(i = 0; i < n; i++) | |||||
if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) | |||||
break; | |||||
} | |||||
x = info[i].x_org; | |||||
y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh; | |||||
mw = info[i].width; | |||||
XFree(info); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
x = 0; | |||||
y = topbar ? 0 : mh - DisplayHeight(dpy, screen); | |||||
mw = DisplayWidth(dpy, screen); | |||||
} | |||||
win = XCreateWindow(dpy, root, x, y, mw, mh, 0, | |||||
DefaultDepth(dpy, screen), CopyFromParent, | |||||
DefaultVisual(dpy, screen), | |||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | |||||
setupdraw(&dc, win); | |||||
if(maxname) | |||||
cmdw = MIN(textw(&dc, maxname), mw / 3); | |||||
if(prompt) | |||||
promptw = MIN(textw(&dc, prompt), mw / 5); | |||||
text[0] = '\0'; | |||||
match(text); | |||||
XMapRaised(dpy, win); | |||||
} | |||||
int | int | ||||
main(int argc, char *argv[]) { | main(int argc, char *argv[]) { | ||||
unsigned int i; | unsigned int i; | ||||
@@ -600,7 +459,10 @@ main(int argc, char *argv[]) { | |||||
readstdin(); | readstdin(); | ||||
grabkeyboard(); | grabkeyboard(); | ||||
setup(); | |||||
setup(lines); | |||||
if(maxname) | |||||
cmdw = MIN(textw(&dc, maxname), mw / 3); | |||||
match(); | |||||
run(); | run(); | ||||
return 0; | return 0; | ||||
} | } |
@@ -0,0 +1,30 @@ | |||||
#include <X11/Xlib.h> | |||||
#include <draw.h> | |||||
#include "config.h" | |||||
/* macros */ | |||||
#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)) | |||||
#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80)) | |||||
/* forward declarations */ | |||||
void drawbar(void); | |||||
void grabkeyboard(void); | |||||
void kpress(XKeyEvent *e); | |||||
void run(void); | |||||
void setup(unsigned int lines); | |||||
/* variables */ | |||||
extern char *prompt; | |||||
extern char text[4096]; | |||||
extern int promptw; | |||||
extern int screen; | |||||
extern unsigned int numlockmask; | |||||
extern unsigned int mw, mh; | |||||
extern unsigned long normcol[ColLast]; | |||||
extern unsigned long selcol[ColLast]; | |||||
extern Bool topbar; | |||||
extern DC dc; | |||||
extern Display *dpy; | |||||
extern Window win, root; |