diff --git a/contrib/remind-conf-mode/remind-conf-mode.el b/contrib/remind-conf-mode/remind-conf-mode.el index ed8199ed..2d9dba04 100644 --- a/contrib/remind-conf-mode/remind-conf-mode.el +++ b/contrib/remind-conf-mode/remind-conf-mode.el @@ -167,26 +167,151 @@ (defconst remind-builtin-functions (sort - (list "_" "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc" - "baseyr" "catch" "catcherr" "char" "choose" "codepoint" "coerce" "columns" "const" "current" "date" - "datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst" - "dusk" "easterdate" "escape" "eval" "evaltrig" "filedate" "filedatetime" - "filedir" "filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear" "hex" - "hour" "htmlescape" "htmlstriptags" "iif" "index" "isany" "isconst" "isdst" - "isleap" "isomitted" "ivritmon" "language" "localtoutc" "lower" "max" - "mbasc" "mbindex" "mbstrlen" "mbsubstr" "min" - "minsfromutc" "minute" "mon" "monnum" "moondate" "moondatetime" - "moonphase" "moonrise" "moonrisedir" "moonset" "moonsetdir" "moontime" - "multitrig" "ndawn" "ndusk" "nonconst" "nonomitted" "now" "ord" "orthodoxeaster" - "ostype" "pad" "plural" "psmoon" "psshade" "realcurrent" "realnow" - "realtoday" "rows" "sgn" "shell" "shellescape" "slide" "soleq" - "stdout" "strlen" "substr" "sunrise" "sunset" "time" "timepart" - "timezone" "today" "trig" "trigback" "trigbase" "trigcompletethrough" "trigdate" "trigdatetime" - "trigdelta" "trigduration" "trigeventduration" "trigeventstart" "trigeventstarttz" - "trigfrom" "trigger" "triginfo" "trigistodo" "trigmaxoverdue" "trigpriority" "trigrep" - "trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep" "trigtimetz" "trigtz" - "triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal" - "value" "version" "weekno" "wkday" "wkdaynum" "year" + (list + "_" + "abs" + "access" + "adawn" + "adusk" + "ampm" + "ansicolor" + "args" + "asc" + "baseyr" + "catch" + "catcherr" + "char" + "choose" + "codepoint" + "coerce" + "columns" + "const" + "current" + "date" + "datepart" + "datetime" + "dawn" + "day" + "daysinmon" + "defined" + "dosubst" + "dusk" + "easterdate" + "escape" + "eval" + "evaltrig" + "filedate" + "filedatetime" + "filedir" + "filename" + "getenv" + "hebdate" + "hebday" + "hebmon" + "hebyear" + "hex" + "hour" + "htmlescape" + "htmlstriptags" + "iif" + "index" + "isany" + "isconst" + "isdst" + "isleap" + "isomitted" + "ivritmon" + "language" + "localtoutc" + "lower" + "max" + "mbasc" + "mbindex" + "mblower" + "mbstrlen" + "mbsubstr" + "mbupper" + "min" + "minsfromutc" + "minute" + "mon" + "monnum" + "moondate" + "moondatetime" + "moonphase" + "moonrise" + "moonrisedir" + "moonset" + "moonsetdir" + "moontime" + "multitrig" + "ndawn" + "ndusk" + "nonconst" + "nonomitted" + "now" + "ord" + "orthodoxeaster" + "ostype" + "pad" + "plural" + "psmoon" + "psshade" + "realcurrent" + "realnow" + "realtoday" + "rows" + "sgn" + "shell" + "shellescape" + "slide" + "soleq" + "stdout" + "strlen" + "substr" + "sunrise" + "sunset" + "time" + "timepart" + "timezone" + "today" + "trig" + "trigback" + "trigbase" + "trigcompletethrough" + "trigdate" + "trigdatetime" + "trigdelta" + "trigduration" + "trigeventduration" + "trigeventstart" + "trigeventstarttz" + "trigfrom" + "trigger" + "triginfo" + "trigistodo" + "trigmaxoverdue" + "trigpriority" + "trigrep" + "trigscanfrom" + "trigtags" + "trigtime" + "trigtimedelta" + "trigtimerep" + "trigtimetz" + "trigtz" + "triguntil" + "trigvalid" + "typeof" + "tzconvert" + "upper" + "utctolocal" + "value" + "version" + "weekno" + "wkday" + "wkdaynum" + "year" ) #'(lambda (a b) (> (length a) (length b))))) diff --git a/man/remind.1.in b/man/remind.1.in index 4559aefb..d0dc6083 100644 --- a/man/remind.1.in +++ b/man/remind.1.in @@ -4224,7 +4224,14 @@ a \fBDATETIME\fR object that expresses the same time in UTC. .TP .B lower(s_string) Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR -converted to lower-case. +converted to lower-case. \fBNote:\fR This function works correctly +only for ASCII strings. If you are using Unicode characters outside +the ASCII set, use \fBmblower\fR instead. +.TP +.B mblower(s_string) +Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR +converted to lower-case. This function works correctly on any +Unicode string. .TP .B max(x_arg1 [,x_arg2...) Can take any number of arguments, and returns the maximum. The arguments @@ -5133,8 +5140,15 @@ of the time zone name. .PP .TP .B upper(s_string) +Returns a \fBSTRING\fR with all lower-case bytes in \fIstring\fR +converted to upper-case. \fBNote:\fR This function works correctly +only for ASCII strings. If you are using Unicode characters outside +the ASCII set, use \fBmbupper\fR instead. +.TP +.B mbupper(s_string) Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR -converted to upper-case. +converted to upper-case. This function works correctly on any +Unicode string. .TP .B utctolocal(q_datetime) Given a \fBDATETIME\fR object interpreted in UTC, return a diff --git a/src/funcs.c b/src/funcs.c index 8a935d3e..6a70b24c 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -140,9 +140,11 @@ static int FLower (func_info *); static int FMax (func_info *); static int FMbchar (func_info *); static int FMbindex (func_info *); +static int FMblower (func_info *); static int FMbpad (func_info *); static int FMbstrlen (func_info *); static int FMbsubstr (func_info *); +static int FMbupper (func_info *); static int FMin (func_info *); static int FMinsfromutc (func_info *); static int FMinute (func_info *); @@ -327,9 +329,11 @@ BuiltinFunc Func[] = { { "max", 1, NO_MAX, 1, FMax, NULL }, { "mbchar", 1, NO_MAX, 1, FMbchar, NULL }, { "mbindex", 2, 3, 1, FMbindex, NULL }, + { "mblower", 1, 1, 1, FMblower, NULL }, { "mbpad", 3, 4, 1, FMbpad, NULL }, { "mbstrlen", 1, 1, 1, FMbstrlen, NULL }, { "mbsubstr", 2, 3, 1, FMbsubstr, NULL }, + { "mbupper", 1, 1, 1, FMbupper, NULL }, { "min", 1, NO_MAX, 1, FMin, NULL }, { "minsfromutc", 0, 2, 0, FMinsfromutc, NULL }, { "minute", 1, 1, 1, FMinute, NULL }, @@ -5173,3 +5177,50 @@ print_builtinfunc_tokens(void) printf("%s\n", Func[i].name); } } + +static int mbupper_lower(func_info *info, int upper) +{ + wchar_t *ws; + char *s; + size_t i, len; + int r; + ASSERT_TYPE(0, STR_TYPE); + len = mbstowcs(NULL, ARGSTR(0), 0); + if (len == (size_t) -1) { + return E_BAD_MB_SEQ; + } + ws = calloc(len+1, sizeof(wchar_t)); + if (!ws) { + return E_NO_MEM; + } + (void) mbstowcs(ws, ARGSTR(0), len+1); + for (i=0; i "ÖÖÇÇÉÔÑÑÉÊ" +mblower("öÖçÇéôñÑÉÊ") => "ööççéôññéê" +upper("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ" +lower("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ" +DynBuf Mallocs: 1132 mallocs; 31873408 bytes Variable hash table statistics: Entries: 100146; Buckets: 87719; Non-empty Buckets: 66303 Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510 @@ -16789,7 +16793,7 @@ Expression nodes high-water: 302076 Expression nodes leaked: 0 Parse level high-water: 34 Max expr node evaluations per line: 2001 -Total expression node evaluations: 106738 +Total expression node evaluations: 106746 Test 2 @@ -24776,9 +24780,11 @@ lower max mbchar mbindex +mblower mbpad mbstrlen mbsubstr +mbupper min minsfromutc minute diff --git a/tests/test.rem b/tests/test.rem index c4a79960..b91362b2 100644 --- a/tests/test.rem +++ b/tests/test.rem @@ -1903,6 +1903,14 @@ SET $TimeSep "FOO" SET $DateSep "BAR" SET $DefaultColor "My oh my, what lovely eyes!" +# mbupper and mblower +DEBUG +x +SET a mbupper("öÖçÇéôñÑÉÊ") +SET a mblower("öÖçÇéôñÑÉÊ") +SET a upper("öÖçÇéôñÑÉÊ") +SET a lower("öÖçÇéôñÑÉÊ") +DEBUG -x + # Don't want Remind to queue reminders EXIT