From 8e02fc0f882fb708f44d3b7f0e2335e360f713b1 Mon Sep 17 00:00:00 2001 From: Pietro Cerutti Date: Sun, 5 Feb 2017 14:22:25 +0000 Subject: [PATCH] Rework the "inbox-first" implementation to make code self-explanatory (#356) Do not sort INBOX before its parent folder This is achieved by considering /a/b/ and /a/b/c/d as different subpaths, thus avoiding this situation /a/b/INBOX /a/b/ Closes #301 --- browser.c | 8 +++----- lib.c | 49 ++++++++++++++++++++++++++++++++----------------- lib.h | 3 +-- sidebar.c | 7 +++---- 4 files changed, 39 insertions(+), 28 deletions(-) diff --git a/browser.c b/browser.c index 5ab2cbceb..24256d0ee 100644 --- a/browser.c +++ b/browser.c @@ -103,11 +103,9 @@ static int browser_compare_subject (const void *a, const void *b) struct folder_file *pb = (struct folder_file *) b; /* inbox should be sorted ahead of its siblings */ - int common_subpath = mutt_have_common_subpath (pa->name, pb->name); - int r = (common_subpath && mutt_is_inbox (pa->name)) ? -1 : - (common_subpath && mutt_is_inbox (pb->name)) ? 1 : - mutt_strcoll (pa->name, pb->name); - + int r = mutt_inbox_cmp (pa->name, pb->name); + if (r == 0) + r = mutt_strcoll (pa->name, pb->name); return ((BrowserSort & SORT_REVERSE) ? -r : r); } diff --git a/lib.c b/lib.c index 299b19dfa..c6b1a1265 100644 --- a/lib.c +++ b/lib.c @@ -1107,26 +1107,29 @@ int mutt_atol (const char *str, long *dst) return 0; } -int mutt_is_inbox (const char *path) -{ - size_t plen = mutt_strlen (path); - return ((plen >= 6) && (mutt_strcasecmp (path + plen - 6, "/inbox") == 0)); -} - /** - * mutt_have_common_subpath - check whether two paths have a common subpath. + * mutt_inbox_cmp - check whether two folders share the same path and one is + * an inbox. + * * @param a First path. * @param b Second path. * - * @return 1 if a and b have a common subpath, 0 otherwise + * @return -1 if a is INBOX of b, 0 if none is INBOX, 1 if b is INBOX for a * - * This function checks whether two paths (where the path separator is assumed - * to be '/', have a common subpath. Examples: + * This function compares two folder paths. It first looks for the position of + * the last common '/' character. If a valid position is found and it's not the + * last character in any of the two paths, the remaining parts of the paths are + * compared (case insensitively) with the string "INBOX". If one of the two + * paths matches, it's reported as being less than the other and the function + * returns -1 (a < b) or 1 (a > b). If no paths match the requirements, the two + * paths are considered equivalent and this function returns 0. * - * /foo/bar/baz and /foo/hey/you do have a common subpath (/foo/) - * /apple/banana and /apples/bananas do NOT have a common subpath + * Examples: + * mutt_inbox_cmp("/foo/bar", "/foo/baz") --> 0 + * mutt_inbox_cmp("/foo/bar/", "/foo/bar/inbox") --> 0 + * mutt_inbox_cmp("/foo/bar/sent", "/foo/bar/inbox") --> 1 */ -int mutt_have_common_subpath(const char *a, const char *b) +int mutt_inbox_cmp (const char *a, const char *b) { const char *a_end = strrchr (a, '/'); const char *b_end = strrchr (b, '/'); @@ -1137,14 +1140,26 @@ int mutt_have_common_subpath(const char *a, const char *b) /* If neither path contains a '/' */ if (!a_end) - return 1; + return 0; - /* Compare the paths */ + /* Compare the subpaths */ size_t a_len = a_end - a; size_t b_len = b_end - b; size_t min = MIN(a_len, b_len); - return (a[min] == '/') && (b[min] == '/') && - (mutt_strncasecmp(a, b, min) == 0); + int same = (a[min] == '/') && (b[min] == '/') && + (a[min+1] != '\0') && (b[min+1] != '\0') && + (mutt_strncasecmp(a, b, min) == 0); + + if (!same) + return 0; + + if (mutt_strcasecmp(&a[min+1], "inbox") == 0) + return -1; + + if (mutt_strcasecmp(&b[min+1], "inbox") == 0) + return 1; + + return 0; } char * strfcpy (char *dest, const char *src, size_t dlen) diff --git a/lib.h b/lib.h index 97e873a3e..ef5e4f3bd 100644 --- a/lib.h +++ b/lib.h @@ -225,8 +225,7 @@ void mutt_str_adjust (char **p); void mutt_unlink (const char *); void safe_free (void *); void safe_realloc (void *, size_t); -int mutt_is_inbox (const char *path); -int mutt_have_common_subpath (const char *a, const char *b); +int mutt_inbox_cmp (const char *a, const char *b); const char *mutt_strsysexit(int e); #endif diff --git a/sidebar.c b/sidebar.c index 4c0baed7f..9c7bd852b 100644 --- a/sidebar.c +++ b/sidebar.c @@ -321,10 +321,9 @@ static int cb_qsort_sbe (const void *a, const void *b) break; case SORT_PATH: { - int common_subpath = mutt_have_common_subpath (b1->path, b2->path); - result = (common_subpath && mutt_is_inbox (b1->path)) ? -1 : - (common_subpath && mutt_is_inbox (b2->path)) ? 1 : - mutt_strcoll (b1->path, b2->path); + result = mutt_inbox_cmp (b1->path, b2->path); + if (result == 0) + result = mutt_strcoll (b1->path, b2->path); break; } } -- 2.40.0