diff --git a/include/helper.h b/include/helper.h index 305e6d61..db9d684f 100644 --- a/include/helper.h +++ b/include/helper.h @@ -103,10 +103,7 @@ int find_arg ( const char * const key ); * * @returns 1 when matches, 0 otherwise */ -int token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive, - __attribute__( ( unused ) ) unsigned int index, - __attribute__( ( unused ) ) Switcher * data ); - +int token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive ); /** * @param cmd The command to execute. * diff --git a/include/rofi.h b/include/rofi.h index 05883004..28b66197 100644 --- a/include/rofi.h +++ b/include/rofi.h @@ -42,7 +42,7 @@ typedef enum typedef SwitcherMode ( *switcher_callback )( char **input, void *data ); typedef void ( *switcher_free )( Switcher *data ); -typedef const char * ( *get_display_value )( unsigned int selected_line, void *data, int *state ); +typedef char * ( *get_display_value )( unsigned int selected_line, struct _Switcher *data, int *state, int get_entry ); /** * State returned by the rofi window. */ @@ -79,7 +79,7 @@ typedef enum * * @returns 1 when it matches, 0 if not. */ -typedef int ( *menu_match_cb )( char **tokens, const char *input, int not_ascii, int case_sensitive, unsigned int index, Switcher *data ); +typedef int ( *menu_match_cb )( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *data ); /** * @param sw the Switcher to show. @@ -288,7 +288,7 @@ struct _Switcher * A switcher normally consists of the following parts: */ void ( *init )( struct _Switcher *sw ); - char ** ( *get_data )( unsigned int *length, struct _Switcher *pd ); + unsigned int ( *get_num_entries )( struct _Switcher *sw ); int ( *match )( char **tokens, const char *input, int case_sensitive, int index, struct _Switcher *data ); SwitcherMode ( *result )( int menu_retv, char **input, unsigned int selected_line, struct _Switcher *pd ); void ( *destroy )( struct _Switcher *pd ); @@ -297,6 +297,8 @@ struct _Switcher get_display_value mgrv; + int (*is_not_ascii)( struct _Switcher *sw, unsigned int index ); + // Pointer to private data. void *private_data; diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 8a38fb8c..c7ed3632 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -37,7 +37,6 @@ typedef struct _CombiModePrivateData { // List of (combined) entries. - char **cmd_list; unsigned int cmd_list_length; // List to validate where each switcher starts. unsigned int *starts; @@ -45,7 +44,6 @@ typedef struct _CombiModePrivateData // List of switchers to combine. unsigned int num_switchers; Switcher **switchers; - char *cache; } CombiModePrivateData; static void combi_mode_parse_switchers ( Switcher *sw ) @@ -111,38 +109,26 @@ static void combi_mode_init ( Switcher *sw ) for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { pd->switchers[i]->init ( pd->switchers[i] ); } - } -} -static char ** combi_mode_get_data ( unsigned int *length, Switcher *sw ) -{ - CombiModePrivateData *pd = sw->private_data; - if ( pd->cmd_list == NULL ) { - pd->cmd_list_length = 0; - for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { - unsigned int length = 0; - pd->switchers[i]->get_data ( &length, pd->switchers[i] ); - pd->starts[i] = pd->cmd_list_length; - pd->lengths[i] = length; - pd->cmd_list_length += length; - } - // Fill the list. - pd->cmd_list = g_malloc0 ( ( pd->cmd_list_length + 1 ) * sizeof ( char* ) ); - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - unsigned int length = 0; - char **retv = pd->switchers[i]->get_data ( &length, pd->switchers[i] ); - for ( unsigned int j = 0; j < length; j++ ) { - pd->cmd_list[j + pd->starts[i]] = retv[j]; + if ( pd->cmd_list_length == 0 ) { + pd->cmd_list_length = 0; + for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { + unsigned int length = pd->switchers[i]->get_num_entries ( pd->switchers[i] );; + pd->starts[i] = pd->cmd_list_length; + pd->lengths[i] = length; + pd->cmd_list_length += length; } } } - *length = pd->cmd_list_length; - return pd->cmd_list; +} +static unsigned int combi_mode_get_num_entries ( Switcher *sw ) +{ + CombiModePrivateData *pd = sw->private_data; + return pd->cmd_list_length; } static void combi_mode_destroy ( Switcher *sw ) { CombiModePrivateData *pd = (CombiModePrivateData *) sw->private_data; if ( pd != NULL ) { - g_free ( pd->cmd_list ); g_free ( pd->starts ); g_free ( pd->lengths ); // Cleanup switchers. @@ -150,7 +136,6 @@ static void combi_mode_destroy ( Switcher *sw ) pd->switchers[i]->destroy ( pd->switchers[i] ); } g_free ( pd->switchers ); - g_free ( pd->cache ); g_free ( pd ); sw->private_data = NULL; } @@ -188,22 +173,22 @@ static SwitcherMode combi_mode_result ( int mretv, char **input, unsigned int se } return MODE_EXIT; } -static int combi_mode_match ( char **tokens, const char *input, int not_ascii, +static int combi_mode_match ( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) { CombiModePrivateData *pd = sw->private_data; for ( unsigned i = 0; i < pd->num_switchers; i++ ) { if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { - if ( tokens && input[0] && tokens[0][0] == '!' ) { + if ( tokens && tokens[0][0] == '!' ) { if ( tokens[0][1] == pd->switchers[i]->name[0] ) { - return pd->switchers[i]->token_match ( &tokens[1], input, not_ascii, case_sensitive, + return pd->switchers[i]->token_match ( &tokens[1], not_ascii, case_sensitive, index - pd->starts[i], pd->switchers[i] ); } return 0; } else { - return pd->switchers[i]->token_match ( tokens, input, not_ascii, case_sensitive, + return pd->switchers[i]->token_match ( tokens, not_ascii, case_sensitive, index - pd->starts[i], pd->switchers[i] ); } } @@ -211,34 +196,53 @@ static int combi_mode_match ( char **tokens, const char *input, int not_ascii, abort (); return 0; } -static const char * combi_mgrv ( unsigned int selected_line, void *sw, int *state ) +static char * combi_mgrv ( unsigned int selected_line, Switcher *sw, int *state, int get_entry ) { - CombiModePrivateData *pd = ( (Switcher *) sw )->private_data; + CombiModePrivateData *pd = sw->private_data; + if ( !get_entry ) { + for ( unsigned i = 0; i < pd->num_switchers; i++ ) { + if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { + pd->switchers[i]->mgrv ( selected_line - pd->starts[i], (void *) pd->switchers[i], state, FALSE ); + return NULL; + } + } + return NULL; + } for ( unsigned i = 0; i < pd->num_switchers; i++ ) { if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - g_free ( pd->cache ); - pd->cache = g_strdup_printf ( "(%s) %s", pd->switchers[i]->name, - pd->switchers[i]->mgrv ( selected_line - pd->starts[i], - (void *) pd->switchers[i], state ) ); - return pd->cache; + char * str = pd->switchers[i]->mgrv ( selected_line - pd->starts[i], (void *) pd->switchers[i], state, TRUE ); + char * retv = g_strdup_printf ( "(%s) %s", pd->switchers[i]->name, str ); + g_free ( str ); + return retv; } } return NULL; } +static int combi_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + CombiModePrivateData *pd = sw->private_data; + for ( unsigned i = 0; i < pd->num_switchers; i++ ) { + if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { + return pd->switchers[i]->is_not_ascii ( pd->switchers[i], index - pd->starts[i] ); + } + } + return FALSE; +} Switcher combi_mode = { - .name = "combi", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = combi_mode_init, - .get_data = combi_mode_get_data, - .result = combi_mode_result, - .destroy = combi_mode_destroy, - .token_match = combi_mode_match, - .mgrv = combi_mgrv, - .private_data = NULL, - .free = NULL + .name = "combi", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = combi_mode_init, + .get_num_entries = combi_mode_get_num_entries, + .result = combi_mode_result, + .destroy = combi_mode_destroy, + .token_match = combi_mode_match, + .mgrv = combi_mgrv, + .is_not_ascii = combi_is_not_ascii, + .private_data = NULL, + .free = NULL }; diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index 0bdae156..eeecef52 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -96,15 +96,10 @@ static char **get_dmenu ( unsigned int *length ) return retv; } -static char ** dmenu_mode_get_data ( unsigned int *length, Switcher *sw ) +static unsigned int dmenu_mode_get_num_entries ( Switcher *sw ) { DmenuModePrivateData *rmpd = (DmenuModePrivateData *) sw->private_data; - if ( rmpd->cmd_list == NULL ) { - rmpd->cmd_list_length = 0; - rmpd->cmd_list = get_dmenu ( &( rmpd->cmd_list_length ) ); - } - *length = rmpd->cmd_list_length; - return rmpd->cmd_list; + return rmpd->cmd_list_length; } static void parse_pair ( char *input, struct range_pair *item ) @@ -142,7 +137,7 @@ static void parse_ranges ( char *input, struct range_pair **list, unsigned int * } } -static const char *get_display_data ( unsigned int index, void *data, G_GNUC_UNUSED int *state ) +static char *get_display_data ( unsigned int index, Switcher *data, int *state, int get_entry ) { Switcher *sw = (Switcher *) data; DmenuModePrivateData *pd = (DmenuModePrivateData *) sw->private_data; @@ -157,7 +152,7 @@ static const char *get_display_data ( unsigned int index, void *data, G_GNUC_UNU *state |= URGENT; } } - return retv[index]; + return get_entry ? g_strdup ( retv[index] ) : NULL; } /** @@ -281,22 +276,36 @@ static void dmenu_mode_init ( Switcher *sw ) if ( find_arg ( "-i" ) >= 0 ) { config.case_sensitive = FALSE; } + pd->cmd_list = get_dmenu ( &( pd->cmd_list_length ) ); +} + +static int dmenu_token_match ( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) +{ + DmenuModePrivateData *rmpd = (DmenuModePrivateData *) sw->private_data; + return token_match ( tokens, rmpd->cmd_list[index], not_ascii, case_sensitive ); +} + +static int dmenu_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + DmenuModePrivateData *rmpd = (DmenuModePrivateData *) sw->private_data; + return is_not_ascii ( rmpd->cmd_list[index] ); } Switcher dmenu_mode = { - .name = "dmenu", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = dmenu_mode_init, - .get_data = dmenu_mode_get_data, - .result = NULL, - .destroy = dmenu_mode_free, - .token_match = token_match, - .mgrv = get_display_data, - .private_data = NULL, - .free = NULL + .name = "dmenu", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = dmenu_mode_init, + .get_num_entries = dmenu_mode_get_num_entries, + .result = NULL, + .destroy = dmenu_mode_free, + .token_match = dmenu_token_match, + .mgrv = get_display_data, + .is_not_ascii = dmenu_is_not_ascii, + .private_data = NULL, + .free = NULL }; int dmenu_switcher_dialog ( void ) @@ -306,8 +315,8 @@ int dmenu_switcher_dialog ( void ) char *input = NULL; int retv = FALSE; int restart = FALSE; - unsigned int cmd_list_length = 0; - char **cmd_list = dmenu_mode.get_data ( &( cmd_list_length ), &dmenu_mode ); + unsigned int cmd_list_length = pd->cmd_list_length; + char **cmd_list = pd->cmd_list; int only_selected = FALSE; if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) { @@ -325,7 +334,7 @@ int dmenu_switcher_dialog ( void ) char **tokens = tokenize ( select, config.case_sensitive ); unsigned int i = 0; for ( i = 0; i < cmd_list_length; i++ ) { - if ( token_match ( tokens, cmd_list[i], is_not_ascii ( cmd_list[i] ), config.case_sensitive, 0, NULL ) ) { + if ( token_match ( tokens, cmd_list[i], is_not_ascii ( cmd_list[i] ), config.case_sensitive ) ) { pd->selected_line = i; break; } diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index 95f073b4..85d0ecf5 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -87,13 +87,18 @@ static void exec_cmd ( const char *cmd, int run_in_term ) */ typedef struct _DRunModeEntry { + /* Executable */ char *exec; + /* Name of the Entry */ + char *name; + /* Generic Name */ + char *generic_name; + /* Application needs to be launched in terminal. */ unsigned int terminal; } DRunModeEntry; typedef struct _DRunModePrivateData { - char **cmd_list; DRunModeEntry *entry_list; unsigned int cmd_list_length; } DRunModePrivateData; @@ -151,29 +156,21 @@ static void get_apps_dir ( DRunModePrivateData *pd, const char *bp ) } if ( g_key_file_has_key ( kf, "Desktop Entry", "Exec", NULL ) ) { size_t nl = ( ( pd->cmd_list_length ) + 2 ); - pd->cmd_list = g_realloc ( pd->cmd_list, nl * sizeof ( *( pd->cmd_list ) ) ); pd->entry_list = g_realloc ( pd->entry_list, nl * sizeof ( *( pd->entry_list ) ) ); if ( g_key_file_has_key ( kf, "Desktop Entry", "Name", NULL ) ) { gchar *n = g_key_file_get_locale_string ( kf, "Desktop Entry", "Name", NULL, NULL ); gchar *gn = g_key_file_get_locale_string ( kf, "Desktop Entry", "GenericName", NULL, NULL ); - if ( gn == NULL ) { - pd->cmd_list[pd->cmd_list_length] = g_markup_escape_text ( n, -1 ); - } - else { - ( pd->cmd_list )[( pd->cmd_list_length )] = g_markup_printf_escaped ( - "%s (%s)", - n, gn ? gn : "" ); - } - g_free ( n ); g_free ( gn ); + pd->entry_list[pd->cmd_list_length].name = n; + pd->entry_list[pd->cmd_list_length].generic_name = gn; } else { - ( pd->cmd_list )[( pd->cmd_list_length )] = g_strdup ( dent->d_name ); + pd->entry_list[pd->cmd_list_length].name = g_strdup ( dent->d_name ); + pd->entry_list[pd->cmd_list_length].generic_name = NULL; } pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, "Desktop Entry", "Exec", NULL ); if ( g_key_file_has_key ( kf, "Desktop Entry", "Terminal", NULL ) ) { pd->entry_list[pd->cmd_list_length].terminal = g_key_file_get_boolean ( kf, "Desktop Entry", "Terminal", NULL ); } - ( pd->cmd_list )[( pd->cmd_list_length ) + 1] = NULL; ( pd->cmd_list_length )++; } @@ -222,22 +219,10 @@ static void drun_mode_init ( Switcher *sw ) if ( sw->private_data == NULL ) { DRunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; + get_apps ( pd ); } } -static char ** drun_mode_get_data ( unsigned int *length, Switcher *sw ) -{ - DRunModePrivateData *rmpd = (DRunModePrivateData *) sw->private_data; - if ( rmpd->cmd_list == NULL ) { - rmpd->cmd_list_length = 0; - get_apps ( rmpd ); - } - if ( length != NULL ) { - *length = rmpd->cmd_list_length; - } - return rmpd->cmd_list; -} - static SwitcherMode drun_mode_result ( int mretv, char **input, unsigned int selected_line, Switcher *sw ) { @@ -255,7 +240,7 @@ static SwitcherMode drun_mode_result ( int mretv, char **input, unsigned int sel else if ( mretv & MENU_QUICK_SWITCH ) { retv = ( mretv & MENU_LOWER_MASK ); } - else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) { + else if ( ( mretv & MENU_OK ) ) { exec_cmd_entry ( &( rmpd->entry_list[selected_line] ) ); } else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { @@ -268,9 +253,10 @@ static void drun_mode_destroy ( Switcher *sw ) { DRunModePrivateData *rmpd = (DRunModePrivateData *) sw->private_data; if ( rmpd != NULL ) { - g_strfreev ( rmpd->cmd_list ); for ( size_t i = 0; i < rmpd->cmd_list_length; i++ ) { g_free ( rmpd->entry_list[i].exec ); + g_free ( rmpd->entry_list[i].name ); + g_free ( rmpd->entry_list[i].generic_name ); } g_free ( rmpd->entry_list ); g_free ( rmpd ); @@ -278,24 +264,74 @@ static void drun_mode_destroy ( Switcher *sw ) } } -static const char *mgrv ( unsigned int selected_line, void *sw, int *state ) +static char *mgrv ( unsigned int selected_line, Switcher *sw, int *state, int get_entry ) { + DRunModePrivateData *pd = (DRunModePrivateData *) sw->private_data; *state |= MARKUP; - return drun_mode_get_data ( NULL, sw )[selected_line]; + if ( !get_entry ) { + return NULL; + } + if ( pd->entry_list == NULL ) { + // Should never get here. + return g_strdup ( "Failed" ); + } + /* Free temp storage. */ + DRunModeEntry *dr = &( pd->entry_list[selected_line] ); + if ( dr->generic_name == NULL ) { + return g_markup_escape_text ( dr->name, -1 ); + } + else { + return g_markup_printf_escaped ( "%s (%s)", dr->name, + dr->generic_name ); + } +} + +static int drun_token_match ( char **tokens, + int not_ascii, + int case_sensitive, + unsigned int index, + Switcher *data ) +{ + DRunModePrivateData *rmpd = (DRunModePrivateData *) data->private_data; + if ( rmpd->entry_list[index].name && + token_match ( tokens, rmpd->entry_list[index].name, not_ascii, case_sensitive ) ) { + return 1; + } + if ( rmpd->entry_list[index].generic_name && + token_match ( tokens, rmpd->entry_list[index].generic_name, not_ascii, case_sensitive ) ) { + return 1; + } + + return 0; +} + +static unsigned int drun_mode_get_num_entries ( Switcher *sw ) +{ + DRunModePrivateData *pd = (DRunModePrivateData *) sw->private_data; + return pd->cmd_list_length; +} +static int drun_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + DRunModePrivateData *pd = (DRunModePrivateData *) sw->private_data; + if ( pd->entry_list[index].generic_name ) { + return is_not_ascii ( pd->entry_list[index].name ) || is_not_ascii ( pd->entry_list[index].generic_name ); + } + return is_not_ascii ( pd->entry_list[index].name ); } Switcher drun_mode = { - .name = "drun", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = drun_mode_init, - .get_data = drun_mode_get_data, - .result = drun_mode_result, - .destroy = drun_mode_destroy, - .token_match = token_match, - .mgrv = mgrv, - .private_data = NULL, - .free = NULL + .name = "drun", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = drun_mode_init, + .get_num_entries = drun_mode_get_num_entries, + .result = drun_mode_result, + .destroy = drun_mode_destroy, + .token_match = drun_token_match, + .mgrv = mgrv, + .is_not_ascii = drun_is_not_ascii, + .private_data = NULL, + .free = NULL }; diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 9653dce4..75fe7722 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -272,20 +272,14 @@ static void run_mode_init ( Switcher *sw ) if ( sw->private_data == NULL ) { RunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; + pd->cmd_list = get_apps ( &( pd->cmd_list_length ) ); } } -static char ** run_mode_get_data ( unsigned int *length, Switcher *sw ) +static unsigned int run_mode_get_num_entries ( Switcher *sw ) { RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; - if ( rmpd->cmd_list == NULL ) { - rmpd->cmd_list_length = 0; - rmpd->cmd_list = get_apps ( &( rmpd->cmd_list_length ) ); - } - if ( length != NULL ) { - *length = rmpd->cmd_list_length; - } - return rmpd->cmd_list; + return rmpd->cmd_list_length; } static SwitcherMode run_mode_result ( int mretv, char **input, unsigned int selected_line, @@ -333,23 +327,35 @@ static void run_mode_destroy ( Switcher *sw ) } } -static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +static char *mgrv ( unsigned int selected_line, Switcher *sw, G_GNUC_UNUSED int *state, int get_entry ) { - return run_mode_get_data ( NULL, sw )[selected_line]; + RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; + return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; +} +static int run_token_match ( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) +{ + RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; + return token_match ( tokens, rmpd->cmd_list[index], not_ascii, case_sensitive ); } +static int run_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; + return is_not_ascii ( rmpd->cmd_list[index] ); +} Switcher run_mode = { - .name = "run", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = run_mode_init, - .get_data = run_mode_get_data, - .result = run_mode_result, - .destroy = run_mode_destroy, - .token_match = token_match, - .mgrv = mgrv, - .private_data = NULL, - .free = NULL + .name = "run", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = run_mode_init, + .get_num_entries = run_mode_get_num_entries, + .result = run_mode_result, + .destroy = run_mode_destroy, + .token_match = run_token_match, + .mgrv = mgrv, + .is_not_ascii = run_is_not_ascii, + .private_data = NULL, + .free = NULL }; diff --git a/source/dialogs/script.c b/source/dialogs/script.c index 915fc602..b67d5be8 100644 --- a/source/dialogs/script.c +++ b/source/dialogs/script.c @@ -102,17 +102,13 @@ static void script_mode_init ( Switcher *sw ) if ( sw->private_data == NULL ) { ScriptModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; + pd->cmd_list = get_script_output ( (const char *) sw->ed, &( pd->cmd_list_length ) ); } } -static char ** script_mode_get_data ( unsigned int *length, Switcher *sw ) +static unsigned int script_mode_get_num_entries ( Switcher *sw ) { ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data; - if ( rmpd->cmd_list == NULL ) { - rmpd->cmd_list_length = 0; - rmpd->cmd_list = get_script_output ( (const char *) sw->ed, &( rmpd->cmd_list_length ) ); - } - *length = rmpd->cmd_list_length; - return rmpd->cmd_list; + return rmpd->cmd_list_length; } static SwitcherMode script_mode_result ( int mretv, char **input, unsigned int selected_line, @@ -161,10 +157,22 @@ static void script_mode_destroy ( Switcher *sw ) sw->private_data = NULL; } } -static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +static char *mgrv ( unsigned int selected_line, Switcher *sw, G_GNUC_UNUSED int *state, int get_entry ) { - ScriptModePrivateData *rmpd = ( (Switcher *) sw )->private_data; - return rmpd->cmd_list[selected_line]; + ScriptModePrivateData *rmpd = sw->private_data; + return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; +} + +static int script_token_match ( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) +{ + ScriptModePrivateData *rmpd = sw->private_data; + return token_match ( tokens, rmpd->cmd_list[index], not_ascii, case_sensitive ); +} + +static int script_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + ScriptModePrivateData *rmpd = sw->private_data; + return is_not_ascii ( rmpd->cmd_list[index] ); } Switcher *script_switcher_parse_setup ( const char *str ) @@ -184,15 +192,16 @@ Switcher *script_switcher_parse_setup ( const char *str ) } g_free ( parse ); if ( index == 2 ) { - sw->free = script_switcher_free; - sw->keysym = None; - sw->modmask = AnyModifier; - sw->init = script_mode_init; - sw->get_data = script_mode_get_data; - sw->result = script_mode_result; - sw->destroy = script_mode_destroy; - sw->token_match = token_match; - sw->mgrv = mgrv; + sw->free = script_switcher_free; + sw->keysym = None; + sw->modmask = AnyModifier; + sw->init = script_mode_init; + sw->get_num_entries = script_mode_get_num_entries; + sw->result = script_mode_result; + sw->destroy = script_mode_destroy; + sw->token_match = script_token_match; + sw->mgrv = mgrv; + sw->is_not_ascii = script_is_not_ascii; return sw; } diff --git a/source/dialogs/ssh.c b/source/dialogs/ssh.c index 9bf610b1..7b870c0f 100644 --- a/source/dialogs/ssh.c +++ b/source/dialogs/ssh.c @@ -327,20 +327,14 @@ static void ssh_mode_init ( Switcher *sw ) if ( sw->private_data == NULL ) { SSHModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; + pd->cmd_list = get_ssh ( &( pd->cmd_list_length ) ); } } -static char ** ssh_mode_get_data ( unsigned int *length, Switcher *sw ) +static unsigned int ssh_mode_get_num_entries ( Switcher *sw ) { SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data; - if ( rmpd->cmd_list == NULL ) { - rmpd->cmd_list_length = 0; - rmpd->cmd_list = get_ssh ( &( rmpd->cmd_list_length ) ); - } - if ( length != NULL ) { - *length = rmpd->cmd_list_length; - } - return rmpd->cmd_list; + return rmpd->cmd_list_length; } static SwitcherMode ssh_mode_result ( int mretv, char **input, unsigned int selected_line, Switcher *sw ) @@ -383,23 +377,36 @@ static void ssh_mode_destroy ( Switcher *sw ) } } -static const char *mgrv ( unsigned int selected_line, void *sw, G_GNUC_UNUSED int *state ) +static char *mgrv ( unsigned int selected_line, Switcher *sw, G_GNUC_UNUSED int *state, int get_entry ) { - return ssh_mode_get_data ( NULL, sw )[selected_line]; + SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data; + return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; +} +static int ssh_token_match ( char **tokens, int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) +{ + SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data; + return token_match ( tokens, rmpd->cmd_list[index], not_ascii, case_sensitive ); +} + +static int ssh_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + SSHModePrivateData *rmpd = (SSHModePrivateData *) sw->private_data; + return is_not_ascii ( rmpd->cmd_list[index] ); } Switcher ssh_mode = { - .name = "ssh", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = ssh_mode_init, - .get_data = ssh_mode_get_data, - .result = ssh_mode_result, - .destroy = ssh_mode_destroy, - .token_match = token_match, - .mgrv = mgrv, - .private_data = NULL, - .free = NULL + .name = "ssh", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = ssh_mode_init, + .get_num_entries = ssh_mode_get_num_entries, + .result = ssh_mode_result, + .destroy = ssh_mode_destroy, + .token_match = ssh_token_match, + .mgrv = mgrv, + .is_not_ascii = ssh_is_not_ascii, + .private_data = NULL, + .free = NULL }; diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 1a30bf11..a922cd9f 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -315,13 +315,12 @@ typedef struct _SwitcherModePrivateData unsigned int cmd_list_length; winlist *ids; int config_i3_mode; - int init; // Current window. unsigned int index; char *cache; } SwitcherModePrivateData; -static int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input, +static int window_match ( char **tokens, __attribute__( ( unused ) ) int not_ascii, int case_sensitive, unsigned int index, Switcher *sw ) { @@ -339,19 +338,19 @@ static int window_match ( char **tokens, __attribute__( ( unused ) ) const char // e.g. when searching 'title element' and 'class element' char *ftokens[2] = { tokens[j], NULL }; if ( !test && c->title[0] != '\0' ) { - test = token_match ( ftokens, c->title, is_not_ascii ( c->title ), case_sensitive, 0, NULL ); + test = token_match ( ftokens, c->title, not_ascii, case_sensitive ); } if ( !test && c->class[0] != '\0' ) { - test = token_match ( ftokens, c->class, is_not_ascii ( c->class ), case_sensitive, 0, NULL ); + test = token_match ( ftokens, c->class, not_ascii, case_sensitive ); } if ( !test && c->role[0] != '\0' ) { - test = token_match ( ftokens, c->role, is_not_ascii ( c->role ), case_sensitive, 0, NULL ); + test = token_match ( ftokens, c->role, not_ascii, case_sensitive ); } if ( !test && c->name[0] != '\0' ) { - test = token_match ( ftokens, c->name, is_not_ascii ( c->name ), case_sensitive, 0, NULL ); + test = token_match ( ftokens, c->name, not_ascii, case_sensitive ); } if ( test == 0 ) { @@ -362,151 +361,151 @@ static int window_match ( char **tokens, __attribute__( ( unused ) ) const char return match; } + +static unsigned int window_mode_get_num_entries ( Switcher *sw ) +{ + SwitcherModePrivateData *pd = (SwitcherModePrivateData *) sw->private_data; + return pd->cmd_list_length; +} +static void _window_mode_load_data ( Switcher *sw, unsigned int cd ) +{ + SwitcherModePrivateData *pd = (SwitcherModePrivateData *) sw->private_data; + Screen *screen = DefaultScreenOfDisplay ( display ); + Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); + // find window list + Atom type; + int nwins = 0; + Window wins[100]; + int count = 0; + Window curr_win_id = 0; + // Create cache + + x11_cache_create (); + // Check for i3 + pd->config_i3_mode = i3_support_initialize ( display ); + + // Get the active window so we can highlight this. + if ( !( window_get_prop ( display, root, netatoms[_NET_ACTIVE_WINDOW], &type, &count, &curr_win_id, sizeof ( Window ) ) + && type == XA_WINDOW && count > 0 ) ) { + curr_win_id = 0; + } + + // Get the current desktop. + unsigned long current_desktop = 0; + if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_CURRENT_DESKTOP], ¤t_desktop, 1 ) ) { + current_desktop = 0; + } + + unsigned int nw = 100 * sizeof ( Window ); + // First try Stacking order.. If this fails. + if ( !( window_get_prop ( display, root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, nw ) + && type == XA_WINDOW ) ) { + // Try to get order by age. + if ( !( window_get_prop ( display, root, netatoms[_NET_CLIENT_LIST], &type, &nwins, wins, nw ) + && type == XA_WINDOW ) ) { + nwins = 0; + } + } + if ( nwins > 0 ) { + char pattern[50]; + int i; + unsigned int classfield = 0; + unsigned long desktops = 0; + // 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... + pd->ids = winlist_new (); + + // calc widths of fields + for ( i = nwins - 1; i > -1; i-- ) { + client *c; + + if ( ( c = window_client ( display, wins[i] ) ) + && !c->xattr.override_redirect + && !client_has_window_type ( c, netatoms[_NET_WM_WINDOW_TYPE_DOCK] ) + && !client_has_window_type ( c, netatoms[_NET_WM_WINDOW_TYPE_DESKTOP] ) + && !client_has_state ( c, netatoms[_NET_WM_STATE_SKIP_PAGER] ) + && !client_has_state ( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) { + classfield = MAX ( classfield, strlen ( c->class ) ); + + if ( client_has_state ( c, netatoms[_NET_WM_STATE_DEMANDS_ATTENTION] ) ) { + c->demands = TRUE; + } + if ( ( c->hint_flags & XUrgencyHint ) == XUrgencyHint ) { + c->demands = TRUE; + } + + if ( c->window == curr_win_id ) { + c->active = TRUE; + } + winlist_append ( pd->ids, c->window, NULL ); + } + } + + // Create pattern for printing the line. + if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) ) { + desktops = 1; + } + if ( pd->config_i3_mode ) { + sprintf ( pattern, "%%-%ds %%s", MAX ( 5, classfield ) ); + } + else{ + sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, + MAX ( 5, classfield ) ); + } + pd->cmd_list = g_malloc0_n ( ( pd->ids->len + 1 ), sizeof ( char* ) ); + + // build the actual list + for ( i = 0; i < ( pd->ids->len ); i++ ) { + Window w = pd->ids->array[i]; + client *c; + + if ( ( c = window_client ( display, w ) ) ) { + // final line format + unsigned long wmdesktop; + char desktop[5]; + desktop[0] = 0; + char *line = g_malloc ( strlen ( c->title ) + strlen ( c->class ) + classfield + 50 ); + if ( !pd->config_i3_mode ) { + // find client's desktop. + if ( !window_get_cardinal_prop ( display, c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) { + // Assume the client is on all desktops. + wmdesktop = 0xFFFFFFFF; + } + else if ( cd && wmdesktop != current_desktop ) { + g_free ( line ); + continue; + } + + if ( wmdesktop < 0xFFFFFFFF ) { + sprintf ( desktop, "%d", (int) wmdesktop ); + } + + sprintf ( line, pattern, desktop, c->class, c->title ); + } + else{ + sprintf ( line, pattern, c->class, c->title ); + } + + pd->cmd_list[pd->cmd_list_length++] = line; + } + } + } +} static void window_mode_init ( Switcher *sw ) { if ( sw->private_data == NULL ) { SwitcherModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; - pd->init = FALSE; + _window_mode_load_data ( sw, FALSE ); } } - -static char ** _window_mode_get_data ( unsigned int *length, Switcher *sw, unsigned int cd ) +static void window_mode_init_cd ( Switcher *sw ) { - SwitcherModePrivateData *pd = (SwitcherModePrivateData *) sw->private_data; - if ( !pd->init ) { - Screen *screen = DefaultScreenOfDisplay ( display ); - Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); - // find window list - Atom type; - int nwins = 0; - Window wins[100]; - int count = 0; - Window curr_win_id = 0; - // Create cache - - x11_cache_create (); - // Check for i3 - pd->config_i3_mode = i3_support_initialize ( display ); - - // Get the active window so we can highlight this. - if ( !( window_get_prop ( display, root, netatoms[_NET_ACTIVE_WINDOW], &type, &count, &curr_win_id, sizeof ( Window ) ) - && type == XA_WINDOW && count > 0 ) ) { - curr_win_id = 0; - } - - // Get the current desktop. - unsigned long current_desktop = 0; - if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_CURRENT_DESKTOP], ¤t_desktop, 1 ) ) { - current_desktop = 0; - } - - unsigned int nw = 100 * sizeof ( Window ); - // First try Stacking order.. If this fails. - if ( !( window_get_prop ( display, root, netatoms[_NET_CLIENT_LIST_STACKING], &type, &nwins, wins, nw ) - && type == XA_WINDOW ) ) { - // Try to get order by age. - if ( !( window_get_prop ( display, root, netatoms[_NET_CLIENT_LIST], &type, &nwins, wins, nw ) - && type == XA_WINDOW ) ) { - nwins = 0; - } - } - if ( nwins > 0 ) { - char pattern[50]; - int i; - unsigned int classfield = 0; - unsigned long desktops = 0; - // 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... - pd->ids = winlist_new (); - - // calc widths of fields - for ( i = nwins - 1; i > -1; i-- ) { - client *c; - - if ( ( c = window_client ( display, wins[i] ) ) - && !c->xattr.override_redirect - && !client_has_window_type ( c, netatoms[_NET_WM_WINDOW_TYPE_DOCK] ) - && !client_has_window_type ( c, netatoms[_NET_WM_WINDOW_TYPE_DESKTOP] ) - && !client_has_state ( c, netatoms[_NET_WM_STATE_SKIP_PAGER] ) - && !client_has_state ( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) { - classfield = MAX ( classfield, strlen ( c->class ) ); - - if ( client_has_state ( c, netatoms[_NET_WM_STATE_DEMANDS_ATTENTION] ) ) { - c->demands = TRUE; - } - if ( ( c->hint_flags & XUrgencyHint ) == XUrgencyHint ) { - c->demands = TRUE; - } - - if ( c->window == curr_win_id ) { - c->active = TRUE; - } - winlist_append ( pd->ids, c->window, NULL ); - } - } - - // Create pattern for printing the line. - if ( !window_get_cardinal_prop ( display, root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) ) { - desktops = 1; - } - if ( pd->config_i3_mode ) { - sprintf ( pattern, "%%-%ds %%s", MAX ( 5, classfield ) ); - } - else{ - sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, - MAX ( 5, classfield ) ); - } - pd->cmd_list = g_malloc0_n ( ( pd->ids->len + 1 ), sizeof ( char* ) ); - - // build the actual list - for ( i = 0; i < ( pd->ids->len ); i++ ) { - Window w = pd->ids->array[i]; - client *c; - - if ( ( c = window_client ( display, w ) ) ) { - // final line format - unsigned long wmdesktop; - char desktop[5]; - desktop[0] = 0; - char *line = g_malloc ( strlen ( c->title ) + strlen ( c->class ) + classfield + 50 ); - if ( !pd->config_i3_mode ) { - // find client's desktop. - if ( !window_get_cardinal_prop ( display, c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) { - // Assume the client is on all desktops. - wmdesktop = 0xFFFFFFFF; - } - else if ( cd && wmdesktop != current_desktop ) { - g_free ( line ); - continue; - } - - if ( wmdesktop < 0xFFFFFFFF ) { - sprintf ( desktop, "%d", (int) wmdesktop ); - } - - sprintf ( line, pattern, desktop, c->class, c->title ); - } - else{ - sprintf ( line, pattern, c->class, c->title ); - } - - pd->cmd_list[pd->cmd_list_length++] = line; - } - } - } - pd->init = TRUE; + if ( sw->private_data == NULL ) { + SwitcherModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); + sw->private_data = (void *) pd; + _window_mode_load_data ( sw, TRUE ); } - *length = pd->cmd_list_length; - return pd->cmd_list; -} -static char ** window_mode_get_data_cd ( unsigned int *length, Switcher *sw ) -{ - return _window_mode_get_data ( length, sw, TRUE ); -} -static char ** window_mode_get_data ( unsigned int *length, Switcher *sw ) -{ - return _window_mode_get_data ( length, sw, FALSE ); } static SwitcherMode window_mode_result ( int mretv, G_GNUC_UNUSED char **input, unsigned int selected_line, @@ -558,47 +557,57 @@ static void window_mode_destroy ( Switcher *sw ) } } -static const char *mgrv ( unsigned int selected_line, void *sw, int *state ) +static char *mgrv ( unsigned int selected_line, Switcher *sw, int *state, int get_entry ) { - SwitcherModePrivateData *rmpd = ( (Switcher *) sw )->private_data; + SwitcherModePrivateData *rmpd = sw->private_data; if ( window_client ( display, rmpd->ids->array[selected_line] )->demands ) { *state |= URGENT; } if ( window_client ( display, rmpd->ids->array[selected_line] )->active ) { *state |= ACTIVE; } - return rmpd->cmd_list[selected_line]; + return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; +} + +static int window_is_not_ascii ( Switcher *sw, unsigned int index ) +{ + SwitcherModePrivateData *rmpd = sw->private_data; + winlist *ids = ( winlist * ) rmpd->ids; + client *c = window_client ( display, ids->array[index] ); + return is_not_ascii ( c->role ) || is_not_ascii ( c->class ) || is_not_ascii ( c->title ) || is_not_ascii ( c->name ); } Switcher window_mode = { - .name = "window", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = window_mode_init, - .get_data = window_mode_get_data, - .result = window_mode_result, - .destroy = window_mode_destroy, - .token_match = window_match, - .mgrv = mgrv, - .private_data = NULL, - .free = NULL + .name = "window", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = window_mode_init, + .get_num_entries = window_mode_get_num_entries, + .result = window_mode_result, + .destroy = window_mode_destroy, + .token_match = window_match, + .mgrv = mgrv, + .is_not_ascii = window_is_not_ascii, + .private_data = NULL, + .free = NULL }; Switcher window_mode_cd = { - .name = "windowcd", - .keycfg = NULL, - .keystr = NULL, - .modmask = AnyModifier, - .init = window_mode_init, - .get_data = window_mode_get_data_cd, - .result = window_mode_result, - .destroy = window_mode_destroy, - .token_match = window_match, - .mgrv = mgrv, - .private_data = NULL, - .free = NULL + .name = "windowcd", + .keycfg = NULL, + .keystr = NULL, + .modmask = AnyModifier, + .init = window_mode_init_cd, + .get_num_entries = window_mode_get_num_entries, + .result = window_mode_result, + .destroy = window_mode_destroy, + .token_match = window_match, + .mgrv = mgrv, + .is_not_ascii = window_is_not_ascii, + .private_data = NULL, + .free = NULL }; #endif // WINDOW_MODE diff --git a/source/helper.c b/source/helper.c index 621775f8..e884115a 100644 --- a/source/helper.c +++ b/source/helper.c @@ -472,9 +472,7 @@ static int glob_token_match ( char **tokens, const char *input, int not_ascii, i return match; } -int token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive, - __attribute__( ( unused ) ) unsigned int index, - __attribute__( ( unused ) ) Switcher *data ) +int token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive ) { if ( config.glob ) { return glob_token_match ( tokens, input, not_ascii, case_sensitive ); diff --git a/source/rofi.c b/source/rofi.c index a26e1ee0..acfb0b82 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -154,7 +154,7 @@ static int lev_sort ( const void *p1, const void *p2, void *arg ) #define MIN3( a, b, c ) ( ( a ) < ( b ) ? ( ( a ) < ( c ) ? ( a ) : ( c ) ) : ( ( b ) < ( c ) ? ( b ) : ( c ) ) ) -static int levenshtein ( char *s1, char *s2 ) +static int levenshtein ( const char *s1, const char *s2 ) { unsigned int x, y, lastdiag, olddiag; size_t s1len = strlen ( s1 ); @@ -222,7 +222,6 @@ typedef struct MenuState // Return state unsigned int *selected_line; MenuReturn retv; - char **lines; int *lines_not_ascii; int line_height; unsigned int border; @@ -643,7 +642,10 @@ static int menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned int else if ( abe_test_action ( ROW_SELECT, modstate, key ) ) { // If a valid item is selected, return that.. if ( state->selected < state->filtered_lines ) { - textbox_text ( state->text, state->lines[state->line_map[state->selected]] ); + int st; + char * str = state->sw->mgrv ( state->line_map[state->selected], state->sw, &st, TRUE ); + textbox_text ( state->text, str ); + g_free ( str ); textbox_cursor_end ( state->text ); state->update = TRUE; state->refilter = TRUE; @@ -752,18 +754,20 @@ static void filter_elements ( thread_state *t, G_GNUC_UNUSED gpointer user_data { // input changed for ( unsigned int i = t->start; i < t->stop; i++ ) { + int st; int match = t->state->sw->token_match ( t->tokens, - t->state->lines[i], t->state->lines_not_ascii[i], config.case_sensitive, i, t->state->sw ); - // If each token was matched, add it to list. if ( match ) { t->state->line_map[t->start + t->count] = i; if ( config.levenshtein_sort ) { - t->state->distance[i] = levenshtein ( t->state->text->text, t->state->lines[i] ); + // This is inefficient, need to fix it. + char * str = t->state->sw->mgrv ( i, t->state->sw, &st, TRUE ); + t->state->distance[i] = levenshtein ( t->state->text->text, str ); + g_free ( str ); } t->count++; } @@ -776,7 +780,7 @@ static void filter_elements ( thread_state *t, G_GNUC_UNUSED gpointer user_data static void check_is_ascii ( thread_state *t, G_GNUC_UNUSED gpointer user_data ) { for ( unsigned int i = t->start; i < t->stop; i++ ) { - t->state->lines_not_ascii[i] = is_not_ascii ( t->state->lines[i] ); + t->state->lines_not_ascii[i] = t->state->sw->is_not_ascii ( t->state->sw, i ); } g_mutex_lock ( t->mutex ); ( *( t->acount ) )--; @@ -933,10 +937,11 @@ static void menu_draw ( MenuState *state, cairo_t *d ) { TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; int fstate = 0; - const char *text = state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate ); + char *text = state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate, TRUE ); TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type ); textbox_font ( state->boxes[i], tbft ); textbox_text ( state->boxes[i], text ); + g_free ( text ); } textbox_draw ( state->boxes[i], d ); } @@ -947,7 +952,7 @@ static void menu_draw ( MenuState *state, cairo_t *d ) for ( i = 0; i < max_elements; i++ ) { TextBoxFontType type = ( ( ( i % state->max_rows ) & 1 ) == 0 ) ? NORMAL : ALT; int fstate = 0; - state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate ); + state->sw->mgrv ( state->line_map[i + offset], state->sw, &fstate, FALSE ); TextBoxFontType tbft = fstate | ( ( i + offset ) == state->selected ? HIGHLIGHT : type ); textbox_font ( state->boxes[i], tbft ); textbox_draw ( state->boxes[i], d ); @@ -1186,11 +1191,11 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select .border = config.padding + config.menu_bw }; // Request the lines to show. - state.lines = sw->get_data ( &( state.num_lines ), sw ); + state.num_lines = sw->get_num_entries ( sw ); state.lines_not_ascii = g_malloc0_n ( state.num_lines, sizeof ( int ) ); // find out which lines contain non-ascii codepoints, so we can be faster in some cases. - if ( state.lines != NULL ) { + if ( state.num_lines > 0 ) { TICK_N ( "Is ASCII start" ) unsigned int nt = MAX ( 1, state.num_lines / 5000 ); thread_state states[nt]; @@ -1487,7 +1492,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select } Status stat; char pad[32]; - KeySym key;// = XkbKeycodeToKeysym ( display, ev.xkey.keycode, 0, 0 ); + KeySym key; // = XkbKeycodeToKeysym ( display, ev.xkey.keycode, 0, 0 ); int len = Xutf8LookupString ( xic, &( ev.xkey ), pad, sizeof ( pad ), &key, &stat ); pad[len] = 0; @@ -1525,6 +1530,7 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select else { textbox_text ( state.case_indicator, " " ); } + break; } // Special delete entry command. else if ( abe_test_action ( DELETE_ENTRY, ev.xkey.state, key ) ) {