1
0
Fork 0
mirror of https://github.com/davatorium/rofi.git synced 2024-11-25 13:55:34 -05:00

Indent the bunch with my astyle line.

This commit is contained in:
Qball Cow 2014-01-10 10:35:38 +01:00
parent bad311adab
commit b47f22ca51
3 changed files with 961 additions and 886 deletions

View file

@ -24,12 +24,16 @@ normal:
debug: debug:
$(CC) -o simpleswitcher-debug simpleswitcher.c -std=c99 $(CFLAGS) -Wunused-parameter -g -DDEBUG $(LDADD) $(CC) -o simpleswitcher-debug simpleswitcher.c -std=c99 $(CFLAGS) -Wunused-parameter -g -DDEBUG $(LDADD)
install: install-man install: normal install-man
install -Dm 755 simpleswitcher $(BINDIR)/simpleswitcher install -Dm 755 simpleswitcher $(BINDIR)/simpleswitcher
install-man: install-man:
install -Dm 644 simpleswitcher.1 $(MANDIR) install -Dm 644 simpleswitcher.1 $(MANDIR)
gzip $(MANDIR)/simpleswitcher.1 gzip -f $(MANDIR)/simpleswitcher.1
clean: clean:
rm -f simpleswitcher simpleswitcher-debug rm -f simpleswitcher simpleswitcher-debug
indent:
@astyle --style=linux -S -C -D -N -H -L -W3 -f simpleswitcher.c textbox.c

View file

