Compare commits

...

104 Commits
1.1 ... 3.1

Author SHA1 Message Date
5a3dfb1c40 removed strip, added -s to LDFLAGs 2007-05-15 13:44:41 +02:00
4042a11e51 applied anydot's dmenu_path caching patch, thank you! 2007-05-14 11:56:41 +02:00
aa2f73fc88 fixed a small bug in dmenu when an empty font is supplied 2007-05-02 15:25:52 +02:00
f189781bbd Added tag 3.0 for changeset 59b3024854db 2007-04-19 09:27:08 +02:00
0e19146d5f making copyright notice more compact 2007-04-13 11:36:44 +02:00
85a151c6a4 next version is 2.9 2007-03-28 08:17:57 +02:00
1fa4fa386a allowing numpad keys as inpyt 2007-03-27 16:52:50 +02:00
e1515a2fdc Added tag 2.8 for changeset dd3d02b07cac 2007-03-07 13:30:57 +01:00
f555908cef attempt to grab the keyboard only 1000 times, not forever. 2007-03-07 11:01:14 +01:00
73120414e2 reverting keyboard grab to root window - invoking several dmenu's now works again... 2007-03-07 10:54:21 +01:00
9911455f5b Wait for an Expose and draw the menu immediately after mapping the window. 2007-03-06 03:24:40 -05:00
2772c51e79 Added tag 2.7 for changeset fbd9e9d63f20 2007-03-05 11:25:18 +01:00
d57c873f10 keyboard grab works on the dmenu window now (not on the root window) - thx for Kris for this hint 2007-03-02 21:48:48 +01:00
724f72142f also, don't set the font all the time 2007-03-02 15:16:36 +01:00
5b8dce15d3 Added tag 2.6 for changeset 775f761a5647 2007-03-01 15:47:54 +01:00
063c3d26e9 useless var declaration prev_nitem 2007-02-27 14:44:21 +01:00
03c2b05bb2 changed Backspace/C-w behavior (now it only removes a single character) 2007-02-26 14:07:19 +01:00
8a066fabd9 if isatty() first read from stdin and then grab the keyboard, otherwise first grab the keyboard and then read from stdin 2007-02-26 11:44:41 +01:00
6c0e05eb0d next is 2.6, but not yet ;) 2007-02-26 10:47:52 +01:00
900d34347b Escape -s in dmenu.1 2007-02-25 16:41:05 -05:00
4d0cc17794 Added tag 2.5 for changeset 041143e9fc54 2007-02-24 15:38:26 +01:00
28b6ea0f67 I also dislike sort -u, I support that each Unix tool does one job and does it right ;) 2007-02-24 15:38:10 +01:00
598d72fba9 removed superfluous externs as well 2007-02-24 14:07:40 +01:00
007be12f2b using the old-style fashion we uses earlier 2007-02-23 15:28:25 +01:00
6b5b580aff fixed a bug when dmenu is run with -v 2007-02-23 14:39:54 +01:00
d8b48d64e1 Added tag 2.4.2 for changeset 1ca5d430524e 2007-02-23 13:51:23 +01:00
a71424ac0e ok 2.4.2 2007-02-23 13:51:06 +01:00
f1ab687c62 Added tag 2.4.1 for changeset 03e83e2788c8 2007-02-23 13:28:43 +01:00
68a24f5535 hotfix 2007-02-23 13:28:38 +01:00
47b37834c4 Added tag 2.4 for changeset 9e9036cbfb4b 2007-02-23 10:42:00 +01:00
5f436fdcb7 added dmenu_path convenience script 2007-02-23 10:16:43 +01:00
de34639883 made Fnt an anonymous struct 2007-02-22 18:16:35 +01:00
18592825d2 Added tag 2.3 for changeset b6e09682c8adcb6569656bee73c311f9ab457715 2007-02-21 11:05:19 +01:00
3bc1f99e3c applied the fix inspired by a recent wmii commit 2007-02-21 10:59:36 +01:00
8a10b35c64 renamed getcolor to initcolor 2007-02-20 13:57:05 +01:00
e4fc905317 s/setfont/initfont/ 2007-02-20 13:54:37 +01:00
a1913a6af7 readded draw.c again (except getcolor and setfont) 2007-02-20 13:54:00 +01:00
66b2e8379f removed -t, now using isatty() instead of select() to prevent execution from an interactive shell 2007-02-19 21:18:36 +01:00
665488a6ee removed draw.c, implemented C-w handling (backward word deletion) 2007-02-19 15:49:50 +01:00
1e01ca0317 Added tag 2.2 for changeset 90f0e34e7f11 2007-02-14 09:42:02 +01:00
f3c12a7bff fixed Copyright notice in Makefile 2007-02-08 14:10:17 +01:00
3ba8b71aba nah nah nah, I can't get used to the bottom bar, pushing the conditional dmenu again 2007-02-08 11:17:11 +01:00
2bac5599b3 letting dmenu appear at the bottom by default 2007-02-08 11:10:29 +01:00
dbccf6fbff got rid of LD, inspired by JGs patch to wmii 2007-02-05 11:10:41 +01:00
aea9bfec5e Added tag 2.1 for changeset 7656557298c9 2007-01-17 11:10:31 +01:00
6175a39e8e hotfix changes 2007-01-17 11:10:26 +01:00
2c7ff85f24 Added tag 2.1 for changeset d91c79020430 2007-01-17 11:10:09 +01:00
447046f7ae Added tag 2.0 for changeset 1fce5c464fcd 2007-01-16 11:42:09 +01:00
b76632b9e3 small fix 2007-01-16 11:39:26 +01:00
f8f5b27036 removed useless mx, my 2007-01-16 11:38:31 +01:00
d6bf35caad applied new default colors 2007-01-16 11:24:51 +01:00
507c030b5b small fix of Control-j in dmenu.1 2007-01-16 11:07:30 +01:00
0245394e4d Added tag 1.9 for changeset c7f5f4d54317 2007-01-12 12:43:44 +01:00
b6cd6ed266 added evil key support to dmenu 2007-01-11 15:52:37 +01:00
09813fcf2c s/Mod1-Shift-g/Mod1-G/ in fact Sander is right 2007-01-11 13:51:15 +01:00
64d68b7de9 documenting undocumented vi-alike shortcuts of dmenu 2007-01-11 11:41:16 +01:00
eaf8909378 commented recent Control-shortcut additions 2007-01-11 10:17:01 +01:00
c0fcfb7827 applied Sanders dmenu_ctrlchars.patch (thanks!) 2007-01-10 23:07:03 +01:00
a45d6983ab applied Alexis Hildebrandts patches 2007-01-10 18:06:16 +01:00
08420a935b corrections 2007-01-02 15:44:32 +01:00
deea1fb5ab corrected 2007-01-02 15:41:13 +01:00
771c0cb607 next version will contain updated copyright notice 2007-01-02 15:38:44 +01:00
43a19425af Added tag 1.8 for changeset d3e6fa22ae45b38b1bdb0d813390365e5930360b 2006-12-19 11:49:38 +01:00
bbfd5391ac fixed a typo in dmenu.1 2006-12-19 11:49:28 +01:00
0e96ae6f48 prepared dmenu-1.8, shortened command line options (-font is -fn, -selbg is -sb, -selfg is -sf, -normbg is -nb, -normfg is -nf now) 2006-12-19 11:39:07 +01:00
989649b5a5 added wmii reference to dmenu(1) 2006-12-18 13:46:44 +01:00
f8d2a29a20 agreed with Sander 2006-12-18 13:25:11 +01:00
3438af001a applied Stefan Tibus' sun patch, added -bottom option to dmenu which makes it appear in the bottom (for wmii compliance), slightly modified version than the patch proposed by Stefan Tibus 2006-12-18 12:52:58 +01:00
201b056e39 hotfix 2006-12-14 14:41:53 +01:00
3dcdbe2a57 added vi-like key-bindings for keyboards without cursor keys (they are undocumented features) 2006-12-14 14:40:58 +01:00
5336608a86 Added tag 1.7.1 for changeset 3696d77aaf02f5d15728dde3b9e35abcaf291496 2006-12-14 09:45:11 +01:00
d398a2e318 foo 2006-12-14 09:45:06 +01:00
2829009138 silent hotfix 2006-12-14 09:34:24 +01:00
cae2fbdf38 Added tag 1.7.1 for changeset 8e0b9b09bf83c429c73e60a23997f32877a645bf 2006-12-14 09:30:31 +01:00
225cd764c3 applied hotfix of sander 2006-12-14 09:30:23 +01:00
279966a16f Added tag 1.7 for changeset 58dbef4aef3d45c7a3da6945e53c9667c0f02d5b 2006-12-14 08:51:21 +01:00
9bd80b3968 changed text in dmenu manpage 2006-12-13 14:36:09 +01:00
65912f2a96 added prompt option (-p 'prompt text'), documented in man page as well 2006-12-13 14:14:41 +01:00
4bd3466215 ordered switch branches in kpress alphabetically, applied Sanders patch for PgUp/Dn and Home/End scrolling 2006-12-12 09:57:42 +01:00
e19e42adbb fixed diagnostic error message 2006-12-08 11:12:11 +01:00
796c4fb9e5 removed hardcoded 'fixed' fallback, useless and misleading 2006-12-08 10:41:16 +01:00
93c3f930c5 Added tag 1.6 for changeset dcc5427f99f51a978386a0dd770467cd911ac84b 2006-12-07 14:54:47 +01:00
c69f397bb9 found compromise 2006-12-07 14:38:31 +01:00
b9fbd59c8a people should define fixed being compatible with their locale 2006-12-07 12:03:47 +01:00
da2b90ddd1 using -*-fixed-*-*-*-*-*-*-*-*-*-*-iso10646-* fixed by default 2006-12-07 11:55:46 +01:00
dd7ee0dae1 also fixing dmenu accordingly 2006-12-07 10:06:06 +01:00
250aa199bb only setting LC_CTYPE 2006-12-05 13:30:37 +01:00
5d43e9243c enforcing using imcomplete fonsets anyways 2006-12-05 10:31:20 +01:00
1026eb8308 Added tag 1.5 for changeset e071fb045bd9e8574947acff7196360bc0270e68 2006-11-30 09:21:14 +01:00
c65fdd6252 next version will be 1.5 2006-11-26 15:49:47 +01:00
8c20e5dbd3 fixing sizeof stuff 2006-11-26 15:49:33 +01:00
26fbf124fa Added tag 1.4 for changeset df3fbb050004c544d14e43c36f6a94cca6ed4a69 2006-10-26 12:14:03 +02:00
194d890517 removed misleading input cursor 2006-10-23 12:53:35 +02:00
f633276774 fixing arg handling in dmenu (thanks to Sander for his report) 2006-10-23 10:12:09 +02:00
bb480fb4b0 Added tag 1.3 for changeset 2eb9997be51cb1b11a8900728ccc0904f9371157 2006-10-13 11:08:35 +02:00
95b19f75cc changing order 2006-10-12 12:59:37 +02:00
3d25a327aa simplified util.c 2006-10-12 12:58:34 +02:00
d78bcf247f simplified main event loop 2006-10-10 19:15:06 +02:00
afaf66dc99 Added tag 1.2 for changeset bee7fe6d1189174d0204ca3195b83cdc1bb4f82e 2006-10-06 13:44:22 +02:00
63be0ee22a small change 2006-10-06 12:40:49 +02:00
ca973eb64e changing version info 2006-10-06 12:39:06 +02:00
5fd7af18c6 removed useless newlines 2006-10-06 11:52:57 +02:00
02238725f6 small update to man page (backported) 2006-09-26 17:51:22 +02:00
2d5afd7c01 Added tag 1.1 for changeset e8c1e9733752db12f2dbd1fa93c46f5806242ba9 2006-09-26 17:39:04 +02:00
10 changed files with 423 additions and 306 deletions

