fixed bugs, no more config.h, updated manpage, new libdraw
This commit is contained in:
		
							parent
							
								
									a3606ecb0e
								
							
						
					
					
						commit
						a7aee433cc
					
				
							
								
								
									
										24
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Makefile
									
									
									
									
									
								
							| @ -3,9 +3,6 @@ | ||||
| 
 | ||||
| include config.mk | ||||
| 
 | ||||
| SRC = dmenu.c | ||||
| OBJ = ${SRC:.c=.o} | ||||
| 
 | ||||
| all: options dmenu | ||||
| 
 | ||||
| options: | ||||
| @ -14,34 +11,28 @@ options: | ||||
| 	@echo "LDFLAGS  = ${LDFLAGS}" | ||||
| 	@echo "CC       = ${CC}" | ||||
| 
 | ||||
| .c.o: | ||||
| dmenu.o: dmenu.c config.mk | ||||
| 	@echo CC $< | ||||
| 	@${CC} -c ${CFLAGS} $< | ||||
| 
 | ||||
| ${OBJ}: config.h config.mk | ||||
| 
 | ||||
| config.h: | ||||
| 	@echo creating $@ from config.def.h | ||||
| 	@cp config.def.h $@ | ||||
| 
 | ||||
| dmenu: ${OBJ} | ||||
| dmenu: dmenu.o | ||||
| 	@echo CC -o $@ | ||||
| 	@${CC} -o $@ $+ ${LDFLAGS} | ||||
| 
 | ||||
| clean: | ||||
| 	@echo cleaning | ||||
| 	@rm -f dmenu ${OBJ} dmenu-${VERSION}.tar.gz | ||||
| 	@rm -f dmenu dmenu.o dmenu-${VERSION}.tar.gz | ||||
| 
 | ||||
| dist: clean | ||||
| 	@echo creating dist tarball | ||||
| 	@mkdir -p dmenu-${VERSION} | ||||
| 	@cp -R LICENSE Makefile README config.mk dmenu.1 config.def.h dmenu_path dmenu_run ${SRC} dmenu-${VERSION} | ||||
| 	@cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.c dmenu_path dmenu_run dmenu-${VERSION} | ||||
| 	@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} | ||||
| 	@gzip dmenu-${VERSION}.tar | ||||
| 	@rm -rf dmenu-${VERSION} | ||||
| 
 | ||||
| install: all | ||||
| 	@echo installing executable file to ${DESTDIR}${PREFIX}/bin | ||||
| 	@echo installing executables to ${DESTDIR}${PREFIX}/bin | ||||
| 	@mkdir -p ${DESTDIR}${PREFIX}/bin | ||||
| 	@cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin | ||||
| 	@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu | ||||
| @ -53,8 +44,9 @@ install: all | ||||
| 	@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1 | ||||
| 
 | ||||
| uninstall: | ||||
| 	@echo removing executable file from ${DESTDIR}${PREFIX}/bin | ||||
| 	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu ${DESTDIR}${PREFIX}/bin/dmenu_path | ||||
| 	@echo removing executables from ${DESTDIR}${PREFIX}/bin | ||||
| 	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu | ||||
| 	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path | ||||
| 	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run | ||||
| 	@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 | ||||
| 	@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1 | ||||
|  | ||||
							
								
								
									
										11
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README
									
									
									
									
									
								
							| @ -1,21 +1,22 @@ | ||||
| dmenu - dynamic menu | ||||
| ==================== | ||||
| dmenu is a generic and efficient menu for X.  | ||||
| dmenu is an efficient dynamic menu for X. | ||||
| 
 | ||||
| 
 | ||||
| Requirements | ||||
| ------------ | ||||
| In order to build dmenu you need the Xlib header files. | ||||
| 
 | ||||
| You also need libdraw, available from http://hg.suckless.org/libdraw | ||||
| 
 | ||||
| 
 | ||||
| Installation | ||||
| ------------ | ||||
| Edit config.mk to match your local setup (dmenu is installed into the | ||||
| /usr/local namespace by default). | ||||
| Edit config.mk to match your local setup (dmenu is installed into | ||||
| the /usr/local namespace by default). | ||||
| 
 | ||||
| Afterwards enter the following command to build and install dmenu (if | ||||
| necessary as root): | ||||
| Afterwards enter the following command to build and install dmenu | ||||
| (if necessary as root): | ||||
| 
 | ||||
