added dmenu.h, common.c

master
Connor Lane Smith 15 years ago
parent 29e8faed6c
commit 855a566319
  1. 10
      Makefile
  2. 129
      common.c
  3. 11
      config.def.h
  4. 150
      dinput.c
  5. 188
      dmenu.c
  6. 30
      dmenu.h

@ -3,7 +3,7 @@
include config.mk
SRC = dinput.c dmenu.c
SRC = dinput.c dmenu.c common.c
OBJ = ${SRC:.c=.o}
all: options dinput dmenu
@ -24,9 +24,13 @@ config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
.o:
dinput: dinput.o common.o
@echo CC -o $@
@${CC} -o $@ $< ${LDFLAGS}
@${CC} -o $@ $+ ${LDFLAGS}
dmenu: dmenu.o common.o
@echo CC -o $@
@${CC} -o $@ $+ ${LDFLAGS}
clean:
@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. */
/* 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/keysym.h>
#include <X11/Xlib.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 */
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 */
static char *prompt = NULL;
static char text[4096];
static int promptw = 0;
static int screen;
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
cleanup(void) {
@ -53,7 +24,7 @@ cleanup(void) {
}
void
drawinput(void)
drawbar(void)
{
dc.x = 0;
dc.y = 0;
@ -72,19 +43,6 @@ drawinput(void)
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
kpress(XKeyEvent *e) {
char buf[sizeof text];
@ -207,101 +165,7 @@ kpress(XKeyEvent *e) {
while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor]));
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
@ -336,11 +200,13 @@ main(int argc, char *argv[]) {
if(++i < argc) selfgcolor = argv[i];
}
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);
}
else if(!*text)
else if(!*text) {
strncpy(text, argv[i], sizeof text);
cursor = strlen(text);
}
else {
fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
" [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr);
@ -356,7 +222,7 @@ main(int argc, char *argv[]) {
root = RootWindow(dpy, screen);
grabkeyboard();
setup();
setup(0);
run();
return 0;
}

@ -8,16 +8,7 @@
#include <X11/keysym.h>
#include <X11/Xlib.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;
struct Item {
@ -33,41 +24,22 @@ static void calcoffsetsv(void);
static char *cistrstr(const char *s, const char *sub);
static void cleanup(void);
static void dinput(void);
static void drawmenu(void);
static void drawmenuh(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 run(void);
static void setup(void);
#include "config.h"
/* variables */
static char **argp = 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 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 *item = NULL; /* first of pattern matching items */
static Item *sel = NULL;
static Item *next = NULL;
static Item *prev = NULL;
static Item *curr = NULL;
static Window win, root;
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
static char *(*fstrstr)(const char *, const char *) = strstr;
static void (*calcoffsets)(void) = calcoffsetsh;
@ -85,14 +57,13 @@ appenditem(Item *i, Item **list, Item **last) {
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)
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)
break;
}
@ -157,7 +128,7 @@ dinput(void) {
}
void
drawmenu(void) {
drawbar(void) {
dc.x = 0;
dc.y = 0;
dc.w = mw;
@ -188,7 +159,7 @@ drawmenuh(void) {
Item *i;
dc.x += cmdw;
dc.w = spaceitem;
dc.w = textw(&dc, "<");
drawtext(&dc, curr->left ? "<" : NULL, normcol);
dc.x += dc.w;
for(i = curr; i != next; i = i->right) {
@ -196,7 +167,7 @@ drawmenuh(void) {
drawtext(&dc, i->text, (sel == i) ? selcol : normcol);
dc.x += dc.w;
}
dc.w = spaceitem;
dc.w = textw(&dc, ">");
dc.x = mw - dc.w;
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);
}
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
kpress(XKeyEvent *e) {
char buf[sizeof text];
@ -285,7 +243,7 @@ kpress(XKeyEvent *e) {
break;
case XK_u:
text[0] = '\0';
match(text);
match();
break;
case XK_w:
if(len == 0)
@ -294,7 +252,7 @@ kpress(XKeyEvent *e) {
while(i-- > 0 && text[i] == ' ');
while(i-- > 0 && text[i] != ' ');
text[++i] = '\0';
match(text);
match();
break;
}
}
@ -304,7 +262,7 @@ kpress(XKeyEvent *e) {
if(num && !iscntrl((int) buf[0])) {
memcpy(text + len, buf, num + 1);
len += num;
match(text);
match();
}
break;
case XK_BackSpace:
@ -313,7 +271,7 @@ kpress(XKeyEvent *e) {
for(i = 1; len - i > 0 && !IS_UTF8_1ST_CHAR(text[len - i]); i++);
len -= i;
text[len] = '\0';
match(text);
match();
break;
case XK_End:
while(next) {
@ -373,24 +331,22 @@ kpress(XKeyEvent *e) {
dinput();
break;
}
drawmenu();
drawbar();
}
void
match(char *pattern) {
unsigned int plen;
match(void) {
unsigned int len;
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;
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);
else if(!fstrncmp(pattern, i->text, plen))
else if(!fstrncmp(text, i->text, len))
appenditem(i, &lprefix, &prefixend);
else if(fstrstr(i->text, pattern))
else if(fstrstr(i->text, text))
appenditem(i, &lsubstr, &substrend);
if(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
main(int argc, char *argv[]) {
unsigned int i;
@ -600,7 +459,10 @@ main(int argc, char *argv[]) {
readstdin();
grabkeyboard();
setup();
setup(lines);
if(maxname)
cmdw = MIN(textw(&dc, maxname), mw / 3);
match();
run();
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;
Loading…
Cancel
Save