Restructure some code, fix a small bug in dmenu mode.

* dmenu crashed on no input lines (wrong free)
 * Pass length of lines to menu function.
This commit is contained in:
QC 2014-07-20 12:29:27 +02:00
parent 842d19231a
commit 0f279b2995
5 changed files with 48 additions and 51 deletions

View file

@ -66,6 +66,7 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, voi
/** /**
* @param lines An array of strings to display. * @param lines An array of strings to display.
* @param num_lines Length of the array with strings to display.
* @param input A pointer to a string where the inputted data is placed. * @param input A pointer to a string where the inputted data is placed.
* @param prompt The prompt to show. * @param prompt The prompt to show.
* @param time The current time (used for window interaction.) * @param time The current time (used for window interaction.)
@ -78,10 +79,10 @@ typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, voi
* *
* @returns The command issued (see MenuReturn) * @returns The command issued (see MenuReturn)
*/ */
MenuReturn menu ( char **lines, char **input, char *prompt, MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt,
Time *time, int *shift, Time *time, int *shift,
menu_match_cb mmc, void *mmc_data, menu_match_cb mmc, void *mmc_data,
int *selected_line ) __attribute__ ( ( nonnull ( 1, 2, 3, 8 ) ) ); int *selected_line ) __attribute__ ( ( nonnull ( 1, 3, 4, 9 ) ) );
void catch_exit ( __attribute__( ( unused ) ) int sig ); void catch_exit ( __attribute__( ( unused ) ) int sig );

View file