@ -61,11 +61,12 @@
static void* allocate( unsigned long bytes ) static void* allocate( unsigned long bytes )
{ {
void *ptr = malloc( bytes ); void *ptr = malloc( bytes );
if (!ptr)
{ if ( !ptr ) {
fprintf( stderr, "malloc failed!\n" ); fprintf( stderr, "malloc failed!\n" );
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
} }
return ptr; return ptr;
} }
static void* allocate_clear( unsigned long bytes ) static void* allocate_clear( unsigned long bytes )
@ -77,17 +78,19 @@ static void* allocate_clear(unsigned long bytes)
static void* reallocate( void *ptr, unsigned long bytes ) static void* reallocate( void *ptr, unsigned long bytes )
{ {
ptr = realloc( ptr, bytes ); ptr = realloc( ptr, bytes );
if (!ptr)
{ if ( !ptr ) {
fprintf( stderr, "realloc failed!\n" ); fprintf( stderr, "realloc failed!\n" );
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
} }
return ptr; return ptr;
} }
static inline char **tokenize( const char *input ) static inline char **tokenize( const char *input )
{ {
if ( input == NULL ) return NULL; if ( input == NULL ) return NULL;
char *saveptr = NULL, *token; char *saveptr = NULL, *token;
char **retv = NULL; char **retv = NULL;
// First entry is always full (modified) stringtext. // First entry is always full (modified) stringtext.
@ -102,8 +105,7 @@ static inline char **tokenize(const char *input)
for ( for (
token = strtok_r( retv[0], " ", &saveptr ); token = strtok_r( retv[0], " ", &saveptr );
token != NULL; token != NULL;
token = strtok_r(NULL, " ", &saveptr)) token = strtok_r( NULL, " ", &saveptr ) ) {
{
retv = realloc( retv, sizeof( char* )*( num_tokens+2 ) ); retv = realloc( retv, sizeof( char* )*( num_tokens+2 ) );
retv[num_tokens+1] = NULL; retv[num_tokens+1] = NULL;
retv[num_tokens] = token; retv[num_tokens] = token;
@ -116,8 +118,10 @@ static inline char **tokenize(const char *input)
static inline void tokenize_free( char **ip ) static inline void tokenize_free( char **ip )
{ {
if ( ip == NULL ) return; if ( ip == NULL ) return;
if ( ip[0] ) if ( ip[0] )
free( ip[0] ); free( ip[0] );
free( ip ); free( ip );
} }
@ -136,21 +140,25 @@ int execsh(char *cmd)
pid_t exec_cmd( char *cmd ) pid_t exec_cmd( char *cmd )
{ {
if ( !cmd || !cmd[0] ) return -1; if ( !cmd || !cmd[0] ) return -1;
signal( SIGCHLD, catch_exit ); signal( SIGCHLD, catch_exit );
pid_t pid = fork(); pid_t pid = fork();
if (!pid)
{ if ( !pid ) {
setsid(); setsid();
execsh( cmd ); execsh( cmd );
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
} }
return pid; return pid;
} }
// cli arg handling // cli arg handling
static int find_arg( const int argc, char * const argv[], const char * const key ) static int find_arg( const int argc, char * const argv[], const char * const key )
{ {
int i; int i;
for ( i = 0; i < argc && strcasecmp( argv[i], key ); i++ ); for ( i = 0; i < argc && strcasecmp( argv[i], key ); i++ );
return i < argc ? i: -1; return i < argc ? i: -1;
} }
static char* find_arg_str( int argc, char *argv[], char *key, char* def ) static char* find_arg_str( int argc, char *argv[], char *key, char* def )
@ -165,7 +173,8 @@ static int find_arg_int(int argc, char *argv[], char *key, int def)
} }
unsigned int NumlockMask = 0; unsigned int NumlockMask = 0;
Display *display; Screen *screen; Display *display;
Screen *screen;
Window root; Window root;
int screen_id; int screen_id;
@ -228,6 +237,7 @@ int oops(__attribute__((unused)) Display *d, XErrorEvent *ee)
|| ( ee->request_code == X_GrabButton && ee->error_code == BadAccess ) || ( ee->request_code == X_GrabButton && ee->error_code == BadAccess )
|| ( ee->request_code == X_GrabKey && ee->error_code == BadAccess ) || ( ee->request_code == X_GrabKey && ee->error_code == BadAccess )
) return 0; ) return 0;
fprintf( stderr, "error: request code=%d, error code=%d\n", ee->request_code, ee->error_code ); fprintf( stderr, "error: request code=%d, error code=%d\n", ee->request_code, ee->error_code );
return xerror( display, ee ); return xerror( display, ee );
} }
@ -255,18 +265,19 @@ winlist *cache_xattr;
winlist* winlist_new() winlist* winlist_new()
{ {
winlist *l = allocate(sizeof(winlist)); l->len = 0; winlist *l = allocate( sizeof( winlist ) );
l->len = 0;
l->array = allocate( sizeof( Window ) * ( WINLIST+1 ) ); l->array = allocate( sizeof( Window ) * ( WINLIST+1 ) );
l->data = allocate( sizeof( void* ) * ( WINLIST+1 ) ); l->data = allocate( sizeof( void* ) * ( WINLIST+1 ) );
return l; return l;
} }
int winlist_append( winlist *l, Window w, void *d ) int winlist_append( winlist *l, Window w, void *d )
{ {
if (l->len > 0 && !(l->len % WINLIST)) if ( l->len > 0 && !( l->len % WINLIST ) ) {
{
l->array = reallocate( l->array, sizeof( Window ) * ( l->len+WINLIST+1 ) ); l->array = reallocate( l->array, sizeof( Window ) * ( l->len+WINLIST+1 ) );
l->data = reallocate( l->data, sizeof( void* ) * ( l->len+WINLIST+1 ) ); l->data = reallocate( l->data, sizeof( void* ) * ( l->len+WINLIST+1 ) );
} }
l->data[l->len] = d; l->data[l->len] = d;
l->array[l->len++] = w; l->array[l->len++] = w;
return l->len-1; return l->len-1;
@ -277,7 +288,10 @@ void winlist_empty(winlist *l)
} }
void winlist_free( winlist *l ) void winlist_free( winlist *l )
{ {
winlist_empty(l); free(l->array); free(l->data); free(l); winlist_empty( l );
free( l->array );
free( l->data );
free( l );
} }
void winlist_empty_2d( winlist *l ) void winlist_empty_2d( winlist *l )
{ {
@ -287,18 +301,27 @@ int winlist_find(winlist *l, Window w)
{ {
// iterate backwards. theory is: windows most often accessed will be // iterate backwards. theory is: windows most often accessed will be
// nearer the end. testing with kcachegrind seems to support this... // nearer the end. testing with kcachegrind seems to support this...
int i; Window o; winlist_descend(l, i, o) if (w == o) return i; int i;
Window o;
winlist_descend( l, i, o ) if ( w == o ) return i;
return -1; return -1;
} }
int winlist_forget( winlist *l, Window w ) int winlist_forget( winlist *l, Window w )
{ {
int i, j; int i, j;
for (i = 0, j = 0; i < l->len; i++, j++)
{ for ( i = 0, j = 0; i < l->len; i++, j++ ) {
l->array[j] = l->array[i]; l->array[j] = l->array[i];
l->data[j] = l->data[i]; l->data[j] = l->data[i];
if (l->array[i] == w) { free(l->data[i]); j--; }
if ( l->array[i] == w ) {
free( l->data[i] );
j--;
} }
}
l->len -= ( i-j ); l->len -= ( i-j );
return j != i ?1:0; return j != i ?1:0;
} }
@ -358,25 +381,32 @@ static unsigned int color_get(const char *const name)
// find mouse pointer location // find mouse pointer location
int pointer_get( Window root, int *x, int *y ) int pointer_get( Window root, int *x, int *y )
{ {
*x = 0; *y = 0; *x = 0;
Window rr, cr; int rxr, ryr, wxr, wyr; unsigned int mr; *y = 0;
if (XQueryPointer(display, root, &rr, &cr, &rxr, &ryr, &wxr, &wyr, &mr)) Window rr, cr;
{ int rxr, ryr, wxr, wyr;
*x = rxr; *y = ryr; unsigned int mr;
if ( XQueryPointer( display, root, &rr, &cr, &rxr, &ryr, &wxr, &wyr, &mr ) ) {
*x = rxr;
*y = ryr;
return 1; return 1;
} }
return 0; return 0;
} }
int take_keyboard( Window w ) int take_keyboard( Window w )
{ {
int i; int i;
for (i = 0; i < 1000; i++)
{ for ( i = 0; i < 1000; i++ ) {
if ( XGrabKeyboard( display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime ) == GrabSuccess ) if ( XGrabKeyboard( display, w, True, GrabModeAsync, GrabModeAsync, CurrentTime ) == GrabSuccess )
return 1; return 1;
usleep( 1000 ); usleep( 1000 );
} }
return 0; return 0;
} }
void release_keyboard() void release_keyboard()
@ -388,37 +418,51 @@ void release_keyboard()
XWindowAttributes* window_get_attributes( Window w ) XWindowAttributes* window_get_attributes( Window w )
{ {
int idx = winlist_find( cache_xattr, w ); int idx = winlist_find( cache_xattr, w );
if (idx < 0)
{ if ( idx < 0 ) {
XWindowAttributes *cattr = allocate( sizeof( XWindowAttributes ) ); XWindowAttributes *cattr = allocate( sizeof( XWindowAttributes ) );
if (XGetWindowAttributes(display, w, cattr))
{ if ( XGetWindowAttributes( display, w, cattr ) ) {
winlist_append( cache_xattr, w, cattr ); winlist_append( cache_xattr, w, cattr );
return cattr; return cattr;
} }
free( cattr ); free( cattr );
return NULL; return NULL;
} }
return cache_xattr->data[idx]; return cache_xattr->data[idx];
} }
// retrieve a property of any type from a window // retrieve a property of any type from a window
int window_get_prop( Window w, Atom prop, Atom *type, int *items, void *buffer, unsigned int bytes ) int window_get_prop( Window w, Atom prop, Atom *type, int *items, void *buffer, unsigned int bytes )
{ {
Atom _type; if (!type) type = &_type; Atom _type;
int _items; if (!items) items = &_items;
int format; unsigned long nitems, nbytes; unsigned char *ret = NULL; if ( !type ) type = &_type;
int _items;
if ( !items ) items = &_items;
int format;
unsigned long nitems, nbytes;
unsigned char *ret = NULL;
memset( buffer, 0, bytes ); memset( buffer, 0, bytes );
if ( XGetWindowProperty( display, w, prop, 0, bytes/4, False, AnyPropertyType, type, if ( XGetWindowProperty( display, w, prop, 0, bytes/4, False, AnyPropertyType, type,
&format, &nitems, &nbytes, &ret) == Success && ret && *type != None && format) &format, &nitems, &nbytes, &ret ) == Success && ret && *type != None && format ) {
{
if ( format == 8 ) memmove( buffer, ret, MIN( bytes, nitems ) ); if ( format == 8 ) memmove( buffer, ret, MIN( bytes, nitems ) );
if ( format == 16 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( short ) ) ); if ( format == 16 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( short ) ) );
if ( format == 32 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( long ) ) ); if ( format == 32 ) memmove( buffer, ret, MIN( bytes, nitems * sizeof( long ) ) );
*items = (int)nitems; XFree(ret);
*items = ( int )nitems;
XFree( ret );
return 1; return 1;
} }
return 0; return 0;
} }
@ -426,30 +470,31 @@ int window_get_prop(Window w, Atom prop, Atom *type, int *items, void *buffer, u
// technically we could use window_get_prop(), but this is better for character set support // technically we could use window_get_prop(), but this is better for character set support
char* window_get_text_prop( Window w, Atom atom ) char* window_get_text_prop( Window w, Atom atom )
{ {
XTextProperty prop; char *res = NULL; XTextProperty prop;
char **list = NULL; int count; char *res = NULL;
if (XGetTextProperty(display, w, &prop, atom) && prop.value && prop.nitems) char **list = NULL;
{ int count;
if (prop.encoding == XA_STRING)
{ if ( XGetTextProperty( display, w, &prop, atom ) && prop.value && prop.nitems ) {
if ( prop.encoding == XA_STRING ) {
res = allocate( strlen( ( char* )prop.value )+1 ); res = allocate( strlen( ( char* )prop.value )+1 );
strcpy( res, ( char* )prop.value ); strcpy( res, ( char* )prop.value );
} } else if ( XmbTextPropertyToTextList( display, &prop, &list, &count ) >= Success && count > 0 && *list ) {
else
if (XmbTextPropertyToTextList(display, &prop, &list, &count) >= Success && count > 0 && *list)
{
res = allocate( strlen( *list )+1 ); res = allocate( strlen( *list )+1 );
strcpy( res, *list ); strcpy( res, *list );
XFreeStringList( list ); XFreeStringList( list );
} }
} }
if ( prop.value ) XFree( prop.value ); if ( prop.value ) XFree( prop.value );
return res; return res;
} }
int window_get_atom_prop( Window w, Atom atom, Atom *list, int count ) int window_get_atom_prop( Window w, Atom atom, Atom *list, int count )
{ {
Atom type; int items; Atom type;
int items;
return window_get_prop( w, atom, &type, &items, list, count*sizeof( Atom ) ) && type == XA_ATOM ? items:0; return window_get_prop( w, atom, &type, &items, list, count*sizeof( Atom ) ) && type == XA_ATOM ? items:0;
} }
@ -460,18 +505,23 @@ void window_set_atom_prop(Window w, Atom prop, Atom *atoms, int count)
int window_get_cardinal_prop( Window w, Atom atom, unsigned long *list, int count ) int window_get_cardinal_prop( Window w, Atom atom, unsigned long *list, int count )
{ {
Atom type; int items; Atom type;
int items;
return window_get_prop( w, atom, &type, &items, list, count*sizeof( unsigned long ) ) && type == XA_CARDINAL ? items:0; return window_get_prop( w, atom, &type, &items, list, count*sizeof( unsigned long ) ) && type == XA_CARDINAL ? items:0;
} }
// a ClientMessage // a ClientMessage
int window_send_message( Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask, Time time ) int window_send_message( Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask, Time time )
{ {
XEvent e; memset(&e, 0, sizeof(XEvent)); XEvent e;
memset( &e, 0, sizeof( XEvent ) );
e.xclient.type = ClientMessage; e.xclient.type = ClientMessage;
e.xclient.message_type = atom; e.xclient.window = subject; e.xclient.message_type = atom;
e.xclient.data.l[0] = protocol; e.xclient.data.l[1] = time; e.xclient.window = subject;
e.xclient.send_event = True; e.xclient.format = 32; e.xclient.data.l[0] = protocol;
e.xclient.data.l[1] = time;
e.xclient.send_event = True;
e.xclient.format = 32;
int r = XSendEvent( display, target, False, mask, &e ) ?1:0; int r = XSendEvent( display, target, False, mask, &e ) ?1:0;
XFlush( display ); XFlush( display );
return r; return r;
@ -485,19 +535,20 @@ void monitor_dimensions(Screen *screen, int x, int y, workarea *mon)
mon->h = HeightOfScreen( screen ); mon->h = HeightOfScreen( screen );
// locate the current monitor // locate the current monitor
if (XineramaIsActive(display)) if ( XineramaIsActive( display ) ) {
{
int monitors, i; int monitors, i;
XineramaScreenInfo *info = XineramaQueryScreens( display, &monitors ); XineramaScreenInfo *info = XineramaQueryScreens( display, &monitors );
if (info) for (i = 0; i < monitors; i++)
{ if ( info ) for ( i = 0; i < monitors; i++ ) {
if (INTERSECT(x, y, 1, 1, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) if ( INTERSECT( x, y, 1, 1, info[i].x_org, info[i].y_org, info[i].width, info[i].height ) ) {
{ mon->x = info[i].x_org;
mon->x = info[i].x_org; mon->y = info[i].y_org; mon->y = info[i].y_org;
mon->w = info[i].width; mon->h = info[i].height; mon->w = info[i].width;
mon->h = info[i].height;
break; break;
} }
} }
XFree( info ); XFree( info );
} }
} }
@ -507,20 +558,24 @@ void monitor_active(workarea *mon)
{ {
Window root = RootWindow( display, XScreenNumberOfScreen( screen ) ); Window root = RootWindow( display, XScreenNumberOfScreen( screen ) );
unsigned long id; Atom type; int count; unsigned long id;
Atom type;
int count;
if ( window_get_prop( root, netatoms[_NET_ACTIVE_WINDOW], &type, &count, &id, 1 ) if ( window_get_prop( root, netatoms[_NET_ACTIVE_WINDOW], &type, &count, &id, 1 )
&& type == XA_WINDOW && count > 0) && type == XA_WINDOW && count > 0 ) {
{
XWindowAttributes *attr = window_get_attributes( id ); XWindowAttributes *attr = window_get_attributes( id );
monitor_dimensions( screen, attr->x, attr->y, mon ); monitor_dimensions( screen, attr->x, attr->y, mon );
return; return;
} }
int x, y; int x, y;
if (pointer_get(root, &x, &y))
{ if ( pointer_get( root, &x, &y ) ) {
monitor_dimensions( screen, x, y, mon ); monitor_dimensions( screen, x, y, mon );
return; return;
} }
monitor_dimensions( screen, 0, 0, mon ); monitor_dimensions( screen, 0, 0, mon );
} }
@ -528,8 +583,10 @@ void monitor_active(workarea *mon)
int client_has_state( client *c, Atom state ) int client_has_state( client *c, Atom state )
{ {
int i; int i;
for ( i = 0; i < c->states; i++ ) for ( i = 0; i < c->states; i++ )
if ( c->state[i] == state ) return 1; if ( c->state[i] == state ) return 1;
return 0; return 0;
} }
@ -538,11 +595,14 @@ int client_has_state(client *c, Atom state)
client* window_client( Window win ) client* window_client( Window win )
{ {
if ( win == None ) return NULL; if ( win == None ) return NULL;
int idx = winlist_find( cache_client, win ); int idx = winlist_find( cache_client, win );
if ( idx >= 0 ) return cache_client->data[idx]; if ( idx >= 0 ) return cache_client->data[idx];
// if this fails, we're up that creek // if this fails, we're up that creek
XWindowAttributes *attr = window_get_attributes( win ); XWindowAttributes *attr = window_get_attributes( win );
if ( !attr ) return NULL; if ( !attr ) return NULL;
client *c = allocate_clear( sizeof( client ) ); client *c = allocate_clear( sizeof( client ) );
@ -561,24 +621,24 @@ client* window_client(Window win)
: netatoms[_NET_WM_WINDOW_TYPE_NORMAL]; : netatoms[_NET_WM_WINDOW_TYPE_NORMAL];
char *name; char *name;
if ((name = window_get_text_prop(c->window, netatoms[_NET_WM_NAME])) && name)
{ if ( ( name = window_get_text_prop( c->window, netatoms[_NET_WM_NAME] ) ) && name ) {
snprintf( c->title, CLIENTTITLE, "%s", name ); snprintf( c->title, CLIENTTITLE, "%s", name );
free( name ); free( name );
} } else if ( XFetchName( display, c->window, &name ) ) {
else
if (XFetchName(display, c->window, &name))
{
snprintf( c->title, CLIENTTITLE, "%s", name ); snprintf( c->title, CLIENTTITLE, "%s", name );
XFree( name ); XFree( name );
} }
XClassHint chint; XClassHint chint;
if (XGetClassHint(display, c->window, &chint))
{ if ( XGetClassHint( display, c->window, &chint ) ) {
snprintf( c->class, CLIENTCLASS, "%s", chint.res_class ); snprintf( c->class, CLIENTCLASS, "%s", chint.res_class );
snprintf( c->name, CLIENTNAME, "%s", chint.res_name ); snprintf( c->name, CLIENTNAME, "%s", chint.res_name );
XFree(chint.res_class); XFree(chint.res_name); XFree( chint.res_class );
XFree( chint.res_name );
} }
monitor_dimensions( c->xattr.screen, c->xattr.x, c->xattr.y, &c->monitor ); monitor_dimensions( c->xattr.screen, c->xattr.x, c->xattr.y, &c->monitor );
winlist_append( cache_client, c->window, c ); winlist_append( cache_client, c->window, c );
return c; return c;
@ -587,7 +647,8 @@ client* window_client(Window win)
#define ALLWINDOWS 1 #define ALLWINDOWS 1
#define DESKTOPWINDOWS 2 #define DESKTOPWINDOWS 2
unsigned int windows_modmask; KeySym windows_keysym; unsigned int windows_modmask;
KeySym windows_keysym;
// flags to set if we switch modes on the fly // flags to set if we switch modes on the fly
int run_windows = 0; int run_windows = 0;
Window main_window = None; Window main_window = None;
@ -598,8 +659,8 @@ void menu_draw(textbox *text, textbox **boxes, int max_lines, int selected, char
{ {
int i; int i;
textbox_draw( text ); textbox_draw( text );
for (i = 0; i < max_lines; i++)
{ for ( i = 0; i < max_lines; i++ ) {
textbox_font( boxes[i], config_menu_font, textbox_font( boxes[i], config_menu_font,
i == selected ? config_menu_hlfg: config_menu_fg, i == selected ? config_menu_hlfg: config_menu_fg,
i == selected ? config_menu_hlbg: config_menu_bg ); i == selected ? config_menu_hlbg: config_menu_bg );
@ -615,31 +676,42 @@ void menu_draw(textbox *text, textbox **boxes, int max_lines, int selected, char
static int calculate_common_prefix( char **filtered, int max_lines ) static int calculate_common_prefix( char **filtered, int max_lines )
{ {
int length_prefix = 0,j,found = 1; int length_prefix = 0,j,found = 1;
if ( filtered[0] != NULL ) { if ( filtered[0] != NULL ) {
char *p = filtered[0]; char *p = filtered[0];
do { do {
found = 1; found = 1;
for ( j=0; j < max_lines && filtered[j] != NULL; j++ ) { for ( j=0; j < max_lines && filtered[j] != NULL; j++ ) {
if ( filtered[j][length_prefix] == '\0' || filtered[j][length_prefix] != *p ) { if ( filtered[j][length_prefix] == '\0' || filtered[j][length_prefix] != *p ) {
if ( found ) if ( found )
found=0; found=0;
break; break;
} }
} }
if ( found ) if ( found )
length_prefix++; length_prefix++;
p++; p++;
} while ( found ); } while ( found );
} }
return length_prefix; return length_prefix;
} }
int menu( char **lines, char **input, char *prompt, int selected, Time *time ) int menu( char **lines, char **input, char *prompt, int selected, Time *time )
{ {
int line = -1, i, j, chosen = 0, aborted = 0; int line = -1, i, j, chosen = 0, aborted = 0;
workarea mon; monitor_active(&mon); workarea mon;
monitor_active( &mon );
int num_lines = 0;
for ( ; lines[num_lines]; num_lines++ );
int num_lines = 0; for (; lines[num_lines]; num_lines++);
int max_lines = MIN( config_menu_lines, num_lines ); int max_lines = MIN( config_menu_lines, num_lines );
selected = MAX( MIN( num_lines-1, selected ), 0 ); selected = MAX( MIN( num_lines-1, selected ), 0 );
@ -650,18 +722,16 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
XWindowAttributes attr; XWindowAttributes attr;
// main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker // main window isn't explicitly destroyed in case we switch modes. Reusing it prevents flicker
if (main_window != None && XGetWindowAttributes(display, main_window, &attr)) if ( main_window != None && XGetWindowAttributes( display, main_window, &attr ) ) {
{
box = main_window; box = main_window;
} } else {
else
{
box = XCreateSimpleWindow( display, root, x, 0, w, 300, 1, color_get( config_menu_bc ), color_get( config_menu_bg ) ); box = XCreateSimpleWindow( display, root, x, 0, w, 300, 1, color_get( config_menu_bc ), color_get( config_menu_bg ) );
XSelectInput( display, box, ExposureMask ); XSelectInput( display, box, ExposureMask );
// make it an unmanaged window // make it an unmanaged window
window_set_atom_prop( box, netatoms[_NET_WM_STATE], &netatoms[_NET_WM_STATE_ABOVE], 1 ); window_set_atom_prop( box, netatoms[_NET_WM_STATE], &netatoms[_NET_WM_STATE_ABOVE], 1 );
//window_set_atom_prop(box, netatoms[_NET_WM_WINDOW_TYPE], &netatoms[_NET_WM_WINDOW_TYPE_DOCK], 1); //window_set_atom_prop(box, netatoms[_NET_WM_WINDOW_TYPE], &netatoms[_NET_WM_WINDOW_TYPE_DOCK], 1);
XSetWindowAttributes sattr; sattr.override_redirect = True; XSetWindowAttributes sattr;
sattr.override_redirect = True;
XChangeWindowAttributes( display, box, CWOverrideRedirect, &sattr ); XChangeWindowAttributes( display, box, CWOverrideRedirect, &sattr );
main_window = box; main_window = box;
@ -686,8 +756,7 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
// filtered list display // filtered list display
textbox **boxes = allocate_clear( sizeof( textbox* ) * max_lines ); textbox **boxes = allocate_clear( sizeof( textbox* ) * max_lines );
for (i = 0; i < max_lines; i++) for ( i = 0; i < max_lines; i++ ) {
{
boxes[i] = textbox_create( box, TB_AUTOHEIGHT, 5, ( i+1 ) * line_height + 5, w-10, 1, boxes[i] = textbox_create( box, TB_AUTOHEIGHT, 5, ( i+1 ) * line_height + 5, w-10, 1,
config_menu_font, config_menu_fg, config_menu_bg, lines[i], NULL ); config_menu_font, config_menu_fg, config_menu_bg, lines[i], NULL );
textbox_show( boxes[i] ); textbox_show( boxes[i] );
@ -699,8 +768,8 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
int filtered_lines = 0; int filtered_lines = 0;
int jin = 0; int jin = 0;
for (i = 0; i < max_lines; i++)
{ for ( i = 0; i < max_lines; i++ ) {
filtered[jin] = lines[i]; filtered[jin] = lines[i];
line_map[jin] = i; line_map[jin] = i;
jin++; jin++;
@ -714,90 +783,87 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
XMapRaised( display, box ); XMapRaised( display, box );
take_keyboard( box ); take_keyboard( box );
for (;;)
{ for ( ;; ) {
XEvent ev; XEvent ev;
XNextEvent( display, &ev ); XNextEvent( display, &ev );
if (ev.type == Expose) if ( ev.type == Expose ) {
{
while ( XCheckTypedEvent( display, Expose, &ev ) ); while ( XCheckTypedEvent( display, Expose, &ev ) );
menu_draw( text, boxes, max_lines, selected, filtered ); menu_draw( text, boxes, max_lines, selected, filtered );
} } else if ( ev.type == KeyPress ) {
else
if (ev.type == KeyPress)
{
while ( XCheckTypedEvent( display, KeyPress, &ev ) ); while ( XCheckTypedEvent( display, KeyPress, &ev ) );
if ( time ) if ( time )
*time = ev.xkey.time; *time = ev.xkey.time;
int rc = textbox_keypress( text, &ev ); int rc = textbox_keypress( text, &ev );
if (rc < 0)
{ if ( rc < 0 ) {
chosen = 1; chosen = 1;
break; break;
} } else if ( rc ) {
else
if (rc)
{
char **tokens = tokenize( text->text ); char **tokens = tokenize( text->text );
// input changed // input changed
for (i = 0, j = 0; i < num_lines && j < max_lines; i++) for ( i = 0, j = 0; i < num_lines && j < max_lines; i++ ) {
{
int match = 1; int match = 1;
// Do a tokenized match. // Do a tokenized match.
if(tokens) for(int j = 1; match && tokens[j]; j++) if ( tokens ) for ( int j = 1; match && tokens[j]; j++ ) {
{
match = ( strcasestr( lines[i], tokens[j] ) != NULL ); match = ( strcasestr( lines[i], tokens[j] ) != NULL );
} }
// If each token was matched, add it to list. // If each token was matched, add it to list.
if(match) if ( match ) {
{
line_map[j] = i; line_map[j] = i;
filtered[j++] = lines[i]; filtered[j++] = lines[i];
} }
} }
// Cleanup + bookkeeping. // Cleanup + bookkeeping.
filtered_lines = j; filtered_lines = j;
selected = MAX( 0, MIN( selected, j-1 ) ); selected = MAX( 0, MIN( selected, j-1 ) );
for ( ; j < max_lines; j++ ) for ( ; j < max_lines; j++ )
filtered[j] = NULL; filtered[j] = NULL;
if ( config_zeltak_mode && filtered_lines == 1 ) { if ( config_zeltak_mode && filtered_lines == 1 ) {
chosen = 1; chosen = 1;
break; break;
} }
tokenize_free( tokens ); tokenize_free( tokens );
} } else {
else
{
// unhandled key // unhandled key
KeySym key = XkbKeycodeToKeysym( display, ev.xkey.keycode, 0, 0 ); KeySym key = XkbKeycodeToKeysym( display, ev.xkey.keycode, 0, 0 );
if ( key == XK_Escape if ( key == XK_Escape
// pressing one of the global key bindings closes the switcher. this allows fast closing of the menu if an item is not selected // pressing one of the global key bindings closes the switcher. this allows fast closing of the menu if an item is not selected
|| ( ( windows_modmask == AnyModifier || ev.xkey.state & windows_modmask ) && key == windows_keysym ) || ( ( windows_modmask == AnyModifier || ev.xkey.state & windows_modmask ) && key == windows_keysym )
) ) {
{
aborted = 1; aborted = 1;
break; break;
} }
else else
// Up or Shift-Tab // Up or Shift-Tab
if ( key == XK_Up || ( key == XK_Tab && ev.xkey.state & ShiftMask ) ) if ( key == XK_Up || ( key == XK_Tab && ev.xkey.state & ShiftMask ) )
selected = selected ? MAX( 0, selected-1 ): MAX( 0, filtered_lines-1 ); selected = selected ? MAX( 0, selected-1 ): MAX( 0, filtered_lines-1 );
else else
// Down or Tab // Down or Tab
if (key == XK_Down || key == XK_Tab) if ( key == XK_Down || key == XK_Tab ) {
{
if ( filtered_lines == 1 ) { if ( filtered_lines == 1 ) {
chosen = 1; chosen = 1;
break; break;
} }
int length_prefix = calculate_common_prefix( filtered, max_lines ); int length_prefix = calculate_common_prefix( filtered, max_lines );
if ( length_prefix && strncasecmp( filtered[0], text->text, length_prefix ) ) { if ( length_prefix && strncasecmp( filtered[0], text->text, length_prefix ) ) {
// Do not want to modify original string, so make copy. // Do not want to modify original string, so make copy.
// not eff.. // not eff..
@ -805,14 +871,15 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
textbox_text( text, str ); textbox_text( text, str );
textbox_cursor_end( text ); textbox_cursor_end( text );
free( str ); free( str );
} } else
else
selected = selected < filtered_lines-1 ? MIN( filtered_lines-1, selected+1 ): 0; selected = selected < filtered_lines-1 ? MIN( filtered_lines-1, selected+1 ): 0;
} }
} }
menu_draw( text, boxes, max_lines, selected, filtered ); menu_draw( text, boxes, max_lines, selected, filtered );
} }
} }
release_keyboard(); release_keyboard();
if ( chosen && filtered[selected] ) if ( chosen && filtered[selected] )
@ -822,6 +889,7 @@ int menu(char **lines, char **input, char *prompt, int selected, Time *time)
*input = strdup( text->text ); *input = strdup( text->text );
textbox_free( text ); textbox_free( text );
for ( i = 0; i < max_lines; i++ ) for ( i = 0; i < max_lines; i++ )
textbox_free( boxes[i] ); textbox_free( boxes[i] );
@ -845,9 +913,9 @@ void run_switcher(int fmode)
// this also happens to isolate the Xft font stuff in a child process // this also happens to isolate the Xft font stuff in a child process
// that gets cleaned up every time. that library shows some valgrind // that gets cleaned up every time. that library shows some valgrind
// strangeness... // strangeness...
if (fmode == FORK) if ( fmode == FORK ) {
{
if ( fork() ) return; if ( fork() ) return;
display = XOpenDisplay( 0 ); display = XOpenDisplay( 0 );
XSync( display, True ); XSync( display, True );
} }
@ -858,7 +926,8 @@ void run_switcher(int fmode)
int i, plen = 0, lines = 0; int i, plen = 0, lines = 0;
unsigned int classfield = 0; unsigned int classfield = 0;
unsigned long desktops = 0, current_desktop = 0; unsigned long desktops = 0, current_desktop = 0;
Window w; client *c; Window w;
client *c;
// windows we actually display. may be slightly different to _NET_CLIENT_LIST_STACKING // windows we actually display. may be slightly different to _NET_CLIENT_LIST_STACKING
// if we happen to have a window destroyed while we're working... // if we happen to have a window destroyed while we're working...
@ -868,21 +937,23 @@ void run_switcher(int fmode)
current_desktop = 0; current_desktop = 0;
// find window list // find window list
Atom type; int nwins; unsigned long *wins = allocate_clear(sizeof(unsigned long) * 100); Atom type;
int nwins;
unsigned long *wins = allocate_clear( sizeof( unsigned long ) * 100 );
if ( window_get_prop( root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, 100 * sizeof( unsigned long ) ) if ( window_get_prop( root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, 100 * sizeof( unsigned long ) )
&& type == XA_WINDOW) && type == XA_WINDOW ) {
{
// calc widths of fields // calc widths of fields
for (i = nwins-1; i > -1; i--) for ( i = nwins-1; i > -1; i-- ) {
{
if ( ( c = window_client( wins[i] ) ) if ( ( c = window_client( wins[i] ) )
&& !c->xattr.override_redirect && !c->xattr.override_redirect
&& !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_PAGER] ) && !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_PAGER] )
&& !client_has_state(c, netatoms[_NET_WM_STATE_SKIP_TASKBAR])) && !client_has_state( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) {
{
classfield = MAX( classfield, strlen( c->class ) ); classfield = MAX( classfield, strlen( c->class ) );
// In i3 mode, skip the i3bar completely. // In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr( c->class, "i3bar" ) != NULL ) continue; if ( config_i3_mode && strstr( c->class, "i3bar" ) != NULL ) continue;
winlist_append( ids, c->window, NULL ); winlist_append( ids, c->window, NULL );
} }
} }
@ -892,13 +963,12 @@ void run_switcher(int fmode)
plen += sprintf( pattern+plen, "%%-%ds %%s", MAX( 5, classfield ) ); plen += sprintf( pattern+plen, "%%-%ds %%s", MAX( 5, classfield ) );
list = allocate_clear(sizeof(char*) * (ids->len+1)); lines = 0; list = allocate_clear( sizeof( char* ) * ( ids->len+1 ) );
lines = 0;
// build the actual list // build the actual list
winlist_ascend(ids, i, w) winlist_ascend( ids, i, w ) {
{ if ( ( c = window_client( w ) ) ) {
if ((c = window_client(w)))
{
// final line format // final line format
char *line = allocate( strlen( c->title ) + strlen( c->class ) + classfield + 50 ); char *line = allocate( strlen( c->title ) + strlen( c->class ) + classfield + 50 );
@ -910,43 +980,41 @@ void run_switcher(int fmode)
char *input = NULL; char *input = NULL;
Time time; Time time;
int n = menu( list, &input, "> ", 1, &time ); int n = menu( list, &input, "> ", 1, &time );
if (n >= 0 && list[n])
{ if ( n >= 0 && list[n] ) {
if(config_i3_mode) if ( config_i3_mode ) {
{
// Hack for i3. // Hack for i3.
char array[128]; char array[128];
snprintf( array,128,"i3-msg [id=\"%d\"] focus",( int )( ids->array[n] ) ); snprintf( array,128,"i3-msg [id=\"%d\"] focus",( int )( ids->array[n] ) );
printf( "Executing: %s\n", array ); printf( "Executing: %s\n", array );
exec_cmd( array ); exec_cmd( array );
} } else {
else if ( isdigit( list[n][0] ) ) {
{
if (isdigit(list[n][0]))
{
// TODO: get rid of strtol // TODO: get rid of strtol
window_send_message( root, root, netatoms[_NET_CURRENT_DESKTOP], strtol( list[n], NULL, 10 )-1, window_send_message( root, root, netatoms[_NET_CURRENT_DESKTOP], strtol( list[n], NULL, 10 )-1,
SubstructureNotifyMask | SubstructureRedirectMask, time ); SubstructureNotifyMask | SubstructureRedirectMask, time );
XSync( display, False ); XSync( display, False );
} }
window_send_message( root, ids->array[n], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager window_send_message( root, ids->array[n], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager
SubstructureNotifyMask | SubstructureRedirectMask, time ); SubstructureNotifyMask | SubstructureRedirectMask, time );
} }
} } else
else
// act as a launcher // act as a launcher
if (input) if ( input ) {
{
exec_cmd( input ); exec_cmd( input );
} }
for ( i = 0; i < lines; i++ ) for ( i = 0; i < lines; i++ )
free( list[i] ); free( list[i] );
free( list ); free( list );
} }
free( wins ); free( wins );
winlist_free( ids ); winlist_free( ids );
} } while ( run_windows );
while (run_windows );
if ( fmode == FORK ) if ( fmode == FORK )
exit( EXIT_SUCCESS ); exit( EXIT_SUCCESS );
@ -965,24 +1033,34 @@ void handle_keypress(XEvent *ev)
void parse_key( char *combo, unsigned int *mod, KeySym *key ) void parse_key( char *combo, unsigned int *mod, KeySym *key )
{ {
unsigned int modmask = 0; unsigned int modmask = 0;
if ( strcasestr( combo, "shift" ) ) modmask |= ShiftMask; if ( strcasestr( combo, "shift" ) ) modmask |= ShiftMask;
if ( strcasestr( combo, "control" ) ) modmask |= ControlMask; if ( strcasestr( combo, "control" ) ) modmask |= ControlMask;
if ( strcasestr( combo, "mod1" ) ) modmask |= Mod1Mask; if ( strcasestr( combo, "mod1" ) ) modmask |= Mod1Mask;
if ( strcasestr( combo, "mod2" ) ) modmask |= Mod2Mask; if ( strcasestr( combo, "mod2" ) ) modmask |= Mod2Mask;
if ( strcasestr( combo, "mod3" ) ) modmask |= Mod3Mask; if ( strcasestr( combo, "mod3" ) ) modmask |= Mod3Mask;
if ( strcasestr( combo, "mod4" ) ) modmask |= Mod4Mask; if ( strcasestr( combo, "mod4" ) ) modmask |= Mod4Mask;
if ( strcasestr( combo, "mod5" ) ) modmask |= Mod5Mask; if ( strcasestr( combo, "mod5" ) ) modmask |= Mod5Mask;
*mod = modmask ? modmask: AnyModifier; *mod = modmask ? modmask: AnyModifier;
char i = strlen( combo ); char i = strlen( combo );
while ( i > 0 && !strchr( "-+", combo[i-1] ) ) i--; while ( i > 0 && !strchr( "-+", combo[i-1] ) ) i--;
KeySym sym = XStringToKeysym( combo+i ); KeySym sym = XStringToKeysym( combo+i );
if (sym == NoSymbol || (!modmask && (strchr(combo, '-') || strchr(combo, '+'))))
{ if ( sym == NoSymbol || ( !modmask && ( strchr( combo, '-' ) || strchr( combo, '+' ) ) ) ) {
fprintf( stderr, "sorry, cannot understand key combination: %s\n", combo ); fprintf( stderr, "sorry, cannot understand key combination: %s\n", combo );
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
} }
*key = sym; *key = sym;
} }
@ -992,19 +1070,16 @@ void grab_key(unsigned int modmask, KeySym key)
KeyCode keycode = XKeysymToKeycode( display, key ); KeyCode keycode = XKeysymToKeycode( display, key );
XUngrabKey( display, keycode, AnyModifier, root ); XUngrabKey( display, keycode, AnyModifier, root );
if (modmask != AnyModifier) if ( modmask != AnyModifier ) {
{
// bind to combinations of mod and lock masks, so caps and numlock don't confuse people // bind to combinations of mod and lock masks, so caps and numlock don't confuse people
XGrabKey( display, keycode, modmask, root, True, GrabModeAsync, GrabModeAsync ); XGrabKey( display, keycode, modmask, root, True, GrabModeAsync, GrabModeAsync );
XGrabKey( display, keycode, modmask|LockMask, root, True, GrabModeAsync, GrabModeAsync ); XGrabKey( display, keycode, modmask|LockMask, root, True, GrabModeAsync, GrabModeAsync );
if (NumlockMask)
{ if ( NumlockMask ) {
XGrabKey( display, keycode, modmask|NumlockMask, root, True, GrabModeAsync, GrabModeAsync ); XGrabKey( display, keycode, modmask|NumlockMask, root, True, GrabModeAsync, GrabModeAsync );
XGrabKey( display, keycode, modmask|NumlockMask|LockMask, root, True, GrabModeAsync, GrabModeAsync ); XGrabKey( display, keycode, modmask|NumlockMask|LockMask, root, True, GrabModeAsync, GrabModeAsync );
} }
} } else {
else
{
// nice simple single key bind // nice simple single key bind
XGrabKey( display, keycode, AnyModifier, root, True, GrabModeAsync, GrabModeAsync ); XGrabKey( display, keycode, AnyModifier, root, True, GrabModeAsync, GrabModeAsync );
} }
@ -1017,32 +1092,37 @@ int main(int argc, char *argv[])
// catch help request // catch help request
if ( find_arg( argc, argv, "-help" ) >= 0 if ( find_arg( argc, argv, "-help" ) >= 0
|| find_arg( argc, argv, "--help" ) >= 0 || find_arg( argc, argv, "--help" ) >= 0
|| find_arg(argc, argv, "-h") >= 0) || find_arg( argc, argv, "-h" ) >= 0 ) {
{
fprintf( stderr, "See the man page or visit http://github.com/DaveDavenport/simpleswitcher\n" ); fprintf( stderr, "See the man page or visit http://github.com/DaveDavenport/simpleswitcher\n" );
fprintf( stderr, "Original code can be found: http://github.com/seanpringle/simpleswitcher\n" ); fprintf( stderr, "Original code can be found: http://github.com/seanpringle/simpleswitcher\n" );
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(!(display = XOpenDisplay(0)))
{ if ( !( display = XOpenDisplay( 0 ) ) ) {
fprintf( stderr, "cannot open display!\n" ); fprintf( stderr, "cannot open display!\n" );
return EXIT_FAILURE; return EXIT_FAILURE;
} }
signal( SIGCHLD, catch_exit ); signal( SIGCHLD, catch_exit );
screen = DefaultScreenOfDisplay( display ); screen = DefaultScreenOfDisplay( display );
screen_id = DefaultScreen( display ); screen_id = DefaultScreen( display );
root = DefaultRootWindow( display ); root = DefaultRootWindow( display );
XSync(display, False); xerror = XSetErrorHandler(oops); XSync(display, False); XSync( display, False );
xerror = XSetErrorHandler( oops );
XSync( display, False );
// determine numlock mask so we can bind on keys with and without it // determine numlock mask so we can bind on keys with and without it
XModifierKeymap *modmap = XGetModifierMapping( display ); XModifierKeymap *modmap = XGetModifierMapping( display );
for ( i = 0; i < 8; i++ ) for ( i = 0; i < 8; i++ )
for ( j = 0; j < ( int )modmap->max_keypermod; j++ ) for ( j = 0; j < ( int )modmap->max_keypermod; j++ )
if ( modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode( display, XK_Num_Lock ) ) if ( modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode( display, XK_Num_Lock ) )
NumlockMask = ( 1<<i ); NumlockMask = ( 1<<i );
XFreeModifiermap( modmap ); XFreeModifiermap( modmap );
int ac = argc; char **av = argv; int ac = argc;
char **av = argv;
cache_client = winlist_new(); cache_client = winlist_new();
cache_xattr = winlist_new(); cache_xattr = winlist_new();
@ -1065,8 +1145,7 @@ int main(int argc, char *argv[])
config_i3_mode = ( find_arg( ac, av, "-i3" ) >= 0 ); config_i3_mode = ( find_arg( ac, av, "-i3" ) >= 0 );
// flags to run immediately and exit // flags to run immediately and exit
if (find_arg(ac, av, "-now") >= 0) if ( find_arg( ac, av, "-now" ) >= 0 ) {
{
run_switcher( NOFORK ); run_switcher( NOFORK );
exit( EXIT_SUCCESS ); exit( EXIT_SUCCESS );
} }
@ -1081,17 +1160,19 @@ int main(int argc, char *argv[])
grab_key( windows_modmask, windows_keysym ); grab_key( windows_modmask, windows_keysym );
XEvent ev; XEvent ev;
for (;;)
{ for ( ;; ) {
// caches only live for a single event // caches only live for a single event
winlist_empty( cache_xattr ); winlist_empty( cache_xattr );
winlist_empty( cache_client ); winlist_empty( cache_client );
// block and wait for something // block and wait for something
XNextEvent( display, &ev ); XNextEvent( display, &ev );
if ( ev.xany.window == None ) continue; if ( ev.xany.window == None ) continue;
if ( ev.type == KeyPress ) handle_keypress( &ev ); if ( ev.type == KeyPress ) handle_keypress( &ev );
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -56,9 +56,13 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
tb->flags = flags; tb->flags = flags;
tb->parent = parent; tb->parent = parent;
tb->x = x; tb->y = y; tb->w = MAX(1, w); tb->h = MAX(1, h); tb->x = x;
tb->y = y;
tb->w = MAX( 1, w );
tb->h = MAX( 1, h );
XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display)); XColor color;
Colormap map = DefaultColormap( display, DefaultScreen( display ) );
unsigned int cp = XAllocNamedColor( display, map, bg, &color, &color ) ? color.pixel: None; unsigned int cp = XAllocNamedColor( display, map, bg, &color, &color ) ? color.pixel: None;
tb->window = XCreateSimpleWindow( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp ); tb->window = XCreateSimpleWindow( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
@ -73,8 +77,7 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
textbox_moveresize( tb, tb->x, tb->y, tb->w, tb->h ); textbox_moveresize( tb, tb->x, tb->y, tb->w, tb->h );
// edit mode controls // edit mode controls
if (tb->flags & TB_EDITABLE) if ( tb->flags & TB_EDITABLE ) {
{
tb->xim = XOpenIM( display, NULL, NULL, NULL ); tb->xim = XOpenIM( display, NULL, NULL, NULL );
tb->xic = XCreateIC( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL ); tb->xic = XCreateIC( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
} }
@ -86,6 +89,7 @@ textbox* textbox_create(Window parent, unsigned long flags, short x, short y, sh
void textbox_font( textbox *tb, char *font, char *fg, char *bg ) void textbox_font( textbox *tb, char *font, char *fg, char *bg )
{ {
if ( tb->font ) XftFontClose( display, tb->font ); if ( tb->font ) XftFontClose( display, tb->font );
tb->font = XftFontOpenName( display, DefaultScreen( display ), font ); tb->font = XftFontOpenName( display, DefaultScreen( display ), font );
XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), fg, &tb->color_fg ); XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), fg, &tb->color_fg );
@ -105,6 +109,7 @@ void textbox_extents(textbox *tb)
void textbox_text( textbox *tb, char *text ) void textbox_text( textbox *tb, char *text )
{ {
if ( tb->text ) free( tb->text ); if ( tb->text ) free( tb->text );
tb->text = strdup( text ); tb->text = strdup( text );
tb->cursor = MAX( 0,MIN( ( int )strlen( text ), tb->cursor ) ); tb->cursor = MAX( 0,MIN( ( int )strlen( text ), tb->cursor ) );
textbox_extents( tb ); textbox_extents( tb );
@ -114,6 +119,7 @@ void textbox_text(textbox *tb, char *text)
void textbox_prompt( textbox *tb, char *text ) void textbox_prompt( textbox *tb, char *text )
{ {
if ( tb->prompt ) free( tb->prompt ); if ( tb->prompt ) free( tb->prompt );
tb->prompt = strdup( text ); tb->prompt = strdup( text );
textbox_extents( tb ); textbox_extents( tb );
} }
@ -127,9 +133,11 @@ void textbox_moveresize(textbox *tb, int x, int y, int w, int h)
if ( tb->flags & TB_AUTOWIDTH ) if ( tb->flags & TB_AUTOWIDTH )
w = tb->extents.width; w = tb->extents.width;
if (x != tb->x || y != tb->y || w != tb->w || h != tb->h) if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h ) {
{ tb->x = x;
tb->x = x; tb->y = y; tb->w = MAX(1, w); tb->h = MAX(1, h); tb->y = y;
tb->w = MAX( 1, w );
tb->h = MAX( 1, h );
XMoveResizeWindow( display, tb->window, tb->x, tb->y, tb->w, tb->h ); XMoveResizeWindow( display, tb->window, tb->x, tb->y, tb->w, tb->h );
} }
} }
@ -147,14 +155,15 @@ void textbox_hide(textbox *tb)
// will also unmap the window if still displayed // will also unmap the window if still displayed
void textbox_free( textbox *tb ) void textbox_free( textbox *tb )
{ {
if (tb->flags & TB_EDITABLE) if ( tb->flags & TB_EDITABLE ) {
{
XDestroyIC( tb->xic ); XDestroyIC( tb->xic );
XCloseIM( tb->xim ); XCloseIM( tb->xim );
} }
if ( tb->text ) free( tb->text ); if ( tb->text ) free( tb->text );
if ( tb->prompt ) free( tb->prompt ); if ( tb->prompt ) free( tb->prompt );
if ( tb->font ) XftFontClose( display, tb->font ); if ( tb->font ) XftFontClose( display, tb->font );
XDestroyWindow( display, tb->window ); XDestroyWindow( display, tb->window );
@ -186,8 +195,7 @@ void textbox_draw(textbox *tb)
int cursor_offset = 0; int cursor_offset = 0;
int cursor_width = MAX( 2, line_height/10 ); int cursor_width = MAX( 2, line_height/10 );
if (tb->flags & TB_EDITABLE) if ( tb->flags & TB_EDITABLE ) {
{
int prompt_len = strlen( prompt ); int prompt_len = strlen( prompt );
length = text_len + prompt_len; length = text_len + prompt_len;
cursor_offset = MIN( tb->cursor + prompt_len, length ); cursor_offset = MIN( tb->cursor + prompt_len, length );
@ -211,7 +219,9 @@ void textbox_draw(textbox *tb)
line_width = extents.width; line_width = extents.width;
int x = 2, y = tb->font->ascent; int x = 2, y = tb->font->ascent;
if ( tb->flags & TB_RIGHT ) x = tb->w - line_width; if ( tb->flags & TB_RIGHT ) x = tb->w - line_width;
if ( tb->flags & TB_CENTER ) x = ( tb->w - line_width ) / 2; if ( tb->flags & TB_CENTER ) x = ( tb->w - line_width ) / 2;
// draw the text, including any prompt in edit mode // draw the text, including any prompt in edit mode
@ -302,8 +312,7 @@ void textbox_cursor_del(textbox *tb)
// back up and delete one character // back up and delete one character
void textbox_cursor_bkspc( textbox *tb ) void textbox_cursor_bkspc( textbox *tb )
{ {
if (tb->cursor > 0) if ( tb->cursor > 0 ) {
{
textbox_cursor_dec( tb ); textbox_cursor_dec( tb );
textbox_cursor_del( tb ); textbox_cursor_del( tb );
} }
@ -315,60 +324,41 @@ void textbox_cursor_bkspc(textbox *tb)
// -1 = handled and return pressed (finished) // -1 = handled and return pressed (finished)
int textbox_keypress( textbox *tb, XEvent *ev ) int textbox_keypress( textbox *tb, XEvent *ev )
{ {
KeySym key; Status stat; KeySym key;
char pad[32]; int len; Status stat;
char pad[32];
int len;
if ( !( tb->flags & TB_EDITABLE ) ) return 0; if ( !( tb->flags & TB_EDITABLE ) ) return 0;
len = XmbLookupString( tb->xic, &ev->xkey, pad, sizeof( pad ), &key, &stat ); len = XmbLookupString( tb->xic, &ev->xkey, pad, sizeof( pad ), &key, &stat );
pad[len] = 0; pad[len] = 0;
if (key == XK_Left) if ( key == XK_Left ) {
{
textbox_cursor_dec( tb ); textbox_cursor_dec( tb );
return 1; return 1;
} } else if ( key == XK_Right ) {
else
if (key == XK_Right)
{
textbox_cursor_inc( tb ); textbox_cursor_inc( tb );
return 1; return 1;
} } else if ( key == XK_Home ) {
else
if (key == XK_Home)
{
textbox_cursor_home( tb ); textbox_cursor_home( tb );
return 1; return 1;
} } else if ( key == XK_End ) {
else
if (key == XK_End)
{
textbox_cursor_end( tb ); textbox_cursor_end( tb );
return 1; return 1;
} } else if ( key == XK_Delete ) {
else
if (key == XK_Delete)
{
textbox_cursor_del( tb ); textbox_cursor_del( tb );
return 1; return 1;
} } else if ( key == XK_BackSpace ) {
else
if (key == XK_BackSpace)
{
textbox_cursor_bkspc( tb ); textbox_cursor_bkspc( tb );
return 1; return 1;
} } else if ( key == XK_Return ) {
else
if (key == XK_Return)
{
return -1; return -1;
} } else if ( !iscntrl( *pad ) ) {
else
if (!iscntrl(*pad))
{
textbox_insert( tb, tb->cursor, pad ); textbox_insert( tb, tb->cursor, pad );
textbox_cursor_inc( tb ); textbox_cursor_inc( tb );
return 1; return 1;
} }
return 0; return 0;
} }