summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/helper.h13
-rw-r--r--source/dialogs/combi.c46
-rw-r--r--source/helper.c23
3 files changed, 65 insertions, 17 deletions
diff --git a/include/helper.h b/include/helper.h
index 5f530dbf..a74a162e 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -221,4 +221,17 @@ PangoAttrList *token_match_get_pango_attr ( ThemeHighlight th, GRegex **tokens,
*/
int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *str, glong slen );
/*@}*/
+
+/**
+ * @param a UTF-8 string to compare
+ * @param b UTF-8 string to compare
+ * @param n Maximum number of characters to compare
+ *
+ * Compares the `G_NORMALIZE_ALL_COMPOSE` forms of the two strings.
+ *
+ * @returns less than, equal to, or greater than zero if the first `n` characters (not bytes) of `a`
+ * are found, respectively, to be less than, to match, or be greater than the first `n`
+ * characters (not bytes) of `b`.
+ */
+int utf8_strncmp ( const char *a, const char* b, size_t n );
#endif // ROFI_HELPER_H
diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c
index a3f09284..f63c49bf 100644
--- a/source/dialogs/combi.c
+++ b/source/dialogs/combi.c
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <rofi.h>
#include "settings.h"
+#include "helper.h"
#include <dialogs/dialogs.h>
@@ -151,18 +152,23 @@ static void combi_mode_destroy ( Mode *sw )
static ModeMode combi_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line )
{
CombiModePrivateData *pd = mode_get_private_data ( sw );
- if ( *input[0] == '!' ) {
+
+ if ( input[0][0] == '!' ) {
int switcher = -1;
- for ( unsigned i = 0; switcher == -1 && i < pd->num_switchers; i++ ) {
- if ( ( *input )[1] == mode_get_name ( pd->switchers[i] )[0] ) {
- switcher = i;
+ char *eob = strchrnul ( input[0], ' ' );
+ ssize_t bang_len = g_utf8_pointer_to_offset ( input[0], eob ) - 1;
+ if ( bang_len > 0 ) {
+ for ( unsigned i = 0; switcher == -1 && i < pd->num_switchers; i++ ) {
+ const char *mode_name = mode_get_name ( pd->switchers[i] );
+ size_t mode_name_len = g_utf8_strlen ( mode_name, -1 );
+ if ( (size_t) bang_len <= mode_name_len && utf8_strncmp ( &input[0][1], mode_name, bang_len ) == 0 ) {
+ switcher = i;
+ }
}
}
- if ( switcher >= 0 ) {
- char *n = strchr ( *input, ' ' );
- // skip whitespace
- if ( n != NULL ) {
- n++;
+ if ( switcher >= 0 ) {
+ if ( eob[0] == ' ' ) {
+ char *n = eob+1;
return mode_result ( pd->switchers[switcher], mretv, &n,
selected_line - pd->starts[switcher] );
}
@@ -223,7 +229,7 @@ static char * combi_get_completion ( const Mode *sw, unsigned int index )
for ( unsigned i = 0; i < pd->num_switchers; i++ ) {
if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) {
char *comp = mode_get_completion ( pd->switchers[i], index - pd->starts[i] );
- char *mcomp = g_strdup_printf ( "!%c %s", mode_get_name ( pd->switchers[i] )[0], comp );
+ char *mcomp = g_strdup_printf ( "!%s %s", mode_get_name ( pd->switchers[i] ), comp );
g_free ( comp );
return mcomp;
}
@@ -237,14 +243,20 @@ static char * combi_preprocess_input ( Mode *sw, const char *input )
{
CombiModePrivateData *pd = mode_get_private_data ( sw );
pd->current = NULL;
- if ( input != NULL && input[0] == '!' && strlen ( input ) > 1 ) {
- for ( unsigned i = 0; i < pd->num_switchers; i++ ) {
- if ( input[1] == mode_get_name ( pd->switchers[i] )[0] ) {
- pd->current = pd->switchers[i];
- if ( input[2] == '\0' ) {
- return NULL;
+ if ( input != NULL && input[0] == '!' ) {
+ char *eob = strchrnul ( input, ' ' );
+ ssize_t bang_len = g_utf8_pointer_to_offset ( input, eob ) - 1;
+ if ( bang_len > 0 ) {
+ for ( unsigned i = 0; i < pd->num_switchers; i++ ) {
+ const char *mode_name = mode_get_name ( pd->switchers[i] );
+ size_t mode_name_len = g_utf8_strlen ( mode_name, -1 );
+ if ( (size_t) bang_len <= mode_name_len && utf8_strncmp ( &input[1], mode_name, bang_len ) == 0 ) {
+ pd->current = pd->switchers[i];
+ if ( eob[0] == '\0' || eob[1] == '\0' ) {
+ return NULL;
+ }
+ return g_strdup ( eob+1 );
}
- return g_strdup ( &input[2] );
}
}
}
diff --git a/source/helper.c b/source/helper.c
index ef4a8a49..6e3fc67a 100644
--- a/source/helper.c
+++ b/source/helper.c
@@ -889,3 +889,26 @@ int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *st
g_free ( dp );
return -lefts;
}
+
+/**
+ * @param a UTF-8 string to compare
+ * @param b UTF-8 string to compare
+ * @param n Maximum number of characters to compare
+ *
+ * Compares the `G_NORMALIZE_ALL_COMPOSE` forms of the two strings.
+ *
+ * @returns less than, equal to, or greater than zero if the first `n` characters (not bytes) of `a`
+ * are found, respectively, to be less than, to match, or be greater than the first `n`
+ * characters (not bytes) of `b`.
+ */
+int utf8_strncmp ( const char* a, const char* b, size_t n )
+{
+ char *na = g_utf8_normalize ( a, -1, G_NORMALIZE_ALL_COMPOSE );
+ char *nb = g_utf8_normalize ( b, -1, G_NORMALIZE_ALL_COMPOSE );
+ *g_utf8_offset_to_pointer ( na, n ) = '\0';
+ *g_utf8_offset_to_pointer ( nb, n ) = '\0';
+ int r = g_utf8_collate ( na, nb );
+ g_free ( na );
+ g_free ( nb );
+ return r;
+}