178 Commits
0.6 ... 3.6

Author SHA1 Message Date
Sander van Dijk
1538bb7426 fix typo 2008-03-25 19:18:16 +01:00
Anselm R Garbe
cbe5e88e4f using limits.h 2008-03-25 10:18:17 +00:00
Anselm R Garbe
2fe3ccdf58 bugfix of the -0 case in dmenu (thanks to Sander for his hint) 2008-03-25 09:43:34 +00:00
Anselm R Garbe
07d82c0c2a applied Jukkas hotfix 2008-03-24 15:56:41 +00:00
Sander van Dijk
e7423f8fc6 more cosmetics 2008-03-23 22:06:09 +01:00
Sander van Dijk
61976c292b cosmetics 2008-03-23 21:17:35 +01:00
Sander van Dijk
63c9e30a76 made some whitespacing consistent. 2008-03-23 21:11:42 +01:00
sander@localhost
015f51ac46 removed unused variable nitem. 2008-03-23 12:09:29 +01:00
anselm@anselm1
542c58d8d0 several performance tweaks 2008-03-22 14:52:00 +00:00
Anselm R Garbe
745c46d8fa fixed match() to prefer prefix-matches to strstr-matches in the match list, extended the -y handling, next version is 3.6 2008-03-18 16:52:51 +00:00
Anselm R Garbe
d058e83570 Added tag 3.5 for changeset 05e5bd706b3b 2008-03-13 16:53:25 +00:00
Anselm R Garbe
301b4e5591 applied next patch of Sander 2008-03-13 12:02:29 +00:00
anselm@anselm1
38b866ba34 applied Sanders patch 2008-03-12 21:37:43 +00:00
Anselm R Garbe
540a78761b removed ido-matching, changed behavior of -i meaning case insensitive matching now, commented -x, -y, -w arguments in dmenu.1 2008-03-12 15:41:19 +00:00
Anselm R Garbe
7804354106 removed set 2008-02-12 09:42:48 +00:00
anselm@aab
6d8e68dcfd updated 2008-02-11 11:22:38 +00:00
anselm@anselm1
d8688f7a4f added dmenu run 2007-12-22 12:20:20 +00:00
Anselm R. Garbe
09d0926bb9 Added tag 3.4 for changeset 9ab649b3b3e5 2007-10-25 20:26:17 +02:00
Anselm R. Garbe
adc4ec02c0 adapted c99 for pedantic checks, even if those checks are somewhat broken 2007-10-10 18:57:51 +02:00
Anselm R. Garbe
8b2f132973 implemented strcasestr for dmenu (I call it cistrstr) for portability issues (cygwin has no strcasestr, oh dear) 2007-10-01 15:28:42 +02:00
Anselm R. Garbe
1c488e6dac fixed font definition 2007-10-01 11:44:25 +02:00
Anselm R. Garbe
03c546c6b3 fixed dmenu 2007-09-30 19:20:31 +02:00
Anselm R. Garbe
fdc1dba7ce using saner defaults 2007-09-30 12:47:40 +02:00
Anselm R. Garbe
3439470a47 applied new color nuance 2007-09-27 18:55:05 +02:00
Anselm R. Garbe
6674bac1d3 applied my favorite color scheme 2007-09-26 19:15:47 +02:00
arg@suckless.org
72a8eb412f casting char to int when using tolower (thanks to Jukkas careful cosmetic checking!) 2007-09-24 15:04:31 +02:00
Anselm R. Garbe
975dfb4163 switching to white 2007-09-23 18:49:24 +02:00
Anselm R. Garbe
2e898a308f yet another cosmetic fix 2007-09-23 18:32:08 +02:00
Anselm R. Garbe
6514b07ad2 small cosmetic fix 2007-09-23 18:31:19 +02:00
Anselm R. Garbe
724fe3cf7f applied Michał Janeczek dmenu patch, made dmenu match case-insensitive by default, added -i command line option to enable ido matching, added Michał to Copyright holders 2007-09-23 18:26:41 +02:00
Anselm R. Garbe
70cb32b021 Added tag 3.3 for changeset 709df5a4bad7 2007-09-22 09:12:50 +02:00
arg@suckless.org
56f9e26b72 applied yiyus initfont fix 2007-09-19 17:33:35 +02:00
Anselm R. Garbe
d094ebea96 reorganized 2007-09-17 20:53:14 +02:00
arg@suckless.org
ccf4d7166f next version is 3.3 2007-09-17 09:13:21 +02:00
Anselm R. Garbe
06ae894434 micromizing dmenu step 1 2007-09-16 20:14:09 +02:00
Anselm R. Garbe
b97783b07f fixed fallback 2007-09-15 20:28:20 +02:00
arg@f00b4r
11cb2e7dcc applied ido-matching to dmenu 2007-07-24 18:19:09 +02:00
Anselm R. Garbe
07239bbddd foooooo 2007-06-01 12:28:30 +02:00
Anselm R. Garbe
124bfd4a08 Added tag 3.2 for changeset e4c81a78ffba 2007-05-30 12:22:38 +02:00
Anselm R. Garbe
d27e3c1092 referred to LICENSE file 2007-05-30 12:19:06 +02:00
Anselm R. Garbe
3a9f3a51ce I agree with the race fix of JG, but I dislike the SUSV3-breaking find, and I don't care about PATH changes, keep it simple, stupid 2007-05-24 10:34:44 +02:00
Kris Maglione
53e92b5c17 Fix the uptodate logic (uptodate if !find newer dirs than the cache). 2007-05-23 19:38:23 -04:00
Kris Maglione
d50ff5ca11 Silence the first find in dmenu_path. 2007-05-23 18:35:05 -04:00
Kris Maglione
383e40dc21 Fix grouping in dmenu_path. 2007-05-23 16:59:38 -04:00
Kris Maglione
8369e1736b Merge. 2007-05-23 16:44:15 -04:00
Kris Maglione
c04b688cc0 Changed dmenu_path (fixed race, improved speed, check that $PATH is the same as the last run). 2007-05-23 16:42:51 -04:00
Anselm R. Garbe
4ebd7c4a21 removed some superflous strncmp's 2007-05-23 22:32:43 +02:00
Anselm R. Garbe
dfe95cb546 made dmenu_path the way anydot proposed in response to Jukka 2007-05-23 22:13:46 +02:00
Anselm R. Garbe
8b633bf17d applied Jukka's fix 2007-05-23 13:22:27 +02:00
Anselm R. Garbe
64697cdd0c Added tag 3.1 for changeset 8f0f917ac988 2007-05-21 14:36:03 +02:00
Anselm R. Garbe
5a3dfb1c40 removed strip, added -s to LDFLAGs 2007-05-15 13:44:41 +02:00
Anselm R. Garbe
4042a11e51 applied anydot's dmenu_path caching patch, thank you! 2007-05-14 11:56:41 +02:00
Anselm R. Garbe
aa2f73fc88 fixed a small bug in dmenu when an empty font is supplied 2007-05-02 15:25:52 +02:00
Anselm R. Garbe
f189781bbd Added tag 3.0 for changeset 59b3024854db 2007-04-19 09:27:08 +02:00
Anselm R. Garbe
0e19146d5f making copyright notice more compact 2007-04-13 11:36:44 +02:00
Anselm R. Garbe
85a151c6a4 next version is 2.9 2007-03-28 08:17:57 +02:00
Anselm R. Garbe
1fa4fa386a allowing numpad keys as inpyt 2007-03-27 16:52:50 +02:00
Anselm R. Garbe
e1515a2fdc Added tag 2.8 for changeset dd3d02b07cac 2007-03-07 13:30:57 +01:00
Anselm R. Garbe
f555908cef attempt to grab the keyboard only 1000 times, not forever. 2007-03-07 11:01:14 +01:00
Anselm R. Garbe
73120414e2 reverting keyboard grab to root window - invoking several dmenu's now works again... 2007-03-07 10:54:21 +01:00
Kris Maglione
9911455f5b Wait for an Expose and draw the menu immediately after mapping the window. 2007-03-06 03:24:40 -05:00
Anselm R. Garbe
2772c51e79 Added tag 2.7 for changeset fbd9e9d63f20 2007-03-05 11:25:18 +01:00
Anselm R. Garbe
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
Anselm R. Garbe
724f72142f also, don't set the font all the time 2007-03-02 15:16:36 +01:00
Anselm R. Garbe
5b8dce15d3 Added tag 2.6 for changeset 775f761a5647 2007-03-01 15:47:54 +01:00
Anselm R. Garbe
063c3d26e9 useless var declaration prev_nitem 2007-02-27 14:44:21 +01:00
Anselm R. Garbe
03c2b05bb2 changed Backspace/C-w behavior (now it only removes a single character) 2007-02-26 14:07:19 +01:00
Anselm R. Garbe
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
Anselm R. Garbe
6c0e05eb0d next is 2.6, but not yet ;) 2007-02-26 10:47:52 +01:00
Kris Maglione
900d34347b Escape -s in dmenu.1 2007-02-25 16:41:05 -05:00
Anselm R. Garbe
4d0cc17794 Added tag 2.5 for changeset 041143e9fc54 2007-02-24 15:38:26 +01:00
Anselm R. Garbe
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
Anselm R. Garbe
598d72fba9 removed superfluous externs as well 2007-02-24 14:07:40 +01:00
Anselm R. Garbe
007be12f2b using the old-style fashion we uses earlier 2007-02-23 15:28:25 +01:00
Anselm R. Garbe
6b5b580aff fixed a bug when dmenu is run with -v 2007-02-23 14:39:54 +01:00
Anselm R. Garbe
d8b48d64e1 Added tag 2.4.2 for changeset 1ca5d430524e 2007-02-23 13:51:23 +01:00
Anselm R. Garbe
a71424ac0e ok 2.4.2 2007-02-23 13:51:06 +01:00
Anselm R. Garbe
f1ab687c62 Added tag 2.4.1 for changeset 03e83e2788c8 2007-02-23 13:28:43 +01:00
Anselm R. Garbe
68a24f5535 hotfix 2007-02-23 13:28:38 +01:00
Anselm R. Garbe
47b37834c4 Added tag 2.4 for changeset 9e9036cbfb4b 2007-02-23 10:42:00 +01:00
Anselm R. Garbe
5f436fdcb7 added dmenu_path convenience script 2007-02-23 10:16:43 +01:00
Anselm R. Garbe
de34639883 made Fnt an anonymous struct 2007-02-22 18:16:35 +01:00
Anselm R. Garbe
18592825d2 Added tag 2.3 for changeset b6e09682c8adcb6569656bee73c311f9ab457715 2007-02-21 11:05:19 +01:00
Anselm R. Garbe
3bc1f99e3c applied the fix inspired by a recent wmii commit 2007-02-21 10:59:36 +01:00
Anselm R. Garbe
8a10b35c64 renamed getcolor to initcolor 2007-02-20 13:57:05 +01:00
Anselm R. Garbe
e4fc905317 s/setfont/initfont/ 2007-02-20 13:54:37 +01:00
Anselm R. Garbe
a1913a6af7 readded draw.c again (except getcolor and setfont) 2007-02-20 13:54:00 +01:00
Anselm R. Garbe
66b2e8379f removed -t, now using isatty() instead of select() to prevent execution from an interactive shell 2007-02-19 21:18:36 +01:00
Anselm R. Garbe
665488a6ee removed draw.c, implemented C-w handling (backward word deletion) 2007-02-19 15:49:50 +01:00
Anselm R. Garbe
1e01ca0317 Added tag 2.2 for changeset 90f0e34e7f11 2007-02-14 09:42:02 +01:00
Anselm R. Garbe
f3c12a7bff fixed Copyright notice in Makefile 2007-02-08 14:10:17 +01:00
Anselm R. Garbe
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
Anselm R. Garbe
2bac5599b3 letting dmenu appear at the bottom by default 2007-02-08 11:10:29 +01:00
Anselm R. Garbe
dbccf6fbff got rid of LD, inspired by JGs patch to wmii 2007-02-05 11:10:41 +01:00
Anselm R. Garbe
aea9bfec5e Added tag 2.1 for changeset 7656557298c9 2007-01-17 11:10:31 +01:00
Anselm R. Garbe
6175a39e8e hotfix changes 2007-01-17 11:10:26 +01:00
Anselm R. Garbe
2c7ff85f24 Added tag 2.1 for changeset d91c79020430 2007-01-17 11:10:09 +01:00
Anselm R. Garbe
447046f7ae Added tag 2.0 for changeset 1fce5c464fcd 2007-01-16 11:42:09 +01:00
Anselm R. Garbe
b76632b9e3 small fix 2007-01-16 11:39:26 +01:00
Anselm R. Garbe
f8f5b27036 removed useless mx, my 2007-01-16 11:38:31 +01:00
Anselm R. Garbe
d6bf35caad applied new default colors 2007-01-16 11:24:51 +01:00
Anselm R. Garbe
507c030b5b small fix of Control-j in dmenu.1 2007-01-16 11:07:30 +01:00
Anselm R. Garbe
0245394e4d Added tag 1.9 for changeset c7f5f4d54317 2007-01-12 12:43:44 +01:00
Anselm R. Garbe
b6cd6ed266 added evil key support to dmenu 2007-01-11 15:52:37 +01:00
Anselm R. Garbe
09813fcf2c s/Mod1-Shift-g/Mod1-G/ in fact Sander is right 2007-01-11 13:51:15 +01:00
Anselm R. Garbe
64d68b7de9 documenting undocumented vi-alike shortcuts of dmenu 2007-01-11 11:41:16 +01:00
Anselm R. Garbe
eaf8909378 commented recent Control-shortcut additions 2007-01-11 10:17:01 +01:00
Anselm R. Garbe
c0fcfb7827 applied Sanders dmenu_ctrlchars.patch (thanks!) 2007-01-10 23:07:03 +01:00
Anselm R. Garbe
a45d6983ab applied Alexis Hildebrandts patches 2007-01-10 18:06:16 +01:00
arg@mig29
08420a935b corrections 2007-01-02 15:44:32 +01:00
arg@mig29
deea1fb5ab corrected 2007-01-02 15:41:13 +01:00
arg@mig29
771c0cb607 next version will contain updated copyright notice 2007-01-02 15:38:44 +01:00
arg@mig29
43a19425af Added tag 1.8 for changeset d3e6fa22ae45b38b1bdb0d813390365e5930360b 2006-12-19 11:49:38 +01:00
arg@mig29
bbfd5391ac fixed a typo in dmenu.1 2006-12-19 11:49:28 +01:00
arg@mig29
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
arg@mig29
989649b5a5 added wmii reference to dmenu(1) 2006-12-18 13:46:44 +01:00
arg@mig29
f8d2a29a20 agreed with Sander 2006-12-18 13:25:11 +01:00
arg@mig29
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
arg@mig29
201b056e39 hotfix 2006-12-14 14:41:53 +01:00
arg@mig29
3dcdbe2a57 added vi-like key-bindings for keyboards without cursor keys (they are undocumented features) 2006-12-14 14:40:58 +01:00
arg@mig29
5336608a86 Added tag 1.7.1 for changeset 3696d77aaf02f5d15728dde3b9e35abcaf291496 2006-12-14 09:45:11 +01:00
arg@mig29
d398a2e318 foo 2006-12-14 09:45:06 +01:00
arg@mig29
2829009138 silent hotfix 2006-12-14 09:34:24 +01:00
arg@mig29
cae2fbdf38 Added tag 1.7.1 for changeset 8e0b9b09bf83c429c73e60a23997f32877a645bf 2006-12-14 09:30:31 +01:00
arg@mig29
225cd764c3 applied hotfix of sander 2006-12-14 09:30:23 +01:00
arg@mig29
279966a16f Added tag 1.7 for changeset 58dbef4aef3d45c7a3da6945e53c9667c0f02d5b 2006-12-14 08:51:21 +01:00
arg@mig29
9bd80b3968 changed text in dmenu manpage 2006-12-13 14:36:09 +01:00
arg@mig29
65912f2a96 added prompt option (-p 'prompt text'), documented in man page as well 2006-12-13 14:14:41 +01:00
arg@mig29
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
arg@mig29
e19e42adbb fixed diagnostic error message 2006-12-08 11:12:11 +01:00
arg@mig29
796c4fb9e5 removed hardcoded 'fixed' fallback, useless and misleading 2006-12-08 10:41:16 +01:00
arg@mig29
93c3f930c5 Added tag 1.6 for changeset dcc5427f99f51a978386a0dd770467cd911ac84b 2006-12-07 14:54:47 +01:00
arg@mig29
c69f397bb9 found compromise 2006-12-07 14:38:31 +01:00
arg@mig29
b9fbd59c8a people should define fixed being compatible with their locale 2006-12-07 12:03:47 +01:00
arg@mig29
da2b90ddd1 using -*-fixed-*-*-*-*-*-*-*-*-*-*-iso10646-* fixed by default 2006-12-07 11:55:46 +01:00
arg@mig29
dd7ee0dae1 also fixing dmenu accordingly 2006-12-07 10:06:06 +01:00
arg@mig29
250aa199bb only setting LC_CTYPE 2006-12-05 13:30:37 +01:00
arg@mig29
5d43e9243c enforcing using imcomplete fonsets anyways 2006-12-05 10:31:20 +01:00
arg@mig29
1026eb8308 Added tag 1.5 for changeset e071fb045bd9e8574947acff7196360bc0270e68 2006-11-30 09:21:14 +01:00
arg@mig29
c65fdd6252 next version will be 1.5 2006-11-26 15:49:47 +01:00
arg@mig29
8c20e5dbd3 fixing sizeof stuff 2006-11-26 15:49:33 +01:00
arg@mig29
26fbf124fa Added tag 1.4 for changeset df3fbb050004c544d14e43c36f6a94cca6ed4a69 2006-10-26 12:14:03 +02:00
Anselm R. Garbe
194d890517 removed misleading input cursor 2006-10-23 12:53:35 +02:00
Anselm R. Garbe
f633276774 fixing arg handling in dmenu (thanks to Sander for his report) 2006-10-23 10:12:09 +02:00
Anselm R. Garbe
bb480fb4b0 Added tag 1.3 for changeset 2eb9997be51cb1b11a8900728ccc0904f9371157 2006-10-13 11:08:35 +02:00
Anselm R. Garbe
95b19f75cc changing order 2006-10-12 12:59:37 +02:00
Anselm R. Garbe
3d25a327aa simplified util.c 2006-10-12 12:58:34 +02:00
Anselm R. Garbe
d78bcf247f simplified main event loop 2006-10-10 19:15:06 +02:00
Anselm R. Garbe
afaf66dc99 Added tag 1.2 for changeset bee7fe6d1189174d0204ca3195b83cdc1bb4f82e 2006-10-06 13:44:22 +02:00
Anselm R. Garbe
63be0ee22a small change 2006-10-06 12:40:49 +02:00
Anselm R. Garbe
ca973eb64e changing version info 2006-10-06 12:39:06 +02:00
Anselm R. Garbe
5fd7af18c6 removed useless newlines 2006-10-06 11:52:57 +02:00
arg@zarathustra
02238725f6 small update to man page (backported) 2006-09-26 17:51:22 +02:00
arg@zarathustra
2d5afd7c01 Added tag 1.1 for changeset e8c1e9733752db12f2dbd1fa93c46f5806242ba9 2006-09-26 17:39:04 +02:00
arg@mmvi
f7615e220e updated README 2006-09-26 14:31:42 +02:00
arg@mmvi
e7ecae0d58 removed crap from Makefile 2006-09-26 14:30:48 +02:00
arg@mmvi
b661ca75de error handling 2006-09-26 13:45:41 +02:00
arg@mmvi
c02da9f87e foo 2006-09-26 13:41:51 +02:00
arg@mmvi
14133be5bd reverting 2006-09-26 13:39:00 +02:00
arg@mmvi
3b590beda2 added fallback to color initialization 2006-09-26 13:37:36 +02:00
arg@mmvi
5c0d28e4ff removed config.h stuff, made dwm configurable due to command line options 2006-09-26 13:20:47 +02:00
arg@mmvi
e0fe9f2fca uriel didn't understood dmenu code, he broke nearly everything 2006-09-26 08:47:10 +02:00
arg@wmii.de
c9465859a6 applied a change made by Uriel to dmenu (though I didn't applied everything) 2006-09-26 08:43:41 +02:00
arg@mmvi
1716159e05 applied something similiar to Jukkas patch 2006-09-25 08:29:20 +02:00
arg@mmvi
11b6401668 Added tag 1.0 for changeset 9e11140d4cc3eecac3b0ab752f91528fd5e04be8 2006-09-16 11:20:54 +02:00
Anselm R. Garbe
81bcf078f6 made function signatures more consistent to my coding style 2006-09-12 10:59:00 +02:00
Anselm R. Garbe
0e5f467aa8 commented dmenu 2006-09-11 13:18:09 +02:00
Anselm R. Garbe
c51406b279 Added tag 0.9 for changeset d046c818ea467555cc338751c9bf3024609f1f12 2006-09-08 08:31:19 +02:00
Anselm R. Garbe
32f7fe4835 implemented early keyboard grab for dmenu with a timeout for stdin data writers to prevent endless grabbings of the keyboard 2006-09-08 07:33:20 +02:00
Anselm R. Garbe
0fa5a339ff new version of dmenu 2006-09-07 19:12:04 +02:00
Anselm R. Garbe
358f078c0b another fix 2006-09-07 09:40:09 +02:00
Anselm R. Garbe
1f207893e6 made dmenu.1 also concise 2006-09-07 09:36:53 +02:00
Anselm R. Garbe
1c5be1c553 Added tag 0.8 for changeset 409667a57221f7e50ba8b5248f638915cd61b366 2006-09-06 10:53:15 +02:00
Anselm R. Garbe
32ea45084b fixed man page 2006-09-04 19:47:09 +02:00
Anselm R. Garbe
cc7d863b6e Added tag 0.7 for changeset 5fc20d7158bd16b4d5f8d1c25e177680b6d54252 2006-09-04 17:17:08 +02:00
Anselm R. Garbe
04eade6a76 small change of main event loop 2006-09-04 07:28:03 +02:00
Anselm R. Garbe
49ce444d32 updated version 2006-08-28 12:26:25 +02:00
Anselm R. Garbe
2e9515ee27 Added tag 0.6 for changeset 25f679fb19686140a907684ffcb423b9e9d44b53 2006-08-28 10:20:10 +02:00
16 changed files with 929 additions and 718 deletions

32
.hgtags
View File

@@ -3,3 +3,35 @@ fcc8a282cb52c6a9343b461026b386825590cd31 0.1
d352e9dc112ee96aa5cad961a0ed880ae9ce7276 0.3
7acf0dde1120542917bae12e0e42293f9d2cc899 0.4
4a0ecd881c4fc15de4a0bebd79308b064be020ef 0.5
25f679fb19686140a907684ffcb423b9e9d44b53 0.6
5fc20d7158bd16b4d5f8d1c25e177680b6d54252 0.7
409667a57221f7e50ba8b5248f638915cd61b366 0.8
d046c818ea467555cc338751c9bf3024609f1f12 0.9
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
8f0f917ac988164e1b4446236e3a6ab6cfcb8c67 3.1
e4c81a78ffbad6ba4d1ad119cc654da6eca63a4c 3.2
709df5a4bad7015a346b2b44b1b3b573ea3088ff 3.3
9ab649b3b3e5bfccf1c8f352c59e5361e070a25f 3.4
05e5bd706b3b3e61399d57c4bb43df296a20112d 3.5

View File

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

View File

@@ -1,9 +1,9 @@
# dmenu - dynamic menu
# (C)opyright MMVI Anselm R. Garbe
# See LICENSE file for copyright and license details.
include config.mk
SRC = draw.c main.c util.c
SRC = dmenu.c
OBJ = ${SRC:.c=.o}
all: options dmenu
@@ -13,22 +13,16 @@ options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: dmenu.h config.h config.mk
config.h:
@echo creating $@ from config.default.h
@cp config.default.h $@
${OBJ}: config.h config.mk
dmenu: ${OBJ}
@echo LD $@
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@@ -37,8 +31,7 @@ clean:
dist: clean
@echo creating dist tarball
@mkdir -p dmenu-${VERSION}
@cp -R LICENSE Makefile README config.*.h config.mk \
dmenu.1 dmenu.h ${SRC} dmenu-${VERSION}
@cp -R LICENSE Makefile README config.mk dmenu.1 config.h dmenu_path dmenu_run ${SRC} dmenu-${VERSION}
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
@gzip dmenu-${VERSION}.tar
@rm -rf dmenu-${VERSION}
@@ -46,16 +39,19 @@ dist: clean
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dmenu ${DESTDIR}${PREFIX}/bin
@cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_path
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_run
@echo installing manual page to ${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
uninstall:
@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
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu ${DESTDIR}${PREFIX}/bin/dmenu_run
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1

10
README
View File

@@ -1,6 +1,6 @@
dmenu - dynamic menu
--------------------
dmenu is a generic, highly customizable, and efficient menu for X.
====================
dmenu is a generic and efficient menu for X.
Requirements
@@ -22,9 +22,3 @@ necessary as root):
Running dmenu
-------------
See the man page for details.
Configuration
-------------
The configuration of dmenu is done by creating a custom config.h
and (re)compiling the source code.

View File

@@ -1,10 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define SELBGCOLOR "#333366"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333333"
#define NORMFGCOLOR "#dddddd"

View File

@@ -1,10 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define FONT "fixed"
#define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc"

10
config.h Normal file
View File

@@ -0,0 +1,10 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
#define FONT "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"
#define NORMBGCOLOR "#cccccc"
#define NORMFGCOLOR "#000000"
#define SELBGCOLOR "#0066ff"
#define SELFGCOLOR "#ffffff"
/* next macro defines the space between menu items */
#define SPACE 30 /* px */

View File

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

126
dmenu.1
View File

@@ -1,64 +1,108 @@
.TH DMENU 1 dmenu-VERSION
.TH DMENU 1 dmenu\-VERSION
.SH NAME
dmenu \- dynamic menu
.SH SYNOPSIS
.B dmenu
.RB [ \-i ]
.RB [ \-x " <x>"]
.RB [ \-y " <y>"]
.RB [ \-w " <width>"]
.RB [ \-fn " <font>"]
.RB [ \-nb " <color>"]
.RB [ \-nf " <color>"]
.RB [ \-p " <prompt>"]
.RB [ \-sb " <color>"]
.RB [ \-sf " <color>"]
.RB [ \-v ]
.SH DESCRIPTION
.SS Overview
.B dmenu
is a generic, highly customizable, and efficient menu for X,
originally designed for
dmenu is a generic menu for X, originally designed for
.BR dwm (1).
It supports arbitrary, user defined menu contents.
It manages huge amounts (up to 10.000 and more) of user defined menu items
efficiently.
.SS Options
.TP
.B \-x
defines the x coordinate dmenu appears at (0 by default).
.TP
.B \-y
defines the y coordinate dmenu appears at (0 by default). If it is negative,
dmenu will appear with the bottom at the given positive coordinate. If it is
-0, dmenu appears at the screen bottom.
.TP
.B \-w
defines the width of the dmenu window (screen width by default).
.TP
.B \-i
makes dmenu match menu entries case insensitively.
.TP
.B \-fn <font>
defines the font.
.TP
.B \-nb <color>
defines the normal background color (#RGB, #RRGGBB, and color names are supported).
.TP
.B \-nf <color>
defines the normal foreground color (#RGB, #RRGGBB, and color names are supported).
.TP
.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).
.TP
.B \-sf <color>
defines the selected foreground color (#RGB, #RRGGBB, and color names are supported).
.TP
.B \-v
prints version information to standard output, then exits.
.SH USAGE
.B 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 choice
is printed to standard output and
.B dmenu
terminates.
.B dmenu
is completely controlled by the keyboard. The following keys are recognized:
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/her
choice is printed to standard output and dmenu terminates.
.P
dmenu is completely controlled by the keyboard. The following keys are recognized:
.TP
Any printable character
Appends the character to the text in the input field. This works as a filter:
.B Any printable character
Appends the character to the text in the input field. This works as a filter:
only items containing this text will be displayed.
.TP
Left/Right
.B Left/Right (Mod1\-h/Mod1\-l)
Select the previous/next item.
.TP
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.
.TP
Return
Confirm selection and quit (print the selected item to standard output).
.TP
Shift-Return
Confirm selection and quit (print the text in the input field to standard output).
.TP
Escape
Quit without selecting an item.
.TP
Backspace (Control-h)
Remove enough characters from the input field to change its filtering effect.
.TP
Control-u
Remove all characters from the input field.
.P
.B dmenu
returns
.B Return (Control\-j)
Confirm selection and quit (print the selected item to standard output). Returns
.B 0
if Return is pressed on termination,
on termination.
.TP
.B Shift\-Return (Control\-Shift\-j)
Confirm selection and quit (print the text in the input field to standard output).
Returns
.B 0
on termination.
.TP
.B Escape (Control\-bracketleft)
Quit without selecting an item. Returns
.B 1
if Escape is pressed.
.SH CUSTOMIZATION
.B dmenu
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
on termination.
.TP
.B Backspace (Control\-h)
Remove a character from the input field.
.TP
.B Control\-u
Remove all characters from the input field.
.TP
.B Control\-w
Remove all characters of current word from the input field.
.SH SEE ALSO
.BR dwm (1)
.BR dwm (1),
.BR wmii (1) .

749
dmenu.c Normal file
View File

@@ -0,0 +1,749 @@
/* See LICENSE file for copyright and license details. */
#include <ctype.h>
#include <limits.h>
#include <locale.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
/* macros */
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
/* enums */
enum { ColFG, ColBG, ColLast };
/* typedefs */
typedef struct {
int x, y, w, h;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
GC gc;
struct {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
int height;
} font;
} DC; /* draw context */
typedef struct Item Item;
struct Item {
char *text;
Item *next; /* traverses all items */
Item *left, *right; /* traverses items matching current search pattern */
};
/* forward declarations */
void appenditem(Item *i, Item **list, Item **last);
void calcoffsets(void);
char *cistrstr(const char *s, const char *sub);
void cleanup(void);
void drawmenu(void);
void drawtext(const char *text, unsigned long col[ColLast]);
void *emalloc(unsigned int size);
void eprint(const char *errstr, ...);
char *estrdup(const char *str);
unsigned long getcolor(const char *colstr);
Bool grabkeyboard(void);
void initfont(const char *fontstr);
void kpress(XKeyEvent * e);
void match(char *pattern);
void readstdin(void);
void run(void);
void setup(int x, int y, int w);
unsigned int textnw(const char *text, unsigned int len);
unsigned int textw(const char *text);
#include "config.h"
/* variables */
char *font = FONT;
char *maxname = NULL;
char *normbg = NORMBGCOLOR;
char *normfg = NORMFGCOLOR;
char *prompt = NULL;
char *selbg = SELBGCOLOR;
char *selfg = SELFGCOLOR;
char text[4096];
int screen;
int ret = 0;
unsigned int cmdw = 0;
unsigned int mw, mh;
unsigned int promptw = 0;
unsigned int numlockmask = 0;
Bool running = True;
Display *dpy;
DC dc = {0};
Item *allitems = NULL; /* first of all items */
Item *item = NULL; /* first of pattern matching items */
Item *sel = NULL;
Item *next = NULL;
Item *prev = NULL;
Item *curr = NULL;
Window root, win;
int (*fstrncmp)(const char *, const char *, size_t n) = strncmp;
char *(*fstrstr)(const char *, const char *) = strstr;
void
appenditem(Item *i, Item **list, Item **last) {
if(!(*last))
*list = i;
else
(*last)->right = i;
i->left = *last;
i->right = NULL;
*last = i;
}
void
calcoffsets(void) {
unsigned int tw, w;
if(!curr)
return;
w = promptw + cmdw + 2 * SPACE;
for(next = curr; next; next=next->right) {
tw = textw(next->text);
if(tw > mw / 3)
tw = mw / 3;
w += tw;
if(w > mw)
break;
}
w = promptw + cmdw + 2 * SPACE;
for(prev = curr; prev && prev->left; prev=prev->left) {
tw = textw(prev->left->text);
if(tw > mw / 3)
tw = mw / 3;
w += tw;
if(w > mw)
break;
}
}
char *
cistrstr(const char *s, const char *sub) {
int c, csub;
unsigned int len;
if(!sub)
return (char *)s;
if((c = *sub++) != 0) {
c = tolower(c);
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;
}
void
cleanup(void) {
Item *itm;
while(allitems) {
itm = allitems->next;
free(allitems->text);
free(allitems);
allitems = itm;
}
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
else
XFreeFont(dpy, dc.font.xfont);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, win);
XUngrabKeyboard(dpy, CurrentTime);
}
void
drawmenu(void) {
Item *i;
dc.x = 0;
dc.y = 0;
dc.w = mw;
dc.h = mh;
drawtext(NULL, dc.norm);
/* print prompt? */
if(promptw) {
dc.w = promptw;
drawtext(prompt, dc.sel);
}
dc.x += promptw;
dc.w = mw - promptw;
/* print command */
if(cmdw && item)
dc.w = cmdw;
drawtext(text[0] ? text : NULL, dc.norm);
dc.x += cmdw;
if(curr) {
dc.w = SPACE;
drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
dc.x += dc.w;
/* determine maximum items */
for(i = curr; i != next; i=i->right) {
dc.w = textw(i->text);
if(dc.w > mw / 3)
dc.w = mw / 3;
drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
dc.x += dc.w;
}
dc.x = mw - SPACE;
dc.w = SPACE;
drawtext(next ? ">" : NULL, dc.norm);
}
XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
XFlush(dpy);
}
void
drawtext(const char *text, unsigned long col[ColLast]) {
int x, y, w, h;
static char buf[256];
unsigned int len, olen;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text)
return;
w = 0;
olen = len = strlen(text);
if(len >= sizeof buf)
len = sizeof buf - 1;
memcpy(buf, text, len);
buf[len] = 0;
h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2);
/* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0;
if(len < olen) {
if(len > 1)
buf[len - 1] = '.';
if(len > 2)
buf[len - 2] = '.';
if(len > 3)
buf[len - 3] = '.';
}
if(w > dc.w)
return; /* too long */
XSetForeground(dpy, dc.gc, col[ColFG]);
if(dc.font.set)
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
else
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
void *
emalloc(unsigned int size) {
void *res = malloc(size);
if(!res)
eprint("fatal: could not malloc() %u bytes\n", size);
return res;
}
void
eprint(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
char *
estrdup(const char *str) {
void *res = strdup(str);
if(!res)
eprint("fatal: could not malloc() %u bytes\n", strlen(str));
return res;
}
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;
}
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;
}
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))
&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
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;
}
void
kpress(XKeyEvent * e) {
char buf[32];
int i, num;
unsigned int len;
KeySym ksym;
len = strlen(text);
buf[0] = 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)
|| IsMiscFunctionKey(ksym) || IsPFKey(ksym)
|| IsPrivateKeypadKey(ksym))
return;
/* first check if a control mask is omitted */
if(e->state & ControlMask) {
switch (ksym) {
default: /* ignore other control sequences */
return;
case XK_bracketleft:
ksym = XK_Escape;
break;
case XK_h:
case XK_H:
ksym = XK_BackSpace;
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:
text[0] = 0;
match(text);
drawmenu();
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;
}
}
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:
if(!(sel && sel->left))
return;
sel=sel->left;
if(sel->right == curr) {
curr = prev;
calcoffsets();
}
break;
case XK_Next:
if(!next)
return;
sel = curr = next;
calcoffsets();
break;
case XK_Prior:
if(!prev)
return;
sel = curr = prev;
calcoffsets();
break;
case XK_Return:
if((e->state & ShiftMask) && text)
fprintf(stdout, "%s", text);
else if(sel)
fprintf(stdout, "%s", sel->text);
else if(text)
fprintf(stdout, "%s", text);
fflush(stdout);
running = False;
break;
case XK_Right:
if(!(sel && sel->right))
return;
sel=sel->right;
if(sel == next) {
curr = next;
calcoffsets();
}
break;
case XK_Tab:
if(!sel)
return;
strncpy(text, sel->text, sizeof text);
match(text);
break;
}
drawmenu();
}
void
match(char *pattern) {
unsigned int plen;
Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
if(!pattern)
return;
plen = strlen(pattern);
item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL;
for(i = allitems; i; i = i->next)
if(!fstrncmp(pattern, i->text, plen + 1))
appenditem(i, &lexact, &exactend);
else if(!fstrncmp(pattern, i->text, plen))
appenditem(i, &lprefix, &prefixend);
else if(fstrstr(i->text, pattern))
appenditem(i, &lsubstr, &substrend);
if(lexact) {
item = lexact;
itemend = exactend;
}
if(lprefix) {
if(itemend) {
itemend->right = lprefix;
lprefix->left = itemend;
}
else
item = lprefix;
itemend = prefixend;
}
if(lsubstr) {
if(itemend) {
itemend->right = lsubstr;
lsubstr->left = itemend;
}
else
item = lsubstr;
}
curr = prev = next = sel = item;
calcoffsets();
}
void
readstdin(void) {
char *p, buf[1024];
unsigned int len = 0, max = 0;
Item *i, *new;
i = 0;
while(fgets(buf, sizeof buf, stdin)) {
len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len - 1] = 0;
p = estrdup(buf);
if(max < len) {
maxname = p;
max = len;
}
new = emalloc(sizeof(Item));
new->next = new->left = new->right = NULL;
new->text = p;
if(!i)
allitems = new;
else
i->next = new;
i = new;
}
}
void
run(void) {
XEvent ev;
/* main event loop */
while(running && !XNextEvent(dpy, &ev))
switch (ev.type) {
default: /* ignore all crap */
break;
case KeyPress:
kpress(&ev.xkey);
break;
case Expose:
if(ev.xexpose.count == 0)
drawmenu();
break;
}
}
void
setup(int x, int y, int w) {
unsigned int i, j;
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);
/* style */
dc.norm[ColBG] = getcolor(normbg);
dc.norm[ColFG] = getcolor(normfg);
dc.sel[ColBG] = getcolor(selbg);
dc.sel[ColFG] = getcolor(selfg);
initfont(font);
/* menu window */
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
mw = w ? w : DisplayWidth(dpy, screen);
mh = dc.font.height + 2;
if(y < 0) {
if(y == INT_MIN)
y = DisplayHeight(dpy, screen) - mh;
else
y = (-1 * y) - mh;
}
win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
/* pixmap */
dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
if(maxname)
cmdw = textw(maxname);
if(cmdw > mw / 3)
cmdw = mw / 3;
if(prompt)
promptw = textw(prompt);
if(promptw > mw / 5)
promptw = mw / 5;
text[0] = 0;
match(text);
XMapRaised(dpy, win);
}
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);
}
unsigned int
textw(const char *text) {
return textnw(text, strlen(text)) + dc.font.height;
}
int
main(int argc, char *argv[]) {
int x = 0, y = 0, w = 0;
unsigned int i;
/* command line args */
for(i = 1; i < argc; i++)
if(!strcmp(argv[i], "-i")) {
fstrncmp = strncasecmp;
fstrstr = cistrstr;
}
else if(!strcmp(argv[i], "-fn")) {
if(++i < argc) font = argv[i];
}
else if(!strcmp(argv[i], "-nb")) {
if(++i < argc) normbg = argv[i];
}
else if(!strcmp(argv[i], "-nf")) {
if(++i < argc) normfg = argv[i];
}
else if(!strcmp(argv[i], "-p")) {
if(++i < argc) prompt = argv[i];
}
else if(!strcmp(argv[i], "-sb")) {
if(++i < argc) selbg = argv[i];
}
else if(!strcmp(argv[i], "-sf")) {
if(++i < argc) selfg = argv[i];
}
else if(!strcmp(argv[i], "-x")) {
if(++i < argc) x = atoi(argv[i]);
}
else if(!strcmp(argv[i], "-y")) {
if(++i < argc)
if(!strcmp(argv[i], "-0"))
y = INT_MIN;
else
y = atoi(argv[i]);
}
else if(!strcmp(argv[i], "-w")) {
if(++i < argc) w = atoi(argv[i]);
}
else if(!strcmp(argv[i], "-v"))
eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
else
eprint("usage: dmenu [-i] [-fn <font>] [-nb <color>] [-nf <color>]\n"
" [-p <prompt>] [-sb <color>] [-sf <color>]\n"
" [-x <x>] [-y <y>] [-w <w>] [-v]\n");
setlocale(LC_CTYPE, "");
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dmenu: cannot open display\n");
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
if(isatty(STDIN_FILENO)) {
readstdin();
running = grabkeyboard();
}
else { /* prevent keypress loss */
running = grabkeyboard();
readstdin();
}
setup(x, y, w);
drawmenu();
XSync(dpy, False);
run();
cleanup();
XCloseDisplay(dpy);
return ret;
}