22
.hgtags
View File

@ -8,3 +8,25 @@ d352e9dc112ee96aa5cad961a0ed880ae9ce7276 0.3
409667a57221f7e50ba8b5248f638915cd61b366 0.8 409667a57221f7e50ba8b5248f638915cd61b366 0.8
d046c818ea467555cc338751c9bf3024609f1f12 0.9 d046c818ea467555cc338751c9bf3024609f1f12 0.9
9e11140d4cc3eecac3b0ab752f91528fd5e04be8 1.0 9e11140d4cc3eecac3b0ab752f91528fd5e04be8 1.0
e8c1e9733752db12f2dbd1fa93c46f5806242ba9 1.1
bee7fe6d1189174d0204ca3195b83cdc1bb4f82e 1.2
2eb9997be51cb1b11a8900728ccc0904f9371157 1.3
df3fbb050004c544d14e43c36f6a94cca6ed4a69 1.4
e071fb045bd9e8574947acff7196360bc0270e68 1.5
dcc5427f99f51a978386a0dd770467cd911ac84b 1.6
58dbef4aef3d45c7a3da6945e53c9667c0f02d5b 1.7
3696d77aaf02f5d15728dde3b9e35abcaf291496 1.7.1
d3e6fa22ae45b38b1bdb0d813390365e5930360b 1.8
c7f5f4d543170f03d70468e98a3a0ec8d2c4161b 1.9
1fce5c464fcd870b9f024aa1853d5cf3a3eb371b 2.0
7656557298c954469a6a9564e6649b1fb5db663e 2.1
90f0e34e7f118c9ad3227a1606211ee825942b1c 2.2
b6e09682c8adcb6569656bee73c311f9ab457715 2.3
9e9036cbfb4b7306c6fb366249e81dc0e65bdfde 2.4
03e83e2788c83ddd63b45a667939d7ec783c98cb 2.4.1
1ca5d430524e838c52ede912533cb90108c5cd66 2.4.2
041143e9fc544c62edc58af52cae9ac5237e5945 2.5
775f761a5647a05038e091d1c99fc35d3034cd68 2.6
fbd9e9d63f202afe6834ccfdf890904f1897ec0b 2.7
dd3d02b07cac44fbafc074a361c1002cebe7aae4 2.8
59b3024854db49739c6d237fa9077f04a2da847a 3.0

