@ -35,16 +35,16 @@ struct Item {
bool out ;
bool out ;
} ;
} ;
static void appenditem ( Item * item , Item * * list , Item * * last ) ;
static void appenditem ( Item * , Item * * , Item * * ) ;
static void calcoffsets ( void ) ;
static void calcoffsets ( void ) ;
static char * cistrstr ( const char * s , const char * sub ) ;
static char * cistrstr ( const char * , const char * ) ;
static void cleanup ( void ) ;
static void cleanup ( void ) ;
static void drawmenu ( void ) ;
static void drawmenu ( void ) ;
static void grabkeyboard ( void ) ;
static void grabkeyboard ( void ) ;
static void insert ( const char * str , ssize_t n ) ;
static void insert ( const char * , ssize_t ) ;
static void keypress ( XKeyEvent * ev ) ;
static void keypress ( XKeyEvent * ) ;
static void match ( void ) ;
static void match ( void ) ;
static size_t nextrune ( int inc ) ;
static size_t nextrune ( int ) ;
static void paste ( void ) ;
static void paste ( void ) ;
static void readstdin ( void ) ;
static void readstdin ( void ) ;
static void run ( void ) ;
static void run ( void ) ;
@ -53,99 +53,30 @@ static void usage(void);
static char text [ BUFSIZ ] = " " ;
static char text [ BUFSIZ ] = " " ;
static int bh , mw , mh ;
static int bh , mw , mh ;
static int sw , sh ; /* X display screen geometry width, height */
static int inputw , promptw ;
static int inputw , promptw ;
static size_t cursor = 0 ;
static size_t cursor ;
static Atom clip , utf8 ;
static Item * items = NULL ;
static Item * items = NULL ;
static Item * matches , * matchend ;
static Item * matches , * matchend ;
static Item * prev , * curr , * next , * sel ;
static Item * prev , * curr , * next , * sel ;
static Window win ;
static int mon = - 1 , screen ;
static Atom clip , utf8 ;
static Display * dpy ;
static Window root , win ;
static XIC xic ;
static XIC xic ;
static int mon = - 1 ;
static ClrScheme scheme [ SchemeLast ] ;
static ClrScheme scheme [ SchemeLast ] ;
static Display * dpy ;
static int screen ;
static Window root ;
static Drw * drw ;
static Drw * drw ;
static int sw , sh ; /* X display screen geometry width, height */
# include "config.h"
# include "config.h"
static int ( * fstrncmp ) ( const char * , const char * , size_t ) = strncmp ;
static int ( * fstrncmp ) ( const char * , const char * , size_t ) = strncmp ;
static char * ( * fstrstr ) ( const char * , const char * ) = strstr ;
static char * ( * fstrstr ) ( const char * , const char * ) = strstr ;
int
static void
main ( int argc , char * argv [ ] ) {
appenditem ( Item * item , Item * * list , Item * * last )
bool fast = false ;
{
int i ;
for ( i = 1 ; i < argc ; i + + )
/* these options take no arguments */
if ( ! strcmp ( argv [ i ] , " -v " ) ) { /* prints version information */
puts ( " dmenu- " VERSION " , © 2006-2015 dmenu engineers, see LICENSE for details " ) ;
exit ( 0 ) ;
}
else if ( ! strcmp ( argv [ i ] , " -b " ) ) /* appears at the bottom of the screen */
topbar = false ;
else if ( ! strcmp ( argv [ i ] , " -f " ) ) /* grabs keyboard before reading stdin */
fast = true ;
else if ( ! strcmp ( argv [ i ] , " -i " ) ) { /* case-insensitive item matching */
fstrncmp = strncasecmp ;
fstrstr = cistrstr ;
}
else if ( i + 1 = = argc )
usage ( ) ;
/* these options take one argument */
else if ( ! strcmp ( argv [ i ] , " -l " ) ) /* number of lines in vertical list */
lines = atoi ( argv [ + + i ] ) ;
else if ( ! strcmp ( argv [ i ] , " -m " ) )
mon = atoi ( argv [ + + i ] ) ;
else if ( ! strcmp ( argv [ i ] , " -p " ) ) /* adds prompt to left of input field */
prompt = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -fn " ) ) /* font or font set */
fonts [ 0 ] = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -nb " ) ) /* normal background color */
normbgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -nf " ) ) /* normal foreground color */
normfgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -sb " ) ) /* selected background color */
selbgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -sf " ) ) /* selected foreground color */
selfgcolor = argv [ + + i ] ;
else
usage ( ) ;
if ( ! setlocale ( LC_CTYPE , " " ) | | ! XSupportsLocale ( ) )
fputs ( " warning: no locale support \n " , stderr ) ;
if ( ! ( dpy = XOpenDisplay ( NULL ) ) )
die ( " dmenu: cannot open display \n " ) ;
screen = DefaultScreen ( dpy ) ;
root = RootWindow ( dpy , screen ) ;
sw = DisplayWidth ( dpy , screen ) ;
sh = DisplayHeight ( dpy , screen ) ;
drw = drw_create ( dpy , screen , root , sw , sh ) ;
drw_load_fonts ( drw , fonts , LENGTH ( fonts ) ) ;
if ( ! drw - > fontcount )
die ( " No fonts could be loaded. \n " ) ;
drw_setscheme ( drw , & scheme [ SchemeNorm ] ) ;
if ( fast ) {
grabkeyboard ( ) ;
readstdin ( ) ;
}
else {
readstdin ( ) ;
grabkeyboard ( ) ;
}
setup ( ) ;
run ( ) ;
return 1 ; /* unreachable */
}
void
appenditem ( Item * item , Item * * list , Item * * last ) {
if ( * last )
if ( * last )
( * last ) - > right = item ;
( * last ) - > right = item ;
else
else
@ -156,8 +87,9 @@ appenditem(Item *item, Item **list, Item **last) {
* last = item ;
* last = item ;
}
}
void
static void
calcoffsets ( void ) {
calcoffsets ( void )
{
int i , n ;
int i , n ;
if ( lines > 0 )
if ( lines > 0 )
@ -173,8 +105,9 @@ calcoffsets(void) {
break ;
break ;
}
}
void
static void
cleanup ( void ) {
cleanup ( void )
{
XUngrabKey ( dpy , AnyKey , AnyModifier , root ) ;
XUngrabKey ( dpy , AnyKey , AnyModifier , root ) ;
drw_clr_free ( scheme [ SchemeNorm ] . bg ) ;
drw_clr_free ( scheme [ SchemeNorm ] . bg ) ;
drw_clr_free ( scheme [ SchemeNorm ] . fg ) ;
drw_clr_free ( scheme [ SchemeNorm ] . fg ) ;
@ -187,8 +120,9 @@ cleanup(void) {
XCloseDisplay ( dpy ) ;
XCloseDisplay ( dpy ) ;
}
}
char *
static char *
cistrstr ( const char * s , const char * sub ) {
cistrstr ( const char * s , const char * sub )
{
size_t len ;
size_t len ;
for ( len = strlen ( sub ) ; * s ; s + + )
for ( len = strlen ( sub ) ; * s ; s + + )
@ -197,8 +131,9 @@ cistrstr(const char *s, const char *sub) {
return NULL ;
return NULL ;
}
}
void
static void
drawmenu ( void ) {
drawmenu ( void )
{
int curpos ;
int curpos ;
Item * item ;
Item * item ;
int x = 0 , y = 0 , h = bh , w ;
int x = 0 , y = 0 , h = bh , w ;
@ -235,8 +170,7 @@ drawmenu(void) {
drw_text ( drw , x , y , w , bh , item - > text , 0 ) ;
drw_text ( drw , x , y , w , bh , item - > text , 0 ) ;
}
}
}
} else if ( matches ) {
else if ( matches ) {
/* draw horizontal list */
/* draw horizontal list */
x + = inputw ;
x + = inputw ;
w = TEXTW ( " < " ) ;
w = TEXTW ( " < " ) ;
@ -266,8 +200,9 @@ drawmenu(void) {
drw_map ( drw , win , 0 , 0 , mw , mh ) ;
drw_map ( drw , win , 0 , 0 , mw , mh ) ;
}
}
void
static void
grabkeyboard ( void ) {
grabkeyboard ( void )
{
int i ;
int i ;
/* try to grab keyboard, we may have to wait for another process to ungrab */
/* try to grab keyboard, we may have to wait for another process to ungrab */
@ -280,8 +215,9 @@ grabkeyboard(void) {
die ( " cannot grab keyboard \n " ) ;
die ( " cannot grab keyboard \n " ) ;
}
}
void
static void
insert ( const char * str , ssize_t n ) {
insert ( const char * str , ssize_t n )
{
if ( strlen ( text ) + n > sizeof text - 1 )
if ( strlen ( text ) + n > sizeof text - 1 )
return ;
return ;
/* move existing text out of the way, insert new text, and update cursor */
/* move existing text out of the way, insert new text, and update cursor */
@ -292,8 +228,9 @@ insert(const char *str, ssize_t n) {
match ( ) ;
match ( ) ;
}
}
void
static void
keypress ( XKeyEvent * ev ) {
keypress ( XKeyEvent * ev )
{
char buf [ 32 ] ;
char buf [ 32 ] ;
int len ;
int len ;
KeySym ksym = NoSymbol ;
KeySym ksym = NoSymbol ;
@ -461,8 +398,9 @@ keypress(XKeyEvent *ev) {
drawmenu ( ) ;
drawmenu ( ) ;
}
}
void
static void
match ( void ) {
match ( void )
{
static char * * tokv = NULL ;
static char * * tokv = NULL ;
static int tokn = 0 ;
static int tokn = 0 ;
@ -497,8 +435,7 @@ match(void) {
if ( matches ) {
if ( matches ) {
matchend - > right = lprefix ;
matchend - > right = lprefix ;
lprefix - > left = matchend ;
lprefix - > left = matchend ;
}
} else
else
matches = lprefix ;
matches = lprefix ;
matchend = prefixend ;
matchend = prefixend ;
}
}
@ -506,8 +443,7 @@ match(void) {
if ( matches ) {
if ( matches ) {
matchend - > right = lsubstr ;
matchend - > right = lsubstr ;
lsubstr - > left = matchend ;
lsubstr - > left = matchend ;
}
} else
else
matches = lsubstr ;
matches = lsubstr ;
matchend = substrend ;
matchend = substrend ;
}
}
@ -515,17 +451,20 @@ match(void) {
calcoffsets ( ) ;
calcoffsets ( ) ;
}
}
size_t
static size_t
nextrune ( int inc ) {
nextrune ( int inc )
{
ssize_t n ;
ssize_t n ;
/* return location of next utf8 rune in the given direction (+1 or -1) */
/* return location of next utf8 rune in the given direction (+1 or -1) */
for ( n = cursor + inc ; n + inc > = 0 & & ( text [ n ] & 0xc0 ) = = 0x80 ; n + = inc ) ;
for ( n = cursor + inc ; n + inc > = 0 & & ( text [ n ] & 0xc0 ) = = 0x80 ; n + = inc )
;
return n ;
return n ;
}
}
void
static void
paste ( void ) {
paste ( void )
{
char * p , * q ;
char * p , * q ;
int di ;
int di ;
unsigned long dl ;
unsigned long dl ;
@ -539,8 +478,9 @@ paste(void) {
drawmenu ( ) ;
drawmenu ( ) ;
}
}
void
static void
readstdin ( void ) {
readstdin ( void )
{
char buf [ sizeof text ] , * p , * maxstr = NULL ;
char buf [ sizeof text ] , * p , * maxstr = NULL ;
size_t i , max = 0 , size = 0 ;
size_t i , max = 0 , size = 0 ;
@ -563,8 +503,9 @@ readstdin(void) {
lines = MIN ( lines , i ) ;
lines = MIN ( lines , i ) ;
}
}
void
static void
run ( void ) {
run ( void )
{
XEvent ev ;
XEvent ev ;
while ( ! XNextEvent ( dpy , & ev ) ) {
while ( ! XNextEvent ( dpy , & ev ) ) {
@ -590,8 +531,9 @@ run(void) {
}
}
}
}
void
static void
setup ( void ) {
setup ( void )
{
int x , y ;
int x , y ;
XSetWindowAttributes swa ;
XSetWindowAttributes swa ;
XIM xim ;
XIM xim ;
@ -647,8 +589,7 @@ setup(void) {
y = info [ i ] . y_org + ( topbar ? 0 : info [ i ] . height - mh ) ;
y = info [ i ] . y_org + ( topbar ? 0 : info [ i ] . height - mh ) ;
mw = info [ i ] . width ;
mw = info [ i ] . width ;
XFree ( info ) ;
XFree ( info ) ;
}
} else
else
# endif
# endif
{
{
x = 0 ;
x = 0 ;
@ -678,9 +619,77 @@ setup(void) {
drawmenu ( ) ;
drawmenu ( ) ;
}
}
void
static void
usage ( void ) {
usage ( void )
{
fputs ( " usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor] \n "
fputs ( " usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor] \n "
" [-nb color] [-nf color] [-sb color] [-sf color] [-v] \n " , stderr ) ;
" [-nb color] [-nf color] [-sb color] [-sf color] [-v] \n " , stderr ) ;
exit ( 1 ) ;
exit ( 1 ) ;
}
}
int
main ( int argc , char * argv [ ] )
{
bool fast = false ;
int i ;
for ( i = 1 ; i < argc ; i + + )
/* these options take no arguments */
if ( ! strcmp ( argv [ i ] , " -v " ) ) { /* prints version information */
puts ( " dmenu- " VERSION ) ;
exit ( 0 ) ;
} else if ( ! strcmp ( argv [ i ] , " -b " ) ) /* appears at the bottom of the screen */
topbar = false ;
else if ( ! strcmp ( argv [ i ] , " -f " ) ) /* grabs keyboard before reading stdin */
fast = true ;
else if ( ! strcmp ( argv [ i ] , " -i " ) ) { /* case-insensitive item matching */
fstrncmp = strncasecmp ;
fstrstr = cistrstr ;
} else if ( i + 1 = = argc )
usage ( ) ;
/* these options take one argument */
else if ( ! strcmp ( argv [ i ] , " -l " ) ) /* number of lines in vertical list */
lines = atoi ( argv [ + + i ] ) ;
else if ( ! strcmp ( argv [ i ] , " -m " ) )
mon = atoi ( argv [ + + i ] ) ;
else if ( ! strcmp ( argv [ i ] , " -p " ) ) /* adds prompt to left of input field */
prompt = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -fn " ) ) /* font or font set */
fonts [ 0 ] = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -nb " ) ) /* normal background color */
normbgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -nf " ) ) /* normal foreground color */
normfgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -sb " ) ) /* selected background color */
selbgcolor = argv [ + + i ] ;
else if ( ! strcmp ( argv [ i ] , " -sf " ) ) /* selected foreground color */
selfgcolor = argv [ + + i ] ;
else
usage ( ) ;
if ( ! setlocale ( LC_CTYPE , " " ) | | ! XSupportsLocale ( ) )
fputs ( " warning: no locale support \n " , stderr ) ;
if ( ! ( dpy = XOpenDisplay ( NULL ) ) )
die ( " cannot open display \n " ) ;
screen = DefaultScreen ( dpy ) ;
root = RootWindow ( dpy , screen ) ;
sw = DisplayWidth ( dpy , screen ) ;
sh = DisplayHeight ( dpy , screen ) ;
drw = drw_create ( dpy , screen , root , sw , sh ) ;
drw_load_fonts ( drw , fonts , LENGTH ( fonts ) ) ;
if ( ! drw - > fontcount )
die ( " no fonts could be loaded. \n " ) ;
drw_setscheme ( drw , & scheme [ SchemeNorm ] ) ;
if ( fast ) {
grabkeyboard ( ) ;
readstdin ( ) ;
} else {
readstdin ( ) ;
grabkeyboard ( ) ;
}
setup ( ) ;
run ( ) ;
return 1 ; /* unreachable */
}