48
dmenu.h
View File

@@ -1,48 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "config.h"
#include <X11/Xlib.h>
#include <X11/Xlocale.h>
#define SPACE 30 /* px */
/* color */
enum { ColFG, ColBG, ColLast };
typedef struct DC DC;
typedef struct Fnt Fnt;
struct Fnt {
XFontStruct *xfont;
XFontSet set;
int ascent;
int descent;
int height;
};
struct DC { /* draw context */
int x, y, w, h;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
Fnt font;
GC gc;
};
extern int screen;
extern Display *dpy;
extern DC dc;
/* draw.c */
extern void drawtext(const char *text, unsigned long col[ColLast]);
extern unsigned long getcolor(const char *colstr);
extern void setfont(const char *fontstr);
extern unsigned int textw(const char *text);
/* util.c */
extern void *emalloc(unsigned int size);
extern void eprint(const char *errstr, ...);
extern char *estrdup(const char *str);

26
dmenu_path Executable file
View File

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

2
dmenu_run Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exe=`dmenu_path | dmenu $*` && exec $exe

143
draw.c
View File

@@ -1,143 +0,0 @@
/*
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dmenu.h"
#include <stdio.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 */
void
drawtext(const char *text, unsigned long col[ColLast])
{
int x, y, w, h;
static char buf[256];
unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text)
return;
w = 0;
olen = len = strlen(text);
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
memcpy(buf, text, len);
buf[len] = 0;
h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2);
/* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0;
if(len < olen) {
if(len > 1)
buf[len - 1] = '.';
if(len > 2)
buf[len - 2] = '.';
if(len > 3)
buf[len - 3] = '.';
}
if(w > dc.w)
return; /* too long */
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;
XAllocNamedColor(dpy, cmap, colstr, &color, &color);
return color.pixel;
}
void
setfont(const char *fontstr)
{
char **missing, *def;
int i, n;
missing = NULL;
setlocale(LC_ALL, "");
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) {
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
textw(const char *text)
{
return textnw(text, strlen(text)) + dc.font.height;
}

386
main.c
View File

@@ -1,386 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam 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.
*/
#include "dmenu.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
typedef struct Item Item;
struct Item {
Item *next; /* traverses all items */
Item *left, *right; /* traverses items matching current search pattern */
char *text;
};
/* static */
static char text[4096];
static int mx, my, mw, mh;
static int ret = 0;
static int nitem = 0;
static unsigned int cmdw = 0;
static Bool running = True;
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 root;
static Window win;
static void
calcoffsets()
{
unsigned int tw, w;
if(!curr)
return;
w = cmdw + 2 * SPACE;
for(next = curr; next; next=next->right) {
tw = textw(next->text);
if(tw > mw / 3)
tw = mw / 3;
w += tw;
if(w > mw)
break;
}
w = cmdw + 2 * SPACE;
for(prev = curr; prev && prev->left; prev=prev->left) {
tw = textw(prev->left->text);
if(tw > mw / 3)
tw = mw / 3;
w += tw;
if(w > mw)
break;
}
}
static void
drawmenu()
{
Item *i;
dc.x = 0;
dc.y = 0;
dc.w = mw;
dc.h = mh;
drawtext(NULL, dc.norm);
/* print command */
if(cmdw && item)
dc.w = cmdw;
drawtext(text[0] ? text : NULL, dc.norm);
dc.x += cmdw;
if(curr) {
dc.w = SPACE;
drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
dc.x += dc.w;
/* determine maximum items */
for(i = curr; i != next; i=i->right) {
dc.w = textw(i->text);
if(dc.w > mw / 3)
dc.w = mw / 3;
drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
dc.x += dc.w;
}
dc.x = mw - SPACE;
dc.w = SPACE;
drawtext(next ? ">" : NULL, dc.norm);
}
XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
XFlush(dpy);
}
static void
match(char *pattern)
{
unsigned int plen;
Item *i, *j;
if(!pattern)
return;
plen = strlen(pattern);
item = j = NULL;
nitem = 0;
for(i = allitems; i; i=i->next)
if(!plen || !strncmp(pattern, i->text, plen)) {
if(!j)
item = i;
else
j->right = i;
i->left = j;
i->right = NULL;
j = i;
nitem++;
}
for(i = allitems; i; i=i->next)
if(plen && strncmp(pattern, i->text, plen)
&& strstr(i->text, pattern)) {
if(!j)
item = i;
else
j->right = i;
i->left = j;
i->right = NULL;
j = i;
nitem++;
}
curr = prev = next = sel = item;
calcoffsets();
}
static void
kpress(XKeyEvent * e)
{
char buf[32];
int num, prev_nitem;
unsigned int i, len;
KeySym ksym;
len = strlen(text);
buf[0] = 0;
num = XLookupString(e, buf, sizeof(buf), &ksym, 0);
if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
|| IsMiscFunctionKey(ksym) || IsPFKey(ksym)
|| IsPrivateKeypadKey(ksym))
return;
/* first check if a control mask is omitted */
if(e->state & ControlMask) {
switch (ksym) {
default: /* ignore other control sequences */
return;
break;
case XK_h:
case XK_H:
ksym = XK_BackSpace;
break;
case XK_u:
case XK_U:
text[0] = 0;
match(text);
drawmenu();
return;
break;
}
}
switch(ksym) {
case XK_Left:
if(!(sel && sel->left))
return;
sel=sel->left;
if(sel->right == curr) {
curr = prev;
calcoffsets();
}
break;
case XK_Tab:
if(!sel)
return;
strncpy(text, sel->text, sizeof(text));
match(text);
break;
case XK_Right:
if(!(sel && sel->right))
return;
sel=sel->right;
if(sel == next) {
curr = next;
calcoffsets();
}
break;
case XK_Return:
if(e->state & ShiftMask) {
if(text)
fprintf(stdout, "%s", text);
}
else if(sel)
fprintf(stdout, "%s", sel->text);
else if(text)
fprintf(stdout, "%s", text);
fflush(stdout);
running = False;
break;
case XK_Escape:
ret = 1;
running = False;
break;
case XK_BackSpace:
if((i = len)) {
prev_nitem = nitem;
do {
text[--i] = 0;
match(text);
} while(i && nitem && prev_nitem == nitem);
match(text);
}
break;
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);
}
}
drawmenu();
}
static char *
readstdin()
{
static char *maxname = NULL;
char *p, buf[1024];
unsigned int len = 0, max = 0;
Item *i, *new;
i = 0;
while(fgets(buf, sizeof(buf), stdin)) {
len = strlen(buf);
if (buf[len - 1] == '\n')
buf[len - 1] = 0;
p = estrdup(buf);
if(max < len) {
maxname = p;
max = len;
}
new = emalloc(sizeof(Item));
new->next = new->left = new->right = NULL;
new->text = p;
if(!i)
allitems = new;
else
i->next = new;
i = new;
}
return maxname;
}
/* extern */
int screen;
Display *dpy;
DC dc = {0};
int
main(int argc, char *argv[])
{
char *maxname;
Item *i;
XEvent ev;
XSetWindowAttributes wa;
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
fputs("dmenu-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
else if(argc != 1)
eprint("usage: dmenu [-v]\n");
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dmenu: cannot open display\n");
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
maxname = readstdin();
/* grab as early as possible, but after reading all items!!! */
while(XGrabKeyboard(dpy, root, True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess)
usleep(1000);
/* style */
dc.sel[ColBG] = getcolor(SELBGCOLOR);
dc.sel[ColFG] = getcolor(SELFGCOLOR);
dc.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR);
setfont(FONT);
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask;
mx = my = 0;
mw = DisplayWidth(dpy, screen);
mh = dc.font.height + 2;
win = XCreateWindow(dpy, root, mx, my, mw, mh, 0,
DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));
/* pixmap */
dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(maxname)
cmdw = textw(maxname);
if(cmdw > mw / 3)
cmdw = mw / 3;
text[0] = 0;
match(text);
XMapRaised(dpy, win);
drawmenu();
XSync(dpy, False);
/* main event loop */
while(running && !XNextEvent(dpy, &ev)) {
switch (ev.type) {
case KeyPress:
kpress(&ev.xkey);
break;
case Expose:
if(ev.xexpose.count == 0)
drawmenu();
break;
default:
break;
}
}
XUngrabKeyboard(dpy, CurrentTime);
while(allitems) {
i = allitems->next;
free(allitems->text);
free(allitems);
allitems = i;
}
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
else
XFreeFont(dpy, dc.font.xfont);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return ret;
}

50
util.c
View File

@@ -1,50 +0,0 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dmenu.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.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 *
emalloc(unsigned int size)
{
void *res = malloc(size);
if(!res)
badmalloc(size);
return res;
}
void
eprint(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
char *
estrdup(const char *str)
{
void *res = strdup(str);
if(!res)
badmalloc(strlen(str));
return res;
}