View File

@ -1,7 +1,7 @@
MIT/X Consortium License MIT/X Consortium License
(C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
(C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View File

@ -1,5 +1,5 @@
# dmenu - dynamic menu # dmenu - dynamic menu
# (C)opyright MMVI Anselm R. Garbe # © 2006-2007 Anselm R. Garbe, Sander van Dijk
include config.mk include config.mk
@ -13,7 +13,6 @@ options:
@echo "CFLAGS = ${CFLAGS}" @echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}" @echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o: .c.o:
@echo CC $< @echo CC $<
@ -22,9 +21,8 @@ options:
${OBJ}: dmenu.h config.mk ${OBJ}: dmenu.h config.mk
dmenu: ${OBJ} dmenu: ${OBJ}
@echo LD $@ @echo CC -o $@
@${LD} -o $@ ${OBJ} ${LDFLAGS} @${CC} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
clean: clean:
@echo cleaning @echo cleaning
@ -33,7 +31,7 @@ clean:
dist: clean dist: clean
@echo creating dist tarball @echo creating dist tarball
@mkdir -p dmenu-${VERSION} @mkdir -p dmenu-${VERSION}
@cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.h ${SRC} dmenu-${VERSION} @cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.h dmenu_path ${SRC} dmenu-${VERSION}
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} @tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
@gzip dmenu-${VERSION}.tar @gzip dmenu-${VERSION}.tar
@rm -rf dmenu-${VERSION} @rm -rf dmenu-${VERSION}
@ -41,16 +39,17 @@ dist: clean
install: all install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin @echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin @mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dmenu ${DESTDIR}${PREFIX}/bin @cp -f dmenu dmenu_path ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu @chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_path
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1 @mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed 's/VERSION/${VERSION}/g' < dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/dmenu.1 @sed "s/VERSION/${VERSION}/g" < dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1 @chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
uninstall: uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin @echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu @rm -f ${DESTDIR}${PREFIX}/bin/dmenu ${DESTDIR}${PREFIX}/bin/dmenu_path
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1 @rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1

