diff --git a/lib/strutil/strutilutf8.c b/lib/strutil/strutilutf8.c index f58536bc2..3f4b83692 100644 --- a/lib/strutil/strutilutf8.c +++ b/lib/strutil/strutilutf8.c @@ -1220,18 +1220,29 @@ str_utf8_caseprefix (const char *text, const char *prefix) static char * str_utf8_create_key_gen (const char *text, int case_sen, - gchar * (*keygen) (const gchar *, gssize size)) + gchar * (*keygen) (const gchar *text, gssize size)) { char *result; if (case_sen) { result = str_utf8_normalize (text); } else { + gboolean dot; + GString *fixed; const char *start, *end; char *fold, *key; - GString *fixed = g_string_new (""); - start = text; + dot = text[0] == '.'; + fixed = g_string_sized_new (16); + + if (!dot) + start = text; + else + { + start = text + 1; + g_string_append_c (fixed, '.'); + } + while (!g_utf8_validate (start, -1, &end) && start[0] != '\0') { if (start != end) @@ -1248,9 +1259,19 @@ str_utf8_create_key_gen (const char *text, int case_sen, if (start == text) { - fold = g_utf8_casefold (text, -1); + fold = g_utf8_casefold (start, -1); result = keygen (fold, -1); g_free (fold); + g_string_free (fixed, TRUE); + } + else if (dot && (start == text + 1)) + { + fold = g_utf8_casefold (start, -1); + key = keygen (fold, -1); + g_string_append (fixed, key); + g_free (key); + g_free (fold); + result = g_string_free (fixed, FALSE); } else { @@ -1262,9 +1283,8 @@ str_utf8_create_key_gen (const char *text, int case_sen, g_free (key); g_free (fold); } - result = g_strdup (fixed->str); + result = g_string_free (fixed, FALSE); } - g_string_free (fixed, TRUE); } return result; } diff --git a/src/dir.c b/src/dir.c index 237f03b14..a55ed5706 100644 --- a/src/dir.c +++ b/src/dir.c @@ -63,6 +63,33 @@ sort_orders_t sort_orders [SORT_TYPES_TOTAL] = { }; */ +static inline int +key_collate (const char *t1, const char *t2) +{ + int dotdot = 0; + int ret; + + dotdot = (t1[0] == '.' ? 1 : 0) | ((t2[0] == '.' ? 1 : 0) << 1); + + switch (dotdot) + { + case 0: + case 3: + ret = str_key_collate (t1, t2, case_sensitive) * reverse; + break; + case 1: + ret = -1; /* t1 < t2 */ + break; + case 2: + ret = 1; /* t1 > t2 */ + break; + default: + ret = 0; /* it must not happen */ + } + + return ret; +} + int unsorted (file_entry *a, file_entry *b) { @@ -84,8 +111,7 @@ sort_name (file_entry *a, file_entry *b) if (b->sort_key == NULL) b->sort_key = str_create_key_for_filename (b->fname, case_sensitive); - return str_key_collate (a->sort_key, b->sort_key, case_sensitive) - * reverse; + return key_collate (a->sort_key, b->sort_key); } return bd - ad; }