@ -38,27 +38,28 @@
char *dmenu_prompt = "dmenu "; char *dmenu_prompt = "dmenu ";
static char **get_dmenu ( void ) static char **get_dmenu ( unsigned int *length )
{ {
char buffer[1024]; char buffer[1024];
char **retv = NULL; char **retv = NULL;
int index = 0;
*length = 0;
while ( fgets ( buffer, 1024, stdin ) != NULL ) { while ( fgets ( buffer, 1024, stdin ) != NULL ) {
char **tr = realloc ( retv, ( index + 2 ) * sizeof ( char* ) ); char **tr = realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
if ( tr == NULL ) { if ( tr == NULL ) {
return retv; return retv;
} }
retv = tr; retv = tr;
retv[index] = strdup ( buffer ); retv[( *length )] = strdup ( buffer );
retv[index + 1] = NULL; retv[( *length ) + 1] = NULL;
// Filter out line-end. // Filter out line-end.
if ( retv[index][strlen ( buffer ) - 1] == '\n' ) { if ( retv[( *length )][strlen ( buffer ) - 1] == '\n' ) {
retv[index][strlen ( buffer ) - 1] = '\0'; retv[( *length )][strlen ( buffer ) - 1] = '\0';
} }
index++; ( *length )++;
} }
return retv; return retv;
@ -68,9 +69,10 @@ SwitcherMode dmenu_switcher_dialog ( char **input )
{ {
int selected_line = 0; int selected_line = 0;
SwitcherMode retv = MODE_EXIT; SwitcherMode retv = MODE_EXIT;
char **list = get_dmenu ( ); unsigned int length = 0;
char **list = get_dmenu ( &length );
int mretv = menu ( list, input, dmenu_prompt, NULL, NULL, int mretv = menu ( list, length, input, dmenu_prompt, NULL, NULL,
token_match, NULL, &selected_line ); token_match, NULL, &selected_line );
if ( mretv == MENU_NEXT ) { if ( mretv == MENU_NEXT ) {
@ -83,7 +85,7 @@ SwitcherMode dmenu_switcher_dialog ( char **input )
fputs ( *input, stdout ); fputs ( *input, stdout );
} }
for ( unsigned int i = 0; list != NULL && list[i] != NULL; i++ ) { for ( unsigned int i = 0; i < length ; i++ ) {
free ( list[i] ); free ( list[i] );
} }

View file

@ -1010,19 +1010,13 @@ static void calculate_window_position ( const workarea *mon, int *x, int *y, int
*y += config.y_offset; *y += config.y_offset;
} }
MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shift, MenuReturn menu ( char **lines, unsigned int num_lines, char **input, char *prompt, Time *time,
menu_match_cb mmc, void *mmc_data, int *selected_line ) int *shift, menu_match_cb mmc, void *mmc_data, int *selected_line )
{ {
int retv = MENU_CANCEL; int retv = MENU_CANCEL;
unsigned int i, j; unsigned int i, j;
unsigned int columns = config.menu_columns; unsigned int columns = config.menu_columns;
workarea mon; workarea mon;
unsigned int num_lines = 0;
// Calculate the number entries.
for (; lines != NULL && lines[num_lines]; num_lines++ ) {
;
}
unsigned int max_elements = MIN ( config.menu_lines * columns, num_lines ); unsigned int max_elements = MIN ( config.menu_lines * columns, num_lines );
// Calculate the number or rows. We do this by getting the num_lines rounded up to X columns // Calculate the number or rows. We do this by getting the num_lines rounded up to X columns
@ -1569,8 +1563,8 @@ SwitcherMode run_switcher_window ( char **input )
#ifdef HAVE_I3_IPC_H #ifdef HAVE_I3_IPC_H
} }
#endif #endif
char **list = calloc ( ( ids->len + 1 ), sizeof ( char* ) ); char **list = calloc ( ( ids->len + 1 ), sizeof ( char* ) );
int lines = 0; unsigned int lines = 0;
// build the actual list // build the actual list
Window w = 0; Window w = 0;
@ -1610,7 +1604,7 @@ SwitcherMode run_switcher_window ( char **input )
} }
Time time; Time time;
int selected_line = 0; int selected_line = 0;
MenuReturn mretv = menu ( list, input, "window:", &time, NULL, window_match, ids, &selected_line ); MenuReturn mretv = menu ( list, lines, input, "window:", &time, NULL, window_match, ids, &selected_line );
if ( mretv == MENU_NEXT ) { if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;

View file

@ -109,10 +109,9 @@ static int sort_func ( const void *a, const void *b )
const char *bstr = *( const char * const * ) b; const char *bstr = *( const char * const * ) b;
return strcasecmp ( astr, bstr ); return strcasecmp ( astr, bstr );
} }
static char ** get_apps ( void ) static char ** get_apps ( unsigned int *length )
{ {
unsigned int num_favorites = 0; unsigned int num_favorites = 0;
unsigned int index = 0;
char *path; char *path;
char **retv = NULL; char **retv = NULL;
#ifdef TIMING #ifdef TIMING
@ -126,10 +125,10 @@ static char ** get_apps ( void )
if ( asprintf ( &path, "%s/%s", cache_dir, RUN_CACHE_FILE ) > 0 ) { if ( asprintf ( &path, "%s/%s", cache_dir, RUN_CACHE_FILE ) > 0 ) {
retv = history_get_list ( path, &index ); retv = history_get_list ( path, length );
free ( path ); free ( path );
// Keep track of how many where loaded as favorite. // Keep track of how many where loaded as favorite.
num_favorites = index; num_favorites = ( *length );
} }
@ -168,12 +167,12 @@ static char ** get_apps ( void )
continue; continue;
} }
char ** tr = realloc ( retv, ( index + 2 ) * sizeof ( char* ) ); char ** tr = realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
if ( tr != NULL ) { if ( tr != NULL ) {
retv = tr; retv = tr;
retv[index] = strdup ( dent->d_name ); retv[( *length )] = strdup ( dent->d_name );
retv[index + 1] = NULL; retv[( *length ) + 1] = NULL;
index++; ( *length )++;
} }
} }
@ -182,8 +181,8 @@ static char ** get_apps ( void )
} }
// TODO: check this is still fast enough. (takes 1ms on laptop.) // TODO: check this is still fast enough. (takes 1ms on laptop.)
if ( index > num_favorites ) { if ( ( *length ) > num_favorites ) {
qsort ( &retv[num_favorites], index - num_favorites, sizeof ( char* ), sort_func ); qsort ( &retv[num_favorites], ( *length ) - num_favorites, sizeof ( char* ), sort_func );
} }
free ( path ); free ( path );
#ifdef TIMING #ifdef TIMING
@ -205,7 +204,8 @@ SwitcherMode run_switcher_dialog ( char **input )
int selected_line = 0; int selected_line = 0;
SwitcherMode retv = MODE_EXIT; SwitcherMode retv = MODE_EXIT;
// act as a launcher // act as a launcher
char **cmd_list = get_apps ( ); unsigned int cmd_list_length = 0;
char **cmd_list = get_apps ( &cmd_list_length );
if ( cmd_list == NULL ) { if ( cmd_list == NULL ) {
cmd_list = malloc ( 2 * sizeof ( char * ) ); cmd_list = malloc ( 2 * sizeof ( char * ) );
@ -213,7 +213,7 @@ SwitcherMode run_switcher_dialog ( char **input )
cmd_list[1] = NULL; cmd_list[1] = NULL;
} }
int mretv = menu ( cmd_list, input, "run:", NULL, &shift, token_match, NULL, &selected_line ); int mretv = menu ( cmd_list, cmd_list_length, input, "run:", NULL, &shift, token_match, NULL, &selected_line );
if ( mretv == MENU_NEXT ) { if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;

View file

@ -122,10 +122,9 @@ static int sort_func ( const void *a, const void *b )
const char *bstr = *( const char * const * ) b; const char *bstr = *( const char * const * ) b;
return strcasecmp ( astr, bstr ); return strcasecmp ( astr, bstr );
} }
static char ** get_ssh ( void ) static char ** get_ssh ( unsigned int *length )
{ {
unsigned int num_favorites = 0; unsigned int num_favorites = 0;
unsigned int index = 0;
char *path; char *path;
char **retv = NULL; char **retv = NULL;
#ifdef TIMING #ifdef TIMING
@ -138,9 +137,9 @@ static char ** get_ssh ( void )
} }
if ( asprintf ( &path, "%s/%s", cache_dir, SSH_CACHE_FILE ) > 0 ) { if ( asprintf ( &path, "%s/%s", cache_dir, SSH_CACHE_FILE ) > 0 ) {
retv = history_get_list ( path, &index ); retv = history_get_list ( path, length );
free ( path ); free ( path );
num_favorites = index; num_favorites = ( *length );
} }
@ -185,12 +184,12 @@ static char ** get_ssh ( void )
continue; continue;
} }
char **tr = realloc ( retv, ( index + 2 ) * sizeof ( char* ) ); char **tr = realloc ( retv, ( ( *length ) + 2 ) * sizeof ( char* ) );
if ( tr != NULL ) { if ( tr != NULL ) {
retv = tr; retv = tr;
retv[index] = strndup ( &buffer[start], stop - start ); retv[( *length )] = strndup ( &buffer[start], stop - start );
retv[index + 1] = NULL; retv[( *length ) + 1] = NULL;
index++; ( *length )++;
} }
} }
} }
@ -199,8 +198,8 @@ static char ** get_ssh ( void )
} }
// TODO: check this is still fast enough. (takes 1ms on laptop.) // TODO: check this is still fast enough. (takes 1ms on laptop.)
if ( index > num_favorites ) { if ( ( *length ) > num_favorites ) {
qsort ( &retv[num_favorites], index - num_favorites, sizeof ( char* ), sort_func ); qsort ( &retv[num_favorites], ( *length ) - num_favorites, sizeof ( char* ), sort_func );
} }
free ( path ); free ( path );
#ifdef TIMING #ifdef TIMING
@ -220,7 +219,8 @@ SwitcherMode ssh_switcher_dialog ( char **input )
{ {
SwitcherMode retv = MODE_EXIT; SwitcherMode retv = MODE_EXIT;
// act as a launcher // act as a launcher
char **cmd_list = get_ssh ( ); unsigned int cmd_list_length = 0;
char **cmd_list = get_ssh ( &cmd_list_length );
if ( cmd_list == NULL ) { if ( cmd_list == NULL ) {
cmd_list = malloc ( 2 * sizeof ( char * ) ); cmd_list = malloc ( 2 * sizeof ( char * ) );
@ -230,7 +230,7 @@ SwitcherMode ssh_switcher_dialog ( char **input )
int shift = 0; int shift = 0;
int selected_line = 0; int selected_line = 0;
int mretv = menu ( cmd_list, input, "ssh:", NULL, &shift, token_match, NULL, &selected_line ); int mretv = menu ( cmd_list, cmd_list_length, input, "ssh:", NULL, &shift, token_match, NULL, &selected_line );
if ( mretv == MENU_NEXT ) { if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG; retv = NEXT_DIALOG;