View File

@ -1,5 +1,5 @@
# dmenu version # dmenu version
VERSION = 1.1 VERSION = 3.1
# Customize below to fit your system # Customize below to fit your system
@ -16,10 +16,14 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags # flags
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS} LDFLAGS = -s ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" #CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS} #LDFLAGS = -g ${LIBS}
# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}
#CFLAGS += -xtarget=ultra
# compiler and linker # compiler and linker
CC = cc CC = cc
LD = ${CC}

64
dmenu.1
View File

@ -1,14 +1,15 @@
.TH DMENU 1 dmenu-VERSION .TH DMENU 1 dmenu\-VERSION
.SH NAME .SH NAME
dmenu \- dynamic menu dmenu \- dynamic menu
.SH SYNOPSIS .SH SYNOPSIS
.B dmenu .B dmenu
.RB [ \-font <name> ] .RB [ \-b ]
.RB [ \-normbg <color> ] .RB [ \-fn " <font>"]
.RB [ \-normfg <color> ] .RB [ \-nb " <color>"]
.RB [ \-selbg <color> ] .RB [ \-nf " <color>"]
.RB [ \-selfg <color> ] .RB [ \-p " <prompt>"]
.RB [ \-t <seconds> ] .RB [ \-sb " <color>"]
.RB [ \-sf " <color>"]
.RB [ \-v ] .RB [ \-v ]
.SH DESCRIPTION .SH DESCRIPTION
.SS Overview .SS Overview
@ -18,29 +19,32 @@ It manages huge amounts (up to 10.000 and more) of user defined menu items
efficiently. efficiently.
.SS Options .SS Options
.TP .TP
.B \-font <name> .B \-b
makes dmenu appear at the screen bottom (by default it appears at the screen top).
.TP
.B \-fn <font>
defines the font. defines the font.
.TP .TP
.B \-normbg <color> .B \-nb <color>
defines the normal background color (#RGB, #RRGGBB, and color names are supported). defines the normal background color (#RGB, #RRGGBB, and color names are supported).
.TP .TP
.B \-normfg <color> .B \-nf <color>
defines the normal foreground color (#RGB, #RRGGBB, and color names are supported). defines the normal foreground color (#RGB, #RRGGBB, and color names are supported).
.TP .TP
.B \-selbg <color> .B \-p <prompt>
defines a prompt to be displayed before the input area.
.TP
.B \-sb <color>
defines the selected background color (#RGB, #RRGGBB, and color names are supported). defines the selected background color (#RGB, #RRGGBB, and color names are supported).
.TP .TP
.B \-selfg <color> .B \-sf <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 \-t <seconds>
defines the seconds to wait for standard input, before exiting (default is 3).
.TP
.B \-v .B \-v
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:
@ -49,32 +53,42 @@ dmenu is completely controlled by the keyboard. The following keys are recognize
Appends the character to the text in the input field. This works as a filter: Appends the character to the text in the input field. This works as a filter:
only items containing this text will be displayed. only items containing this text will be displayed.
.TP .TP
.B Left/Right .B Left/Right (Mod1\-h/Mod1\-l)
Select the previous/next item. Select the previous/next item.
.TP .TP
.B Tab .B PageUp/PageDown (Mod1\-k/Mod1\-j)
Select the first item of the previous/next 'page' of items.
.TP
.B Home/End (Mod1\-g/Mod1\-G)
Select the first/last item.
.TP
.B Tab (Control\-i)
Copy the selected item to the input field. Copy the selected item to the input field.
.TP .TP
.B Return .B Return (Control\-j)
Confirm selection and quit (print the selected item to standard output). Returns Confirm selection and quit (print the selected item to standard output). Returns
.B 0 .B 0
on termination. on termination.
.TP .TP
.B Shift-Return .B Shift\-Return (Control\-Shift\-j)
Confirm selection and quit (print the text in the input field to standard output). Confirm selection and quit (print the text in the input field to standard output).
Returns Returns
.B 0 .B 0
on termination. on termination.
.TP .TP
.B Escape .B Escape (Control\-bracketleft)
Quit without selecting an item. Returns Quit without selecting an item. Returns
.B 1 .B 1
on termination. on termination.
.TP .TP
.B Backspace (Control-h) .B Backspace (Control\-h)
Remove enough characters from the input field to change its filtering effect. Remove a character from the input field.
.TP .TP
.B Control-u .B Control\-u
Remove all characters from the input field. Remove all characters from the input field.
.TP
.B Control\-w
Remove all characters of current word from the input field.
.SH SEE ALSO .SH SEE ALSO
.BR dwm (1) .BR dwm (1),
.BR wmii (1) .

62
dmenu.h
View File

@ -1,53 +1,43 @@
/* /* © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> * © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details. */
*/
#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 "#eeeeee"
#define NORMFGCOLOR "#cccccc" #define NORMFGCOLOR "#222222"
#define SELBGCOLOR "#666699" #define SELBGCOLOR "#006699"
#define SELFGCOLOR "#eeeeee" #define SELFGCOLOR "#ffffff"
#define SPACE 30 /* px */ #define SPACE 30 /* px */
/* color */ /* color */
enum { ColFG, ColBG, ColLast }; enum { ColFG, ColBG, ColLast };
typedef struct DC DC; typedef struct {
typedef struct Fnt Fnt; int x, y, w, h;
unsigned long norm[ColLast];
struct Fnt { unsigned long sel[ColLast];
Drawable drawable;
GC gc;
struct {
XFontStruct *xfont; XFontStruct *xfont;
XFontSet set; XFontSet set;
int ascent; int ascent;
int descent; int descent;
int height; int height;
}; } font;
} DC; /* draw context */
struct DC { int screen;
int x, y, w, h; Display *dpy;
unsigned long norm[ColLast]; DC dc; /* global drawing context */
unsigned long sel[ColLast];
Drawable drawable;
Fnt font;
GC gc;
}; /* draw context */
extern int screen;
extern Display *dpy;
extern DC dc; /* global drawing context */
/* draw.c */ /* draw.c */
extern void drawtext(const char *text, void drawtext(const char *text, unsigned long col[ColLast]);
unsigned long col[ColLast]); /* draws text with the defined color tuple */ unsigned int textw(const char *text);
extern unsigned long getcolor(const char *colstr); /* returns color of colstr */ unsigned int textnw(const char *text, unsigned int len);
extern void setfont(const char *fontstr); /* sets global font */
extern unsigned int textw(const char *text); /* returns width of text in px */
/* util.c */ /* util.c */
extern void *emalloc(unsigned int size); /* allocates memory, exits on error */ void *emalloc(unsigned int size); /* allocates memory, exits on error */
extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */ void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */
extern char *estrdup(const char *str); /* duplicates str, exits on allocation error */ char *estrdup(const char *str); /* duplicates str, exits on allocation error */

30
dmenu_path Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
CACHE=$HOME/.dmenu_cache
UPTODATE=1
IFS=:
if test ! -f $CACHE
then
unset UPTODATE
fi
if test $UPTODATE
then
for dir in $PATH
do
test $dir -nt $CACHE && unset UPTODATE
done
fi
if test ! $UPTODATE
then
for dir in $PATH
do
for file in "$dir"/*
do
test -x "$file" && echo "${file##*/}"
done
done | sort | uniq > $CACHE
fi
cat $CACHE

116
draw.c
View File

@ -1,24 +1,8 @@
/* /* © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> * © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details. */
*/
#include "dmenu.h" #include "dmenu.h"
#include <stdio.h>
#include <string.h> #include <string.h>
#include <X11/Xlocale.h>
/* static */
static unsigned int
textnw(const char *text, unsigned int len) {
XRectangle r;
if(dc.font.set) {
XmbTextExtents(dc.font.set, text, len, NULL, &r);
return r.width;
}
return XTextWidth(dc.font.xfont, text, len);
}
/* extern */ /* extern */
@ -27,26 +11,21 @@ drawtext(const char *text, unsigned long col[ColLast]) {
int x, y, w, h; int x, y, w, h;
static char buf[256]; static char buf[256];
unsigned int len, olen; unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, col[ColBG]); XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text) if(!text)
return; return;
w = 0; w = 0;
olen = len = strlen(text); olen = len = strlen(text);
if(len >= sizeof(buf)) if(len >= sizeof buf)
len = sizeof(buf) - 1; len = sizeof buf - 1;
memcpy(buf, text, len); memcpy(buf, text, len);
buf[len] = 0; buf[len] = 0;
h = dc.font.ascent + dc.font.descent; h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2); x = dc.x + (h / 2);
/* shorten text if necessary */ /* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h) while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0; buf[--len] = 0;
@ -58,82 +37,27 @@ drawtext(const char *text, unsigned long col[ColLast]) {
if(len > 3) if(len > 3)
buf[len - 3] = '.'; buf[len - 3] = '.';
} }
if(w > dc.w) if(w > dc.w)
return; /* too long */ return; /* too long */
XSetForeground(dpy, dc.gc, col[ColFG]);
gcv.foreground = col[ColFG];
if(dc.font.set) {
XChangeGC(dpy, dc.gc, GCForeground, &gcv);
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc,
x, y, buf, len);
}
else {
gcv.font = dc.font.xfont->fid;
XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
}
unsigned long
getcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
return color.pixel;
}
void
setfont(const char *fontstr) {
char **missing, *def;
int i, n;
missing = NULL;
setlocale(LC_ALL, "");
if(dc.font.set) if(dc.font.set)
XFreeFontSet(dpy, dc.font.set); XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); else
if(missing) { XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
XFreeStringList(missing);
if(dc.font.set) {
XFreeFontSet(dpy, dc.font.set);
dc.font.set = NULL;
}
}
if(dc.font.set) {
XFontSetExtents *font_extents;
XFontStruct **xfonts;
char **font_names;
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
if(dc.font.ascent < (*xfonts)->ascent)
dc.font.ascent = (*xfonts)->ascent;
if(dc.font.descent < (*xfonts)->descent)
dc.font.descent = (*xfonts)->descent;
xfonts++;
}
}
else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
dc.font.xfont = XLoadQueryFont(dpy, fontstr);
if (!dc.font.xfont)
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.descent = dc.font.xfont->descent;
}
dc.font.height = dc.font.ascent + dc.font.descent;
} }
unsigned int unsigned int
textw(const char *text) { textw(const char *text) {
return textnw(text, strlen(text)) + dc.font.height; return textnw(text, strlen(text)) + dc.font.height;
} }
unsigned int
textnw(const char *text, unsigned int len) {
XRectangle r;
if(dc.font.set) {
XmbTextExtents(dc.font.set, text, len, NULL, &r);
return r.width;
}
return XTextWidth(dc.font.xfont, text, len);
}