|     make clean install | ||||
| 
 | ||||
|  | ||||
| @ -1,8 +0,0 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| 
 | ||||
| /* appearance */ | ||||
| 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"; | ||||
							
								
								
									
										17
									
								
								config.mk
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								config.mk
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| # dmenu version
 | ||||
| VERSION = 4.1.1 | ||||
| VERSION = 4.2 | ||||
| 
 | ||||
| # Customize below to fit your system
 | ||||
| 
 | ||||
| @ -7,25 +7,22 @@ VERSION = 4.1.1 | ||||
| PREFIX = /usr/local | ||||
| MANPREFIX = ${PREFIX}/share/man | ||||
| 
 | ||||
| # Xlib
 | ||||
| X11INC = /usr/X11R6/include | ||||
| X11LIB = /usr/X11R6/lib | ||||
| 
 | ||||
| # Xinerama, comment if you don't want it
 | ||||
| XINERAMALIBS = -L${X11LIB} -lXinerama | ||||
| XINERAMALIBS  = -lXinerama | ||||
| XINERAMAFLAGS = -DXINERAMA | ||||
| 
 | ||||
| # includes and libs
 | ||||
| INCS = -I. -I/usr/include -I${X11INC} | ||||
| LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -ldraw ${XINERAMALIBS} | ||||
| INCS = -I${X11INC} | ||||
| LIBS = -L${X11LIB} -ldraw -lX11 ${XINERAMALIBS} | ||||
| 
 | ||||
| # flags
 | ||||
| CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} | ||||
| CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | ||||
| LDFLAGS = -s ${LIBS} | ||||
| 
 | ||||
| # Solaris
 | ||||
| #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
 | ||||
| #LDFLAGS = ${LIBS}
 | ||||
| CFLAGS   = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | ||||
| LDFLAGS  = -s ${LIBS} | ||||
| 
 | ||||
| # compiler and linker
 | ||||
| CC = cc | ||||
|  | ||||
							
								
								
									
										98
									
								
								dmenu.1
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								dmenu.1
									
									
									
									
									
								
							| @ -5,81 +5,76 @@ dmenu \- dynamic menu | ||||
