From 05635c5c82aac5d6ef3d182725552e50852737c1 Mon Sep 17 00:00:00 2001 From: Richard Russon Date: Wed, 6 Dec 2017 01:03:32 +0000 Subject: [PATCH] Add mutt_mb_is_lower() to muttlib This is based on mutt_which_case() which had a unnecessary Regex constant embedded in it. --- color.c | 18 ++++++++++++++---- init.c | 11 +++++++---- menu.c | 5 ++++- mutt/mbyte.c | 30 ++++++++++++++++++++++++++++++ mutt/mbyte.h | 1 + pager.c | 15 ++++++++------- pattern.c | 39 ++++++--------------------------------- 7 files changed, 70 insertions(+), 49 deletions(-) diff --git a/color.c b/color.c index a09616860..708bf5277 100644 --- a/color.c +++ b/color.c @@ -653,11 +653,21 @@ static int add_pattern(struct ColorLineHead *top, const char *s, int sensitive, for (int i = 0; Context && i < Context->msgcount; i++) Context->hdrs[i]->pair = 0; } - else if ((r = REGCOMP(&tmp->regex, s, (sensitive ? mutt_which_case(s) : REG_ICASE))) != 0) + else { - regerror(r, &tmp->regex, err->data, err->dsize); - free_color_line(tmp, 1); - return -1; + int flags = 0; + if (sensitive) + flags = mutt_mb_is_lower(s) ? REG_ICASE : 0; + else + flags = REG_ICASE; + + r = REGCOMP(&tmp->regex, s, flags); + if (r != 0) + { + regerror(r, &tmp->regex, err->data, err->dsize); + free_color_line(tmp, 1); + return -1; + } } tmp->pattern = mutt_str_strdup(s); tmp->match = match; diff --git a/init.c b/init.c index 36075906a..2ab74487d 100644 --- a/init.c +++ b/init.c @@ -183,8 +183,8 @@ static int parse_regex(int idx, struct Buffer *tmp, struct Buffer *err) bool not = false; /* $mask is case-sensitive */ - if (mutt_str_strcmp(MuttVars[idx].option, "mask") != 0) - flags |= mutt_which_case(tmp->data); + if ((mutt_str_strcmp(MuttVars[idx].option, "mask") != 0) && mutt_mb_is_lower(tmp->data)) + flags |= REG_ICASE; p = tmp->data; if (mutt_str_strcmp(MuttVars[idx].option, "mask") == 0) @@ -2187,8 +2187,11 @@ static void restore_default(struct Option *p) pp->regex = mutt_mem_calloc(1, sizeof(regex_t)); pp->pattern = mutt_str_strdup((char *) p->init); - if (mutt_str_strcmp(p->option, "mask") != 0) - flags |= mutt_which_case((const char *) p->init); + if ((mutt_str_strcmp(p->option, "mask") != 0) && + (mutt_mb_is_lower((const char *) p->init))) + { + flags |= REG_ICASE; + } if ((mutt_str_strcmp(p->option, "mask") == 0) && *s == '!') { s++; diff --git a/menu.c b/menu.c index 91ea41d72..76a111d74 100644 --- a/menu.c +++ b/menu.c @@ -959,7 +959,10 @@ static int menu_search(struct Menu *menu, int op) search_dir = -search_dir; if (search_buf) - r = REGCOMP(&re, search_buf, REG_NOSUB | mutt_which_case(search_buf)); + { + int flags = mutt_mb_is_lower(search_buf) ? REG_ICASE : 0; + r = REGCOMP(&re, search_buf, REG_NOSUB | flags); + } if (r != 0) { diff --git a/mutt/mbyte.c b/mutt/mbyte.c index 55e4e2a8a..e164517e6 100644 --- a/mutt/mbyte.c +++ b/mutt/mbyte.c @@ -33,6 +33,7 @@ * | :---------------------- | :--------------------------------------------------------- * | mutt_mb_charlen() | Count the bytes in a (multibyte) character * | mutt_mb_get_initials() | Turn a name into initials + * | mutt_mb_is_lower() | Does a multi-byte string contain only lowercase characters? * | mutt_mb_is_shell_char() | Is character not typically part of a pathname * | mutt_mb_mbstowcs() | Convert a string from multibyte to wide characters * | mutt_mb_wcstombs() | Convert a string from wide to multibyte characters @@ -355,3 +356,32 @@ bool mutt_mb_is_shell_char(wchar_t ch) static const wchar_t shell_chars[] = L"<>&()$?*;{}| "; /* ! not included because it can be part of a pathname in NeoMutt */ return wcschr(shell_chars, ch) != NULL; } + +/** + * mutt_mb_is_lower - Does a multi-byte string contain only lowercase characters? + * @param s String to check + * @retval true String contains no uppercase characters + * @retval false Error, or contains some uppercase characters + * + * Non-alphabetic characters are considered lowercase. + */ +bool mutt_mb_is_lower(const char *s) +{ + wchar_t w; + mbstate_t mb; + size_t l; + + memset(&mb, 0, sizeof(mb)); + + for (; (l = mbrtowc(&w, s, MB_CUR_MAX, &mb)) != 0; s += l) + { + if (l == (size_t) -2) + continue; /* shift sequences */ + if (l == (size_t) -1) + return false; + if (iswalpha((wint_t) w) && iswupper((wint_t) w)) + return false; + } + + return true; +} diff --git a/mutt/mbyte.h b/mutt/mbyte.h index fad6d6d15..9fc4e0ff2 100644 --- a/mutt/mbyte.h +++ b/mutt/mbyte.h @@ -43,6 +43,7 @@ extern wchar_t ReplacementChar; int mutt_mb_charlen(const char *s, int *width); bool mutt_mb_get_initials(const char *name, char *buf, int buflen); +bool mutt_mb_is_lower(const char *s); bool mutt_mb_is_shell_char(wchar_t ch); size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf); void mutt_mb_wcstombs(char *dest, size_t dlen, const wchar_t *src, size_t slen); diff --git a/pager.c b/pager.c index 482c451ee..3b06494e0 100644 --- a/pager.c +++ b/pager.c @@ -847,9 +847,9 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n, } else if (check_sig(buf, line_info, n - 1) == 0) line_info[n].type = MT_COLOR_SIGNATURE; - else if (regexec((regex_t *) QuoteRegexp.regex, buf, 1, pmatch, 0) == 0) + else if (regexec(QuoteRegexp.regex, buf, 1, pmatch, 0) == 0) { - if (regexec((regex_t *) Smileys.regex, buf, 1, smatch, 0) == 0) + if ((regexec(Smileys.regex, buf, 1, smatch, 0) == 0)) { if (smatch[0].rm_so > 0) { @@ -859,7 +859,7 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n, c = buf[smatch[0].rm_so]; buf[smatch[0].rm_so] = 0; - if (regexec((regex_t *) QuoteRegexp.regex, buf, 1, pmatch, 0) == 0) + if (regexec(QuoteRegexp.regex, buf, 1, pmatch, 0) == 0) { if (q_classify && line_info[n].quote == NULL) line_info[n].quote = classify_quote(quote_list, buf + pmatch[0].rm_so, @@ -1491,7 +1491,7 @@ static int display_line(FILE *f, LOFF_T *last_pos, struct Line **line_info, (*last)--; goto out; } - if (regexec((regex_t *) QuoteRegexp.regex, (char *) fmt, 1, pmatch, 0) != 0) + if (regexec(QuoteRegexp.regex, (char *) fmt, 1, pmatch, 0) != 0) goto out; (*line_info)[n].quote = classify_quote(quote_list, (char *) fmt + pmatch[0].rm_so, @@ -1810,8 +1810,8 @@ static void pager_menu_redraw(struct Menu *pager_menu) rd->search_compiled = Resize->search_compiled; if (rd->search_compiled) { - err = REGCOMP(&rd->search_re, rd->searchbuf, - REG_NEWLINE | mutt_which_case(rd->searchbuf)); + int flags = mutt_mb_is_lower(rd->searchbuf) ? REG_ICASE : 0; + err = REGCOMP(&rd->search_re, rd->searchbuf, REG_NEWLINE | flags); if (err != 0) { regerror(err, &rd->search_re, buffer, sizeof(buffer)); @@ -2501,7 +2501,8 @@ int mutt_pager(const char *banner, const char *fname, int flags, struct Pager *e } } - err = REGCOMP(&rd.search_re, searchbuf, REG_NEWLINE | mutt_which_case(searchbuf)); + int rflags = mutt_mb_is_lower(searchbuf) ? REG_ICASE : 0; + err = REGCOMP(&rd.search_re, searchbuf, REG_NEWLINE | rflags); if (err != 0) { regerror(err, &rd.search_re, buffer, sizeof(buffer)); diff --git a/pattern.c b/pattern.c index ca83f682e..936257f01 100644 --- a/pattern.c +++ b/pattern.c @@ -101,7 +101,7 @@ static bool eat_regex(struct Pattern *pat, struct Buffer *s, struct Buffer *err) if (pat->stringmatch) { pat->p.str = mutt_str_strdup(buf.data); - pat->ign_case = mutt_which_case(buf.data) == REG_ICASE; + pat->ign_case = mutt_mb_is_lower(buf.data); FREE(&buf.data); } else if (pat->groupmatch) @@ -112,8 +112,8 @@ static bool eat_regex(struct Pattern *pat, struct Buffer *s, struct Buffer *err) else { pat->p.regex = mutt_mem_malloc(sizeof(regex_t)); - r = REGCOMP(pat->p.regex, buf.data, - REG_NEWLINE | REG_NOSUB | mutt_which_case(buf.data)); + int flags = mutt_mb_is_lower(buf.data) ? REG_ICASE : 0; + r = REGCOMP(pat->p.regex, buf.data, REG_NEWLINE | REG_NOSUB | flags); if (r != 0) { regerror(r, pat->p.regex, errmsg, sizeof(errmsg)); @@ -881,36 +881,9 @@ static const struct PatternFlags { 0, 0, 0, NULL }, }; -static struct Pattern *SearchPattern = NULL; /* current search pattern */ -static char LastSearch[STRING] = { 0 }; /* last pattern searched for */ -static char LastSearchExpn[LONG_STRING] = { 0 }; /* expanded version of - LastSearch */ - -/** - * mutt_which_case - Smart-case searching - * - * if no uppercase letters are given, do a case-insensitive search - */ -int mutt_which_case(const char *s) -{ - wchar_t w; - mbstate_t mb; - size_t l; - - memset(&mb, 0, sizeof(mb)); - - for (; (l = mbrtowc(&w, s, MB_CUR_MAX, &mb)) != 0; s += l) - { - if (l == (size_t) -2) - continue; /* shift sequences */ - if (l == (size_t) -1) - return 0; /* error; assume case-sensitive */ - if (iswalpha((wint_t) w) && iswupper((wint_t) w)) - return 0; /* case-sensitive */ - } - - return REG_ICASE; /* case-insensitive */ -} +static struct Pattern *SearchPattern = NULL; /**< current search pattern */ +static char LastSearch[STRING] = { 0 }; /**< last pattern searched for */ +static char LastSearchExpn[LONG_STRING] = { 0 }; /**< expanded version of LastSearch */ static int patmatch(const struct Pattern *pat, const char *buf) { -- 2.40.0