376
main.c
View File

@ -1,22 +1,18 @@
/* /* © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> * © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
* (C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com> * See LICENSE file for license details. */
* See LICENSE file for license details.
*/
#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>
#include <unistd.h> #include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
typedef struct Item Item; typedef struct Item Item;
struct Item { struct Item {
Item *next; /* traverses all items */ Item *next; /* traverses all items */
@ -27,10 +23,13 @@ struct Item {
/* static */ /* static */
static char text[4096]; static char text[4096];
static int mx, my, mw, mh; static char *prompt = NULL;
static int 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 unsigned int numlockmask = 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 */
@ -47,8 +46,7 @@ calcoffsets(void) {
if(!curr) if(!curr)
return; return;
w = promptw + cmdw + 2 * SPACE;
w = 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)
@ -57,8 +55,7 @@ calcoffsets(void) {
if(w > mw) if(w > mw)
break; break;
} }
w = promptw + cmdw + 2 * SPACE;
w = 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)
@ -78,18 +75,22 @@ 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;
drawtext(text[0] ? text : NULL, dc.norm); drawtext(text[0] ? text : NULL, dc.norm);
dc.x += cmdw; dc.x += cmdw;
if(curr) { if(curr) {
dc.w = SPACE; dc.w = SPACE;
drawtext((curr && curr->left) ? "<" : NULL, dc.norm); drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
dc.x += dc.w; dc.x += dc.w;
/* determine maximum items */ /* determine maximum items */
for(i = curr; i != next; i=i->right) { for(i = curr; i != next; i=i->right) {
dc.w = textw(i->text); dc.w = textw(i->text);
@ -98,7 +99,6 @@ drawmenu(void) {
drawtext(i->text, (sel == i) ? dc.sel : dc.norm); drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
dc.x += dc.w; dc.x += dc.w;
} }
dc.x = mw - SPACE; dc.x = mw - SPACE;
dc.w = SPACE; dc.w = SPACE;
drawtext(next ? ">" : NULL, dc.norm); drawtext(next ? ">" : NULL, dc.norm);
@ -107,6 +107,69 @@ drawmenu(void) {
XFlush(dpy); XFlush(dpy);
} }
static Bool
grabkeyboard(void) {
unsigned int len;
for(len = 1000; len; len--) {
if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
== GrabSuccess)
break;
usleep(1000);
}
return len > 0;
}
static unsigned long
initcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
return color.pixel;
}
static void
initfont(const char *fontstr) {
char *def, **missing;
int i, n;
if(!fontstr || fontstr[0] == '\0')
eprint("error, cannot load font: '%s'\n", fontstr);
missing = NULL;
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing)
XFreeStringList(missing);
if(dc.font.set) {
XFontSetExtents *font_extents;
XFontStruct **xfonts;
char **font_names;
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
if(dc.font.ascent < (*xfonts)->ascent)
dc.font.ascent = (*xfonts)->ascent;
if(dc.font.descent < (*xfonts)->descent)
dc.font.descent = (*xfonts)->descent;
xfonts++;
}
}
else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
eprint("error, cannot load font: '%s'\n", fontstr);
dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent;
}
dc.font.height = dc.font.ascent + dc.font.descent;
}
static void static void
match(char *pattern) { match(char *pattern) {
unsigned int plen; unsigned int plen;
@ -114,11 +177,9 @@ match(char *pattern) {
if(!pattern) if(!pattern)
return; return;
plen = strlen(pattern); plen = strlen(pattern);
item = j = NULL; item = j = NULL;
nitem = 0; nitem = 0;
for(i = allitems; i; i=i->next) for(i = allitems; i; i=i->next)
if(!plen || !strncmp(pattern, i->text, plen)) { if(!plen || !strncmp(pattern, i->text, plen)) {
if(!j) if(!j)
@ -142,7 +203,6 @@ match(char *pattern) {
j = i; j = i;
nitem++; nitem++;
} }
curr = prev = next = sel = item; curr = prev = next = sel = item;
calcoffsets(); calcoffsets();
} }
@ -150,39 +210,124 @@ match(char *pattern) {
static void static void
kpress(XKeyEvent * e) { kpress(XKeyEvent * e) {
char buf[32]; char buf[32];
int num, prev_nitem; int i, num;
unsigned int i, len; unsigned int len;
KeySym ksym; KeySym ksym;
len = strlen(text); len = strlen(text);
buf[0] = 0; buf[0] = 0;
num = XLookupString(e, buf, sizeof(buf), &ksym, 0); num = XLookupString(e, buf, sizeof buf, &ksym, 0);
if(IsKeypadKey(ksym)) {
if(ksym == XK_KP_Enter) {
ksym = XK_Return;
} else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) {
ksym = (ksym - XK_KP_0) + XK_0;
}
}
if(IsFunctionKey(ksym) || IsKeypadKey(ksym) if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
|| IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
|| IsPrivateKeypadKey(ksym)) || IsPrivateKeypadKey(ksym))
return; return;
/* first check if a control mask is omitted */ /* first check if a control mask is omitted */
if(e->state & ControlMask) { if(e->state & ControlMask) {
switch (ksym) { switch (ksym) {
default: /* ignore other control sequences */ default: /* ignore other control sequences */
return; return;
case XK_bracketleft:
ksym = XK_Escape;
break; break;
case XK_h: case XK_h:
case XK_H: case XK_H:
ksym = XK_BackSpace; ksym = XK_BackSpace;
break; break;
case XK_i:
case XK_I:
ksym = XK_Tab;
break;
case XK_j:
case XK_J:
ksym = XK_Return;
break;
case XK_u: case XK_u:
case XK_U: case XK_U:
text[0] = 0; text[0] = 0;
match(text); match(text);
drawmenu(); drawmenu();
return; return;
case XK_w:
case XK_W:
if(len) {
i = len - 1;
while(i >= 0 && text[i] == ' ')
text[i--] = 0;
while(i >= 0 && text[i] != ' ')
text[i--] = 0;
match(text);
drawmenu();
}
return;
}
}
if(CLEANMASK(e->state) & Mod1Mask) {
switch(ksym) {
default: return;
case XK_h:
ksym = XK_Left;
break;
case XK_l:
ksym = XK_Right;
break;
case XK_j:
ksym = XK_Next;
break;
case XK_k:
ksym = XK_Prior;
break;
case XK_g:
ksym = XK_Home;
break;
case XK_G:
ksym = XK_End;
break; break;
} }
} }
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(len) {
text[--len] = 0;
match(text);
}
break;
case XK_End:
if(!item)
return;
while(next) {
sel = curr = next;
calcoffsets();
}
while(sel && sel->right)
sel = sel->right;
break;
case XK_Escape:
ret = 1;
running = False;
break;
case XK_Home:
if(!item)
return;
sel = curr = item;
calcoffsets();
break;
case XK_Left: case XK_Left:
if(!(sel && sel->left)) if(!(sel && sel->left))
return; return;
@ -192,20 +337,17 @@ kpress(XKeyEvent * e) {
calcoffsets(); calcoffsets();
} }
break; break;
case XK_Tab: case XK_Next:
if(!sel) if(!next)
return; return;
strncpy(text, sel->text, sizeof(text)); sel = curr = next;
match(text); calcoffsets();
break; break;
case XK_Right: case XK_Prior:
if(!(sel && sel->right)) if(!prev)
return; return;
sel=sel->right; sel = curr = prev;
if(sel == next) {
curr = next;
calcoffsets(); calcoffsets();
}
break; break;
case XK_Return: case XK_Return:
if((e->state & ShiftMask) && text) if((e->state & ShiftMask) && text)
@ -217,29 +359,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));
else
strncpy(text, buf, sizeof(text));
match(text); match(text);
} break;
} }
drawmenu(); drawmenu();
} }
@ -252,7 +386,7 @@ readstdin(void) {
Item *i, *new; Item *i, *new;
i = 0; i = 0;
while(fgets(buf, sizeof(buf), stdin)) { while(fgets(buf, sizeof buf, stdin)) {
len = strlen(buf); len = strlen(buf);
if (buf[len - 1] == '\n') if (buf[len - 1] == '\n')
buf[len - 1] = 0; buf[len - 1] = 0;
@ -261,7 +395,6 @@ readstdin(void) {
maxname = p; maxname = p;
max = len; max = len;
} }
new = emalloc(sizeof(Item)); new = emalloc(sizeof(Item));
new->next = new->left = new->right = NULL; new->next = new->left = new->right = NULL;
new->text = p; new->text = p;
@ -275,6 +408,12 @@ readstdin(void) {
return maxname; return maxname;
} }
static void
usage(void) {
eprint("usage: dmenu [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
" [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
}
/* extern */ /* extern */
int screen; int screen;
@ -283,94 +422,101 @@ DC dc = {0};
int int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
Bool bottom = False;
char *font = FONT; char *font = FONT;
char *maxname; char *maxname;
char *normbg = NORMBGCOLOR; char *normbg = NORMBGCOLOR;
char *normfg = NORMFGCOLOR; char *normfg = NORMFGCOLOR;
char *selbg = SELBGCOLOR; char *selbg = SELBGCOLOR;
char *selfg = SELFGCOLOR; char *selfg = SELFGCOLOR;
fd_set rd; int i, j;
int i;
struct timeval timeout;
Item *itm; Item *itm;
XEvent ev; XEvent ev;
XModifierKeymap *modmap;
XSetWindowAttributes wa; XSetWindowAttributes wa;
timeout.tv_usec = 0;
timeout.tv_sec = 3;
/* command line args */ /* command line args */
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
if(!strncmp(argv[i], "-font", 6)) if(!strncmp(argv[i], "-b", 3)) {
font = argv[++i]; bottom = True;
else if(!strncmp(argv[i], "-normbg", 8))
normbg = argv[++i];
else if(!strncmp(argv[i], "-normfg", 8))
normfg = argv[++i];
else if(!strncmp(argv[i], "-selbg", 7))
selbg = argv[++i];
else if(!strncmp(argv[i], "-selfg", 7))
selfg = argv[++i];
else if(!strncmp(argv[i], "-t", 3))
timeout.tv_sec = atoi(argv[++i]);
else if(!strncmp(argv[i], "-v", 3)) {
fputs("dmenu-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
} }
else if(!strncmp(argv[i], "-fn", 4)) {
if(++i < argc) font = argv[i];
}
else if(!strncmp(argv[i], "-nb", 4)) {
if(++i < argc) normbg = argv[i];
}
else if(!strncmp(argv[i], "-nf", 4)) {
if(++i < argc) normfg = argv[i];
}
else if(!strncmp(argv[i], "-p", 3)) {
if(++i < argc) prompt = argv[i];
}
else if(!strncmp(argv[i], "-sb", 4)) {
if(++i < argc) selbg = argv[i];
}
else if(!strncmp(argv[i], "-sf", 4)) {
if(++i < argc) selfg = argv[i];
}
else if(!strncmp(argv[i], "-v", 3))
eprint("dmenu-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk\n");
else else
eprint("usage: dmenu [-font <name>] [-{norm,sel}{bg,fg} <color>] [-t <seconds>] [-v]\n", stdout); usage();
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");
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
if(isatty(STDIN_FILENO)) {
/* Note, the select() construction allows to grab all keypresses as
* early as possible, to not loose them. But if there is no standard
* input supplied, we will make sure to exit after MAX_WAIT_STDIN
* seconds. This is convenience behavior for rapid typers.
*/
while(XGrabKeyboard(dpy, root, True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess)
usleep(1000);
FD_ZERO(&rd);
FD_SET(STDIN_FILENO, &rd);
if(select(ConnectionNumber(dpy) + 1, &rd, NULL, NULL, &timeout) < 1)
goto UninitializedEnd;
maxname = readstdin(); maxname = readstdin();
running = grabkeyboard();
}
else { /* prevent keypress loss */
running = grabkeyboard();
maxname = readstdin();
}
/* 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);
/* style */ /* style */
dc.norm[ColBG] = getcolor(normbg); dc.norm[ColBG] = initcolor(normbg);
dc.norm[ColFG] = getcolor(normfg); dc.norm[ColFG] = initcolor(normfg);
dc.sel[ColBG] = getcolor(selbg); dc.sel[ColBG] = initcolor(selbg);
dc.sel[ColFG] = getcolor(selfg); dc.sel[ColFG] = initcolor(selfg);
setfont(font); initfont(font);
/* menu window */
wa.override_redirect = 1; wa.override_redirect = 1;
wa.background_pixmap = ParentRelative; wa.background_pixmap = ParentRelative;
wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask; wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
mx = my = 0;
mw = DisplayWidth(dpy, screen); mw = DisplayWidth(dpy, screen);
mh = dc.font.height + 2; mh = dc.font.height + 2;
win = XCreateWindow(dpy, root, 0,
win = XCreateWindow(dpy, root, mx, my, mw, mh, 0, bottom ? DisplayHeight(dpy, screen) - mh : 0, mw, mh, 0,
DefaultDepth(dpy, screen), CopyFromParent, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen), DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));
/* pixmap */ /* pixmap */
dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen)); dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0); dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
if(maxname) if(maxname)
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);
@ -378,7 +524,7 @@ main(int argc, char *argv[]) {
XSync(dpy, False); XSync(dpy, False);
/* main event loop */ /* main event loop */
while(running && !XNextEvent(dpy, &ev)) { while(running && !XNextEvent(dpy, &ev))
switch (ev.type) { switch (ev.type) {
default: /* ignore all crap */ default: /* ignore all crap */
break; break;
@ -390,8 +536,8 @@ main(int argc, char *argv[]) {
drawmenu(); drawmenu();
break; break;
} }
}
/* cleanup */
while(allitems) { while(allitems) {
itm = allitems->next; itm = allitems->next;
free(allitems->text); free(allitems->text);
@ -405,9 +551,7 @@ main(int argc, char *argv[]) {
XFreePixmap(dpy, dc.drawable); XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc); XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, win); XDestroyWindow(dpy, win);
UninitializedEnd:
XUngrabKeyboard(dpy, CurrentTime); XUngrabKeyboard(dpy, CurrentTime);
XCloseDisplay(dpy); XCloseDisplay(dpy);
return ret; return ret;
} }

24
util.c
View File

@ -1,29 +1,18 @@
/* /* © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> * © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details. */
*/
#include "dmenu.h" #include "dmenu.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/wait.h>
#include <unistd.h>
/* static */
static void
badmalloc(unsigned int size) {
eprint("fatal: could not malloc() %u bytes\n", size);
}
/* extern */
void * void *
emalloc(unsigned int size) { emalloc(unsigned int size) {
void *res = malloc(size); void *res = malloc(size);
if(!res) if(!res)
badmalloc(size); eprint("fatal: could not malloc() %u bytes\n", size);
return res; return res;
} }
@ -40,7 +29,8 @@ eprint(const char *errstr, ...) {
char * char *
estrdup(const char *str) { estrdup(const char *str) {
void *res = strdup(str); void *res = strdup(str);
if(!res) if(!res)
badmalloc(strlen(str)); eprint("fatal: could not malloc() %u bytes\n", strlen(str));
return res; return res;
} }