diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 9d856deb3d..5b0d76706d 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -3043,6 +3043,20 @@ *: "Numeric" + + id: LANG_DISPLAY_SPECIAL_CHARACTER + desc: Special character (japanese, accents, etc) + user: core + + *: "Special character" + + + *: "Special character" + + + *: "Special character" + + id: LANG_PM_MENU desc: in the display menu diff --git a/apps/lang/francais.lang b/apps/lang/francais.lang index be68a68903..0277129a01 100644 --- a/apps/lang/francais.lang +++ b/apps/lang/francais.lang @@ -2971,6 +2971,20 @@ *: "Numérique" + + id: LANG_DISPLAY_SPECIAL_CHARACTER + desc: Special character (japanese, accents, etc) + user: core + + *: "Special character" + + + *: "Caractère spécial" + + + *: "Caractère spécial" + + id: LANG_PM_MENU desc: in the display menu diff --git a/apps/tagcache.c b/apps/tagcache.c index 5ee9ff4f9c..fd61d4bc90 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -234,6 +234,9 @@ static const char * const tag_type_str[] = { [clause_oneof] = "clause_oneof", [clause_begins_oneof] = "clause_begins_oneof", [clause_ends_oneof] = "clause_ends_oneof", + [clause_not_oneof] = "clause_not_oneof", + [clause_not_begins_oneof] = "clause_not_begins_oneof", + [clause_not_ends_oneof] = "clause_not_ends_oneof", [clause_logical_or] = "clause_logical_or" }; #define logf_clauses logf @@ -1441,11 +1444,18 @@ static bool check_against_clause(long numeric, const char *str, return !str_ends_with(str, clause->str); case clause_oneof: return str_oneof(str, clause->str); + case clause_not_oneof: + return !str_oneof(str, clause->str); case clause_ends_oneof: /* Fall-Through */ case clause_begins_oneof: return str_begins_ends_oneof(str, clause->str, clause->type == clause_begins_oneof); + case clause_not_ends_oneof: + /* Fall-Through */ + case clause_not_begins_oneof: + return !str_begins_ends_oneof(str, clause->str, + clause->type == clause_not_begins_oneof); default: logf("Incorrect tag: %d", clause->type); } diff --git a/apps/tagcache.h b/apps/tagcache.h index a20a13900a..5c510e02e6 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -74,7 +74,8 @@ enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, clause_lt, clause_lteq, clause_contains, clause_not_contains, clause_begins_with, clause_not_begins_with, clause_ends_with, clause_not_ends_with, clause_oneof, - clause_begins_oneof, clause_ends_oneof, + clause_begins_oneof, clause_ends_oneof, clause_not_oneof, + clause_not_begins_oneof, clause_not_ends_oneof, clause_logical_or }; struct tagcache_stat { diff --git a/apps/tagtree.c b/apps/tagtree.c index 67abc4e9b8..f414cf3dd4 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -479,6 +479,9 @@ static int get_clause(int *condition) CLAUSE('@', '^', clause_begins_oneof), CLAUSE('@', '$', clause_ends_oneof), CLAUSE('@', ' ', clause_oneof), + CLAUSE('*', '^', clause_not_begins_oneof), + CLAUSE('*', '$', clause_not_ends_oneof), + CLAUSE('!', '@', clause_not_oneof), CLAUSE(0, 0, 0) /* sentinel */ }; @@ -1121,9 +1124,9 @@ static void build_firstletter_menu(char *buf, size_t bufsz) const char * const showsub = /* album subitem for canonicalartist */ ((strcasestr(subitem, "artist") == NULL) ? "title" : "album -> title"); - /* Numeric ex: "Numeric" -> album ? album < "A" -> title = "fmt_title" */ - snprintf(buf, bufsz, fmt, - str(LANG_DISPLAY_NUMERIC), subitem, subitem,'<', 'A', showsub); + const char * fmt_numeric ="\"%s\"-> %s ? %s @^ \"0|1|2|3|4|5|6|7|8|9\" -> %s =\"fmt_title\""; + snprintf(buf, bufsz, fmt_numeric, + str(LANG_DISPLAY_NUMERIC), subitem, subitem, showsub); if (!alloc_menu_parse_buf(buf, menu_byfirstletter)) { @@ -1140,6 +1143,16 @@ static void build_firstletter_menu(char *buf, size_t bufsz) return; } } + + const char * fmt_special ="\"%s\"-> %s ? %s *^ \"0|1|2|3|4|5|6|7|8|9\" & "\ + "%s *^ \"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z\" -> %s =\"fmt_title\""; + snprintf(buf, bufsz, fmt_special, + str(LANG_DISPLAY_SPECIAL_CHARACTER), subitem, subitem, subitem, showsub); + + if (!alloc_menu_parse_buf(buf, menu_byfirstletter)) + { + return; + } } static bool parse_menu(const char *filename);