| .B dmenu | ||||
| .RB [ \-b ] | ||||
| .RB [ \-i ] | ||||
| .RB [ \-l " <lines>]" | ||||
| .RB [ \-p " <prompt>]" | ||||
| .RB [ \-fn " <font>]" | ||||
| .RB [ \-nb " <color>]" | ||||
| .RB [ \-nf " <color>]" | ||||
| .RB [ \-sb " <color>]" | ||||
| .RB [ \-sf " <color>]" | ||||
| .RB [ \-l | ||||
| .IR lines ] | ||||
| .RB [ \-p | ||||
| .IR prompt ] | ||||
| .RB [ \-fn | ||||
| .IR font ] | ||||
| .RB [ \-nb | ||||
| .IR color ] | ||||
| .RB [ \-nf | ||||
| .IR color ] | ||||
| .RB [ \-sb | ||||
| .IR color ] | ||||
| .RB [ \-sf | ||||
| .IR color ] | ||||
| .RB [ \-v ] | ||||
| 
 | ||||
| .B dmenu_run | ||||
| .RB [ \-b ] | ||||
| .RB [ \-i ] | ||||
| .RB [ \-l " <lines>]" | ||||
| .RB [ \-p " <prompt>]" | ||||
| .RB [ \-fn " <font>]" | ||||
| .RB [ \-nb " <color>]" | ||||
| .RB [ \-nf " <color>]" | ||||
| .RB [ \-sb " <color>]" | ||||
| .RB [ \-sf " <color>]" | ||||
| .RB [ \-v ] | ||||
| 
 | ||||
| .P | ||||
| .BR dmenu_run " ..." | ||||
| .P | ||||
| .B dmenu_path | ||||
| .SH DESCRIPTION | ||||
| .SS Overview | ||||
| .B dmenu | ||||
| is a generic menu for X, originally designed for | ||||
| is a dynamic menu for X, originally designed for | ||||
| .BR dwm (1). | ||||
| It manages huge amounts (10000 and more) of user defined menu items efficiently. | ||||
| It manages huge numbers of user-defined menu items efficiently. | ||||
| .P | ||||
| 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, | ||||
| their choice is printed to standard output and dmenu terminates. | ||||
| .P | ||||
| .B dmenu_run | ||||
| is a dmenu script which lists programs in the user's PATH and executes | ||||
| the selected item. | ||||
| is a dmenu script used by dwm which lists programs in the user's PATH and | ||||
| executes the selected item. | ||||
| .P | ||||
| .B dmenu_path | ||||
| is a script used by | ||||
| .I dmenu_run | ||||
| to find and cache a list of programs. | ||||
| .SS Options | ||||
| is a script used by dmenu_run to find and cache a list of programs. | ||||
| .SH OPTIONS | ||||
| .TP | ||||
| .B \-b | ||||
| dmenu appears at the bottom of the screen. | ||||
| .TP | ||||
| .B \-i | ||||
| dmenu matches menu entries case insensitively. | ||||
| dmenu matches menu items case insensitively. | ||||
| .TP | ||||
| .B \-l <lines> | ||||
| .BI \-l " lines" | ||||
| dmenu lists items vertically, with the given number of lines. | ||||
| .TP | ||||
| .B \-p <prompt> | ||||
| sets the prompt to be displayed to the left of the input area. | ||||
| .BI \-p " prompt" | ||||
| defines the prompt to be displayed to the left of the input area. | ||||
| .TP | ||||
| .B \-fn <font> | ||||
| sets the font. | ||||
| .BI \-fn " font" | ||||
| defines the font set used. | ||||
| .TP | ||||
| .B \-nb <color> | ||||
| sets the background color (#RGB, #RRGGBB, and color names are supported). | ||||
| .BI \-nb " color" | ||||
| defines the normal background color. | ||||
| .IR #RGB , | ||||
| .IR #RRGGBB , | ||||
| and color names are supported. | ||||
| .TP | ||||
| .B \-nf <color> | ||||
| sets the foreground color (#RGB, #RRGGBB, and color names are supported). | ||||
| .BI \-nf " color" | ||||
| defines the normal foreground color. | ||||
| .TP | ||||
| .B \-sb <color> | ||||
| sets the background color of selected items (#RGB, #RRGGBB, and color names are | ||||
| supported). | ||||
| .BI \-sb " color" | ||||
| defines the selected background color. | ||||
| .TP | ||||
| .B \-sf <color> | ||||
| sets the foreground color of selected items (#RGB, #RRGGBB, and color names are | ||||
| supported). | ||||
| .BI \-sf " color" | ||||
| defines the selected foreground color. | ||||
| .TP | ||||
| .B \-v | ||||
| prints version information to standard output, then exits. | ||||
| .SH USAGE | ||||
| 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, | ||||
| their choice is printed to standard output and dmenu terminates. | ||||
| .P | ||||
| dmenu is completely controlled by the keyboard.  Besides standard Unix line | ||||
| editing and item selection (Up/Down/Left/Right, PageUp/PageDown, Home/End), the | ||||
| following keys are recognized: | ||||
| @ -96,10 +91,9 @@ Confirm input.  Prints the input text to standard output and exits, returning | ||||
| success. | ||||
| .TP | ||||
| .B Escape (Control\-c) | ||||
| Quit without selecting an item, returning failure. | ||||
| Exit without selecting an item, returning failure. | ||||
| .TP | ||||
| .B Control\-y | ||||
| Paste the current X selection into the input field. | ||||
| .SH SEE ALSO | ||||
| .BR dwm (1), | ||||
| .BR wmii (1). | ||||
| .BR dwm (1) | ||||
|  | ||||
							
								
								
									
										222
									
								
								dmenu.c
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								dmenu.c
									
									
									
									
									
								
							| @ -1,11 +1,9 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #include <ctype.h> | ||||
| #include <locale.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <X11/keysym.h> | ||||
| #include <X11/Xatom.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/Xutil.h> | ||||
| @ -13,7 +11,6 @@ | ||||
| #include <X11/extensions/Xinerama.h> | ||||
| #endif | ||||
| #include <draw.h> | ||||
| #include "config.h" | ||||
| 
 | ||||
| #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)) | ||||
| @ -38,25 +35,27 @@ static void grabkeyboard(void); | ||||
| static void insert(const char *s, ssize_t n); | ||||
| static void keypress(XKeyEvent *e); | ||||
| static void match(void); | ||||
| static void paste(Atom atom); | ||||
| static void paste(void); | ||||
| static void readstdin(void); | ||||
| static void run(void); | ||||
| static void setup(void); | ||||
| static void usage(void); | ||||
| 
 | ||||
| static char *prompt; | ||||
| static char text[4096]; | ||||
| static int screen; | ||||
| static size_t cursor = 0; | ||||
| static const char *prompt = NULL; | ||||
| static const char *normbgcolor = "#cccccc"; | ||||
| static const char *normfgcolor = "#000000"; | ||||
| static const char *selbgcolor  = "#0066ff"; | ||||
| static const char *selfgcolor  = "#ffffff"; | ||||
| static unsigned int inputw = 0; | ||||
| static unsigned int lines = 0; | ||||
| static unsigned int mw, mh; | ||||
| static unsigned int promptw = 0; | ||||
| static unsigned long normcol[ColLast]; | ||||
| static unsigned long selcol[ColLast]; | ||||
| static Atom utf8; | ||||
| static Bool topbar = True; | ||||
| static DC dc; | ||||
| static DC *dc; | ||||
| static Item *allitems, *matches; | ||||
| static Item *curr, *prev, *next, *sel; | ||||
| static Window root, win; | ||||
| @ -67,7 +66,7 @@ static void (*calcoffsets)(void) = calcoffsetsh; | ||||
| 
 | ||||
| void | ||||
| appenditem(Item *item, Item **list, Item **last) { | ||||
| 	if(!(*last)) | ||||
| 	if(!*last) | ||||
| 		*list = item; | ||||
| 	else | ||||
| 		(*last)->right = item; | ||||
| @ -80,12 +79,12 @@ void | ||||
| calcoffsetsh(void) { | ||||
| 	unsigned int w, x; | ||||
| 
 | ||||
| 	w = promptw + inputw + textw(&dc, "<") + textw(&dc, ">"); | ||||
| 	w = (prompt ? textw(dc, prompt) : 0) + inputw + 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; | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
| @ -96,101 +95,75 @@ calcoffsetsv(void) { | ||||
| 	next = prev = curr; | ||||
| 	for(i = 0; i < lines && next; i++) | ||||
| 		next = next->right; | ||||
| 	mh = (dc.font.height + 2) * (i + 1); | ||||
| 	for(i = 0; i < lines && prev && prev->left; i++) | ||||
| 		prev = prev->left; | ||||
| } | ||||
| 
 | ||||
| char * | ||||
| cistrstr(const char *s, const char *sub) { | ||||
| 	int c, csub; | ||||
| 	unsigned int len; | ||||
| 	size_t len; | ||||
| 
 | ||||
| 	if(!sub) | ||||
| 		return (char *)s; | ||||
| 	if((c = tolower(*sub++)) != '\0') { | ||||
| 		len = strlen(sub); | ||||
| 		do { | ||||
| 			do { | ||||
| 				if((csub = *s++) == '\0') | ||||
| 					return NULL; | ||||
| 			} | ||||
| 			while(tolower(csub) != c); | ||||
| 		} | ||||
| 		while(strncasecmp(s, sub, len) != 0); | ||||
| 		s--; | ||||
| 	} | ||||
| 	return (char *)s; | ||||
| 	for(len = strlen(sub); *s; s++) | ||||
| 		if(!strncasecmp(s, sub, len)) | ||||
| 			return (char *)s; | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| drawmenu(void) { | ||||
| 	dc.x = 0; | ||||
| 	dc.y = 0; | ||||
| 	dc.w = mw; | ||||
| 	dc.h = mh; | ||||
| 	drawbox(&dc, normcol); | ||||
| 	dc.h = dc.font.height + 2; | ||||
| 	dc.y = topbar ? 0 : mh - dc.h; | ||||
| 	dc->x = 0; | ||||
| 	dc->y = 0; | ||||
| 	drawrect(dc, 0, 0, mw, mh, BG(dc, normcol)); | ||||
| 	dc->h = dc->font.height + 2; | ||||
| 	dc->y = topbar ? 0 : mh - dc->h; | ||||
| 	/* print prompt? */ | ||||
| 	if(prompt) { | ||||
| 		dc.w = promptw; | ||||
| 		drawbox(&dc, selcol); | ||||
| 		drawtext(&dc, prompt, selcol); | ||||
| 		dc.x += dc.w; | ||||
| 		dc->w = textw(dc, prompt); | ||||
| 		drawtext(dc, prompt, selcol); | ||||
| 		dc->x = dc->w; | ||||
| 	} | ||||
| 	dc.w = mw - dc.x; | ||||
| 	dc->w = mw - dc->x; | ||||
| 	/* print input area */ | ||||
| 	if(matches && lines == 0 && textw(&dc, text) <= inputw) | ||||
| 		dc.w = inputw; | ||||
| 	drawtext(&dc, text, normcol); | ||||
| 	drawline(&dc, textnw(&dc, text, cursor) + dc.h/2 - 2, 2, 1, dc.h-4, normcol); | ||||
| 	if(matches && lines == 0 && textw(dc, text) <= inputw) | ||||
| 		dc->w = inputw; | ||||
| 	drawtext(dc, text, normcol); | ||||
| 	drawrect(dc, textnw(dc, text, cursor) + dc->h/2 - 2, 2, 1, dc->h - 4, FG(dc, normcol)); | ||||
| 	if(lines > 0) | ||||
| 		drawmenuv(); | ||||
| 	else if(curr && (dc.w == inputw || curr->next)) | ||||
| 	else if(curr && (dc->w == inputw || curr->next)) | ||||
| 		drawmenuh(); | ||||
| 	commitdraw(&dc, win); | ||||
| 	commitdraw(dc, win); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| drawmenuh(void) { | ||||
| 	Item *item; | ||||
| 
 | ||||
| 	dc.x += inputw; | ||||
| 	dc.w = textw(&dc, "<"); | ||||
| 	dc->x += inputw; | ||||
| 	dc->w = textw(dc, "<"); | ||||
| 	if(curr->left) | ||||
| 		drawtext(&dc, "<", normcol); | ||||
| 	dc.x += dc.w; | ||||
| 		drawtext(dc, "<", normcol); | ||||
| 	for(item = curr; item != next; item = item->right) { | ||||
| 		dc.w = MIN(textw(&dc, item->text), mw / 3); | ||||
| 		if(item == sel) | ||||
| 			drawbox(&dc, selcol); | ||||
| 		drawtext(&dc, item->text, (item == sel) ? selcol : normcol); | ||||
| 		dc.x += dc.w; | ||||
| 		dc->x += dc->w; | ||||
| 		dc->w = MIN(textw(dc, item->text), mw / 3); | ||||
| 		drawtext(dc, item->text, (item == sel) ? selcol : normcol); | ||||
| 	} | ||||
| 	dc.w = textw(&dc, ">"); | ||||
| 	dc.x = mw - dc.w; | ||||
| 	dc->w = textw(dc, ">"); | ||||
| 	dc->x = mw - dc->w; | ||||
| 	if(next) | ||||
| 		drawtext(&dc, ">", normcol); | ||||
| 		drawtext(dc, ">", normcol); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| drawmenuv(void) { | ||||
| 	Item *item; | ||||
| 	XWindowAttributes wa; | ||||
| 
 | ||||
| 	dc.y = topbar ? dc.h : 0; | ||||
| 	dc.w = mw - dc.x; | ||||
| 	dc->y = topbar ? dc->h : 0; | ||||
| 	dc->w = mw - dc->x; | ||||
| 	for(item = curr; item != next; item = item->right) { | ||||
| 		if(item == sel) | ||||
| 			drawbox(&dc, selcol); | ||||
| 		drawtext(&dc, item->text, (item == sel) ? selcol : normcol); | ||||
| 		dc.y += dc.h; | ||||
| 		drawtext(dc, item->text, (item == sel) ? selcol : normcol); | ||||
| 		dc->y += dc->h; | ||||
| 	} | ||||
| 	if(!XGetWindowAttributes(dc.dpy, win, &wa)) | ||||
| 		eprintf("cannot get window attributes\n"); | ||||
| 	if(wa.height != mh) | ||||
| 		XMoveResizeWindow(dc.dpy, win, wa.x, wa.y + (topbar ? 0 : wa.height - mh), mw, mh); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| @ -198,7 +171,7 @@ grabkeyboard(void) { | ||||
| 	int i; | ||||
| 
 | ||||
| 	for(i = 0; i < 1000; i++) { | ||||
| 		if(!XGrabKeyboard(dc.dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)) | ||||
| 		if(!XGrabKeyboard(dc->dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)) | ||||
| 			return; | ||||
| 		usleep(1000); | ||||
| 	} | ||||
| @ -254,6 +227,7 @@ keypress(XKeyEvent *e) { | ||||
| 			break; | ||||
| 		case XK_k:  /* delete right */ | ||||
| 			text[cursor] = '\0'; | ||||
| 			match(); | ||||
| 			break; | ||||
| 		case XK_n: | ||||
| 			ksym = XK_Down; | ||||
| @ -270,10 +244,10 @@ keypress(XKeyEvent *e) { | ||||
| 			n = 0; | ||||
| 			while(cursor - n++ > 0 && text[cursor - n] == ' '); | ||||
| 			while(cursor - n++ > 0 && text[cursor - n] != ' '); | ||||
| 			insert(NULL, -(--n)); | ||||
| 			insert(NULL, 1-n); | ||||
| 			break; | ||||
| 		case XK_y:  /* paste selection */ | ||||
| 			XConvertSelection(dc.dpy, XA_PRIMARY, utf8, None, win, CurrentTime); | ||||
| 			XConvertSelection(dc->dpy, XA_PRIMARY, utf8, None, win, CurrentTime); | ||||
| 			/* causes SelectionNotify event */ | ||||
| 			return; | ||||
| 		} | ||||
| @ -348,7 +322,7 @@ keypress(XKeyEvent *e) { | ||||
| 		break; | ||||
| 	case XK_Return: | ||||
| 	case XK_KP_Enter: | ||||
| 		fputs(((e->state & ShiftMask) || sel) ? sel->text : text, stdout); | ||||
| 		fputs((sel && !(e->state & ShiftMask)) ? sel->text : text, stdout); | ||||
| 		fflush(stdout); | ||||
| 		exit(EXIT_SUCCESS); | ||||
| 	case XK_Right: | ||||
| @ -418,15 +392,14 @@ match(void) { | ||||
| } | ||||
| 
 | ||||
| void | ||||
| paste(Atom atom) | ||||
| { | ||||
| paste(void) { | ||||
| 	char *p, *q; | ||||
| 	int di; | ||||
| 	unsigned long dl; | ||||
| 	Atom da; | ||||
| 
 | ||||
| 	XGetWindowProperty(dc.dpy, win, atom, 0, sizeof text - cursor, True, | ||||
| 			utf8, &da, &di, &dl, &dl, (unsigned char **)&p); | ||||
| 	XGetWindowProperty(dc->dpy, win, utf8, 0, sizeof text - cursor, True, | ||||
| 	                   utf8, &da, &di, &dl, &dl, (unsigned char **)&p); | ||||
| 	insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p)); | ||||
| 	XFree(p); | ||||
| 	drawmenu(); | ||||
| @ -434,24 +407,22 @@ paste(Atom atom) | ||||
| 
 | ||||
| void | ||||
| readstdin(void) { | ||||
| 	char buf[sizeof text]; | ||||
| 	size_t len; | ||||
| 	char buf[sizeof text], *p; | ||||
| 	Item *item, *new; | ||||
| 
 | ||||
| 	allitems = NULL; | ||||
| 	for(item = NULL; fgets(buf, sizeof buf, stdin); item = new) { | ||||
| 		len = strlen(buf); | ||||
| 		if(buf[len-1] == '\n') | ||||
| 			buf[--len] = '\0'; | ||||
| 		if((p = strchr(buf, '\n'))) | ||||
| 			*p = '\0'; | ||||
| 		if(!(new = malloc(sizeof *new))) | ||||
| 			eprintf("cannot malloc %u bytes\n", sizeof *new); | ||||
| 		if(!(new->text = strdup(buf))) | ||||
| 			eprintf("cannot strdup %u bytes\n", len); | ||||
| 		inputw = MAX(inputw, textw(&dc, new->text)); | ||||
| 			eprintf("cannot strdup %u bytes\n", strlen(buf)); | ||||
| 		inputw = MAX(inputw, textw(dc, new->text)); | ||||
| 		new->next = new->left = new->right = NULL; | ||||
| 		if(item) | ||||
| 			item->next = new; | ||||
| 		else  | ||||
| 		else | ||||
| 			allitems = new; | ||||
| 	} | ||||
| } | ||||
| @ -460,7 +431,7 @@ void | ||||
| run(void) { | ||||
| 	XEvent ev; | ||||
| 
 | ||||
| 	while(!XNextEvent(dc.dpy, &ev)) | ||||
| 	while(!XNextEvent(dc->dpy, &ev)) | ||||
| 		switch(ev.type) { | ||||
| 		case Expose: | ||||
| 			if(ev.xexpose.count == 0) | ||||
| @ -470,39 +441,43 @@ run(void) { | ||||
| 			keypress(&ev.xkey); | ||||
| 			break; | ||||
| 		case SelectionNotify: | ||||
| 			if(ev.xselection.property != None) | ||||
| 				paste(ev.xselection.property); | ||||
| 			if(ev.xselection.property == utf8) | ||||
| 				paste(); | ||||
| 			break; | ||||
| 		case VisibilityNotify: | ||||
| 			if(ev.xvisibility.state != VisibilityUnobscured) | ||||
| 				XRaiseWindow(dc.dpy, win); | ||||
| 				XRaiseWindow(dc->dpy, win); | ||||
| 			break; | ||||
| 		} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| setup(void) { | ||||
| 	int x, y; | ||||
| 	int x, y, screen; | ||||
| 	XSetWindowAttributes wa; | ||||
| #ifdef XINERAMA | ||||
| 	int i, n; | ||||
| 	int n; | ||||
| 	XineramaScreenInfo *info; | ||||
| #endif | ||||
| 	XSetWindowAttributes wa; | ||||
| 
 | ||||
| 	normcol[ColBG] = getcolor(&dc, normbgcolor); | ||||
| 	normcol[ColFG] = getcolor(&dc, normfgcolor); | ||||
| 	selcol[ColBG] = getcolor(&dc, selbgcolor); | ||||
| 	selcol[ColFG] = getcolor(&dc, selfgcolor); | ||||
| 	screen = DefaultScreen(dc->dpy); | ||||
| 	root = RootWindow(dc->dpy, screen); | ||||
| 	utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False); | ||||
| 
 | ||||
| 	normcol[ColBG] = getcolor(dc, normbgcolor); | ||||
| 	normcol[ColFG] = getcolor(dc, normfgcolor); | ||||
| 	selcol[ColBG] = getcolor(dc, selbgcolor); | ||||
| 	selcol[ColFG] = getcolor(dc, selfgcolor); | ||||
| 
 | ||||
| 	/* input window geometry */ | ||||
| 	mh = (dc.font.height + 2) * (lines + 1); | ||||
| 	mh = (dc->font.height + 2) * (lines + 1); | ||||
| #ifdef XINERAMA | ||||
| 	if((info = XineramaQueryScreens(dc.dpy, &n))) { | ||||
| 		int di; | ||||
| 	if((info = XineramaQueryScreens(dc->dpy, &n))) { | ||||
| 		int i, di; | ||||
| 		unsigned int du; | ||||
| 		Window dw; | ||||
| 
 | ||||
| 		XQueryPointer(dc.dpy, root, &dw, &dw, &x, &y, &di, &di, &du); | ||||
| 		XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du); | ||||
| 		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; | ||||
| @ -515,31 +490,30 @@ setup(void) { | ||||
| #endif | ||||
| 	{ | ||||
| 		x = 0; | ||||
| 		y = topbar ? 0 : DisplayHeight(dc.dpy, screen) - mh; | ||||
| 		mw = DisplayWidth(dc.dpy, screen); | ||||
| 		y = topbar ? 0 : DisplayHeight(dc->dpy, screen) - mh; | ||||
| 		mw = DisplayWidth(dc->dpy, screen); | ||||
| 	} | ||||
| 
 | ||||
| 	/* input window */ | ||||
| 	wa.override_redirect = True; | ||||
| 	wa.background_pixmap = ParentRelative; | ||||
| 	wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; | ||||
| 	win = XCreateWindow(dc.dpy, root, x, y, mw, mh, 0, | ||||
| 			DefaultDepth(dc.dpy, screen), CopyFromParent, | ||||
| 			DefaultVisual(dc.dpy, screen), | ||||
| 	win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0, | ||||
| 			DefaultDepth(dc->dpy, screen), CopyFromParent, | ||||
| 			DefaultVisual(dc->dpy, screen), | ||||
| 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); | ||||
| 
 | ||||
| 	match(); | ||||
| 	grabkeyboard(); | ||||
| 	setupdraw(&dc, win); | ||||
| 	inputw = MIN(inputw, mw / 3); | ||||
| 	utf8 = XInternAtom(dc.dpy, "UTF8_STRING", False); | ||||
| 	XMapRaised(dc.dpy, win); | ||||
| 	setcanvas(dc, win, mw, mh); | ||||
| 	inputw = MIN(inputw, mw/3); | ||||
| 	XMapRaised(dc->dpy, win); | ||||
| 	match(); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| usage(void) { | ||||
| 	fputs("usage: dmenu [-b] [-i] [-l <lines>] [-p <prompt>] [-fn <font>] [-nb <color>]\n" | ||||
| 		      "             [-nf <color>] [-sb <color>] [-sf <color>] [-v]\n", stderr); | ||||
| 	fputs("usage: dmenu [-b] [-i] [-l lines] [-p prompt] [-fn font] [-nb color]\n" | ||||
| 	      "             [-nf color] [-sb color] [-sf color] [-v]\n", stderr); | ||||
| 	exit(EXIT_FAILURE); | ||||
| } | ||||
| 
 | ||||
| @ -548,8 +522,10 @@ main(int argc, char *argv[]) { | ||||
| 	int i; | ||||
| 
 | ||||
| 	progname = "dmenu"; | ||||
| 	dc = initdraw(); | ||||
| 
 | ||||
| 	for(i = 1; i < argc; i++) | ||||
| 		/* 1-arg flags */ | ||||
| 		/* single flags */ | ||||
| 		if(!strcmp(argv[i], "-v")) { | ||||
| 			fputs("dmenu-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n", stdout); | ||||
| 			exit(EXIT_SUCCESS); | ||||
| @ -562,17 +538,15 @@ main(int argc, char *argv[]) { | ||||
| 		} | ||||
| 		else if(i == argc-1) | ||||
| 			usage(); | ||||
| 		/* 2-arg flags */ | ||||
| 		/* double flags */ | ||||
| 		else if(!strcmp(argv[i], "-l")) { | ||||
| 			if((lines = atoi(argv[++i])) > 0) | ||||
| 				calcoffsets = calcoffsetsv; | ||||
| 		} | ||||
| 		else if(!strcmp(argv[i], "-p")) { | ||||
| 		else if(!strcmp(argv[i], "-p")) | ||||
| 			prompt = argv[++i]; | ||||
| 			promptw = MIN(textw(&dc, prompt), mw/5); | ||||
| 		} | ||||
| 		else if(!strcmp(argv[i], "-fn")) | ||||
| 			font = argv[++i]; | ||||
| 			initfont(dc, argv[i++]); | ||||
| 		else if(!strcmp(argv[i], "-nb")) | ||||
| 			normbgcolor = argv[++i]; | ||||
| 		else if(!strcmp(argv[i], "-nf")) | ||||
| @ -584,14 +558,6 @@ main(int argc, char *argv[]) { | ||||
| 		else | ||||
| 			usage(); | ||||
| 
 | ||||
| 	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) | ||||
| 		fputs("dmenu: warning: no locale support\n", stderr); | ||||
| 	if(!(dc.dpy = XOpenDisplay(NULL))) | ||||
| 		eprintf("cannot open display\n"); | ||||
| 	screen = DefaultScreen(dc.dpy); | ||||
| 	root = RootWindow(dc.dpy, screen); | ||||
| 	initfont(&dc, font); | ||||
| 
 | ||||
| 	readstdin(); | ||||
| 	setup(); | ||||
| 	run(); | ||||
|  | ||||
| @ -19,7 +19,7 @@ then | ||||
| 		do | ||||
| 			test -x "$file" && echo "$file" | ||||
| 		done | ||||
| 	done | sort | uniq > "$CACHE".$$ && | ||||
| 	done | sort -u > "$CACHE".$$ && | ||||
| 	mv "$CACHE".$$ "$CACHE" | ||||
| fi | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Connor Lane Smith
						Connor Lane Smith