diff --git a/config/config.c b/config/config.c index a36097c5..346e47d0 100644 --- a/config/config.c +++ b/config/config.c @@ -67,7 +67,7 @@ Settings config = { /** Command executed when running application in terminal */ .run_shell_command = "{terminal} -e {cmd}", /** Command executed on accep-entry-custom for window modus */ - .window_command = "xkill -id {window}", + .window_command = "xkill -id {window}", /** * Location of the window. * Enumeration indicating location or gravity of window. diff --git a/include/helper.h b/include/helper.h index 93bbc022..cca31cc0 100644 --- a/include/helper.h +++ b/include/helper.h @@ -24,18 +24,6 @@ */ int helper_parse_setup ( char * string, char ***output, int *length, ... ); -/** - * @param token The string for which we want a collation key. - * @param case_sensitive Whether case is significant. - * - * Get a collation key for @p token. @p token must be a null-terminated string. - * This collation key can be used for matching the user input against the list - * of commands, windows, or ssh commands. - * - * @returns A newly allocated string containing the collation key. - */ -char *token_collate_key ( const char *token, int case_sensitive ); - /** * @param input The input string. * @param case_sensitive Whether case is significant. @@ -172,6 +160,6 @@ unsigned int levenshtein ( const char *needle, const char *haystack ); */ char * rofi_force_utf8 ( gchar *data ); char * rofi_latin_to_utf8_strdup ( const char *input, gssize length ); -PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv ); +PangoAttrList *token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv ); /*@}*/ #endif // ROFI_HELPER_H diff --git a/include/textbox.h b/include/textbox.h index c315f08a..103898c6 100644 --- a/include/textbox.h +++ b/include/textbox.h @@ -39,15 +39,15 @@ typedef struct typedef enum { - TB_AUTOHEIGHT = 1 << 0, - TB_AUTOWIDTH = 1 << 1, - TB_LEFT = 1 << 16, - TB_RIGHT = 1 << 17, - TB_CENTER = 1 << 18, - TB_EDITABLE = 1 << 19, - TB_MARKUP = 1 << 20, - TB_WRAP = 1 << 21, - TB_PASSWORD = 1 << 22, + TB_AUTOHEIGHT = 1 << 0, + TB_AUTOWIDTH = 1 << 1, + TB_LEFT = 1 << 16, + TB_RIGHT = 1 << 17, + TB_CENTER = 1 << 18, + TB_EDITABLE = 1 << 19, + TB_MARKUP = 1 << 20, + TB_WRAP = 1 << 21, + TB_PASSWORD = 1 << 22, } TextboxFlags; typedef enum diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 5e5dd63e..f228cbf7 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -534,7 +534,7 @@ static inline int act_on_window ( xcb_window_t window ) int argc = 0; char window_str[100]; /* We are probably safe here */ - g_snprintf(window_str, sizeof window_str, "%d", window); + g_snprintf ( window_str, sizeof window_str, "%d", window ); helper_parse_setup ( config.window_command, &args, &argc, "{window}", window_str, NULL ); diff --git a/source/helper.c b/source/helper.c index 179a99ff..3d36b538 100644 --- a/source/helper.c +++ b/source/helper.c @@ -136,70 +136,75 @@ int helper_parse_setup ( char * string, char ***output, int *length, ... ) return FALSE; } -char *token_collate_key ( const char *token, int case_sensitive ) -{ - char *tmp, *compk; - - if ( case_sensitive ) { - tmp = g_strdup ( token ); - } - else { - tmp = g_utf8_casefold ( token, -1 ); - } - - compk = g_utf8_normalize ( tmp, -1, G_NORMALIZE_ALL ); - g_free ( tmp ); - - return compk; -} void tokenize_free ( char ** tokens ) { - if ( config.glob ) { - for ( size_t i = 0; tokens && tokens[i]; i++ ) { - g_pattern_spec_free ( (GPatternSpec *) tokens[i] ); + for ( size_t i = 0; tokens && tokens[i]; i++ ) { + g_regex_unref ( (GRegex *) tokens[i] ); + } + g_free ( tokens ); +} + +static gchar *glob_to_regex ( const char *input ) +{ + gchar *r = g_regex_escape_string ( input, -1 ); + size_t str_l = strlen ( r ); + for ( size_t i = 0; i < str_l; i++ ) { + if ( r[i] == '\\' ) { + if ( r[i + 1] == '*' ) { + r[i] = '.'; + } + else if ( r[i + 1] == '?' ) { + r[i + 1] = 'S'; + } + i++; } - g_free ( tokens ); + } + return r; +} +static GRegex * create_regex ( const char *input, int case_sensitive ) +{ +#define R( s ) g_regex_new ( s, G_REGEX_OPTIMIZE | ( ( case_sensitive ) ? 0 : G_REGEX_CASELESS ), G_REGEX_MATCH_PARTIAL, NULL ) + GRegex *retv = NULL; + if ( config.glob ) { + gchar *r = glob_to_regex ( input ); + retv = R ( r ); + g_free ( r ); } else if ( config.regex ) { - for ( size_t i = 0; tokens && tokens[i]; i++ ) { - g_regex_unref ( (GRegex *) tokens[i] ); + retv = R ( input ); + if ( retv == NULL ) { + gchar *r = g_regex_escape_string ( input, -1 ); + retv = R ( r ); + g_free ( r ); } - g_free ( tokens ); } - else { - g_strfreev ( tokens ); + else if ( config.fuzzy ) { + gchar *r = g_regex_escape_string ( input, -1 ); + // TODO either strip fuzzy, or fix this pattern. + gchar *str = g_strdup_printf ( "[%s]+", r ); + retv = R ( str ); + g_free ( r ); + g_free ( str ); } + else{ + // TODO; regex should be default? + gchar *r = g_regex_escape_string ( input, -1 ); + retv = R ( r ); + g_free ( r ); + } + return retv; } char **tokenize ( const char *input, int case_sensitive ) { - if ( input == NULL ) { + if ( input == NULL || strlen(input) == 0 ) { return NULL; } char *saveptr = NULL, *token; char **retv = NULL; if ( !config.tokenize ) { - retv = g_malloc0 ( sizeof ( char* ) * 2 ); - if ( config.glob ) { - token = g_strdup_printf ( "*%s*", input ); - char *str = token_collate_key ( token, case_sensitive ); - retv[0] = (char *) g_pattern_spec_new ( str ); - g_free ( token ); token = NULL; - g_free ( str ); - } - else if ( config.regex ) { - GRegex *reg = g_regex_new ( input, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL ); - if ( reg == NULL ) { - gchar *r = g_regex_escape_string ( input, -1 ); - reg = g_regex_new ( r, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL ); - g_free ( r ); - g_free ( retv ); - } - retv[0] = (char *) reg; - } - else{ - retv[0] = token_collate_key ( input, case_sensitive ); - } + retv = g_malloc0 ( sizeof ( char* ) * 2 ); + retv[0] = (char *) create_regex ( input, case_sensitive ); return retv; } @@ -213,25 +218,8 @@ char **tokenize ( const char *input, int case_sensitive ) // strtok should still be valid for utf8. const char * const sep = " "; for ( token = strtok_r ( str, sep, &saveptr ); token != NULL; token = strtok_r ( NULL, sep, &saveptr ) ) { - retv = g_realloc ( retv, sizeof ( char* ) * ( num_tokens + 2 ) ); - if ( config.glob ) { - char *str = g_strdup_printf ( "*%s*", token ); - char *t = token_collate_key ( str, case_sensitive ); - retv[num_tokens] = (char *) g_pattern_spec_new ( t ); - g_free ( t ); - g_free ( str ); - } - else if ( config.regex ) { - retv[num_tokens] = (char *) g_regex_new ( token, case_sensitive ? 0 : G_REGEX_CASELESS, 0, NULL ); - if ( retv[num_tokens] == NULL ) { - gchar *r = g_regex_escape_string ( input, -1 ); - retv[num_tokens] = (char *) g_regex_new ( r, ( case_sensitive ) ? 0 : G_REGEX_CASELESS, G_REGEX_MATCH_PARTIAL, NULL ); - g_free ( r ); - } - } - else { - retv[num_tokens] = token_collate_key ( token, case_sensitive ); - } + retv = g_realloc ( retv, sizeof ( char* ) * ( num_tokens + 2 ) ); + retv[num_tokens] = (char *) create_regex ( token, case_sensitive ); retv[num_tokens + 1] = NULL; num_tokens++; } @@ -347,56 +335,6 @@ int find_arg_char ( const char * const key, char *val ) return FALSE; } -/** - * Shared 'token_match' function. - * Matches tokenized. - */ -static int fuzzy_token_match ( char **tokens, const char *input, __attribute__( ( unused ) ) int not_ascii, int case_sensitive ) -{ - int match = 1; - - // Do a tokenized match. - - if ( tokens ) { - char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : (char *) g_ascii_strdown ( input, -1 ); - for ( int j = 0; match && tokens[j]; j++ ) { - char *t = compk; - char *token = tokens[j]; - - while ( *t && *token ) { - if ( ( g_utf8_get_char ( t ) == g_utf8_get_char ( token ) ) ) { - token = g_utf8_next_char ( token ); - } - t = g_utf8_next_char ( t ); - } - match = !( *token ); - } - g_free ( compk ); - } - - return match; -} -static int normal_token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive ) -{ - int match = 1; - - // Do a tokenized match. - - if ( tokens ) { - char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : (char *) input; - char *( *comparison )( const char *, const char * ); - comparison = ( case_sensitive || not_ascii ) ? strstr : strcasestr; - for ( int j = 0; match && tokens[j]; j++ ) { - match = ( comparison ( compk, tokens[j] ) != NULL ); - } - if ( not_ascii ) { - g_free ( compk ); - } - } - - return match; -} - static int regex_token_match ( char **tokens, const char *input, G_GNUC_UNUSED int not_ascii, G_GNUC_UNUSED int case_sensitive ) { int match = 1; @@ -410,9 +348,8 @@ static int regex_token_match ( char **tokens, const char *input, G_GNUC_UNUSED i return match; } -PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv ) +static PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv ) { - if ( config.regex == FALSE ) return retv; // Do a tokenized match. if ( tokens ) { for ( int j = 0; tokens[j]; j++ ) { @@ -432,34 +369,14 @@ PangoAttrList *regex_token_match_get_pango_attr ( char **tokens, const char *inp } return retv; } - -static int glob_token_match ( char **tokens, const char *input, int not_ascii, int case_sensitive ) +PangoAttrList *token_match_get_pango_attr ( char **tokens, const char *input, PangoAttrList *retv ) { - int match = 1; - char *compk = not_ascii ? token_collate_key ( input, case_sensitive ) : g_ascii_strdown ( input, -1 ); - - // Do a tokenized match. - if ( tokens ) { - for ( int j = 0; match && tokens[j]; j++ ) { - match = g_pattern_match_string ( (GPatternSpec *) tokens[j], compk ); - } - } - g_free ( compk ); - return match; + return regex_token_match_get_pango_attr ( tokens, input, retv ); } 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 ); - } - else if ( config.regex ) { - return regex_token_match ( tokens, input, not_ascii, case_sensitive ); - } - else if ( config.fuzzy ) { - return fuzzy_token_match ( tokens, input, not_ascii, case_sensitive ); - } - return normal_token_match ( tokens, input, not_ascii, case_sensitive ); + return regex_token_match ( tokens, input, not_ascii, case_sensitive ); } int execute_generator ( const char * cmd ) diff --git a/source/view.c b/source/view.c index de9b00cf..2c98b972 100644 --- a/source/view.c +++ b/source/view.c @@ -949,10 +949,11 @@ static void rofi_view_draw ( RofiViewState *state, cairo_t *d ) textbox_text ( state->boxes[i], text ); PangoAttrList *list = textbox_get_pango_attributes ( state->boxes[i] ); - if ( list != NULL ) + if ( list != NULL ) { pango_attr_list_ref ( list ); - else list = pango_attr_list_new (); - regex_token_match_get_pango_attr ( tokens, textbox_get_visible_text ( state->boxes[i] ), list ); + } + else{ list = pango_attr_list_new (); } + token_match_get_pango_attr ( tokens, textbox_get_visible_text ( state->boxes[i] ), list ); textbox_set_pango_attributes ( state->boxes[i], list ); pango_attr_list_unref ( list ); g_free ( text );