Compare commits

...

297 Commits

Author SHA1 Message Date
Dianne Skoll
24e0178d1a Fix tests for 3.3.2 release. 2020-11-08 16:01:57 -05:00
Dianne Skoll
1ede5775f2 Prep for 3.3.2 release. 2020-11-08 16:01:39 -05:00
Dianne Skoll
a5c9b07052 Fix for calendar alignment for reminders with embedded tabs.
Convert all whitespace chars to space in calendar mode.
2020-11-03 08:41:24 -05:00
Dianne Skoll
22353d4833 Fix typo (patch from Yigit Sever) 2020-11-02 08:31:28 -05:00
Dianne Skoll
7499ada891 Properly fix combining-char-word-wrapping. 2020-11-01 12:05:21 -05:00
Dianne Skoll
3f0a4e5c39 Fix another instance of mis-counting display width. 2020-11-01 10:13:51 -05:00
Dianne Skoll
b8d6472974 Add UTF-8 test. 2020-11-01 10:06:48 -05:00
Dianne Skoll
6358297724 Fix column misalignment with UTF-8 text. 2020-11-01 10:03:32 -05:00
Dianne Skoll
4f6dcde980 Upper-case section references.
Prevent potential null pointer dereference.
2020-10-31 16:57:13 -04:00
Dianne Skoll
8a7985c48e Highlight that longitude sign is opposite from the usual convention. 2020-10-12 18:54:26 -04:00
Dianne Skoll
4ddbe54e55 Fix typo 2020-09-25 22:27:48 -04:00
Dianne Skoll
ef0bf73a29 Document MAYBE-UNCOMPUTABLE. 2020-09-25 22:20:16 -04:00
Dianne Skoll
beda9014d8 Add test for MAYBE-UNCOMPUTABLE 2020-09-25 22:11:56 -04:00
Dianne Skoll
498a429b2c Add MAYBE-UNCOMPUTABLE modifier to trigger. 2020-09-25 22:08:49 -04:00
Dianne Skoll
6aa2aa0fb3 Align system vars in output. 2020-09-20 17:43:51 -04:00
Dianne Skoll
1bef88fccd Update released notes. 2020-09-20 17:40:58 -04:00
Dianne Skoll
8308068067 Don't bother aligning "DUMP" output.
It looks ridiculous with 64-char long variable names.
2020-09-20 17:39:33 -04:00
Dianne Skoll
8385c7f1b0 Update custom.h 2020-09-20 17:35:24 -04:00
Dianne Skoll
0537d02fef Increase max variable length from 16 to 64 characters.
Modern computers have plenty of memory, so meh.
2020-09-20 17:32:22 -04:00
Dianne Skoll
c33a1a3b0b Mention that variables are global. 2020-09-20 12:45:29 -04:00
Dianne Skoll
fd39999128 Fix bugs where month numbers with leading zeros are misinterpreted as octal instead of decimal.
Reported by Peter Geddes.
2020-09-13 12:34:27 -04:00
Dianne Skoll
0aa40094fa Make TwentyFourHourMode global. 2020-08-18 15:24:19 -04:00
Dianne Skoll
e3bbbe07be Respect 24-hour mode option. 2020-08-18 15:24:13 -04:00
Dianne Skoll
5633798d33 Document that time is fed to reminder command. 2020-08-18 15:24:09 -04:00
Dianne Skoll
0e7e1b1b75 When feeding reminder on stdin, prefix with "$time: " 2020-08-18 15:24:04 -04:00
Dianne Skoll
4d3790bc1a More tweaking of defs.rem to remove cruft and modernize usage. 2020-08-18 15:24:00 -04:00
Dianne Skoll
2002c7f1f8 Fix up defs.rem. 2020-08-18 15:23:51 -04:00
Dianne Skoll
1be14e99a2 Update docs for -itkremind=1 and -itkprint=1 options in TkRemind. 2020-06-11 15:06:09 -04:00
Dianne Skoll
78efdaf85f Fix bug that broke printing by putting cmdline options in wrong spot. 2020-06-10 10:26:06 -04:00
Dianne Skoll
0e98a1c656 Always set tkremind=1; set tkprint=1 if we're printing. 2020-06-10 10:22:46 -04:00
Dianne Skoll
7aa483e201 Fix bug reported by Jurgen Bollerhey
I have a
"REM Mon SPECIAL WEEK (W[weekno()])"
in my reminders file.
With tkremind -m the week number is displayed on the 2nd column which is
Tuesday and the date of this Tuesday is taken from the monday of the
next week, sometimes of Monday the same week.
2020-03-30 11:29:19 -04:00
Dianne Skoll
a6dbf05af4 Update WHATSNEW. 2020-03-20 09:18:48 -04:00
Dianne Skoll
8ab78fd8be Suppress compile warnings on Ubuntu 18.04 2020-03-19 20:27:45 -04:00
Dianne Skoll
4f119031a4 One more warning to suppress. 2020-03-19 20:24:53 -04:00
Dianne Skoll
19bdd6c2db Avoid warning about ignoring return value of fgets. 2020-03-19 20:24:01 -04:00
Dianne Skoll
f1557b8243 Try to suppress fallthrough warning. 2020-03-19 20:21:29 -04:00
Dianne Skoll
85f96e2e01 Update man page. 2020-03-14 11:37:11 -04:00
Dianne Skoll
47331cd919 Make ampm() function accept a DATETIME and obey $TimeSep, $DateSep and $DateTimeSep 2020-03-14 11:32:35 -04:00
Dianne Skoll
d9f18ed6a7 Don't use many-json2dict 2020-03-03 11:43:54 -05:00
Dianne Skoll
efa4816371 Properly-form JSON output. 2020-03-03 10:36:01 -05:00
Dianne Skoll
2dc8c63adb Proper prefix for beta versions. 2020-02-29 09:38:51 -05:00
Dianne Skoll
c3c1781021 Update COPYRIGHT date. 2020-02-28 08:56:49 -05:00
Dianne Skoll
cd39480a98 Remove extraneous spaces. 2020-02-27 16:50:44 -05:00
Dianne Skoll
281a1a206e Implement JSONQUEUE daemon command. 2020-02-27 15:18:23 -05:00
Dianne Skoll
cbff2a7bf2 Document ampm() 2020-02-27 08:39:21 -05:00
Dianne Skoll
2a08be8fd0 Fix up unit tests. 2020-02-26 17:43:47 -05:00
Dianne Skoll
0826678209 Make coerce from string to time and datetime accept ampm 2020-02-26 17:41:51 -05:00
Dianne Skoll
f2e421bfa5 Add acceptance tests for ampm() function. 2020-02-26 17:25:09 -05:00
Dianne Skoll
ce53a9b91a Add "ampm" built-in function. 2020-02-26 17:21:34 -05:00
Dianne Skoll
b166b1cf82 Fix up test file. 2020-02-24 15:17:07 -05:00
Dianne Skoll
d09fbb03b2 Bump version to 3.3.1. 2020-02-24 15:16:20 -05:00
Dianne Skoll
7a835f3b10 Update docs. 2020-02-23 16:02:59 -05:00
Dianne Skoll
6b991cdf9c Refactor saving of trigger info. 2020-02-23 11:38:17 -05:00
Dianne Skoll
018e9d0323 JSON can handle newlines (the literal newlines will be escaped to "\n" by the JSON writer.) 2020-02-23 11:17:59 -05:00
Dianne Skoll
f499ae096f Don't include filename or line number in synthesized tag. 2020-02-23 11:15:38 -05:00
Dianne Skoll
725e046a15 Fix bug in recording trigdate() for SATISFY-type reminders. :( 2020-02-22 19:15:24 -05:00
Dianne Skoll
275b1f62b6 For overlapping reminders, prefer the *later* version. 2020-02-22 16:50:42 -05:00
Dianne Skoll
6e58dea198 Handle overlapping events better. 2020-02-22 16:30:08 -05:00
Dianne Skoll
ad4e62c8c3 Test specifying DURATION as an integer. 2020-02-22 12:48:07 -05:00
Dianne Skoll
a5768d55d8 Update man page to document integer form of DURATION. 2020-02-22 12:46:57 -05:00
Dianne Skoll
7db49971c8 Update man page. 2020-02-22 12:40:32 -05:00
Dianne Skoll
45ca6631ac Make sure AM/PM is case-insensitive. 2020-02-22 12:32:52 -05:00
Dianne Skoll
d51944f36c Allow duration to be specified as a single number, meaning minutes.
Don't convert 90-99 to 1990-1999 when parsing numbers.
2020-02-22 12:31:17 -05:00
Dianne Skoll
037c79fb0f Allow times to have am/pm specifications. 2020-02-22 12:24:37 -05:00
Dianne Skoll
993373414f Parse times and datetimes with trailing am/pm 2020-02-22 12:14:18 -05:00
Dianne Skoll
38a0a9992a Leave a space after the asterisk row. 2020-02-12 11:19:30 -05:00
Dianne Skoll
a82bbe3776 Highlight today in month mode also. 2020-02-12 11:17:21 -05:00
Dianne Skoll
a32ba217ba Update man page. 2020-02-08 15:11:15 -05:00
Dianne Skoll
d322cf54ac Allow $FormWidth to be as large as 500. 2020-02-08 15:10:48 -05:00
Dianne Skoll
b1d07a231d Document $FormWidth. 2020-02-08 15:06:09 -05:00
Dianne Skoll
97851a08e6 Clamp min cal width at 72 2020-02-08 15:04:59 -05:00
Dianne Skoll
8547b30a8f Set $FormWidth to terminal width - 8 on startup. 2020-02-08 15:04:48 -05:00
Dianne Skoll
405c7d9ed0 Set release date. 2020-01-31 11:17:55 -05:00
Dianne Skoll
ac5b641d93 Note that back-ends MUST ignore unknown SPECIALs. 2020-01-30 16:07:57 -05:00
Dianne Skoll
06a79989c0 Minor tweaks. 2020-01-28 15:16:41 -05:00
Dianne Skoll
671db64436 Fix various typos. 2020-01-28 09:51:12 -05:00
Dianne Skoll
33344cefe6 Fix typo 2020-01-28 09:47:06 -05:00
Dianne Skoll
5ef0341537 Avoid memory leak. 2020-01-28 09:43:42 -05:00
Dianne Skoll
6abca08189 Add test to ensure rem2ps ignores unknown SPECIALs. 2020-01-28 09:42:13 -05:00
Dianne Skoll
35670ce651 Update docs 2020-01-28 09:38:06 -05:00
Dianne Skoll
e230d53d84 Ignore unknown SPECIALs in rem2ps. 2020-01-28 09:37:35 -05:00
Dianne Skoll
88537a3471 Remove ancient pointer to doe.carleton.ca 2020-01-28 09:29:42 -05:00
Dianne Skoll
7c9d74da73 Fix typo 2020-01-27 16:46:57 -05:00
Dianne Skoll
3b582935ee Sign beta tarballs too. 2020-01-27 16:46:07 -05:00
Dianne Skoll
508fafb875 Update WHATSNEW. 2020-01-27 16:28:57 -05:00
Dianne Skoll
6f718f0fe5 Update rem2ps man page. 2020-01-27 13:29:33 -05:00
Dianne Skoll
53acbf2052 Don't swallow %" %" markers in -ppp mode. 2020-01-27 13:21:48 -05:00
Dianne Skoll
1606dbbe77 Rework -@ option and tests. 2020-01-27 11:49:41 -05:00
Dianne Skoll
adced3ac6c Rework -@ option to be n,m 2020-01-27 11:44:16 -05:00
Dianne Skoll
14f207140a Better clamping algorithm for true colors 2020-01-27 11:31:57 -05:00
Dianne Skoll
d2da32de6c Don't hard-code number. 2020-01-26 18:26:03 -05:00
Dianne Skoll
e5d6a36f05 Update WHATSNEW 2020-01-26 18:10:11 -05:00
Dianne Skoll
68ecfcf876 Update test for change to rem2ps 2020-01-26 18:09:27 -05:00
Dianne Skoll
fcb14b9dfe Add PageBoundingBox comment. 2020-01-26 18:09:06 -05:00
Dianne Skoll
6a4b4257a6 Fix compilation failure on pre-C99 compilers. 2020-01-26 17:47:00 -05:00
Dianne Skoll
385b57e269 Update whatsnew 2020-01-25 17:43:10 -05:00
Dianne Skoll
a8e81e3984 Update WHATSNEW. 2020-01-25 17:41:47 -05:00
Dianne Skoll
46c5f0e752 Update man page for exact color setting. 2020-01-25 16:18:09 -05:00
Dianne Skoll
454d859fdd Support true RGB coloring. 2020-01-25 16:16:51 -05:00
Dianne Skoll
57134a182c Make SPECIALs case-insensitive. 2020-01-25 16:07:18 -05:00
Dianne Skoll
5801e143ea Make specials case-insensitive. 2020-01-25 16:04:53 -05:00
Dianne Skoll
4e0d0ff98b Test Xterm 256-color mode. 2020-01-25 15:16:30 -05:00
Dianne Skoll
d4ac1849ae Add comment for Xterm 256 colors. 2020-01-25 15:12:13 -05:00
Dianne Skoll
c16ac1bd8c Support 256-color mode on XTerm and other terminals. 2020-01-25 15:06:43 -05:00
Dianne Skoll
16222ac3bc Fix to man page. 2020-01-25 14:35:20 -05:00
Dianne Skoll
8d88931fb1 Fix indentation. 2020-01-25 14:27:25 -05:00
Dianne Skoll
63f0356e70 Fix man page wording. 2020-01-25 14:26:32 -05:00
Dianne Skoll
786b0dee6f Add test for =@ 2020-01-25 14:23:52 -05:00
Dianne Skoll
e7ef9dc295 Document -@ 2020-01-25 14:12:56 -05:00
Dianne Skoll
f59461b95d Convert black-on-black or white-on-white to grey. 2020-01-25 14:00:28 -05:00
Dianne Skoll
566a86b9fd Obey default color settings. 2020-01-25 11:29:06 -05:00
Dianne Skoll
8589a3730d Put -@[n] in help. 2020-01-25 11:13:50 -05:00
Dianne Skoll
c05fd366df Implement -@, -@0 and -@1 options to colorize reminders. 2020-01-25 11:12:10 -05:00
Dianne Skoll
fc9fd1e53c Start adding support for colored reminders in Agenda Mode. 2020-01-24 16:31:01 -05:00
Dianne Skoll
a5e6eb9f7c Add -@ commandline option. Yuck. 2020-01-24 16:26:55 -05:00
Dianne Skoll
a9430fea5f Make Remind adjust calendar to fit terminal. 2020-01-18 15:11:28 -05:00
Dianne Skoll
828a0d6589 Emit prevmonthyear and nextmonthyear items in -ppp format. 2020-01-18 14:52:17 -05:00
Dianne Skoll
32601da748 Update tests. 2020-01-18 14:48:27 -05:00
Dianne Skoll
ac50f119cf Document that -pp and -ppp enable -l 2020-01-18 14:45:23 -05:00
Dianne Skoll
7622ebaa0a Document remind -ppp format. 2020-01-18 14:43:21 -05:00
Dianne Skoll
a586d5cd37 Fix bug that incorrectly printed # fileinfo lines for -ppp format. 2020-01-18 14:43:04 -05:00
Dianne Skoll
edbc88bd19 Reformat error message. 2020-01-16 20:00:38 -05:00
Dianne Skoll
94f99f3414 Make rem2ps bail out if fed "-ppp"-format. 2020-01-16 19:59:30 -05:00
Dianne Skoll
fd4f84349e Include filename and lineno in tag synthesis. 2020-01-16 19:19:13 -05:00
Dianne Skoll
f86350b2ff More man page tweakage. 2020-01-16 18:56:28 -05:00
Dianne Skoll
564b72066a Document $DefaultColor 2020-01-16 18:53:30 -05:00
Dianne Skoll
2890c52090 Fix typo in man page 2020-01-15 11:27:43 -05:00
Dianne Skoll
c1d45485c1 Update test suite. 2020-01-15 09:20:31 -05:00
Dianne Skoll
8b2a69cf8d Do a small bit of refactoring to get rid of some copy/paste code. 2020-01-15 09:18:32 -05:00
Dianne Skoll
034c1341b3 Fix typos. 2020-01-14 21:47:26 -05:00
Dianne Skoll
29bbf1a030 Be strict in what we accept for SET $DefaultColor "r g b" 2020-01-14 21:44:08 -05:00
Dianne Skoll
be6661d6be Don't assume a potentially-colored reminder unless it's MSG/MSF/CAL type. 2020-01-14 21:43:46 -05:00
Dianne Skoll
3f876e792c Reset $DefaultColor each time we iterate. 2020-01-14 21:15:27 -05:00
Dianne Skoll
f2457b90ff Add patch for $DefaultColor, courtesy of Tim Chase. 2020-01-14 21:07:20 -05:00
Dianne Skoll
e999e9009b Minor formatting tweak. 2020-01-14 20:17:38 -05:00
Dianne Skoll
46326c001b Output true JSON if you invoke as "remind -ppp" 2020-01-14 20:09:24 -05:00
Dianne Skoll
b84c2c403c Add more balloon help. 2020-01-13 21:19:45 -05:00
Dianne Skoll
861ad72187 Add popup help. 2020-01-13 18:26:40 -05:00
Dianne Skoll
7dbbc34ccc Make Remind compile on older gcc that doesn't allow declarations in for(...) 2020-01-13 10:00:25 -05:00
Dianne Skoll
4ea45d1d14 Update rem2ps man page. 2020-01-12 20:03:43 -05:00
Dianne Skoll
c1b9243e2f Document new REM2PS format. 2020-01-12 19:56:45 -05:00
Dianne Skoll
a41c40c7a4 Document -pp option. 2020-01-12 19:24:21 -05:00
Dianne Skoll
318d4547ef Use r, g, b settings from SHADE special. 2020-01-12 18:11:35 -05:00
Dianne Skoll
6f98b60a6a Output "r", "g", "b" for shade-style reminders. 2020-01-12 18:09:41 -05:00
Dianne Skoll
baa8f7f3c4 Add test that OMITFUNC raises nonconst_expr indicator. 2020-01-12 17:51:06 -05:00
Dianne Skoll
6297622072 Write JSON using English day names. 2020-01-12 17:47:41 -05:00
Dianne Skoll
9f3ba0bf2b More intelligent filling out of GUI. 2020-01-12 17:27:50 -05:00
Dianne Skoll
9591dec708 Write out fully-specified dates in Reminders more compactly. 2020-01-12 17:15:38 -05:00
Dianne Skoll
ee2d0b7518 Production file location! 2020-01-12 14:05:55 -05:00
Dianne Skoll
2d46749c58 Add blank line when *first* creating AppendFile. 2020-01-12 14:01:20 -05:00
Dianne Skoll
494664d1b6 Take out blank line from warning header lines. 2020-01-12 14:00:04 -05:00
Dianne Skoll
49686210ae Better reverse-engineering of ordinal. 2020-01-12 13:57:25 -05:00
Dianne Skoll
ddfa44188b Reset HighestTagSoFar when we rewrite the appendfile after deletion. 2020-01-12 13:52:17 -05:00
Dianne Skoll
73cf93d27b Renumber tags when we delete a tagged reminder. 2020-01-12 13:34:22 -05:00
Dianne Skoll
60d1a34bf0 Fix up AM/PM handling; delete old comment lines. 2020-01-12 13:28:45 -05:00
Dianne Skoll
6f80986801 New version of tkremind seems to be decent... 2020-01-12 13:14:32 -05:00
Dianne Skoll
2078f087b2 An OMITFUNC should set the nonconst_expr flag. 2020-01-12 13:06:55 -05:00
Dianne Skoll
68d110826e First version of TkRemind that can reverse-engineer reminder without needing comments to set up GUI. 2020-01-12 12:45:34 -05:00
Dianne Skoll
9fb04c54ae Start work on reverse-engineering reminder dialog from JSON instead of relying on comments. 2020-01-11 19:08:35 -05:00
Dianne Skoll
d82314594b Make rem2html understand JSON interchange format. 2020-01-10 15:06:59 -05:00
Dianne Skoll
ad169a5248 Eliminate compiler warnings. 2020-01-10 13:57:13 -05:00
Dianne Skoll
a9bab81226 Test that rem2ps can parse "remind -pp" output. 2020-01-10 13:48:58 -05:00
Dianne Skoll
fa63a9ba51 Add comments. 2020-01-10 13:46:20 -05:00
Dianne Skoll
1e7a630737 rem2ps can read the new-style JSON output of "remind -pp" 2020-01-10 13:41:27 -05:00
Dianne Skoll
de1afce8da Suppress unused param warnings. 2020-01-09 18:53:00 -05:00
Dianne Skoll
ac3cb19c26 Simplify code. 2020-01-09 18:42:14 -05:00
Dianne Skoll
af0479d11d Start preparing rem2ps for parsing JSON input. 2020-01-09 18:38:08 -05:00
Dianne Skoll
0d9c04707f Output nonconst_expr and if_depth indicators in JSON mode. 2020-01-08 08:42:23 -05:00
Dianne Skoll
c2218f133b Preserve RGB info for a COLOR reminder. 2020-01-07 13:27:22 -05:00
Dianne Skoll
1ad0645fab Only print rawbody if it differs from body. 2020-01-06 22:25:49 -05:00
Dianne Skoll
3c16f6839a Pass raw body through to back-end in JSON mode. 2020-01-06 22:19:22 -05:00
Dianne Skoll
e8bac1e469 More info over JSON via -pp commandline switch. 2020-01-05 17:15:37 -05:00
Dianne Skoll
b3b69596f4 Output SKIP value in JSON. 2020-01-05 12:18:10 -05:00
Dianne Skoll
6a7bcb0956 Print the "wd" entry as array of weekday names. 2020-01-05 12:15:20 -05:00
Dianne Skoll
f18a0704c1 More work on emitting JSON. 2020-01-05 12:10:05 -05:00
Dianne Skoll
d6f24b7c1e rem2ps will only support "remind -p" protocol and not "remind -pp" 2020-01-03 18:00:21 -05:00
Dianne Skoll
e2c9bbf94c Start working on JSON-based alternate "remind -p" protocol. 2020-01-03 17:24:01 -05:00
Dianne Skoll
f53aa4f656 Start working on Version 2 of Rem2PS protocol. 2020-01-03 16:51:47 -05:00
Dianne Skoll
a7ab9b8bf8 Update release date. :( 2020-01-03 13:14:53 -05:00
Dianne Skoll
4448271166 Update WHATSNEW. 2020-01-03 13:05:33 -05:00
Dianne Skoll
4861b535a2 Use nicer moon graphics. 2020-01-03 13:02:16 -05:00
Dianne Skoll
167f0100c7 Minor tweaks. 2020-01-03 12:43:22 -05:00
Dianne Skoll
b0367c7a5c Update README.UNIX. 2020-01-02 14:45:31 -05:00
Dianne Skoll
4ae8ad52f5 Update WHATSNEW. 2020-01-02 14:42:46 -05:00
Dianne Skoll
dbd64828ab Use nicer moon images. 2020-01-02 11:39:29 -05:00
Dianne Skoll
158ca882ba Fix typo 2020-01-01 18:32:24 -05:00
Dianne Skoll
623ed44608 Update man page. 2020-01-01 18:30:46 -05:00
Dianne Skoll
f13b867626 Update WHATSNEW 2020-01-01 18:04:20 -05:00
Dianne Skoll
ff85325886 Support DATETIME - TIME 2020-01-01 18:00:22 -05:00
Dianne Skoll
aa830116ea Update copyright dates, etc. 2020-01-01 10:13:50 -05:00
Dianne Skoll
1a4504ba28 Catch date overflow if we use a crazy-long DURATION. 2020-01-01 10:01:02 -05:00
Dianne Skoll
20365c4627 Document DURATION 00:00 2020-01-01 09:50:13 -05:00
Dianne Skoll
fae8f89ed6 Handle self-overlapping events correctly; avoid 0-duration events; document
self-overlapping behaviour.
2020-01-01 09:45:28 -05:00
Dianne Skoll
a0689999fe Adjust duration_days to not include zero-duration tails. 2020-01-01 09:31:55 -05:00
Dianne Skoll
a42a0ab032 Update WHATSNEW. 2019-12-31 23:32:18 -05:00
Dianne Skoll
b66eb5d3ec Suppress printing subdirectory entry for "make test" 2019-12-31 23:11:55 -05:00
Dianne Skoll
8b4bc0f56e Print warning if we truncate a function name. 2019-12-31 22:54:22 -05:00
Dianne Skoll
c9d984983f Add a warning if we truncate variable names. 2019-12-31 22:50:42 -05:00
Dianne Skoll
47125b051a Clarify that IFTRIG can't take SATISFY 2019-12-31 22:41:34 -05:00
Dianne Skoll
e5e6ff6031 Return "Can't compute trigger" if SATISFY uses up too many iterations. 2019-12-31 22:26:23 -05:00
Dianne Skoll
9f0aedb608 Don't suppress errors in trigger computation. 2019-12-31 22:13:53 -05:00
Dianne Skoll
08af33ece5 Don't allow DURATION without an AT. 2019-12-31 21:51:34 -05:00
Dianne Skoll
9b421d0b94 Fix typo 2019-12-31 21:44:49 -05:00
Dianne Skoll
7bd8d2dd25 Tweak formatting. 2019-12-31 21:40:32 -05:00
Dianne Skoll
a7c4879a0a Update man page and WHATSNEW. 2019-12-31 21:38:18 -05:00
Dianne Skoll
8b3585a6b8 Add test for trigeventstart() and trigeventduration() 2019-12-31 21:12:44 -05:00
Dianne Skoll
a223149aee Add trigeventstart() and trigeventduration() functions. 2019-12-31 21:09:21 -05:00
Dianne Skoll
9185341b0c Add a test. 2019-12-31 19:14:15 -05:00
Dianne Skoll
bf2d707e13 Skip duration_days at least in each SATISFY loop. 2019-12-31 18:51:22 -05:00
Dianne Skoll
f081e5c54d Update test. 2019-12-31 18:42:10 -05:00
Dianne Skoll
18a3db0f31 Fix interation between multi-day events and SATISFY. 2019-12-31 18:41:25 -05:00
Dianne Skoll
d2c115127d Add a FIXME. 2019-12-31 18:02:49 -05:00
Dianne Skoll
c12e7e1b8f Update tests with new version. 2019-12-31 17:47:40 -05:00
Dianne Skoll
d3495ab3aa Update version to 3.2.0. Events spanning >1 day are a major new feature. 2019-12-31 17:46:40 -05:00
Dianne Skoll
b93a7a6195 Update tests. 2019-12-31 17:43:46 -05:00
Dianne Skoll
e5519a8498 Handle events that span >1 day. 2019-12-31 17:39:26 -05:00
Dianne Skoll
eb2256f873 Use proper arrow icons instead of text <- and -> 2019-12-30 20:51:37 -05:00
Dianne Skoll
637b137b1c Use open |foo rather than exec to handle cmdline option parsing more uniformly. 2019-12-30 20:27:12 -05:00
Dianne Skoll
e2d14e73bf Update copyright date. 2019-12-30 11:18:01 -05:00
Dianne Skoll
fbbffb4672 Bump version to 3.1.18 and copyright year to 2020. 2019-12-30 11:15:00 -05:00
Dianne Skoll
422e098727 Don't use a static coerce_buf 2019-12-30 11:02:09 -05:00
Dianne Skoll
87347e30b2 Make string concatenation more efficient. 2019-12-30 10:59:32 -05:00
Dianne Skoll
3314ce9823 Update WHATSNEW 2019-12-30 10:42:17 -05:00
Dianne Skoll
402c1fe614 Proper fix. 2019-12-30 10:37:30 -05:00
Dianne Skoll
1d57856aa8 Avoid startup error if ShowTodaysReminders is true and ExtraRemindArgs is empty. 2019-12-30 10:34:37 -05:00
Dianne Skoll
c027c215d6 Update WHATSNEW 2019-12-29 21:03:27 -05:00
Dianne Skoll
fa0428b9fe Fix compile error for Romanian language; avoid compiler warning for non-English languages. 2019-12-29 19:08:48 -05:00
Dianne Skoll
b01c499ce5 Tweak man page. 2019-12-29 18:53:29 -05:00
Dianne Skoll
4e5033dd24 Implement adding DATETIME+TIME, TIME+DATETIME and TIME+TIME 2019-12-29 18:46:10 -05:00
Dianne Skoll
00863f3830 Add header file dependency. 2019-12-28 17:46:17 -05:00
Dianne Skoll
2d4b35e8b9 Add tests for introspection functions. 2019-12-28 17:28:31 -05:00
Dianne Skoll
6e4f2b9466 Implement remaining trigger introspection functions. 2019-12-28 17:09:05 -05:00
Dianne Skoll
9a6fc0253b Clear last triggers in all necessary spots. 2019-12-28 16:42:10 -05:00
Dianne Skoll
3180c781ed Start working on making bits of the trigger and time trigger introspectable. 2019-12-28 16:37:47 -05:00
Dianne Skoll
632152e8b6 Remember the last trigger and time trigger. 2019-12-28 16:24:16 -05:00
Dianne Skoll
1048f7e98d Add TAGS to omitted files. 2019-12-28 16:17:32 -05:00
Dianne Skoll
3de265216e Document $MaxStringLen 2019-11-21 11:41:25 -05:00
Dianne Skoll
2bdcadc7ab Minor cleanups. 2019-11-21 11:36:49 -05:00
Dianne Skoll
421ddfc68e Catch date overflow in slide() function. 2019-11-21 11:06:00 -05:00
Dianne Skoll
41594bc1ac Update release notes. 2019-11-15 11:14:23 -05:00
Dianne Skoll
e85199d464 Remove obsolete line. 2019-11-15 11:08:04 -05:00
Dianne Skoll
a6ee3bc704 Use git-archive to create tarball. 2019-11-15 11:06:19 -05:00
Dianne Skoll
2909106f30 Update copyright date. 2019-11-15 10:57:01 -05:00
Dianne Skoll
05b97aabb2 Sign releases. 2019-11-15 10:56:40 -05:00
Dianne Skoll
84af60d817 Delete COMMIT_EDITMSG when syncing to public git repo. 2019-11-14 17:04:43 -05:00
Dianne Skoll
72403a2512 Warn if "OMIT a THROUGH b" has a > b 2019-11-14 11:09:51 -05:00
Dianne Skoll
4ec619d646 Update copyright date. 2019-11-07 20:52:38 -05:00
Dianne Skoll
6178a627a0 Fix bug that prevented warning if we redefine a built-in function. 2019-11-07 20:50:35 -05:00
Dianne Skoll
3095fd7e4a Enable warning-free compilation even with -Wextra. 2019-11-04 16:35:14 -05:00
Dianne Skoll
74a6041760 Update version to 03.01.17. 2019-11-04 16:18:56 -05:00
Dianne Skoll
96127e37ff Update man page. 2019-11-04 16:16:15 -05:00
Dianne Skoll
df5484ea35 Add test for "SCANFROM -n" form. 2019-11-04 16:10:53 -05:00
Dianne Skoll
0ae3dae030 Allow shortand: SCANFROM -n meaning SCANFROM [today() - n] 2019-11-04 16:08:44 -05:00
Dianne Skoll
e5979139ac Fix typo. 2019-02-13 11:04:20 -05:00
Dianne Skoll
f81f6deb20 Apply patch from Dov Feldstern to fix Adar behaviour. 2018-12-11 10:05:11 -05:00
Dianne Skoll
f9951909d8 First part of patch to fix ADAR behaviour 2018-12-11 10:04:05 -05:00
Dianne Skoll
bbda972b05 Properly react to changes in extra remind args. 2018-12-07 14:54:02 -05:00
Dianne Skoll
4445e9c434 Add "Extra remind options" option. 2018-12-07 14:47:47 -05:00
Dianne Skoll
709adacac2 Add helper script to sync to dianne.skoll.ca git repo 2018-11-29 11:18:35 -05:00
Dianne Skoll
9841cdd355 When dumping queue contents, omit expired reminders. 2018-11-28 14:27:40 -05:00
Dianne Skoll
4cabe5fd71 Update docs/WHATSNEW with release notes. 2018-11-09 08:27:21 -05:00
Dianne Skoll
0db239f8a0 Bump version to 03.01.16. 2018-11-09 08:20:08 -05:00
Dianne Skoll
32fb1706c8 Fix a few more SystemTime calls. 2018-11-04 13:47:18 -05:00
Dianne Skoll
c9e6cd9796 Queue should use actual clock in computer. 2018-11-04 13:45:23 -05:00
Dianne Skoll
81677528a5 In -z0 mode, wake up exactly on the minute. 2018-11-04 13:39:00 -05:00
Dianne Skoll
7761baba10 ? 2018-11-04 13:29:59 -05:00
Dianne Skoll
52d252723f Depenguinization. 2018-11-04 10:56:47 -05:00
Dianne Skoll
d476709b59 Update DST rules. 2018-10-31 10:44:44 -04:00
Dianne Skoll
0910e3da74 Center popups over cal window. 2018-10-29 13:22:33 -04:00
Dianne Skoll
2cc7b7c817 Make queue grid resize gracefully. 2018-04-19 14:06:52 -04:00
Dianne Skoll
011a95ebbd Format the queue output better. 2018-04-19 14:01:09 -04:00
Dianne Skoll
bbdc086a1f Correct definitions for Yom Hazikaron and Yom Ha'atzmaut. 2018-04-19 14:00:46 -04:00
Dianne Skoll
7d6617d21e Finish adding queue feature. 2018-04-18 10:57:51 -04:00
Dianne Skoll
f684baeeb9 Add a QUEUE daemon command to dump the queue. 2018-04-18 10:43:49 -04:00
Dianne Skoll
308104853b Redraw window if file time is updated. 2018-04-13 08:46:26 -04:00
Dianne Skoll
6953bcac35 Monitor .reminders for mtime changes and restart daemon if it changes. 2018-04-12 11:44:04 -04:00
Dianne Skoll
69e9fa4721 Put hostname in tkremind window. Silence gcc warning. 2017-07-18 10:36:08 -04:00
Dianne Skoll
72d154c5e0 Patch from Stephen Morgan to calculate astronomical and nautical twilight in addition to civil twilight. 2017-01-19 10:11:54 -05:00
Dianne Skoll
84b0a96170 Accept datetimes in ISO-8601 format on input.
Add $DateTimeSep system variable to select T or @ as separator
on output.
2016-07-25 10:05:25 -04:00
Dianne Skoll
6d3b8f7a09 Handle the "SHADE nnn" special with just one number.
Pointed out by hymie@lactose.homelinux.net
2016-01-15 10:16:02 -05:00
Dianne Skoll
81749ac1c9 Update release notes. 2015-07-27 15:41:14 -04:00
Dianne Skoll
65989c29b7 Add test for bug found by Alexander Keller 2015-07-27 15:38:11 -04:00
Dianne Skoll
ec4e58f25c Proper fix for overflow. 2015-07-27 13:20:00 -04:00
Dianne Skoll
0c699c2a19 Fix potential buffer overflow. 2015-07-27 13:18:16 -04:00
Dianne Skoll
739a938d32 Don't permit repeated DELTA or REPEATs either. 2015-05-27 13:21:33 -04:00
Dianne Skoll
61ad405b4a Reject AT clause with more than one following TIME. 2015-05-27 13:19:25 -04:00
Dianne Skoll
700e649e76 Fix typo in year. Pointed out by hymie@lactose.homelinux.net 2015-04-24 15:33:35 -04:00
Dianne Skoll
7bfdb1f0eb Document the magic __EOF__ marker. 2015-04-24 14:42:48 -04:00
Dianne Skoll
0c0280b2a9 Add test for __EOF__ 2015-04-24 14:40:12 -04:00
Dianne Skoll
57a1871077 Fix test output. 2015-04-24 14:37:32 -04:00
Dianne Skoll
ee972ad29f Update version to 3.1.14 2015-04-24 14:37:06 -04:00
David F. Skoll
29c8475ea9 s/David/Dianne/ 2015-04-17 02:07:18 -04:00
David F. Skoll
6dd0f6ed63 Fix typo. 2014-11-06 14:32:30 -05:00
David F. Skoll
fc2d7ae446 Add support for __EOF__ to make Remind stop reading a file. 2014-05-22 14:19:06 -04:00
David F. Skoll
d232ac0334 Clear out MD5 context correctly. 2014-02-14 12:46:12 -05:00
David F. Skoll
6e8dd68c8a Use ADVANCE_MODE rather than CAL_MODE for "-n" cmdline option. 2013-04-30 15:58:02 -04:00
David F. Skoll
495cc1b38d Improve PNG images. 2013-03-22 16:21:52 -04:00
100 changed files with 9909 additions and 1591 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
.gitignore export-ignore
.gitattributes export-ignore
remind.php export-ignore
sync-to-dianne-git export-ignore

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ tests/test.out
*~
src/rem2ps
src/version.h
TAGS

View File

@@ -3,8 +3,8 @@ THE REMIND COPYRIGHT
1. REMIND refers to the entire set of files and documentation in the
REMIND package.
2. REMIND is Copyright 1999-2010 Roaring Penguin Software Inc.,
except where noted in individual files.
2. REMIND is Copyright 1992-2020 Dianne Skoll, except where noted in
individual files.
3. DISTRIBUTION AND USE
@@ -293,8 +293,8 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
--
David F. Skoll <dfs@roaringpenguin.com>
Dianne Skoll <dianne@skoll.ca>
https://dianne.skoll.ca/projects/remind
Tel. (613) 231-6599
http://www.roaringpenguin.com

View File

@@ -27,4 +27,4 @@ iPhone or iPad, please don't. Those products enforce Apple's rigorous
controls much more stringently than Mac OS X on an Apple PC.
--
David F. Skoll
Dianne Skoll

View File

@@ -8,7 +8,7 @@ all: src/Makefile
@echo "* *"
@echo "*******************"
@echo ""
@cd src; $(MAKE) all LANGDEF=$(LANGDEF)
@cd src && $(MAKE) all LANGDEF=$(LANGDEF)
install:
@echo ""
@@ -18,14 +18,14 @@ install:
@echo "* *"
@echo "*********************"
@echo ""
cd src; $(MAKE) install
@cd src && $(MAKE) install
clean:
find . -name '*~' -exec rm {} \;
cd src; $(MAKE) clean
cd src && $(MAKE) clean
test:
@cd src && $(MAKE) test
@cd src && $(MAKE) -s test
distclean: clean
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile

4
README
View File

@@ -34,5 +34,5 @@ If you do NOT have Tcl/Tk or are NOT running X Windows:
5) Type: "make install" -- you may need to be root to do this.
Contact info: mailto:dfs@roaringpenguin.com
Home page: http://www.roaringpenguin.com/remind
Contact info: mailto:dianne@skoll.ca
Home page: https://dianne.skoll.ca/projects/remind/

126
build.tk Executable file → Normal file
View File

@@ -7,8 +7,7 @@
# A cheesy graphical front-end for building and installing REMIND.
#
# This file is part of REMIND.
# Copyright (C) 1992-1999 David F. Skoll
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 Dianne Skoll
#
#--------------------------------------------------------------
@@ -95,10 +94,6 @@ proc CreateMainDialog {} {
wm title . "Remind Configuration"
wm iconname . "Remind Config"
doLogo
destroy .c
update idletasks
SetConfigFromRemind
tabnotebook_create .tn
@@ -757,125 +752,6 @@ proc notebook_fix_size {win} {
$win configure -width $maxw -height $maxh
}
#***********************************************************************
# %PROCEDURE: drawLogo
# %ARGUMENTS:
# c -- canvas to draw logo in
# bg -- background color of canvas
# %RETURNS:
# Nothing
# %DESCRIPTION:
# Draws Roaring Penguin logo in a Tcl canvas
#***********************************************************************
proc drawLogo { c bg } {
set logo_objs {
{polygon 558 0 557 0 556 0 554 0 551 0 550 0 549 0 547 0 546 0 544 0 542 1 539 1 537 2 535 3 534 3 533 3 532 3 530 4 528 5 525 6 523 6 522 7 521 7 519 8 516 9 514 10 512 11 510 11 509 12 507 12 507 13 506 13 505 12 502 12 500 11 498 11 497 11 496 11 495 11 493 11 491 12 489 12 488 12 488 13 487 13 485 14 483 15 482 16 481 17 480 19 478 21 477 22 476 23 476 24 475 25 474 26 473 28 472 30 470 33 467 37 464 41 462 45 459 48 457 52 456 54 455 55 454 56 454 57 453 58 452 59 452 61 451 63 449 65 448 68 447 71 445 74 443 77 442 81 440 86 438 90 436 95 435 99 434 103 433 105 433 106 432 107 432 108 432 109 431 111 431 113 430 116 429 121 428 125 427 130 425 135 425 138 424 140 424 142 424 143 424 144 424 145 423 147 423 149 423 152 422 157 421 162 421 167 420 172 420 176 419 180 419 183 419 187 419 189 419 192 418 195 418 196 418 198 418 199 417 199 416 199 415 199 414 199 413 200 412 200 411 200 411 201 410 201 410 202 409 202 409 203 408 203 407 204 407 205 408 205 410 206 413 208 416 209 418 210 419 210 419 211 420 211 421 211 422 212 424 212 426 212 429 213 432 213 435 214 439 214 442 214 444 214 445 214 446 214 447 214 449 214 452 214 457 214 461 214 464 214 466 214 467 214 468 214 469 214 470 214 472 214 474 214 477 213 482 213 486 213 490 212 494 212 497 212 500 211 502 211 505 211 507 211 508 210 509 210 510 210 510 208 511 206 512 203 513 198 514 194 515 189 516 185 517 182 517 179 518 178 518 177 518 176 518 175 519 174 519 171 520 169 520 166 521 163 522 160 522 157 523 153 524 149 524 144 525 139 526 135 526 132 526 130 526 129 526 128 526 127 527 127 527 126 527 124 527 122 527 119 527 115 527 110 527 106 527 102 527 99 527 96 527 95 527 94 527 93 527 92 527 91 527 88 527 85 526 81 526 77 525 72 524 67 524 64 523 60 522 57 521 54 521 51 520 49 520 47 519 45 519 44 518 43 520 42 521 42 523 41 524 40 525 40 526 40 527 40 528 39 530 39 532 39 533 38 534 38 536 38 538 37 539 37 540 37 541 36 543 35 544 34 545 33 546 32 545 32 543 33 542 33 541 34 540 34 539 34 537 34 536 34 534 34 532 34 531 34 530 34 529 34 527 33 525 33 524 33 523 33 522 33 520 32 518 32 517 32 515 31 514 31 514 30 516 29 517 27 519 25 520 24 521 23 521 22 522 22 523 21 524 20 526 19 528 17 530 15 533 14 534 13 535 12 536 12 537 11 538 10 541 9 543 7 545 6 546 6 546 5 547 5 549 4 551 3 553 2 555 1 556 0 557 0 -outline {} -fill \#000000 -width 0}
{line 558 0 557 0 556 0 554 0 551 0 550 0 549 0 547 0 546 0 544 0 542 1 539 1 537 2 535 3 534 3 533 3 532 3 530 4 528 5 525 6 523 6 522 7 521 7 519 8 516 9 514 10 512 11 510 11 509 12 507 12 507 13 506 13 505 12 502 12 500 11 498 11 497 11 496 11 495 11 493 11 491 12 489 12 488 12 488 13 487 13 485 14 483 15 482 16 481 17 480 19 478 21 477 22 476 23 476 24 475 25 474 26 473 28 472 30 470 33 467 37 464 41 462 45 459 48 457 52 456 54 455 55 454 56 454 57 453 58 452 59 452 61 451 63 449 65 448 68 447 71 445 74 443 77 442 81 440 86 438 90 436 95 435 99 434 103 433 105 433 106 432 107 432 108 432 109 431 111 431 113 430 116 429 121 428 125 427 130 425 135 425 138 424 140 424 142 424 143 424 144 424 145 423 147 423 149 423 152 422 157 421 162 421 167 420 172 420 176 419 180 419 183 419 187 419 189 419 192 418 195 418 196 418 198 418 199 417 199 416 199 415 199 414 199 413 200 412 200 411 200 411 201 410 201 410 202 409 202 409 203 408 203 407 204 407 205 408 205 410 206 413 208 416 209 418 210 419 210 419 211 420 211 421 211 422 212 424 212 426 212 429 213 432 213 435 214 439 214 442 214 444 214 445 214 446 214 447 214 449 214 452 214 457 214 461 214 464 214 466 214 467 214 468 214 469 214 470 214 472 214 474 214 477 213 482 213 486 213 490 212 494 212 497 212 500 211 502 211 505 211 507 211 508 210 509 210 510 210 510 208 511 206 512 203 513 198 514 194 515 189 516 185 517 182 517 179 518 178 518 177 518 176 518 175 519 174 519 171 520 169 520 166 521 163 522 160 522 157 523 153 524 149 524 144 525 139 526 135 526 132 526 130 526 129 526 128 526 127 527 127 527 126 527 124 527 122 527 119 527 115 527 110 527 106 527 102 527 99 527 96 527 95 527 94 527 93 527 92 527 91 527 88 527 85 526 81 526 77 525 72 524 67 524 64 523 60 522 57 521 54 521 51 520 49 520 47 519 45 519 44 518 43 520 42 521 42 523 41 524 40 525 40 526 40 527 40 528 39 530 39 532 39 533 38 534 38 536 38 538 37 539 37 540 37 541 36 543 35 544 34 545 33 546 32 545 32 543 33 542 33 541 34 540 34 539 34 537 34 536 34 534 34 532 34 531 34 530 34 529 34 527 33 525 33 524 33 523 33 522 33 520 32 518 32 517 32 515 31 514 31 514 30 516 29 517 27 519 25 520 24 521 23 521 22 522 22 523 21 524 20 526 19 528 17 530 15 533 14 534 13 535 12 536 12 537 11 538 10 541 9 543 7 545 6 546 6 546 5 547 5 549 4 551 3 553 2 555 1 556 0 557 0 558 0 -joinstyle bevel}
{polygon 490 94 490 95 490 96 489 99 489 103 489 106 488 109 488 111 488 112 488 113 488 115 487 117 487 119 487 121 486 123 485 126 485 130 484 133 483 136 483 137 483 138 483 139 482 139 482 140 482 141 481 144 480 147 479 150 478 153 477 154 477 155 477 156 476 157 476 159 475 161 473 164 472 167 471 170 470 172 468 175 467 176 467 178 466 179 466 180 465 180 465 179 464 177 463 174 462 171 461 169 461 168 461 167 460 166 460 165 460 163 459 161 458 158 458 155 457 152 457 151 457 150 457 149 457 148 456 146 456 143 456 141 456 139 456 138 456 137 456 136 456 134 456 132 456 129 457 126 457 124 457 123 457 121 458 121 458 120 458 121 458 123 458 125 458 127 457 129 457 130 457 131 457 132 458 134 458 136 458 139 458 141 458 143 458 144 459 145 459 148 460 150 460 151 460 152 460 153 461 154 461 155 462 158 462 160 463 162 464 164 464 166 465 167 465 168 465 169 466 169 466 168 467 166 468 163 470 160 470 158 471 157 471 156 472 155 472 154 473 152 474 150 475 147 476 144 477 141 478 139 478 138 479 137 479 136 480 134 480 132 481 129 482 126 483 124 483 122 483 121 484 121 484 120 484 118 485 116 486 112 487 109 487 106 488 103 488 101 489 99 489 97 490 95 490 94 -outline {} -fill $bg -width 0}
{line 490 94 490 95 490 96 489 99 489 103 489 106 488 109 488 111 488 112 488 113 488 115 487 117 487 119 487 121 486 123 485 126 485 130 484 133 483 136 483 137 483 138 483 139 482 139 482 140 482 141 481 144 480 147 479 150 478 153 477 154 477 155 477 156 476 157 476 159 475 161 473 164 472 167 471 170 470 172 468 175 467 176 467 178 466 179 466 180 465 180 465 179 464 177 463 174 462 171 461 169 461 168 461 167 460 166 460 165 460 163 459 161 458 158 458 155 457 152 457 151 457 150 457 149 457 148 456 146 456 143 456 141 456 139 456 138 456 137 456 136 456 134 456 132 456 129 457 126 457 124 457 123 457 121 458 121 458 120 458 121 458 123 458 125 458 127 457 129 457 130 457 131 457 132 458 134 458 136 458 139 458 141 458 143 458 144 459 145 459 148 460 150 460 151 460 152 460 153 461 154 461 155 462 158 462 160 463 162 464 164 464 166 465 167 465 168 465 169 466 169 466 168 467 166 468 163 470 160 470 158 471 157 471 156 472 155 472 154 473 152 474 150 475 147 476 144 477 141 478 139 478 138 479 137 479 136 480 134 480 132 481 129 482 126 483 124 483 122 483 121 484 121 484 120 484 118 485 116 486 112 487 109 487 106 488 103 488 101 489 99 489 97 490 95 490 94 -joinstyle bevel}
{polygon 503 22 503 23 504 23 504 24 505 24 505 25 505 26 505 27 505 28 505 29 504 29 504 30 503 30 502 30 502 31 501 31 501 30 500 30 499 30 499 29 499 28 499 27 499 26 499 25 499 24 500 24 500 23 501 23 502 22 503 22 -outline {} -fill $bg -width 0}
{line 503 22 503 23 504 23 504 24 505 24 505 25 505 26 505 27 505 28 505 29 504 29 504 30 503 30 502 30 502 31 501 31 501 30 500 30 499 30 499 29 499 28 499 27 499 26 499 25 499 24 500 24 500 23 501 23 502 22 503 22 -joinstyle bevel}
{polygon 517 44 516 45 515 46 513 47 513 48 512 48 511 48 510 49 508 49 506 50 505 50 504 50 503 50 501 50 498 50 497 51 496 51 495 50 492 50 490 50 487 50 486 49 484 49 483 49 482 48 481 48 481 49 480 51 479 53 479 54 478 55 478 56 477 58 477 59 477 61 477 62 477 63 477 65 477 67 476 68 476 69 477 71 477 72 477 74 477 75 477 76 478 76 479 77 481 77 484 78 485 79 486 79 487 79 488 80 490 81 491 82 493 83 494 84 495 85 496 87 498 88 498 89 499 90 500 92 500 94 500 96 501 98 501 99 501 100 501 101 500 102 500 103 500 104 500 105 499 106 499 107 498 108 498 109 498 110 497 111 497 112 497 113 497 114 497 115 498 115 498 116 499 117 499 118 500 118 500 119 501 120 502 121 502 122 503 122 503 123 502 125 502 128 501 132 501 136 500 139 500 141 500 142 499 143 499 144 499 146 498 148 497 151 496 153 495 156 494 160 493 163 492 165 491 167 491 168 491 169 490 169 490 171 489 174 487 177 486 180 485 182 484 184 484 185 483 185 483 186 482 188 481 190 479 193 478 197 477 199 476 202 475 204 474 206 473 208 472 209 472 210 474 210 476 209 479 209 483 209 488 208 492 207 496 207 499 206 502 206 503 206 504 205 504 204 505 201 506 198 507 193 509 188 510 183 512 179 513 176 514 173 514 172 514 171 514 170 515 169 515 167 516 165 516 162 517 160 518 157 518 154 519 150 520 146 521 142 521 137 522 133 523 129 523 126 523 124 523 122 524 122 524 121 524 120 524 118 524 116 524 113 524 109 524 105 525 101 525 97 525 94 525 92 525 91 525 90 525 89 525 88 525 87 524 85 524 82 524 78 523 74 523 70 522 66 522 62 521 59 521 56 520 54 519 51 519 49 518 47 518 46 518 45 518 44 -outline {} -fill $bg -width 0}
{line 517 44 516 45 515 46 513 47 513 48 512 48 511 48 510 49 508 49 506 50 505 50 504 50 503 50 501 50 498 50 497 51 496 51 495 50 492 50 490 50 487 50 486 49 484 49 483 49 482 48 481 48 481 49 480 51 479 53 479 54 478 55 478 56 477 58 477 59 477 61 477 62 477 63 477 65 477 67 476 68 476 69 477 71 477 72 477 74 477 75 477 76 478 76 479 77 481 77 484 78 485 79 486 79 487 79 488 80 490 81 491 82 493 83 494 84 495 85 496 87 498 88 498 89 499 90 500 92 500 94 500 96 501 98 501 99 501 100 501 101 500 102 500 103 500 104 500 105 499 106 499 107 498 108 498 109 498 110 497 111 497 112 497 113 497 114 497 115 498 115 498 116 499 117 499 118 500 118 500 119 501 120 502 121 502 122 503 122 503 123 502 125 502 128 501 132 501 136 500 139 500 141 500 142 499 143 499 144 499 146 498 148 497 151 496 153 495 156 494 160 493 163 492 165 491 167 491 168 491 169 490 169 490 171 489 174 487 177 486 180 485 182 484 184 484 185 483 185 483 186 482 188 481 190 479 193 478 197 477 199 476 202 475 204 474 206 473 208 472 209 472 210 474 210 476 209 479 209 483 209 488 208 492 207 496 207 499 206 502 206 503 206 504 205 504 204 505 201 506 198 507 193 509 188 510 183 512 179 513 176 514 173 514 172 514 171 514 170 515 169 515 167 516 165 516 162 517 160 518 157 518 154 519 150 520 146 521 142 521 137 522 133 523 129 523 126 523 124 523 122 524 122 524 121 524 120 524 118 524 116 524 113 524 109 524 105 525 101 525 97 525 94 525 92 525 91 525 90 525 89 525 88 525 87 524 85 524 82 524 78 523 74 523 70 522 66 522 62 521 59 521 56 520 54 519 51 519 49 518 47 518 46 518 45 518 44 517 44 -joinstyle bevel}
{polygon 11 126 12 126 13 126 16 126 19 126 23 126 27 126 32 126 36 126 39 126 41 126 43 126 45 126 47 126 50 127 51 127 52 127 53 128 54 128 56 129 57 130 58 132 59 132 59 133 60 134 61 135 61 137 62 138 62 139 62 140 62 142 62 144 62 145 62 147 62 148 62 149 62 150 61 152 61 154 61 155 61 156 60 157 60 158 59 159 58 161 57 162 57 163 56 164 55 165 54 166 53 167 51 168 49 169 48 169 47 170 46 170 47 171 49 171 51 172 52 172 53 173 54 174 55 175 56 177 56 178 57 180 57 181 57 182 57 183 57 184 57 185 57 187 57 189 57 190 57 191 56 192 56 194 56 196 56 199 56 200 56 201 56 202 55 203 55 205 55 206 55 207 55 208 55 209 56 209 56 210 56 211 57 212 58 212 58 213 57 213 56 213 55 213 51 213 47 213 43 213 40 213 38 213 37 213 37 212 37 211 36 210 36 209 36 208 36 207 36 206 36 205 37 204 37 203 37 202 37 201 37 199 37 198 37 197 37 196 37 195 37 194 38 192 38 189 38 188 38 187 38 186 38 185 38 184 38 182 37 181 37 180 37 179 36 179 36 178 35 178 34 177 33 177 32 177 31 177 30 177 28 177 26 177 24 177 24 178 24 179 24 182 23 186 23 190 22 195 22 200 21 205 21 208 20 211 20 213 19 213 17 213 14 213 10 213 7 213 4 213 2 213 1 213 1 212 1 211 2 208 2 205 2 201 3 196 4 190 4 184 5 177 6 169 7 162 8 155 9 149 9 143 10 138 10 134 11 131 11 129 11 127 11 126 -outline {} -fill \#000000 -width 0}
{polygon 26 163 27 163 29 163 31 163 32 163 33 162 35 162 36 162 37 161 38 161 39 160 40 159 40 158 41 157 42 156 42 154 43 153 43 152 43 151 43 150 43 149 43 148 43 147 43 146 42 145 42 144 42 143 41 143 41 142 40 142 40 141 39 141 38 141 37 141 36 140 35 140 34 140 33 140 31 140 30 140 29 140 28 141 28 142 28 145 28 148 27 151 27 155 26 158 26 161 26 162 26 163 -outline {} -fill \#000000 -width 0}
{line 11 126 12 126 13 126 16 126 19 126 23 126 27 126 32 126 36 126 39 126 41 126 43 126 45 126 47 126 50 127 51 127 52 127 53 128 54 128 56 129 57 130 58 132 59 132 59 133 60 134 61 135 61 137 62 138 62 139 62 140 62 142 62 144 62 145 62 147 62 148 62 149 62 150 61 152 61 154 61 155 61 156 60 157 60 158 59 159 58 161 57 162 57 163 56 164 55 165 54 166 53 167 51 168 49 169 48 169 47 170 46 170 47 171 49 171 51 172 52 172 53 173 54 174 55 175 56 177 56 178 57 180 57 181 57 182 57 183 57 184 57 185 57 187 57 189 57 190 57 191 56 192 56 194 56 196 56 199 56 200 56 201 56 202 55 203 55 205 55 206 55 207 55 208 55 209 56 209 56 210 56 211 57 212 58 212 58 213 57 213 56 213 55 213 51 213 47 213 43 213 40 213 38 213 37 213 37 212 37 211 36 210 36 209 36 208 36 207 36 206 36 205 37 204 37 203 37 202 37 201 37 199 37 198 37 197 37 196 37 195 37 194 38 192 38 189 38 188 38 187 38 186 38 185 38 184 38 182 37 181 37 180 37 179 36 179 36 178 35 178 34 177 33 177 32 177 31 177 30 177 28 177 26 177 24 177 24 178 24 179 24 182 23 186 23 190 22 195 22 200 21 205 21 208 20 211 20 213 19 213 17 213 14 213 10 213 7 213 4 213 2 213 1 213 1 212 1 211 2 208 2 205 2 201 3 196 4 190 4 184 5 177 6 169 7 162 8 155 9 149 9 143 10 138 10 134 11 131 11 129 11 127 11 126 -joinstyle bevel}
{polygon 26 163 27 163 29 163 31 163 32 163 33 162 35 162 36 162 37 161 38 161 39 160 40 159 40 158 41 157 42 156 42 154 43 153 43 152 43 151 43 150 43 149 43 148 43 147 43 146 42 145 42 144 42 143 41 143 41 142 40 142 40 141 39 141 38 141 37 141 36 140 35 140 34 140 33 140 31 140 30 140 29 140 28 141 28 142 28 145 28 148 27 151 27 155 26 158 26 161 26 162 26 163 -outline {} -fill $bg -width 0}
{polygon 90 215 89 215 86 214 84 214 81 213 79 213 78 213 77 213 77 212 75 212 74 211 72 209 70 207 69 205 68 204 68 203 68 202 67 202 67 200 66 198 66 195 66 193 66 192 66 191 66 190 66 188 66 185 66 182 66 180 66 177 66 175 66 174 67 172 67 171 67 170 67 169 67 167 68 165 68 162 68 159 69 156 69 155 69 154 70 152 70 151 70 149 71 147 72 144 73 142 74 139 75 138 75 137 76 136 76 135 77 134 79 132 81 130 82 129 83 129 83 128 84 128 85 127 88 126 91 125 93 125 95 124 97 124 99 124 100 124 101 124 102 124 104 125 107 125 110 126 112 126 113 126 114 127 115 127 116 128 117 129 118 130 120 131 121 133 122 135 123 136 123 137 123 138 123 139 124 141 124 143 125 146 125 148 125 149 125 150 125 152 125 156 125 159 124 162 124 164 124 166 124 168 124 169 123 169 123 170 123 171 123 173 122 177 122 180 122 182 121 183 121 184 121 185 121 187 120 189 120 191 119 193 118 196 117 199 116 200 116 201 116 202 115 203 114 204 112 206 111 208 109 209 109 210 108 210 107 211 106 211 103 213 100 213 98 214 96 214 94 215 92 215 91 215 90 215 -outline {} -fill \#000000 -width 0}
{polygon 91 201 92 201 94 200 95 200 96 200 96 199 97 198 98 197 99 196 99 195 100 194 100 193 100 191 101 189 101 188 101 187 102 185 102 182 103 179 103 177 103 175 103 173 104 171 104 170 104 169 104 168 104 166 104 163 105 160 105 158 105 157 105 156 105 154 105 153 106 150 106 148 105 146 105 145 105 144 105 143 105 142 104 141 104 140 103 139 101 138 100 138 99 138 98 138 96 138 95 139 94 139 94 140 93 141 92 142 91 143 91 144 91 145 91 146 90 148 89 150 89 151 89 152 89 154 88 157 88 160 87 162 87 164 87 166 87 168 86 169 86 170 86 171 86 173 86 176 85 179 85 181 85 182 85 183 85 185 85 186 85 189 85 191 85 193 85 194 85 195 85 196 86 197 86 198 86 199 87 199 88 200 89 201 90 201 91 201 -outline {} -fill $bg -width 0}
{line 90 215 89 215 86 214 84 214 81 213 79 213 78 213 77 213 77 212 75 212 74 211 72 209 70 207 69 205 68 204 68 203 68 202 67 202 67 200 66 198 66 195 66 193 66 192 66 191 66 190 66 188 66 185 66 182 66 180 66 177 66 175 66 174 67 172 67 171 67 170 67 169 67 167 68 165 68 162 68 159 69 156 69 155 69 154 70 152 70 151 70 149 71 147 72 144 73 142 74 139 75 138 75 137 76 136 76 135 77 134 79 132 81 130 82 129 83 129 83 128 84 128 85 127 88 126 91 125 93 125 95 124 97 124 99 124 100 124 101 124 102 124 104 125 107 125 110 126 112 126 113 126 114 127 115 127 116 128 117 129 118 130 120 131 121 133 122 135 123 136 123 137 123 138 123 139 124 141 124 143 125 146 125 148 125 149 125 150 125 152 125 156 125 159 124 162 124 164 124 166 124 168 124 169 123 169 123 170 123 171 123 173 122 177 122 180 122 182 121 183 121 184 121 185 121 187 120 189 120 191 119 193 118 196 117 199 116 200 116 201 116 202 115 203 114 204 112 206 111 208 109 209 109 210 108 210 107 211 106 211 103 213 100 213 98 214 96 214 94 215 92 215 91 215 90 215 -joinstyle bevel}
{polygon 149 126 173 126 182 213 163 213 162 197 142 197 138 213 118 213 -outline {} -fill \#000000 -width 0}
{polygon 158 142 147 181 161 181 -outline {} -fill \#000000 -width 0}
{line 149 126 173 126 182 213 163 213 162 197 142 197 138 213 118 213 149 126}
{polygon 158 142 147 181 161 181 -outline {} -fill $bg -width 0}
{polygon 196 126 197 126 198 126 201 126 204 126 208 126 212 126 217 126 221 126 224 126 226 126 228 126 230 126 232 126 235 127 236 127 237 127 238 128 239 128 241 129 242 130 244 132 244 133 245 133 245 134 246 135 246 137 247 138 247 139 247 140 247 142 247 144 247 145 247 147 247 148 247 149 247 150 246 152 246 154 246 155 246 156 245 157 245 158 244 159 244 161 242 162 242 163 241 164 240 165 239 166 238 167 236 168 235 169 233 169 232 169 232 170 231 170 232 171 234 171 236 172 237 172 238 172 238 173 239 174 240 175 241 177 241 178 242 180 242 181 242 182 242 183 242 184 242 185 242 187 242 189 242 190 242 191 241 192 241 194 241 196 241 199 241 200 241 201 241 202 241 203 240 205 240 206 240 207 240 208 241 208 241 209 241 210 241 211 242 212 243 212 243 213 242 213 240 213 236 213 232 213 228 213 225 213 223 213 222 213 222 212 222 211 221 210 221 209 221 208 221 207 221 206 221 205 221 204 221 203 221 202 222 201 222 199 222 198 222 197 222 196 222 195 222 194 223 192 223 189 223 188 223 187 223 186 223 185 223 184 223 182 222 181 222 180 222 179 221 178 220 178 218 177 217 177 216 177 215 177 213 177 211 177 209 177 209 178 209 179 209 182 208 186 208 190 207 195 206 200 206 205 206 208 205 211 205 213 204 213 202 213 199 213 196 213 192 213 189 213 187 213 186 213 186 212 186 211 187 208 187 205 188 201 188 196 189 190 190 184 190 177 191 169 192 162 193 155 194 149 194 143 195 138 196 134 196 131 196 129 196 127 196 126 -outline {} -fill \#000000 -width 0}
{polygon 211 163 212 163 214 163 216 163 217 163 218 162 220 162 221 162 222 161 223 161 224 160 225 159 225 158 226 157 227 157 227 156 227 154 228 153 228 152 228 151 228 150 228 149 228 148 228 147 228 146 227 145 227 144 227 143 226 142 225 142 225 141 224 141 223 141 222 141 221 140 220 140 219 140 218 140 217 140 215 140 214 140 214 141 213 142 213 145 213 148 212 151 212 155 212 158 211 161 211 162 211 163 -outline {} -fill \#000000 -width 0}
{line 196 126 197 126 198 126 201 126 204 126 208 126 212 126 217 126 221 126 224 126 226 126 228 126 230 126 232 126 235 127 236 127 237 127 238 128 239 128 241 129 242 130 244 132 244 133 245 133 245 134 246 135 246 137 247 138 247 139 247 140 247 142 247 144 247 145 247 147 247 148 247 149 247 150 246 152 246 154 246 155 246 156 245 157 245 158 244 159 244 161 242 162 242 163 241 164 240 165 239 166 238 167 236 168 235 169 233 169 232 169 232 170 231 170 232 171 234 171 236 172 237 172 238 172 238 173 239 174 240 175 241 177 241 178 242 180 242 181 242 182 242 183 242 184 242 185 242 187 242 189 242 190 242 191 241 192 241 194 241 196 241 199 241 200 241 201 241 202 241 203 240 205 240 206 240 207 240 208 241 208 241 209 241 210 241 211 242 212 243 212 243 213 242 213 240 213 236 213 232 213 228 213 225 213 223 213 222 213 222 212 222 211 221 210 221 209 221 208 221 207 221 206 221 205 221 204 221 203 221 202 222 201 222 199 222 198 222 197 222 196 222 195 222 194 223 192 223 189 223 188 223 187 223 186 223 185 223 184 223 182 222 181 222 180 222 179 221 178 220 178 218 177 217 177 216 177 215 177 213 177 211 177 209 177 209 178 209 179 209 182 208 186 208 190 207 195 206 200 206 205 206 208 205 211 205 213 204 213 202 213 199 213 196 213 192 213 189 213 187 213 186 213 186 212 186 211 187 208 187 205 188 201 188 196 189 190 190 184 190 177 191 169 192 162 193 155 194 149 194 143 195 138 196 134 196 131 196 129 196 127 196 126 -joinstyle bevel}
{polygon 211 163 212 163 214 163 216 163 217 163 218 162 220 162 221 162 222 161 223 161 224 160 225 159 225 158 226 157 227 157 227 156 227 154 228 153 228 152 228 151 228 150 228 149 228 148 228 147 228 146 227 145 227 144 227 143 226 142 225 142 225 141 224 141 223 141 222 141 221 140 220 140 219 140 218 140 217 140 215 140 214 140 214 141 213 142 213 145 213 148 212 151 212 155 212 158 211 161 211 162 211 163 -outline {} -fill $bg -width 0}
{polygon 259 126 278 126 268 213 249 213 -outline {} -fill \#000000 -width 0}
{line 259 126 278 126 268 213 249 213 259 126}
{polygon 288 126 310 126 319 183 326 126 343 126 333 213 311 213 302 153 295 213 278 213 -outline {} -fill \#000000 -width 0}
{line 288 126 310 126 319 183 326 126 343 126 333 213 311 213 302 153 295 213 278 213 288 126}
{polygon 383 152 384 151 384 150 384 149 384 148 384 147 384 146 384 145 384 144 383 143 383 142 383 141 382 140 382 139 381 139 380 138 379 138 378 138 377 138 376 138 375 139 374 139 373 139 373 140 372 141 371 142 370 144 370 145 369 145 369 146 368 148 368 151 368 152 368 153 367 154 367 157 366 160 366 162 366 164 366 166 365 168 365 169 365 170 365 171 365 173 365 176 364 179 364 181 364 182 364 183 364 185 364 186 364 189 364 191 364 193 364 194 364 195 364 196 364 197 365 198 365 199 366 199 366 200 368 201 369 201 370 201 371 201 373 201 373 200 374 200 375 200 375 199 376 198 377 197 377 196 378 196 378 195 379 193 379 192 379 191 380 189 380 187 380 186 381 185 381 184 381 183 381 182 381 181 381 180 380 180 377 180 374 180 373 180 372 180 373 179 373 176 373 173 374 170 374 168 374 166 375 166 376 166 379 166 383 166 387 166 392 166 395 166 398 166 400 166 401 166 401 167 400 168 400 171 400 174 399 179 398 184 398 190 397 196 397 201 396 205 395 209 395 211 395 213 394 213 392 213 389 213 385 213 383 213 382 213 382 212 382 209 382 207 383 205 382 205 381 206 380 208 380 209 379 209 378 210 377 211 376 212 375 213 374 213 372 214 371 214 370 214 368 215 367 215 365 215 364 215 363 215 361 214 359 214 356 213 355 213 354 213 353 213 352 212 351 211 349 209 348 207 346 205 346 204 346 203 345 201 345 198 344 196 344 194 344 193 344 192 344 190 344 186 344 184 344 181 345 179 345 177 345 175 345 174 345 172 345 171 346 171 346 169 346 166 347 163 347 160 347 158 347 156 348 156 348 155 348 153 348 152 349 150 349 148 350 145 351 142 352 140 353 138 353 137 354 137 354 136 355 134 357 132 359 131 360 130 361 129 362 128 364 127 366 126 369 125 371 125 374 124 376 124 378 124 379 124 380 124 381 124 383 125 386 125 388 125 390 126 391 126 392 126 392 127 394 127 395 128 397 129 398 131 400 133 400 134 400 135 401 136 401 138 402 140 402 141 402 142 402 143 402 146 402 148 402 150 402 151 402 152 401 152 399 152 396 152 393 152 389 152 386 152 384 152 -outline {} -fill \#000000 -width 0}
{line 383 152 384 151 384 150 384 149 384 148 384 147 384 146 384 145 384 144 383 143 383 142 383 141 382 140 382 139 381 139 380 138 379 138 378 138 377 138 376 138 375 139 374 139 373 139 373 140 372 141 371 142 370 144 370 145 369 145 369 146 368 148 368 151 368 152 368 153 367 154 367 157 366 160 366 162 366 164 366 166 365 168 365 169 365 170 365 171 365 173 365 176 364 179 364 181 364 182 364 183 364 185 364 186 364 189 364 191 364 193 364 194 364 195 364 196 364 197 365 198 365 199 366 199 366 200 368 201 369 201 370 201 371 201 373 201 373 200 374 200 375 200 375 199 376 198 377 197 377 196 378 196 378 195 379 193 379 192 379 191 380 189 380 187 380 186 381 185 381 184 381 183 381 182 381 181 381 180 380 180 377 180 374 180 373 180 372 180 373 179 373 176 373 173 374 170 374 168 374 166 375 166 376 166 379 166 383 166 387 166 392 166 395 166 398 166 400 166 401 166 401 167 400 168 400 171 400 174 399 179 398 184 398 190 397 196 397 201 396 205 395 209 395 211 395 213 394 213 392 213 389 213 385 213 383 213 382 213 382 212 382 209 382 207 383 205 382 205 381 206 380 208 380 209 379 209 378 210 377 211 376 212 375 213 374 213 372 214 371 214 370 214 368 215 367 215 365 215 364 215 363 215 361 214 359 214 356 213 355 213 354 213 353 213 352 212 351 211 349 209 348 207 346 205 346 204 346 203 345 201 345 198 344 196 344 194 344 193 344 192 344 190 344 186 344 184 344 181 345 179 345 177 345 175 345 174 345 172 345 171 346 171 346 169 346 166 347 163 347 160 347 158 347 156 348 156 348 155 348 153 348 152 349 150 349 148 350 145 351 142 352 140 353 138 353 137 354 137 354 136 355 134 357 132 359 131 360 130 361 129 362 128 364 127 366 126 369 125 371 125 374 124 376 124 378 124 379 124 380 124 381 124 383 125 386 125 388 125 390 126 391 126 392 126 392 127 394 127 395 128 397 129 398 131 400 133 400 134 400 135 401 136 401 138 402 140 402 141 402 142 402 143 402 146 402 148 402 150 402 151 402 152 401 152 399 152 396 152 393 152 389 152 386 152 384 152 383 152 -joinstyle bevel}
{polygon 118 229 119 229 121 229 124 229 128 229 133 229 137 229 142 229 145 229 146 229 147 229 148 229 150 229 152 230 155 230 156 230 157 231 158 231 159 231 160 232 162 233 163 235 165 236 165 237 166 237 166 238 166 239 167 241 167 243 168 243 168 244 168 245 168 247 168 249 168 251 168 252 168 253 168 254 167 255 167 258 166 261 166 262 166 263 165 264 165 265 164 267 162 269 161 271 160 272 159 273 157 274 155 275 154 276 153 276 153 277 152 277 149 278 147 278 145 279 143 279 142 279 140 279 139 279 137 279 135 279 132 279 131 279 130 280 130 281 130 283 130 286 129 291 128 295 128 300 127 304 127 307 127 309 127 310 127 311 126 311 124 311 121 311 117 311 113 311 110 311 109 311 108 311 108 310 108 308 108 305 109 301 109 297 110 291 111 284 112 277 113 270 114 263 115 255 115 249 116 243 117 238 117 235 118 232 118 230 118 229 -outline {} -fill \#1892ff -width 0}
{polygon 132 265 133 265 134 265 136 265 137 265 138 265 139 265 140 264 141 264 142 264 143 264 143 263 144 263 145 262 146 262 146 261 146 260 147 259 148 258 148 256 148 255 148 254 148 253 148 252 148 251 148 250 148 249 148 248 147 247 147 246 146 245 145 244 144 244 143 243 142 243 141 243 140 243 138 243 137 243 135 243 135 244 135 245 134 247 134 250 134 254 133 257 133 261 133 263 133 264 132 265 -outline {} -fill \#1892ff -width 0}
{line 118 229 119 229 121 229 124 229 128 229 133 229 137 229 142 229 145 229 146 229 147 229 148 229 150 229 152 230 155 230 156 230 157 231 158 231 159 231 160 232 162 233 163 235 165 236 165 237 166 237 166 238 166 239 167 241 167 243 168 243 168 244 168 245 168 247 168 249 168 251 168 252 168 253 168 254 167 255 167 258 166 261 166 262 166 263 165 264 165 265 164 267 162 269 161 271 160 272 159 273 157 274 155 275 154 276 153 276 153 277 152 277 149 278 147 278 145 279 143 279 142 279 140 279 139 279 137 279 135 279 132 279 131 279 130 280 130 281 130 283 130 286 129 291 128 295 128 300 127 304 127 307 127 309 127 310 127 311 126 311 124 311 121 311 117 311 113 311 110 311 109 311 108 311 108 310 108 308 108 305 109 301 109 297 110 291 111 284 112 277 113 270 114 263 115 255 115 249 116 243 117 238 117 235 118 232 118 230 118 229 -joinstyle bevel -fill \#1892ff}
{polygon 176 229 223 229 221 244 193 244 191 261 217 261 215 277 189 277 187 295 215 295 214 311 166 311 -outline {} -fill \#1892ff -width 0}
{line 176 229 223 229 221 244 193 244 191 261 217 261 215 277 189 277 187 295 215 295 214 311 166 311 176 229 -fill \#1892ff}
{polygon 232 229 254 229 263 282 270 229 288 229 277 311 256 311 246 254 239 311 222 311 -outline {} -fill \#1892ff -width 0}
{line 232 229 254 229 263 282 270 229 288 229 277 311 256 311 246 254 239 311 222 311 232 229 -fill \#1892ff}
{polygon 328 254 328 253 328 251 328 250 328 249 328 248 328 247 328 246 328 245 328 244 327 243 327 242 326 242 325 241 324 241 323 240 322 240 321 240 319 241 318 241 317 242 316 243 315 244 314 246 314 247 314 248 313 250 312 252 312 253 312 254 312 256 311 259 311 261 311 263 310 265 310 267 310 268 310 270 310 271 309 273 309 276 309 279 308 281 308 282 308 283 308 284 308 286 308 288 308 290 308 292 308 293 308 294 309 296 309 297 310 298 311 299 312 300 313 300 314 300 315 300 316 300 317 299 318 299 319 299 319 298 320 298 321 297 322 296 322 295 323 293 323 292 324 291 324 289 325 287 325 285 325 284 325 283 325 282 326 282 326 281 326 280 325 280 324 280 321 280 319 280 317 280 317 279 317 276 318 273 318 270 318 268 319 267 321 267 324 267 327 267 332 267 336 267 340 267 343 267 344 267 345 267 345 268 345 269 344 271 344 274 343 279 343 284 342 289 341 294 341 300 340 304 340 307 340 309 339 310 339 311 338 311 336 311 333 311 330 311 328 311 327 311 326 311 327 310 327 307 327 305 327 304 327 303 326 304 325 306 324 307 324 308 323 308 322 309 321 310 320 311 319 311 318 311 317 312 316 312 315 312 314 312 313 312 311 313 310 313 309 313 308 313 307 313 306 312 303 312 301 311 299 311 298 311 298 310 296 310 295 309 294 308 292 306 291 304 290 302 290 301 290 300 289 297 289 295 289 293 289 292 289 291 289 289 289 286 289 283 289 280 289 278 289 275 290 274 290 273 290 272 290 271 290 270 291 267 291 264 291 261 292 259 292 258 292 257 292 256 292 255 293 253 293 252 294 249 295 247 296 244 297 242 298 240 298 239 299 238 300 237 301 235 303 234 304 232 305 232 306 231 308 230 311 229 313 228 316 228 318 227 320 227 322 227 323 227 324 227 325 227 327 228 330 228 333 229 335 229 336 229 337 229 338 230 340 231 341 232 343 234 344 236 345 237 345 238 346 240 346 242 347 244 347 246 347 247 347 250 347 251 346 252 346 253 346 254 345 254 343 254 341 254 337 254 334 254 331 254 329 254 328 254 -outline {} -fill \#1892ff -width 0}
{line 328 254 328 253 328 251 328 250 328 249 328 248 328 247 328 246 328 245 328 244 327 243 327 242 326 242 325 241 324 241 323 240 322 240 321 240 319 241 318 241 317 242 316 243 315 244 314 246 314 247 314 248 313 250 312 252 312 253 312 254 312 256 311 259 311 261 311 263 310 265 310 267 310 268 310 270 310 271 309 273 309 276 309 279 308 281 308 282 308 283 308 284 308 286 308 288 308 290 308 292 308 293 308 294 309 296 309 297 310 298 311 299 312 300 313 300 314 300 315 300 316 300 317 299 318 299 319 299 319 298 320 298 321 297 322 296 322 295 323 293 323 292 324 291 324 289 325 287 325 285 325 284 325 283 325 282 326 282 326 281 326 280 325 280 324 280 321 280 319 280 317 280 317 279 317 276 318 273 318 270 318 268 319 267 321 267 324 267 327 267 332 267 336 267 340 267 343 267 344 267 345 267 345 268 345 269 344 271 344 274 343 279 343 284 342 289 341 294 341 300 340 304 340 307 340 309 339 310 339 311 338 311 336 311 333 311 330 311 328 311 327 311 326 311 327 310 327 307 327 305 327 304 327 303 326 304 325 306 324 307 324 308 323 308 322 309 321 310 320 311 319 311 318 311 317 312 316 312 315 312 314 312 313 312 311 313 310 313 309 313 308 313 307 313 306 312 303 312 301 311 299 311 298 311 298 310 296 310 295 309 294 308 292 306 291 304 290 302 290 301 290 300 289 297 289 295 289 293 289 292 289 291 289 289 289 286 289 283 289 280 289 278 289 275 290 274 290 273 290 272 290 271 290 270 291 267 291 264 291 261 292 259 292 258 292 257 292 256 292 255 293 253 293 252 294 249 295 247 296 244 297 242 298 240 298 239 299 238 300 237 301 235 303 234 304 232 305 232 306 231 308 230 311 229 313 228 316 228 318 227 320 227 322 227 323 227 324 227 325 227 327 228 330 228 333 229 335 229 336 229 337 229 338 230 340 231 341 232 343 234 344 236 345 237 345 238 346 240 346 242 347 244 347 246 347 247 347 250 347 251 346 252 346 253 346 254 345 254 343 254 341 254 337 254 334 254 331 254 329 254 328 254 -joinstyle bevel -fill \#1892ff}
{polygon 405 284 404 286 404 289 403 291 403 293 403 294 402 295 402 297 401 299 400 301 398 303 397 304 397 305 396 306 394 307 392 309 391 309 391 310 390 310 389 310 386 311 384 312 381 312 380 312 378 313 376 313 375 313 374 313 372 312 369 312 367 312 365 311 364 311 363 311 362 310 360 310 358 309 356 307 355 306 354 305 354 304 353 303 353 301 352 299 352 298 352 297 351 295 351 293 351 290 351 288 352 286 352 285 352 284 352 283 352 282 352 280 353 277 353 273 354 268 355 262 355 256 356 250 357 245 357 240 358 236 358 233 359 231 359 229 360 229 362 229 365 229 368 229 372 229 375 229 377 229 378 229 377 230 377 232 377 234 376 238 376 242 375 247 375 253 374 259 373 265 372 271 372 276 371 280 371 284 370 287 370 288 370 289 370 290 370 291 370 292 370 293 370 294 370 295 370 296 371 297 372 298 372 299 373 299 374 299 374 300 375 300 376 300 377 300 378 300 379 299 380 299 381 299 381 298 382 297 383 297 383 296 383 295 384 295 384 294 384 293 385 292 385 291 385 290 385 289 385 288 386 287 386 284 386 280 387 276 388 271 388 265 389 259 390 253 390 247 391 242 392 238 392 234 392 232 393 230 393 229 394 229 396 229 399 229 402 229 406 229 409 229 411 229 412 229 412 231 411 233 411 236 410 240 410 245 409 250 408 256 407 262 407 268 406 273 406 277 405 280 405 282 405 283 -outline {} -fill \#1892ff -width 0}
{line 405 284 404 286 404 289 403 291 403 293 403 294 402 295 402 297 401 299 400 301 398 303 397 304 397 305 396 306 394 307 392 309 391 309 391 310 390 310 389 310 386 311 384 312 381 312 380 312 378 313 376 313 375 313 374 313 372 312 369 312 367 312 365 311 364 311 363 311 362 310 360 310 358 309 356 307 355 306 354 305 354 304 353 303 353 301 352 299 352 298 352 297 351 295 351 293 351 290 351 288 352 286 352 285 352 284 352 283 352 282 352 280 353 277 353 273 354 268 355 262 355 256 356 250 357 245 357 240 358 236 358 233 359 231 359 229 360 229 362 229 365 229 368 229 372 229 375 229 377 229 378 229 377 230 377 232 377 234 376 238 376 242 375 247 375 253 374 259 373 265 372 271 372 276 371 280 371 284 370 287 370 288 370 289 370 290 370 291 370 292 370 293 370 294 370 295 370 296 371 297 372 298 372 299 373 299 374 299 374 300 375 300 376 300 377 300 378 300 379 299 380 299 381 299 381 298 382 297 383 297 383 296 383 295 384 295 384 294 384 293 385 292 385 291 385 290 385 289 385 288 386 287 386 284 386 280 387 276 388 271 388 265 389 259 390 253 390 247 391 242 392 238 392 234 392 232 393 230 393 229 394 229 396 229 399 229 402 229 406 229 409 229 411 229 412 229 412 231 411 233 411 236 410 240 410 245 409 250 408 256 407 262 407 268 406 273 406 277 405 280 405 282 405 283 405 284 -joinstyle bevel -fill \#1892ff}
{polygon 421 229 439 229 429 311 410 311 -outline {} -fill \#1892ff -width 0}
{line 421 229 439 229 429 311 410 311 421 229 -fill \#1892ff}
{polygon 449 229 471 229 480 282 487 229 504 229 494 311 473 311 463 254 456 311 439 311 -outline {} -fill \#1892ff -width 0}
{line 449 229 471 229 480 282 487 229 504 229 494 311 473 311 463 254 456 311 439 311 449 229 -fill \#1892ff}
{polygon 114 354 114 355 114 356 114 357 114 358 114 359 115 359 115 360 116 360 117 360 118 360 119 359 119 358 120 358 120 357 120 356 119 355 119 354 118 353 117 352 116 352 115 351 114 350 113 350 112 349 110 348 109 347 109 346 108 345 108 343 107 342 107 341 107 340 107 339 107 338 108 337 108 336 108 335 109 334 109 333 110 333 110 332 111 331 112 331 113 331 114 330 115 330 116 330 117 330 118 330 119 330 120 330 121 331 122 331 123 332 124 332 124 333 125 334 125 335 125 336 126 336 126 337 126 338 126 339 126 340 125 340 123 340 121 340 119 340 119 339 119 338 119 337 119 336 118 336 118 335 117 335 116 335 116 336 115 336 115 337 114 337 114 338 114 339 115 340 115 341 115 342 116 343 117 343 118 344 120 345 121 345 122 346 123 347 124 347 124 348 125 349 126 351 126 352 126 353 126 354 126 355 126 356 126 358 126 359 126 360 125 361 125 362 124 363 123 364 122 364 122 365 121 365 120 365 119 366 118 366 117 366 116 366 115 366 114 365 113 365 112 365 111 364 110 364 109 363 108 362 108 361 108 360 107 359 107 358 107 357 107 356 107 355 107 354 108 354 110 354 112 354 113 354 -outline {} -fill \#000000 -width 0}
{polygon 152 366 151 365 149 365 148 365 147 364 146 364 145 363 144 361 143 360 143 359 143 357 142 357 142 356 142 354 142 352 142 351 142 349 142 348 142 347 142 345 142 343 142 342 142 341 142 340 143 339 143 337 143 336 144 335 144 334 145 333 146 332 146 331 148 331 149 330 150 330 151 330 152 330 154 330 155 331 157 331 158 332 159 333 160 334 161 335 161 336 161 337 162 339 162 340 162 341 162 342 162 344 162 345 162 346 162 347 162 348 162 349 162 351 162 352 162 353 162 354 162 355 162 357 161 358 161 360 161 361 160 362 159 363 159 364 158 364 157 365 155 365 154 366 153 366 152 366 -outline {} -fill \#000000 -width 0}
{polygon 152 360 153 360 154 360 154 359 155 358 155 357 155 356 155 355 155 354 155 353 155 351 155 350 155 349 155 348 155 346 155 344 155 343 155 342 155 341 155 339 155 338 154 337 154 336 153 336 153 335 152 335 152 336 151 336 150 336 150 337 150 338 149 338 149 339 149 340 149 341 149 342 149 343 149 345 149 346 149 347 149 348 149 349 149 351 149 352 149 353 149 354 149 355 149 356 149 357 149 358 150 358 150 359 151 360 152 360 -outline {} -fill $bg -width 0}
{polygon 179 331 195 331 195 337 185 337 185 344 195 344 195 351 185 351 185 365 179 365 -outline {} -fill \#000000 -width 0}
{polygon 215 337 209 337 209 331 228 331 228 337 222 337 222 365 215 365 -outline {} -fill \#000000 -width 0}
{polygon 241 331 248 331 251 355 254 331 260 331 263 355 266 331 272 331 267 365 260 365 257 341 254 365 247 365 -outline {} -fill \#000000 -width 0}
{polygon 293 331 301 331 308 365 302 365 301 358 294 358 293 365 286 365 -outline {} -fill \#000000 -width 0}
{polygon 297 337 295 352 299 352 -outline {} -fill $bg -width 0}
{polygon 324 331 325 331 327 331 329 331 332 331 334 331 335 331 336 331 337 331 338 331 339 332 340 332 340 333 341 333 341 334 342 334 342 335 342 336 343 337 343 338 343 339 343 340 343 341 343 342 343 343 342 343 342 344 342 345 341 345 341 346 340 347 339 348 338 348 339 349 340 349 341 349 341 350 342 351 342 352 342 353 342 354 342 355 343 356 343 357 343 358 343 359 343 360 343 361 343 362 343 363 343 364 344 364 344 365 342 365 340 365 338 365 337 365 336 365 336 364 336 363 336 362 336 361 336 360 336 359 336 358 336 357 336 356 336 355 336 354 335 353 335 352 335 351 334 351 333 351 332 351 331 351 330 351 330 352 330 355 330 358 330 361 330 364 330 365 329 365 327 365 325 365 324 365 324 364 324 363 324 360 324 357 324 353 324 348 324 343 324 339 324 335 324 333 324 331 -outline {} -fill \#000000 -width 0}
{polygon 330 345 331 345 332 345 333 345 334 345 335 345 335 344 335 343 336 343 336 342 336 341 336 340 336 339 335 338 335 337 334 337 333 336 332 336 331 336 330 336 330 337 330 338 330 341 330 343 330 345 -outline {} -fill $bg -width 0}
{polygon 360 331 376 331 376 337 367 337 367 344 376 344 376 351 367 351 367 358 377 358 377 365 360 365 -outline {} -fill \#000000 -width 0}
{polygon 416 331 423 331 423 365 416 365 -outline {} -fill \#000000 -width 0}
{polygon 440 331 448 331 454 353 454 331 460 331 460 365 452 365 446 341 446 365 440 365 -outline {} -fill \#000000 -width 0}
{polygon 485 343 485 342 485 341 485 340 485 339 485 338 485 337 484 337 484 336 483 336 483 335 482 335 482 336 481 336 480 337 480 338 480 339 480 340 480 341 479 341 479 343 479 344 479 346 479 347 479 348 479 349 479 351 479 352 479 353 480 354 480 355 480 356 480 357 480 358 480 359 481 359 481 360 482 360 483 360 484 360 484 359 485 359 485 358 485 357 485 356 485 355 485 354 485 353 485 352 487 352 489 352 491 352 492 352 492 353 492 354 492 356 492 357 491 357 491 358 491 359 491 360 490 361 490 362 490 363 489 363 488 364 487 364 486 365 485 365 484 366 482 366 480 365 479 365 478 365 477 365 477 364 476 364 476 363 475 362 474 361 474 360 473 358 473 357 473 356 473 355 473 353 472 352 472 350 472 349 472 348 472 347 472 346 473 344 473 343 473 342 473 341 473 339 473 338 474 336 474 335 475 334 476 333 476 332 478 331 479 330 481 330 482 330 483 330 485 330 486 330 486 331 487 331 488 332 489 332 489 333 490 333 490 334 491 335 491 336 491 337 491 338 492 340 492 341 492 342 492 343 491 343 490 343 488 343 486 343 485 343 -outline {} -fill \#000000 -width 0}
{polygon 500 356 506 356 506 365 500 365 -outline {} -fill \#000000 -width 0}
{polygon 132 265 133 265 134 265 136 265 137 265 138 265 139 265 140 264 141 264 142 264 143 264 143 263 144 263 145 262 146 262 146 261 146 260 147 259 148 258 148 256 148 255 148 254 148 253 148 252 148 251 148 250 148 249 148 248 147 247 147 246 146 245 145 244 144 244 143 243 142 243 141 243 140 243 138 243 137 243 135 243 135 244 135 245 134 247 134 250 134 254 133 257 133 261 133 263 133 264 132 265 -outline {} -fill $bg -width 0}
}
foreach obj $logo_objs {
eval $c create $obj -tags logo
}
}
#***********************************************************************
# %PROCEDURE: doLogo
# %ARGUMENTS:
# None
# %RETURNS:
# Nothing
# %DESCRIPTION:
# Does the logo thing
#***********************************************************************
proc doLogo {} {
canvas .c -width 600 -height 400 -bg #FFFFFF
pack .c
drawLogo .c #FFFFFF
# Funky effect
.c create text 4 4 -anchor nw -text "Welcome to Remind" \
-fill red -font {-family times -size -24 -weight bold} -tags remind
.c lower remind
.c move logo -300 20
update idletasks
for {set i 0} {$i < 16} {incr i} {
.c move logo 20 0
update idletasks
after 30
}
.c create text 4 28 -anchor nw -text "http://www.roaringpenguin.com" \
-fill red -font {-family courier -size -14 -weight bold}
set rem [FindRemind]
if {$rem != ""} {
.c create text 4 52 -anchor nw -text "Found existing Remind... reusing settings" -fill red -font {-family courier -size -14 -weight bold}
.c create text 4 66 -anchor nw -text "from $rem" -fill red -font {-family courier -size -14 -weight bold}
}
update idletasks
after 2500
}
#***********************************************************************
# %PROCEDURE: FindRemind
# %ARGUMENTS:

391
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -71,10 +71,10 @@ AC_FUNC_UTIME_NULL
AC_HEADER_TIME
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
VERSION=03.01.13
VERSION=03.03.02
AC_SUBST(VERSION)
AC_OUTPUT(src/Makefile www/Makefile src/version.h)

View File

@@ -1,10 +1,9 @@
This directory contains contributed scripts. They are provided
"as-is" with no warranty. Please do not contact David Skoll
or Roaring Penguin Software Inc. for help with these scripts;
instead, contact the script authors.
"as-is" with no warranty. Please do not contact Dianne Skoll for help
with these scripts; instead, contact the script authors.
You should check the upstream sources; there may be newer versions
of these scripts available.
--
David F. Skoll
Dianne Skoll

View File

@@ -238,7 +238,7 @@ L<http://en.wikipedia.org/wiki/ICalendar>
L<http://tools.ietf.org/html/rfc2445>
L<http://www.roaringpenguin.com/en/penguin/openSourceProducts/remind>
L<https://dianne.skoll.ca/projects/remind/>
L<remind(1)>
@@ -251,7 +251,7 @@ Please report bugs (with patches, if possible).
Inspired by Anthony J. Chivetta E<lt>achivetta@gmail.comE<gt>'s
rem2ics in awk.
Thank you to David Skoll E<lt>dfs@roaringpengiun.com<gt> for Remind,
Thank you to Dianne Skoll E<lt>dianne@skoll.ca<gt> for Remind,
and to the IETF calsch wg for the iCalendar specification.
=cut

View File

@@ -3,7 +3,7 @@
;; Copyright (C) 2008 Shelagh Manton <shelagh.manton@gmail.com>
;; Author: Shelagh Manton <shelagh.manton@gmail.com> with help from
;; David F. Skoll
;; Dianne Skoll
;; Keywords: remind configure mode
;; Version: .04

View File

@@ -1,4 +1,4 @@
REMIND version 3.1 for UNIX
REMIND version 3.2 for UNIX
REMIND is a sophisticated alarm/calendar program. Details are given
in the man page, "remind.1".
@@ -6,16 +6,16 @@ in the man page, "remind.1".
INSTALLING REMIND:
-----------------
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X Windows:
--------------------------------------------------------------
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X11:
----------------------------------------------------------------------
1) Type: wish ./build.tk from the top-level Remind directory.
Fill in the various options and hit "Build Remind"
2) Type: "make install" -- you may need to be root to do this.
If you do NOT have Tcl/Tk or are NOT running X Windows:
-------------------------------------------------------
If you do NOT have Tcl/Tk or are NOT running X11:
-------------------------------------------------
1) Edit the file "src/custom.h" according to your preferences.
@@ -73,12 +73,12 @@ RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
1. POPUP REMINDERS
If you're running under X-Windows and you have the TCL tools,
you can create simple pop-up reminders by creating the following
TCL script called 'popup'. It pops a message on to the screen and
waits for you to press the 'OK' button. If you don't press the OK button
within 15 seconds, it exits anyway. To use it, you can use the '-k' option
for Remind as follows:
If you're running under X11 and you have the Tcl tools, you can create
simple pop-up reminders by creating the following Tcl script called
'popup'. It pops a message on to the screen and waits for you to
press the 'OK' button. If you don't press the OK button within 15
seconds, it exits anyway. To use it, you can use the '-k' option for
Remind as follows:
remind "-kpopup '%s'&" .reminders
@@ -93,12 +93,12 @@ Norman Walsh.
#!/usr/local/bin/wish
wm withdraw .
after 15000 { destroy . ; exit }
tk_dialog .d { Message } $argv warning 0 { OK }
tk_dialog .d { Message } $argv warning 0 { OK }
destroy .
exit
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
--
David F. Skoll <dfs@roaringpenguin.com>
http://www.roaringpenguin.com/remind/
Dianne Skoll <dianne@skoll.ca>
https://dianne.skoll.ca/projects/remind/

View File

@@ -1,5 +1,213 @@
CHANGES TO REMIND
* VERSION 3.3 Patch 2 - 2020-11-08
- MINOR NEW FEATURE: Add MAYBE-UNCOMPUTABLE keyword; see the man page
and discussion at
https://dianne.skoll.ca/pipermail/remind-fans/2020/003745.html
- CHANGE: TkRemind always invokes Remind with the "-itkremind=1" option,
even when printing. NOTE INCOMPATIBILITY: This is a behavior change!
When you print from TkRemind, we also invoke Remind with "-itkprint=1"
so you can detect that PostScript is being generated.
- CHANGE: The maxmimum length of a variable name has been increased from
16 characters to 64 characters. Modern computers have plenty of memory.
- BUG FIXES: Minor documentation updates, typo fixes, clarifications, etc.
- BUG FIX: Fix calendar-drawing alignment errors when displaying UTF-8
strings with zero-width combining characters and strings with tabs.
- BUG FIX: TkRemind would mess up placement of the WEEK special if invoked
with the "-m" option. This has been fixed.
- BUG FIX: TkRemind would sometimes fail with an error message when editing
a reminder; this is because it was interpreting months 08 and 09 as
illegal octal numbers. This has been fixed.
* VERSION 3.3 Patch 1 - 2020-03-20
- CHANGE: For overlapping multi-day events, issue a reminder for the
most *recent* event rather than the earliest event. NOTE
INCOMPATIBILITY: This is a behavior change!
- CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to
recognize years. NOTE INCOMPATIBILITY: This is a behavior change!
- CHANGE: Revert change to -y option that included filename and line
number in the hash.
- CHANGE: Retain newlines (produced by %_) in JSON output.
- FIX: Document $FormWidth system variable
- FIX: Highlight today's date in "remind -c" output
- FIX: Eliminate compiler warnings on Ubuntu 18.04.
- IMPROVEMENT: Allow times to be specified either in 24-hour mode
(HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.)
- IMPROVEMENT: Allow DURATION to be specified as a time (1:30) or a
number of minutes (90).
- IMPROVEMENT: If terminal size can be determined, set $FormWidth to
terminal width - 8; if not, set $FormWidth to 72.
- MINOR IMPROVEMENT: Add the "ampm()" built-in function.
* Version 3.3 Patch 0 - 2020-01-31
- FIX: rem2ps: Add a %%PageBoundingBox: document structuring convention
comment.
- FIX: rem2ps: Ignore unknown SPECIAL-type reminders.
- IMPROVEMENT: In calendar mode ("-c" option), Remind automatically adjusts
the width of the calendar to fit the terminal window if standard output
is a TTY.
- IMPROVEMENT: Add JSON-based output with "remind -pp" and "remind -ppp"
The JSON-based intermediate format preserves a lot more information
about the original reminder, allowing back-ends more insight into
the intent of the reminder, the recurrence used, etc. See the documentation
in "man rem2ps"
- IMPROVEMENT: TkRemind can "reverse-engineer" reminders that it creates
using the additional information in the "remind -pp" format, so it
doesn't create or use ugly comment blocks to delimit the reminders
it creates.
- IMPROVEMENT: TkRemind: Add popup help to most buttons and controls.
- NEW FEATURE: Add support for $DefaultColor system variable, suggested
by Tim Chase.
- NEW FEATURE: The "-@[n][,m]" command-line option allows colored reminders
in Agenda Mode as well as in Calendar Mode. It also adds support for
terminal emulators that can handle the xterm 256-color escape sequences
as well as the true 24-bit color escape sequences.
- CHANGE: SPECIALs are now case-insensitive. Before, only SPECIAL COLOR
would work. Now you can use Special Color, special color, etc.
* Version 3.2 Patch 0 - 2020-01-03
- IMPROVEMENT: Add support for events spanning multiple days (with AT
and DURATION). Add trigeventstart() and trigeventduration()
introspection functions; see "MULTI-DAY EVENTS" in the man page.
- IMPROVEMENT: Add introspection functions trigback(), trigdelta(),
trigduration(), trigfrom(), trigpriority(), trigrep(),
trigscanfrom(), trigtimedelta(), trigtimerep(), and triguntil(). See
man page for details; thanks to Tim Chase for the suggestion.
- IMPROVEMENT: TkRemind: Use PNG images for the next month / previous
month buttons rather than -> and <-. Also use nice anti-aliased
moon phase images instead of ugly blocky bitmaps.
- CHANGE: Modify addition so that previously-illegal combinations
TIME + TIME, TIME + DATETIME and DATETIME + TIME are now allowed.
Also allow DATETIME - TIME. If t1 and t2 are expressions of type TIME
and dt is an expression of type DATETIME, then the following are now
equivalent (before, the expressions on the left-hand side would fail
with a "Type mismatch" error.)
t1 + t2 == t1 + coerce("INT", t2)
dt + t2 == dt + coerce("INT", t2)
t1 + dt == coerce("INT", t1) + dt
dt - t2 == dt - coerce("INT", t2)
- DOC FIX: Document previously-undocumented $MaxStringLen system variable
- DOC FIX: Various minor documentation fixes.
- BUG FIX: Specifying a DURATION without an AT clause results in an error.
Before, it would be accepted but not do anything useful.
- BUG FIX: Catch potential date overflow in slide() function
- BUG FIX: Fix compile error when compiling Romanian version; eliminate
compiler warning when compiling non-English versions.
- BUG FIX: TkRemind: Fix startup failure of TkRemind if options are at
default. :(
* Version 3.1 Patch 17 - 2019-11-15
- IMPROVEMENT: Add "Extra Remind Options" setting to TkRemind.
- IMPROVEMENT: Enable warning-free compilation even with gcc -Wextra flag.
- IMPROVEMENT: Warn if "OMIT a THROUGH b" has a > b.
- SYNTACTIC SUGAR: Make "SCANFROM -n" the same as "SCANFROM [today() - n]"
- BUG FIX: Don't dump expired reminders when dumping queue.
- BUG FIX: Fix failure when specifying a Jahrzeit in Adar. Fix
courtesy of Dov Feldstern
- BUG FIX: Fix various documentation errors and update man page.
* Version 3.1 Patch 16 - 2018-11-09
- IMPROVEMENT: Add patch from Stephen Morgan to calculate astronomical and
nautical twilight in addition to civil twilight.
- BUG FIX: The rem2html script correctly handles a SHADE special with only
one number (a grey level).
- IMPROVEMENT: Remind accepts DATETIME constants in ISO-8601 format and can
optionally be configured to output them that way too.
- MINOR IMPROVEMENT: TkRemind puts its hostname in the window title bar.
- MINOR IMPROVEMENT: TkRemind restarts the background remind daemon if
the .reminders file changes
- MINOR IMPROVEMENT: TkRemind has a "Queue" button that lets you see details
of upcoming queued reminders. This is mostly for debugging and the output
is not particularly readable.
- BUG FIX: The definitions form Yom Hazikaron and Yom Ha'atzmaut were not
quite right; they have been fixed.
- MINOR IMPROVEMENT: TkRemind centers popups over the main calendar
window rather than over the desktop background. This is better
behavior in multi-monitor setups.
- BUG FIX: In "remind -z0" mode, remind wakes up exactly on the minute instead
of sleeping for 60 seconds each time, which could cause it to fall behind.
* Version 3.1 Patch 15 - 2015-07-27
- BUG FIX: Fix a buffer overflow found by Alexander Keller
- BUG FIX: Fix a typo in this file: was 2014 instead of 2015.
- BUG FIX: Make parser reject an AT followed by more than one time.
- BUG FIX: Make parser reject epeated delta or *repeat values.
* Version 3.1 Patch 14 - 2015-04-24
- NEW FEATURE: Putting the line __EOF__ in a .rem file causes Remind
to treat it as end-of-file.
- IMPROVEMENT: Use better PNG images for moons in the HTML display
- CHANGE: Author name updated from "David" to "Dianne"
- BUG FIX: The "-n" command-line option should really run in "ADVANCE_MODE"
rather than "CAL_MODE" internally; otherwise, the substitution sequences
may be misinterpreted.
- BUG FIX: A typo in clearing out MD5 sum context has been fixed.
- BUG FIX: Typo in Spanish translation was fixed.
* Version 3.1 Patch 13 - 2013-03-22
- BUG FIX: Sunrise/Sunset calculations greatly improved thanks to John
@@ -239,7 +447,7 @@ CHANGES TO REMIND
*** THIS MAY AFFECT BACKENDS ***
Backends supplied by Roaring Penguin (rem2ps, rem2html and tkremind)
Backends supplied with Remind (rem2ps, rem2html and tkremind)
are known to work properly.
- "remind -p" no longer suppresses any AT-time associated with SPECIAL
@@ -247,7 +455,7 @@ CHANGES TO REMIND
*** THIS MAY AFFECT BACKENDS ***
Backends supplied by Roaring Penguin (rem2ps, rem2html and tkremind)
Backends supplied with Remind (rem2ps, rem2html and tkremind)
are known to work properly.
+ BUG FIXES
@@ -460,11 +668,6 @@ CHANGES TO REMIND
* Version 3.0 Patch 20 - 1999-04-12
+ NEWS
- I have started a company, Roaring Penguin Software
Inc. (http://www.roaringpenguin.com) and it now holds the Remind copyright.
+ LICENSE CHANGE
- Remind is now distributed under the pure GPL. See the file WINDOWS for my
@@ -480,8 +683,6 @@ CHANGES TO REMIND
+ BUG FIXES
- Changed copyright notices to Roaring Penguin Software Inc.
- Rem2PS was passing specials like HTML, etc. in PostScript output.
YECH! Fix courtesty of Derek J. Decker.

View File

@@ -17,8 +17,7 @@
# "#COLORS" for examples of ANSI color escape sequences. #
# #
# This file is part of REMIND. #
# Copyright (C) 1992-1997 David F. Skoll #
# Copyright (C) 1999-2000 Roaring Penguin Software Inc. #
# Copyright (C) 1992-2018 Dianne Skoll #
# #
#############################################################################
@@ -27,8 +26,8 @@ RUN OFF
################################################
# Ensure required version of remind is used... #
################################################
IF version() < "03.01.08"
ERRMSG This file requires at least version 03.01.08 of Remind.%
IF version() < "03.01.09"
ERRMSG This file requires at least version 03.01.09 of Remind.%
ERRMSG This version is version [version()].
EXIT
ENDIF
@@ -85,7 +84,6 @@ SET December 12
###########################################################
# Other symbolic constants and functions for "pasting"... #
###########################################################
SET Quote CHAR(34)
# Handy constants/function for specifing week of month...
@@ -96,29 +94,17 @@ SET Week_4 22
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
# Handy function to provide SCANFROM dates...
FSET _back(days) TODAY()-days
###########################################################
# Function which returns a string in "am/pm" format based #
# on the time. For example, set a am_pm(NOW())... #
###########################################################
FSET _am_pm(tm) IIF(tm<01:00, tm+12*60+"am", \
tm<12:00, tm+"am", \
tm<13:00, tm+"pm", \
tm-12*60+"pm")
FSET _back(days) $U-days
#################################################################
# Function which removes a single leading zero from a string... #
# Function that removes a single leading zero from a string... #
#################################################################
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
#################################################################
# Return the length of the daylight/night portion of a date, #
# in minutes. #
#################################################################
FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0)
FSET _dark_len(date) 1440-_light_len(date)
@@ -126,26 +112,12 @@ FSET _dark_len(date) 1440-_light_len(date)
# Function to calculate number of years since a given year #
# or number of months since a given month and year... #
############################################################
FSET _yr_num(yr) ORD(YEAR(TRIGDATE()) - yr)
FSET _mo_num(mo, yr) ORD(12 * (YEAR(TRIGDATE()) - yr) + \
MONNUM(TRIGDATE()) - mo)
FSET _yr_num(yr) ORD($Ty - yr)
FSET _mo_num(mo, yr) ORD(12 * ($Ty - yr) + $Tm - mo)
# Here's an example of how to use them:
REM 1 Nov ++12 MSG %"Dean's [_yr_num(1984)] birthday%" is %b.
REM 1 MSG Dean's [_mo_num(11, 1984)] 'monthly' anniversary
###########################################################
# Function to send mail via elm's "fastmail" (by GMS!)... #
###########################################################
#FSET _mail(from, subj) "mailx -s " + \
# Quote + from + " : " + subj + Quote \
# GETENV("LOGNAME") + " < /dev/null 1>&0"
FSET _mail(from, subj) "fastmail -f " + \
Quote + from + Quote + \
" -s " + Quote + subj + Quote + \
" /dev/null " + GETENV("LOGNAME")
REM 1 Nov ++12 MSG %"John's [_yr_num(1984)] birthday%" is %b.
REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
#############################################################################
# Here's a tricky problem: The 4th of July is a holiday in the U.S.
@@ -159,29 +131,28 @@ FSET _mail(from, subj) "fastmail -f " + \
# dependent upon the current date, it's tricky and results may not be
# what you expect. You should try to make sure that the OMIT context
# "near" any current reminders will not change during a calendar run.
# The SCANFROM clause should help make these OMITs very safe.
# The SCANFROM clause will make these OMITs safe.
############################################################################
# Calculate the weekday of the holiday.
REM 4 July SCANFROM [_back(7)] SATISFY 1
IF WKDAYNUM(TRIGDATE()) == Sat
REM [TRIGDATE()] MSG Independence day (actual)
OMIT [TRIGDATE()-1] MSG Independence day (observed)
SET iday $T
IF WKDAYNUM(iday) == Sat
REM [iday] MSG Independence day (actual)
OMIT [iday-1] MSG Independence day (observed)
ELSE
IF WKDAYNUM(TRIGDATE()) == Sun
REM [TRIGDATE()] MSG Independence day (actual)
OMIT [TRIGDATE()+1] MSG Independence day (observed)
IF WKDAYNUM(iday) == Sun
REM [iday] MSG Independence day (actual)
OMIT [iday+1] MSG Independence day (observed)
ELSE
OMIT [TRIGDATE()] MSG Independence day
OMIT [iday] MSG Independence day
ENDIF
ENDIF
############################################################################
# #
# A meeting on the first Monday of every month which is moved to the #
# second Monday in the event of a holiday. #
# #
############################################################################
# First, the normal meeting. However, the SKIP keyword means this
@@ -193,68 +164,21 @@ REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous
# Monday was a holiday
IF ISOMITTED(TRIGDATE()-7)
REM [TRIGDATE()] MSG Delayed meeting
IF ISOMITTED($T-7)
REM [$T] MSG Delayed meeting
ENDIF
############################################################################
# #
# A very complicated reminder sent in by a Remind user. #
# This person gets paid every two weeks, starting from 8 January 1993. #
# If a pay date occurs before the twelfth of a month, then that #
# he pays his mortgage on that pay date. Otherwise, he pays the mortgage #
# on the previous pay date. Furthermore, he has to schedule his #
# mortgage payment six days before it is due. He wants to be reminded #
# a further four days before the scheduling deadline. He also #
# wants to be mailed a notice two weeks before the scheduling deadline. #
# #
# Here's the solution - if you can follow this, consider yourself a #
# Remind programmer extraordinaire! #
# #
############################################################################
# A function to determine whether or not a pay-date is a mortgage-date.
FSET _IsMortDate(x) DAY(x) < 12 || (DAY(x+14) >= 12 && DAY(x+14) <= 14)
# Paydays - for reference
REM 8 Jan 1993 *14 MSG Payday
# Calculate the mortgage payment six days ahead of time. Note that this
# is done "implicitly" by subtracting 6 from the starting date - we start
# on 2 Jan rather than 8 Jan. We add 6 to TRIGDATE() in _IsMortDate to
# compensate.
REM 2 Jan 1993 *14 ++4 SATISFY [_IsMortDate(TRIGDATE()+6)] \
MSG %"Schedule mortgage payment%" for %a.
# Now the mail reminder two weeks before the payment date - because two
# weeks before a payment date is also a payment date, no pre-compensation
# in the starting date of 8 Jan is necessary - convince yourself of this!
# This uses the _mail() function defined earlier.
REM ONCE 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE()+14)] \
RUN [_mail("Decatur Federal", \
"Pay mortgage by the " + ORD(DAY(TRIGDATE()+14)))]
# Make an entry on the calendar when the mortgage should be paid
REM 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE())] \
CAL Mortgage payment
##########################################################################
# #
# On our UNIX system, I run a program which queries the university #
# On our UNIX system, I run a program that queries the university #
# library and creates a file called ".booksdue". This file is #
# a REMIND script to tell me when my library books are due. Here's #
# an example from my reminder file - it shows the use of filedate(). #
# When the .booksdue file is at least 7 days old, I create a new version #
# by querying the library computer. Note the use of realtoday() rather #
# than today. #
# than today(). #
# #
##########################################################################
IF !$RunOff && !$CalMode && !$SimpleCal
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
REM RUN /home/dfs/bilge/library/getbooks
@@ -284,7 +208,7 @@ REM Sat Sun SPECIAL SHADE 220
#############################################################################
SET SaveTrig $NumTrig
SET easter EASTERDATE(YEAR(TODAY()))
SET easter EASTERDATE($Uy)
REM [easter-46] MSG %"Ash Wednesday%"
REM [easter-7] MSG %"Palm Sunday%"
OMIT [easter-2] MSG %"Good Friday%"
@@ -302,7 +226,7 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"President's Day%"
OMIT [$T] MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's%" Day
# The DST rules are accurate for most locations in
@@ -310,6 +234,9 @@ REM Mar 17 MSG %"St. Patrick's%" Day
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun [_last(Oct)] ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM Sun 1 Nov ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
REM May 5 MSG %"Cinco de Mayo%"
@@ -317,28 +244,23 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Memorial Day%"
OMIT [$T] MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Labor Day%"
OMIT [$T] MSG %"Labor Day%"
REM Mon Oct [Week_2] MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%"
# The DST rules are accurate for most locations in
# North America
REM Sun [_last(Oct)] UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST over%"
REM Sun 1 Nov FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST over%"
REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM [_back(7)] \
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \
SATISFY [($Ty % 4) == 0] \
MSG %"Election%" Day
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" Day
OMIT [$T] MSG %"Thanksgiving%" Day
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" (cont.)
OMIT [$T] MSG %"Thanksgiving%" (cont.)
OMIT Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day
@@ -353,13 +275,6 @@ if $NumTrig > SaveTrig
REM SPECIAL SHADE 220
endif
# Seasons (valid from 1992 to 2000)...
REM Mar 20 MSG %"Spring%" begins
REM Jun [IIF(YEAR(TODAY())%4, 21, 20)] MSG %"Summer%" begins
REM Sep [CHOOSE(YEAR(TODAY())-1991, 22,22,23,23,22,22,22,23,22)] \
MSG %"Fall%" begins
REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
#PSSTUFF2
##########################################################################
# #
@@ -373,7 +288,7 @@ REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
# example, I recommend that you use the -sd 10 option for Rem2PS.
REM PS Border Border moveto \
/DayFont findfont DaySize scalefont setfont \
([hebday(today())] [hebmon(today())]) show
([hebday($U)] [hebmon($U)]) show
# Fill in the phases of the moon on the PostScript calendar
[moondate(0)] SPECIAL MOON 0
@@ -385,7 +300,7 @@ REM PS Border Border moveto \
# calendar - the sizes are hard-coded, however, and work best in landscape.
REM PS Border Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \
(Sunrise: [sunrise(trigdate())] Sunset: [sunset(trigdate())]) show
(Sunrise: [sunrise($T)] Sunset: [sunset($T)]) show
# The next one puts the day number (1-366) and days left in the year at the
# bottom of the post-script calendar. Again, the hard-coded sizes work best
@@ -393,7 +308,7 @@ REM PS Border Border 5 sub moveto \
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \
([_DayOfYear(today())]([365+isleap(today())-_DayOfYear(today())])) show
([_DayOfYear($U)]([365+isleap($U)-_DayOfYear($U)])) show
#JHOLS
##########################################################################
@@ -402,7 +317,7 @@ REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
# dates were obtained from "The First Jewish Catalog" by Richard Siegel #
# and Michael and Sharon Strassfeld, published by the Jewish Publication #
# Society of America. The Reform version of the calendar was guessed #
# at by David Skoll based on experience. There is probably no standard #
# at by Dianne Skoll based on experience. There is probably no standard #
# Reform position on many of the holidays, so you may have to adjust #
# the file as required. #
# #
@@ -433,7 +348,7 @@ SET Reform 0
# Convenient function definition to save typing
FSET _h(x, y) HEBDATE(x,y)
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7)
FSET _h2(x, y) HEBDATE(x, y, $U-7)
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
FSET _PastSun(x, y) IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1)
FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
@@ -467,7 +382,7 @@ ELSE
ENDIF
# Because Kislev can change length, we must be more careful about Chanukah
FSET _chan(x) HEBDATE(24, "Kislev", today()-9)+x
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%"
@@ -516,11 +431,11 @@ ELSE
REM [_PastSun(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
ENDIF
# If 4 Iyar is a Friday, then Yom Hazikaron is
# If 4 Iyar is a Thursday or Friday, then Yom Hazikaron is
# the Wednesday before and Yom Ha'atzmaut is on
# Thursday. If 4 Iyar is a Sunday, then Yom Hazikaron
# moves to 5 Iyar and Yom Ha'atzmaut to 6 Iyar.
IF WKDAYNUM(_h2(4, "Iyar")) == 5
IF WKDAYNUM(_h2(4, "Iyar")) == 4 || WKDAYNUM(_h2(4, "Iyar")) == 5
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
ELSE
@@ -556,9 +471,9 @@ ENDIF
# Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here!
SET ostart HEBDATE(16, "Nisan", TODAY()-50)
IF ostart <= TODAY() && (TODAY() - ostart < 49)
SET odays TODAY()-ostart+1
SET ostart HEBDATE(16, "Nisan", $U-50)
IF ostart <= $U && ($U - ostart < 49)
SET odays $U-ostart+1
IF odays < 7
MSG %"%"Today is the [ORD(odays)] day of the Omer.
ELSE
@@ -576,8 +491,8 @@ ENDIF
### for Friday and Saturday. Note: You must set your latitude, longitude
### and possibly time zone for these to work properly!
REM Friday CAL Candle lighting at [sunset(trigdate())-18]
REM Saturday CAL Havdalah at [sunset(trigdate())+42]
REM Friday CAL Candle lighting at [sunset($T)-18]
REM Saturday CAL Havdalah at [sunset($T)+42]
#COLORS
##########################################################################

View File

@@ -7,7 +7,7 @@
"
" remind is a sophisticated reminder service
" you can download remind from:
" http://www.roaringpenguin.com/penguin/open_source_remind.php
" https://dianne.skoll.ca/projects/remind/
if version < 600
syntax clear

View File

@@ -10,10 +10,7 @@ it into a \fBRemind\fR script. Note that \fBcm2rem.tcl\fR can convert
\fIonly\fR version 3 calendar manager files. If you are using version 4
files, there should be a system utility to convert them to version 3 files.
.SH AUTHOR
\fBcm2rem.tcl\fR is supported by Roaring Penguin Software
Inc. (http://www.roaringpenguin.com)
.PP
\fBcm2rem.tcl\fR was written by David F. Skoll <dfs@roaringpenguin.com>.
\fBcm2rem.tcl\fR was written by Dianne Skoll <dianne@skoll.ca>.
.SH BUGS
Not all of the Sun calendar manager options are respected. In particular,
nothing is done for e-mail actions. Also, the resulting Remind script

View File

@@ -1,4 +1,4 @@
.TH REM 1 "30 August 2007"
.TH REM 1 "1 January 2020"
.UC 4
.SH NAME
rem \- Invoke Remind with a default filename
@@ -15,6 +15,6 @@ value of DOTREMINDERS as the filename. Otherwise, \fBremind\fR uses
the filename $HOME/.reminders
.PP
.SH AUTHOR
Remind was written by David F. Skoll <dfs@roaringpenguin.com>
Remind was written by Dianne Skoll <dianne@skoll.ca>
.SH SEE ALSO
\fBremind\fR

View File

@@ -1,13 +1,13 @@
.TH REM2PS 1 "11 April 2005"
.TH REM2PS 1 "1 January 2020"
.UC 4
.SH NAME
rem2ps \- draw a PostScript calendar from Remind output
.SH SYNOPSIS
.B rem2ps [\fIoptions\fR]
.SH DESCRIPTION
\fBRem2ps\fR reads the standard input, which should be the results of running
\fBRemind\fR with the \fB\-p\fR option. It emits PostScript code (which
draws a calendar) to the standard output.
\fBRem2ps\fR reads the standard input, which should be the results of
running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
emits PostScript code (which draws a calendar) to the standard output.
.PP
See the section "Rem2PS Input Format" for details about the \fB\-p\fR
data. This may be useful if you wish to create other \fBRemind\fR
@@ -267,7 +267,7 @@ hold:
.TP
o
The PostScript origin is at the bottom left-hand corner of the page, and
PostScript units of 1/72" are in effect.
PostScript units of 1/72 inch are in effect.
.TP
o
The variables MinX, MinY, MaxX and MaxY define the bounding box within
@@ -313,7 +313,13 @@ Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
with the year and month in large grey letters in the background of the
calendar.
.PP
.SH REM2PS INPUT FORMAT
.SH REM2PS INPUT FORMAT (-P OPTION)
The \fB\-p\fR option is an older, simpler interchange format used by
\fBRemind\fR to communicate with back-ends. New back-ends are
encoraged to support the new \fB\-pp\fR format preferably, though they
are encouraged to support the older \fB\-p\fR format as well if the
older format contains enough information for them to work properly.
.PP
\fBRemind \-p\fR sends the following lines to standard output.
The information is designed to be easily parsed by back-end programs:
.TP
@@ -375,6 +381,9 @@ was provided.
.PP
\fIbody\fR is the body of the reminder.
.PP
Future versions of \fBRemind\fR may add additional keys to the JSON
object. Back-ends \fImust\fR ignore keys they don't recognize.
.PP
After a month's worth of reminders have been emitted, \fBRemind\fR
emits the line:
.PP
@@ -393,11 +402,249 @@ the line number and file name of the file containing the reminder. Back-ends
that don't care about this information should ignore lines starting with
"#" (except, of course, for the # rem2ps lines.)
.PP
.SH AUTHOR
Rem2PS is now supported by Roaring Penguin Software
Inc. (http://www.roaringpenguin.com)
.SH REM2PS PARTIAL JSON INPUT FORMAT (-PP OPTION)
\fBRemind \-pp\fR sends the following lines to standard output. They
are designed to be easily parsed, but contain much more information
than the old-style \fBremind -p\fR output. The extra information
contains a representation of the parsed "REM" statement, which could
allow converters to better preserve semantics of a reminder. For
example, this format passes enough information to allow a back-end to
(in many cases) determine a reminder's recurrence rather than just treating
each reminder as a one-off event.
.PP
Rem2PS was written by David F. Skoll <dfs@roaringpenguin.com>.
The lines emitted by \fBremind \-pp\fR are as follows:
.TP
.B # rem2ps2 begin
This line signifies the start of calendar data. Back-ends can search
for it to verify they are being fed correct information. Note the
"2" after "rem2ps", which distinguishes this format from the older \fB\-p\fR
format.
.TP
\fImonth_name year num_days first_day monday_first\fR
Same as the \fB\-p\fR format
.TP
\fIsun mon tue wed thu fri sat\fR
Same as the \fB\-p\fR format
.TP
\fInext_mon next_days\fR
Same as the \fB\-p\fR format
.TP
\fIprev_mon prev_days\fR
Same as the \fB\-p\fR format
.PP
.B CALENDAR ENTRIES
.PP
The remaining data consists of calendar entries expressed as a JSON object
on a single line. Each such line will begin with "{" and will be a well-formed
JSON object. The keys that may be present in the JSON object are as
follows:
.TP
.B date \fIYYYY-MM-DD\fR
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
.TP
.B filename \fIf\fR
The filename in which the reminder was found.
.TP
.B lineno \fIn\fR
The line number within the file on which the reminder was found.
.TP
.B nonconst_expr 1
If the reminder contained a non-constant expression that had to be evaluated
to determine the trigger date, this key will be present with the value 1.
If this key is present, then it is unsafe for a back-end to rely on
recurrence semantics or even the semantics of any part of the parsed
reminder, as they may have been computed in a way that cannot be expressed
in JSON.
.TP
.B if_depth \fIn\fR
If the reminder is inside one or more IF or ELSE statements, this key
will be present and the value will be the number of nested IFs from
the top-level to the reminder. Back-ends should be wary of
interpreting recurrence semantics of reminders within an IF or ELSE
block.
.TP
.B passthru \fIspecial\fR
If the reminder was a SPECIAL reminder, the \fBpassthru\fR key will be
present and the value will be the type of SPECIAL (such as SHADE, COLOR,
MOON, etc.)
.TP
.B tags \fIdata\fR
If any TAG clauses are present, the \fBtag\fR key will be present and consist
of a comma-separated list of tags.
.TP
.B time \fIt\fR
If an AT clause was present, this key will contain the time of the AT clause
in minutes after midnight.
.TP
.B tdelta \fIn\fR
If a time delta (+n after an AT clause) was present, this key contains the
delta value in minutes.
.TP
.B trep \fIn\fR
If a time repeat (*n after an AT clause) was present, this key contains the
repeat value in minutes.
.TP
.B eventduration \fIn\fR
If a DURATION clause was present, this key contains the event duration in
minutes.
.TP
.B duration \fIn\fR
If a DURATION clause was present, this key contains today's duration in
minutes. See the \fBremind(1)\fR man page, "MULTI-DAY EVENTS", for a
discussion of duration vs. event duration.
.TP
.B eventstart \fIdt\fR
If an AT clause was present, this key contains the event start time in
the format \fIYYYY-MM-DDTHH:MM\fR.
.TP
.B back \fIn\fR
If the reminder contained a "back" clause (\-n or \-\-n), this key
contains the back value. If the "back" value was \-n, the value will
be positive; if it was \-\-n, the value will be negative.
.TP
.B delta \fIn\fR
If the reminder contained a "delta" clause (\+n or \+\+n), this key
contains the delta value. If the "delta" value was \+n, the value will
be positive; if it was \+\+n, the value will be negative.
.TP
.B rep \fIn\fR
If the reminder contained a "repeat" clause (*n), this key contains
the repeat value.
.TP
.B skip \fItype\fR
If the reminder contained a SKIP, BEFORE or AFTER keyword, then this
key will contain that keyword.
.TP
.B localomit \fIarray\fR
If the reminder contains a local OMIT keyword, this key will be present.
Its value will be an array of English day names that are OMITted.
.TP
.B wd \fIarray\fR
If the reminder contains one or more weekdays, this key will be present.
Its value will be an array of English day names that are present.
.TP
.B d \fIn\fR
If a day-of-month is present in the reminder specification, this key
will be present and its value will be the day number.
.TP
.B m \fIn\fR
If a month is present in the reminder specification, this key
will be present and its value will be the month number.
.TP
.B y \fIn\fR
If a year is present in the reminder specification, this key
will be present and its value will be the year.
.TP
.B until \fIYYYY-MM-DD\fR
If the reminder contains an UNTIL or THROUGH clause, this key
will be present. Its value will be a string of the form YYYY-MM-DD.
.TP
.B once 1
If the reminder contains a ONCE keyword, this key will be present
with a value of 1.
.TP
.B scanfrom \fIYYYY-MM-DD\fR
If the reminder contains a SCANFROM keyword, this key will be present
and its value will be a string of the form YYYY-MM-DD.
.TP
.B from \fIYYYY-MM-DD\fR
If the reminder contains a FROM keyword, this key will be present
and its value will be a string of the form YYYY-MM-DD.
.TP
.B priority \fIn\fR
The priority of the reminder. Always present; if no PRIORITY keyword
is specified, then a reminder has a default priority of 5000.
.TP
.B r \fIn\fR
For a SHADE or COLOR special, the red color component.
.TP
.B g \fIn\fR
For a SHADE or COLOR special, the green color component.
.TP
.B b \fIn\fR
For a SHADE or COLOR special, the blue color component.
.TP
.B body \fIbody\fR
The body of the reminder to issue. Always present.
.TP
.B rawbody \fIraw\fR
The "raw" body of the reminder, before any expression-pasting or
substitution-sequence processing. If the raw body would be the same
as the processed body, then this key is not present.
.PP
After a month's worth of reminders have been emitted, \fBRemind\fR
emits the line:
.PP
\fB# rem2ps2 end
.PP
However, back-ends should keep reading until EOF in case more data for
subsequent months is forthcoming.
.PP
.SH REM2PS PURE JSON INPUT FORMAT (-PPP OPTION)
\fBRemind \-ppp\fR emits \fIpure JSON\fR output. The format is
as follows:
.PP
\fBRemind\fR outputs a JSON array. Each element of the array is a
\fImonth descriptor\fR.
.PP
Each month descriptor is a JSON object with the following elements:
.TP
.B monthname \fIname\fR
The name of the month.
.TP
.B year \fIyyyy\fR
The year.
.TP
.B daysinmonnth \fIn\fR
The number of days in the current month.
.TP
.B firstwkday \fIn\fR
The weekday of the first day of the month (0 = Sunday, 1 = Monday, 6 = Saturday).
.TP
.B mondayfirst \fIn\fR
An indicator of whether or not the calendar week should start with
Sunday (n=0) or Monday (n=1).
.TP
.B daynames \fR[\fIdays\fR]
A seven-element array of day names; each element is a string representing
the names of the days from Sunday through Saturday.
.TP
.B prevmonthname \fIname\fR
The name of the previous month.
.TP
.B daysinprevmonth \fIn\fR
The number of days in the previous month.
.TP
.B prevmonthyear \fIyyyy\fR
The year of the previous month. (The same as \fByear\fR unless the current
month is January.)
.TP
.B nextmonthname \fIname\fR
The name of the following month.
.TP
.B daysinnextmonth \fIn\fR
The number of days in the following month.
.TP
.B nextmonthyear \fIyyyy\fR
The year of the following month. (The same as \fByear\fR unless the
current month is December.)
.TP
.B entries \fR[\fIarray\fR]
The \fBentries\fR key consists of an array of calendar entries; each
entry is a JSON object that has the same format as described in the
\fBCALENDAR ENTRIES\fR section in the \fB\-PP FORMAT\fR section,
\fIwith the following difference\fR: In \fB\-PP\fR mode, if a reminder
has \fB%"\fR markers, only the text between the markers
is included in the \fBbody\fR element. In \fB\-PPP\fR mode, the
entire text \fIincluding\fR the \fB%"\fR markers is included and it's up to
the back-end to extract the portion between the markers if that
is desired.
.SH AUTHOR
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
.SH BUGS
All \fBRem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
Any time you supply

View File

@@ -1,4 +1,4 @@
.TH REMIND 1 "31 August 2008"
.TH REMIND 1 "1 January 2020"
.UC 4
.SH NAME
remind \- a sophisticated reminder service
@@ -19,10 +19,14 @@ be a directory rather than a plain file, then \fBRemind\fR reads all of
the files in that directory that match the pattern "*.rem". The files
are read in sorted order; the sort order may depend on your locale, but
should match the sort order used by the shell to expand "*.rem".
.PP
\fBRemind\fR reads its files starting from the beginning to the end, or
until it encounters a line whose sole content is "__EOF__" (without the quotes.)
Anything after the __EOF__ marker is completely ignored.
.SH OPTIONS
\fBRemind\fR has a slew of options. If you're new to the program,
ignore them for now and skip to the section "Reminder Files".
ignore them for now and skip to the section "REMINDER FILES".
.TP
.B \-n
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
@@ -42,7 +46,8 @@ The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
sent to standard output. If you supply a number \fIn\fR, then a
calendar will be generated for \fIn\fR months, starting with the
current month. By default, a calendar for only the current month is
produced.
produced.
.RS
.PP
You can precede \fIn\fR (if any) with a set of flags. The flags
are as follows:
@@ -68,24 +73,54 @@ only work on terminals that are set to UTF-8 character encoding.
.TP
.B 'c'
causes \fBRemind\fR to use VT100 escape sequences to approximate
SPECIAL COLOR reminders. The approximation is (of necessity) very
SPECIAL COLOR reminders. Note that this flag is kept for
backwards-compatibility; you should use the \fB\-@\fI[n][,m]\fR
command-line option instead.
.RE
.TP
.B \-@\fR[\fIn\fR][,\fIm\fR]
Tells \fBRemind\fR to approximate SPECIAL COLOR reminders using VT100
escape sequences. The approximation is (of necessity) very
coarse, because the VT100 only has eight different color sequences,
each with one of two brightnesses. A color component greater than
64 is considered "on", and if any of the three color components is
greater than 128, the color is considered "bright".
.RS
.PP
If you supply the optional numeric parameters, the have the following
meanings: \fIn\fR=0 tells \fBRemind\fR to use the standard 16 VT100
colors. \fIn\fR=1 tells it to use an extended 256-color palette supported
by many terminal emulators such as xterm. And \fIn\fR=2 tells it to
use escape sequences that support true 24-bit colors, again supported
by many terminal emulators such as xterm.
.PP
If the optional \fIm\fR parameter is supplied following a comma,
then \fIm\fR=0 tells \fBRemind\fR that the terminal background is dark,
and \fBRemind\fR will brighten up dark colors to make them visible. If
\fIm\fR=1, then \fBRemind\fR assumes the terminal background is light
and it will darken bright colors to make them visible. If no \fIm\fR
is supplied, then \fBRemind\fR does not perform any adjustments, and
some reminders may be hard or impossible to see if the color is too close
to the terminal background color.
.RE
.TP
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
The \fB\-w\fR option specifies the output width, padding and spacing
of the formatted calendar output. \fICol\fR specifies the number of
columns in the output device, and defaults to 80. \fIPad\fR specifies
how many lines to use to "pad" empty calendar boxes. This defaults to
5. If you have many reminders on certain days that make your calendar
too large to fit on a page, you can try reducing \fIpad\fR to make the
empty boxes smaller. \fISpc\fR specifies how many blank lines to leave
between the day number and the first reminder entry. It defaults to 1.
columns in the output device. If not specified, or specified as 0,
it defaults to the larger of 71 or the actual width of your terminal,
or to 80 if standard output is not a terminal.
.RS
.PP
\fIPad\fR specifies how many lines
to use to "pad" empty calendar boxes. This defaults to 5. If you
have many reminders on certain days that make your calendar too large
to fit on a page, you can try reducing \fIpad\fR to make the empty
boxes smaller. \fISpc\fR specifies how many blank lines to leave
between the day number and the first reminder entry. It defaults to
1.
.PP
Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you
provide the correct number of commas. Don't use any spaces in the option.
.RE
@@ -102,17 +137,27 @@ If you immediately follow the \fBs\fR with the letter
day they actually occur \fIas well as\fR on any preceding days specified
by the reminder's \fIdelta\fR.
.TP
.B \-p\fR[\fBa\fR]\fIn\fR
.B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR]\fIn\fR
The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
that the output contains additional information for use by the
\fBRem2PS\fR program, which creates a PostScript calendar. For this
\fBRem2PS\fR program, which creates a PostScript calendar, and various
other back-end programs. For this
option, \fIn\fR cannot start with "+"; it must specify a number of months.
The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR
man page. If you immediately follow the \fBp\fR with the letter
\fBa\fR, then \fBRemind\fR displays reminders on the calendar on the
day they actually occur \fIas well as\fR on any preceding days specified
by the reminder's \fIdelta\fR.
by the reminder's \fIdelta\fR. If you follow the \fBp\fR with another
\fBp\fR, then \fBRemind\fR uses a more comprehensive JSON-based
format rather than the "simple calendar" format. This format is
also documented in the \fBrem2ps(1)\fR man page. Finally, if you use
three p's, as in \fB\-ppp\fR, then \fBRemind\fR uses a pure JSON
format, again documented in \fBrem2ps(1)\fR.
.RS
.PP
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
option.
.RE
.TP
.B \-l
If you use the \-l option in conjunction with the \-p option, then
@@ -203,7 +248,7 @@ encountered in the reminder script. The \fB\-g\fR option cause
\fBRemind\fR to sort reminders by date and time prior to issuing them.
The optional \fBa\fR and \fBd\fR characters specify the sort order
(ascending or descending) for the date, time and priority fields. See
the section "Sorting Reminders" for more information.
the section "SORTING REMINDERS" for more information.
.TP
\fB\-b\fR[\fIn\fR]
@@ -278,7 +323,7 @@ TAG clause.
\fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
\fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the
section "Initializing Variables on the Command Line" for more details.
section "INITIALIZING VARIABLES ON THE COMMAND LINE" for more details.
.TP
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
Allows you to define a function on the command line.
@@ -289,14 +334,15 @@ If you supply a \fIdate\fR on the command line, it must consist of
of the month, and \fIyear\fR is a year (all 4 digits) from 1990 to
about 2075. You can leave out the \fIday\fR, which then defaults to 1.
.PP
If you do supply a \fIdate\fR on the command line, then \fBRemind\fR uses
it, rather than the actual system date, as its notion of "today."
This lets you create calendars for future months, or test to see
how your reminders will be triggered in the future. Similarly,
you can supply a \fItime\fR (in 24-hour format -- for example, 17:15) to
set \fBRemind\fR's notion of "now" to a particular time. Supplying
a \fItime\fR on the command line also implicitly enables the \fB\-q\fR
option and disables the \fB\-z\fR option.
If you do supply a \fIdate\fR on the command line, then \fBRemind\fR
uses it, rather than the actual system date, as its notion of "today."
This lets you create calendars for future months, or test to see how
your reminders will be triggered in the future. Similarly, you can
supply a \fItime\fR to set \fBRemind\fR's notion of "now" to a
particular time. Supplying a \fItime\fR on the command line also
implicitly enables the \fB\-q\fR option and disables the \fB\-z\fR
option. The \fItime\fR may be specified in 24-hour format (eg, 13:20)
or common "AM/PM" format (1:20pm).
.PP
If you would rather specify the date more succinctly, you can supply
it as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and
@@ -306,7 +352,7 @@ In addition, you can supply a \fIrepeat\fR parameter, which has the
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
with the date incrementing on each iteration. You may have to enclose
the parameter in quotes to avoid shell expansion. See the subsection
"Repeated Execution" in the section "Calendar Mode" for more
"Repeated Execution" in the section "CALENDAR MODE" for more
information.
.SH REMINDER FILES
.PP
@@ -316,7 +362,7 @@ text editor capable of creating plain ASCII files to create a
very simple and almost immediately understandable:
.PP
.nf
REM 6 Jan MSG David's birthday
REM 6 Jan MSG Dianne's birthday
.fi
.PP
to the baroque and obscure:
@@ -393,7 +439,7 @@ These keywords denote the \fItype\fR
of the reminder. (\fBSATISFY\fR is more complicated and will be explained
later.) A \fBMSG\fR-type reminder normally prints a message to the standard
output, after passing the \fIbody\fR through a special substitution filter,
described in the section "The Substitution Filter." However, if you have
described in the section "THE SUBSTITUTION FILTER." However, if you have
used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
passed to the appropriate program. Note that the options \fB\-c\fR,
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
@@ -402,7 +448,7 @@ Note that you can omit the reminder type, in which case it
defaults to \fBMSG\fR. So you can write:
.PP
.nf
6 January David's Birthday
6 January Dianne's Birthday
.fi
.PP
although this is not recommended.
@@ -411,7 +457,7 @@ The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
except that the reminder is formatted to fit into a paragraph-like
format. Three system variables control the formatting of \fBMSF\fR-type
reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and
\fB$FormWidth\fR. They are discussed in the section "System Variables."
\fB$FormWidth\fR. They are discussed in the section "SYSTEM VARIABLES."
The \fBMSF\fR keyword causes the spacing of your reminder to be altered -
extra spaces are discarded, and two spaces are placed after periods and
other characters, as specified by the system variables \fB$EndSent\fR and
@@ -444,7 +490,8 @@ of a special reminder depends on the back-end. For the \fBRem2PS\fR
back-end, \fBSPECIAL PostScript\fR is equivalent to a \fBPS\fR-type
reminder, and \fBSPECIAL PSFile\fR is equivalent to a \fBPSFILE\fR-type
reminder. The body of a \fBSPECIAL\fR reminder is obviously dependent
upon the back-end.
upon the back-end. A back-end \fImust\fR ignore a \fBSPECIAL\fR that
it does not recognize.
.PP
.B DATE SPECIFICATIONS
.PP
@@ -471,7 +518,7 @@ characters must be used. The following are examples of the various parts of a
JANUARY, feb, March, ApR, may, Aug
.TP
.I year:
1990, 1993, 2030, 95 (interpreted as 1995). The year can range
1990, 1993, 2030. The year can range
from 1990 to 2075.
.TP
.I weekday:
@@ -768,7 +815,7 @@ the initial date, and does not affect the repetition period.
.B SCANFROM \fRand\fB FROM
.PP
The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers
only, and will be explained in the section "Details about Trigger Computation"
only, and will be explained in the section "DETAILS ABOUT TRIGGER COMPUTATION"
near the end of this manual. Note that \fBSCANFROM\fR is available only
in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only
from 03.01.00 and later.
@@ -780,7 +827,7 @@ It is used in calendar mode and when sorting reminders. If two reminders
have the same trigger date and time, then they are sorted by priority.
If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000
is used. (This default can be changed by adjusting the system variable
\fB$DefaultPrio\fR. See the section "System Variables" for more
\fB$DefaultPrio\fR. See the section "SYSTEM VARIABLES" for more
information.)
.PP
.B EXPIRY DATES
@@ -921,8 +968,13 @@ it terminates the search after the \fBSATISFY\fR iteration limit
.PP
Timed reminders are those that have an \fBAT\fR keyword followed
by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR
must be specified in 24-hour format, with 0:00 representing midnight,
may be specified in 24-hour format, with 0:00 representing midnight,
12:00 representing noon, and 23:59 representing one minute to midnight.
Alternatively, it may be specified in common "AM/PM" format; in this case,
the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm
represents noon, and 11:59pm represents one minute to midnight. The "am"
and "pm" portions are case-insensitive and the "m" is optional.
.PP
You can use either a colon or a period to separate the hours from the
minutes. That is, 13:39 and 13.39 are equivalent.
.PP
@@ -949,7 +1001,7 @@ The following reminder will be triggered on Thursdays and Fridays,
but will only be queued on Fridays:
.PP
.nf
REM Fri ++1 AT 13:00 MSG Lunch at 1pm Friday.
REM Fri ++1 AT 1:00PM MSG Lunch at 1pm Friday.
.fi
.PP
The \fItdelta\fR and \fItrepeat\fR have the same form as a \fIrepeat\fR
@@ -1009,7 +1061,7 @@ of timed reminders, and the \fBWARN\fR keyword allows precise control
over the advance triggering of all types of reminders.
However, discussion must be deferred until after
expressions and user-defined functions are explained. See the subsection
"Precise Scheduling" further on.
"PRECISE SCHEDULING" further on.
.PP
.B TAG AND DURATION
.PP
@@ -1029,17 +1081,23 @@ by the hexadecimal representation of the MD5 sum of the REM
command line. This lets you give a more-or-less unique identifier
to each distinct REM command.
.PP
The \fBDURATION\fR keyword makes sense only for timed reminders;
it specifies the duration of an event. Currently, this is not
used, but it may be used in future by back-ends or scheduling
systems built around \fBRemind\fR. For example, if you have
a 90-minute meeting starting at 1:00pm, you could use:
The \fBDURATION\fR keyword makes sense only for timed reminders; it
specifies the duration of an event. For example, if you have a
90-minute meeting starting at 1:00pm, you could use any of the following:
.PP
.nf
REM 5 March 1999 AT 13:00 DURATION 1:30 MSG Meeting
REM 5 March 2021 AT 13:00 DURATION 1:30 MSG Meeting
REM 5 March 2021 AT 13:00 DURATION 90 MSG Meeting
REM 5 March 2021 AT 1:00pm DURATION 1:30 MSG Meeting
REM 5 March 2021 AT 1:00pm DURATION 90 MSG Meeting
.fi
.PP
Note that \fIduration\fR is specified in hours and minutes.
Note that \fIduration\fR is specified either in hours and minutes as a
\fItime\fR, or in minutes as an \fIinteger\fR. If you specify a
duration of 00:00 or 0, then \fBRemind\fR behaves exactly as if no
\fBDURATION\fR at all had been present.
.PP
.SH THE SUBSTITUTION FILTER
.PP
@@ -1265,7 +1323,7 @@ is similar to \fB%3\fR but displays the current time.
used by the substitution filter,
but is used to tell \fBRemind\fR which text to include in a calendar
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
See "Calendar Mode"
See "CALENDAR MODE"
.PP
Notes:
.TP
@@ -1619,13 +1677,15 @@ in C.
.RE
.TP
.B TIME constants
12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11
12:33, 0:01, 14:15, 16:42, 12.16, 13.00, 1.11, 4:30PM, 12:20am
.PP
.RS
Note that \fBTIME\fR constants are written in 24-hour format. Either the
period or colon can be used to separate the minutes from the hours.
However, Remind will consistently output times using only one separator
character. (The output separator character is chosen at compile-time.)
Note that \fBTIME\fR constants may be written in 24-hour format or in
common "AM/PM" format. If you use "AM/PM" format, then the hour can
range from 1 to 12. Either a period or colon can be used to separate
the minutes from the hours. However, Remind will consistently output
times in 24-hour format using only one separator character. (The
output separator character is chosen at compile-time.)
.RE
.TP
.B DATE constants
@@ -1648,11 +1708,12 @@ versions prior to 03.00.02 did not support the '-' date separator.
.RE
.TP
.B DATETIME constants
\fBDATETIME\fR constants are expressed similarly to \fBDATE\fR constants
with the addition of an "@HH:MM" part. For example:
\fBDATETIME\fR constants are expressed similarly to \fBDATE\fR
constants with the addition of an "@HH:MM" part, optionally followed
by "am" or "pm". For example:
.PP
.RS
\'2008-04-05@23:11', '1999/02/03@14:06', '2001-04-07@08:30'
\'2008-04-05@23:11', '1999/02/03@14:06', '2001-04-07@08:30', '2020-01-01@3:20pm'
.PP
\fBDATETIME\fR values are printed without the quotes. Notes about date
and time separator characters for \fBDATE\fR and \fBTIME\fR constants apply
@@ -1705,7 +1766,12 @@ Has several uses. These are:
.PP
\fBINT\fR + \fBTIME\fR or \fBTIME\fR + \fBINT\fR - returns a \fBTIME\fR
obtained by adding
\fBINT\fR minutes to the original \fBTIME\fR.
\fBINT\fR minutes to the original \fBTIME\fR. The result will always
range from 00:00 through 23:59.
.PP
\fBTIME\fR + \fBTIME\fR treats the second \fBTIME\fR parameter as a
duration, converting it to an integer number of minutes past midnight,
and then performs addition as with \fBTIME\fR + \fBINT\fR.
.PP
\fBINT\fR + \fBDATE\fR or \fBDATE\fR + \fBINT\fR - returns a \fBDATE\fR
obtained by adding \fBINT\fR days to the original \fBDATE\fR.
@@ -1714,6 +1780,11 @@ obtained by adding \fBINT\fR days to the original \fBDATE\fR.
\fBDATETIME\fR obtained by adding \fBINT\fR minutes to the original
\fBDATETIME\fR.
.PP
\fBDATETIME\fR + \fBTIME\fR or \fBTIME\fR + \fBDATETIME\fR
treats the \fBTIME\fR parameter as a
duration, converting it to an integer number of minutes past midnight,
and then performs addition as with \fBDATETIME\fR + \fBINT\fR.
.PP
\fBSTRING\fR + \fBSTRING\fR - returns a \fBSTRING\fR that is the
concatenation of the two original
\fBSTRING\fRs.
@@ -1747,9 +1818,11 @@ the original \fBDATE\fR.
earlier
than the original \fBTIME\fR.
.PP
\fBDATETIME\fR - \fBINT\fR - returns a \fBDATETIME\fR that is \fBINT\fR minutes
earlier
than the original \fBDATETIME\fR.
\fBDATETIME\fR - \fBINT\fR - returns a \fBDATETIME\fR that is
\fBINT\fR minutes earlier than the original \fBDATETIME\fR.
.PP
\fBDATETIME\fR - \fBTIME\fR - coerces the \fBTIME\fR to an \fBINT\fR
and then performs subtraction as above.
.RE
.TP
.B <, <=, >, and >=
@@ -1827,6 +1900,9 @@ variable. Examples:
Note that variables themselves have no type. They take on the type of
whatever you store in them.
.PP
Variables set with SET or on the command-line with \fB\-i\fR\fIvar\fB=\fR\fIexpr\fR
have global scope.
.PP
To delete a variable, use the \fBUNSET\fR command:
.PP
\fBUNSET\fR \fIvar\fR [\fIvar\fR...]
@@ -1879,6 +1955,22 @@ This variable can be set only to "/" or "-". It holds the character
used to separate portions of a date when \fBRemind\fR prints a DATE or
DATETIME value.
.TP
.B $DefaultColor
This variable can be set to a string that has the form of three
space-separated numbers. Each number must be an integer from 0 to
255, or all three numbers must be -1. The default value of
\fB$DefaultColor\fR is "-1 -1 -1", which suppresses default coloring
of MSG-type reminders. If you set \fB$DefaultColor\fR to any other
value, then all MSG-, MSF- and CAL-type reminders are effectively
converted into SPECIAL COLOR reminders whose color value is specified
by \fB$DefaultColor\fR.
.RS
.PP
Unlike other system variables, the value of \fB$DefaultColor\fR is
\fInot\fR preserved between calendar iterations; rather, it is reset
to "-1 -1 -1" at the start of each iteration.
.RE
.TP
.B $DefaultPrio
The default priority assigned to reminders without a \fBPRIORITY\fR
clause. You can set this as required to adjust the priorities of
@@ -1937,9 +2029,11 @@ for years greater than 2037.
.TP
.B $FormWidth
The maximum width of each line of text for formatting \fBMSF\fR-type
reminders. The default is 72. If an \fBMSF\fR-type reminder contains
a word too long to fit in this width, it will not be truncated - the
width limit will be ignored.
reminders. The default is the width of the terminal in columns, minus
8, but clamped at a minimum of 20 and a maximum of 500. If standard
output is not a terminal, then the default is 72.If an \fBMSF\fR-type
reminder contains a word too long to fit in this width, it will not be
truncated - the width limit will be ignored.
.TP
.B $HushMode (read-only)
If non-zero, then the \fB\-h\fR option was supplied on the command line.
@@ -1968,8 +2062,13 @@ the latitude and longitude system variables.
These specify the longitude of your location. \fB$LongDeg\fR can
range from \-180 to 180. Western longitudes are positive; eastern
ones are negative. Note that all three components should have the
same sign: All positive for Western longitudes and all negative
for Eastern longitudes.
same sign: All positive for Western longitudes and all negative for
Eastern longitudes. Note that for historical reasons, the sign for
longitude is \fIdifferent\fR from the usual convention! If you find
the longitude of your location from a search engine, you will most
likely \fIneed to invert the sign to have it work correctly with
Remind.\fR
.RS
.PP
The latitude and longitude information is required for the functions
@@ -1982,6 +2081,10 @@ start of your reminder scripts.
The maximum number of iterations for the \fBSATISFY\fR clause
(described later.) Must be at least 10.
.TP
.B $MaxStringLen
A limit on the longest string that \fBRemind\fR will allow you
to create. The default is 65535.
.TP
.B $MinsFromUTC
The number of minutes between Universal Time Coordinated and local time. If
\fB$CalcUTC\fR is non-zero, this is calculated upon startup of \fBRemind\fR.
@@ -2119,6 +2222,32 @@ be a number as described in the UNIX \fBaccess\fR(2) system call. The
function returns 0 if the file can be accessed with the specified \fImode\fR,
and \-1 otherwise.
.TP
.B adawn([dq_date])
Returns the time of "astronomical dawn" on the specified \fIdate\fR. If
\fIdate\fR is omitted, defaults to \fBtoday()\fR. If a \fIdatetime\fR object
is supplied, only the date component is used.
.TP
.B adusk([dq_date])
Returns the time of "astronomical twilight" on the specified \fIdate\fR. If
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
.TP
.B ampm(tq_time [,s_am [,s_pm]])
Returns a \fBSTRING\fR that is the result of converting \fItime\fR
(which is either a \fBTIME\R or a \fBDATETIME\fR object) to "AM/PM"
format. The optional arguments \fIam\fR and \fIpm\fR are the strings
to append in the AM and PM case, respectively; they default to "AM"
and "PM". The function obeys the system variables $DateSep,
$TimeSep and $DateTimeSep when formatting its output. For example:
.RS
.PP
.nf
ampm(0:22) returns "12:22AM"
ampm(17:45, "am", "pm") returns "5:45pm"
ampm('2020-03-14@21:34') returns "2020-03-14@9:34PM"
.fi
.PP
.RE
.TP
.B args(s_fname)
Returns the number of arguments expected by the user-defined function
\fIfname\fR, or \-1 if no such user-defined function exists. Note that
@@ -2365,16 +2494,16 @@ variables are generally case-sensitive; thus, getenv("HOME") is not
the same as getenv("home").
.TP
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
Support for Hebrew dates - see the section "The Hebrew Calendar"
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP
.B hebday(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar"
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP
.B hebmon(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar"
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP
.B hebyear(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar"
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP
.B hour(tq_time)
Returns the hour component of \fItime\fR.
@@ -2513,6 +2642,15 @@ which default to \fBtoday()\fR and midnight, respectively. The returned
value is an integer from 0 to 359, representing the phase of the moon
in degrees. 0 is a new moon, 180 is a full moon, 90 is first-quarter, etc.
.TP
.B ndawn([dq_date])
Returns the time of "nautical dawn" on the specified \fIdate\fR. If
\fIdate\fR is omitted, defaults to \fBtoday()\fR. If a \fIdatetime\fR object
is supplied, only the date component is used.
.TP
.B ndusk([dq_date])
Returns the time of "nautical twilight" on the specified \fIdate\fR. If
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
.TP
.B nonomitted(dq_start, dq_end [,s_wkday...])
This function returns the number of \fInon-\fRomitted days between
\fIstart\fR and \fIend\fR. If \fIstart\fR is non-omitted, then it is
@@ -2769,10 +2907,77 @@ date, returns the integer 0.
Similar to trigdate(), but returns a \fBDATETIME\fR if the most recent
triggerable \fBREM\fR command had an \fBAT\fR clause. If there was no
\fBAT\fR clause, returns a \fBDATE\fR. If no trigger could be computed,
returns the integer 0.
returns the integer 0. See "MULTI-DAY EVENTS" for more information.
.TP
.B trigeventstart()
Returns a \fBDATETIME\fR representing the start of the most recent
triggerable \fBREM\fR command that had an \fBAT\fR clause. For events
without a \fBDURATION\fR or that do not span multiple days, returns
the same as \fBtrigdatetime()\fR. If the \fBREM\fR command did not
have an \fBAT\fR clause, returns the integer -1 (and differs from
\fBtrigdatetime()\fR in this respect.) See "MULTI-DAY EVENTS" for more
information.
.TP
.B trigeventduration()
Returns a \fBTIME\fR representing the duration of the most recent
triggerable \fBREM\fR command that had an \fBAT\fR and a
\fBDURATION\fR clause. If the event does not span multiple days,
returns the same thing as \fBtrigduration()\fR. If the \fBREM\fR
command lacked an \fBAT\fR or \fBDURATION\fR clause, returns -1. See
"MULTI-DAY EVENTS" for more information.
.TP
.B trigback()
Returns the "back" amount of the last \fBREM\fR or \fBIFTRIG\fR command.
Returns a positive integer N if the "back" is of the form -N, or a negative
integer if it is of the form --N. If there is no "back", then returns 0.
.TP
.B trigdelta()
Returns the "delta" amount of the last \fBREM\fR or \fBIFTRIG\fR command.
Returns a positive integer N if the "delta" is of the form +N, or a negative
integer if it is of the form ++N. If there is no "delta", then returns 0.
.TP
.B trigtimedelta()
Similar to \fBtrigdelta()\fR, but returns the delta used in the
\fBAT\fR clause of a timed reminder.
.TP
.B trigrep()
Returns the "repeat" amount of the last \fBREM\fR or \fBIFTRIG\fR
command. Returns a positive integer N if the "repeat" is of the form
*N. If there is no "repeat", then returns 0.
.TP
.B trigtimerep()
Similar to \fBtrigrep()\fR, but returns the repeat used in the \fBAT\fR clause
of a timed reminder.
.TP
.B trigduration()
Returns (as a TIME type) the \fBDURATION\fR parameter of a timed
reminder. If there is no \fBDURATION\fR parameter, returns the
integer -1. See "MULTI-DAY EVENTS" for more information.
.TP
.B trigpriority()
Returns the \fBPRIORITY\fR of the last \fBREM\fR or \fBIFTRIG\fR command.
.TP
.B triguntil()
Returns (as a \fBDATE\fR type) the \fBUNTIL\fR parameter of the last
\fBREM\fR or \fBIFTRIG\fR command. If there was no \fBUNTIL\fR
parameter, returns the integer -1. If there is a \fBTHROUGH\fR parameter,
that will be returned by \fBtriguntil()\fR since "THROUGH yyyy-mm-dd" is simply
syntactic sugar for "*1 UNTIL yyyy-mm-dd".
.TP
.B trigscanfrom()
Returns (as a \fBDATE\fR type) the \fBSCANFROM\fR parameter of the last \fBREM\fR
or \fBIFTRIG\fR command. If there was no \fBSCANFROM\fR parameter, returns
the integer -1. Note that \fBFROM\fR and \fBSCANFROM\fR interact; a reminder that
has a "FROM yyyy-mm-dd" parameter will act as if it has a \fBSCANFROM\fR parameter
whose value is the maximum of "yyyy-mm-dd" and today.
.TP
.B trigfrom()
Returns (as a \fBDATE\fR type) the \fBFROM\fR parameter of the last \fBREM\fR or
\fBIFTRIG\fR command. If there was no \fBFROM\fR parameter, returns the integer -1.
.TP
.B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag])
Returns a string suitable for use in a \fBREM\fR command or a SCANFROM
Returns a string suitable for use in a \fBREM\fR command or a \fBSCANFROM\fR
or UNTIL clause, allowing you to calculate trigger dates in advance.
Note that in earlier versions of \fBRemind\fR, \fBtrigger\fR was
required to convert a date into something the \fBREM\fR command could
@@ -2805,9 +3010,11 @@ The value for your time zone may differ.
.RE
.TP
.B trigtime()
Returns the time of the last \fBREM\fR command with an \fBAT\fR clause.
If the last \fBREM\fR did not have an \fBAT\fR clause, returns the integer
0.
Returns the time of the last \fBREM\fR command with an \fBAT\fR
clause. If the last \fBREM\fR did not have an \fBAT\fR clause,
returns the integer 0. If a \fBREM\fR command has an \fBAT\fR clause
with a \fBDURATION\fR, then you can compute the end time as
\fBtrigtime() + trigduration()\fR.
.TP
.B trigvalid()
Returns 1 if the value returned by \fBtrigdate()\fR is valid for the most
@@ -2887,6 +3094,98 @@ Returns a number from 0 to 6 representing the day-of-week of the specified
.TP
.B year(dq_date)
Returns a \fBINT\fR that is the year component of \fIdate\fR.
.SH MULTI-DAY EVENTS
If you specify a start time with \fBAT\fR and a duration with
\fBDURATION\fR, you can create events that span multiple days.
Consider these two REM statements:
.PP
.nf
REM 1991-02-13 AT 16:00 DURATION 72:00 MSG 72-hour event
REM 1991-02-13 THROUGH 1991-02-16 AT 16:00 MSG Four events
.fi
.PP
The first statement creates a \fIsingle\fR event that starts on
13 February 1991 at 16:00 and runs through 16 February 1991 at 16:00
.PP
The second statements creates \fIfour separate\fR events that start
at 16:00 on 13, 14, 15 and 16 February 1991 and have indefinite duration.
.PP
Remind handles multi-day events specially. These are the rules:
.PP
On the \fIfirst\fR day of a multi-day event, \fBtrigdatetime()\fR will
return the starting date and time of the event, and \fBtrigduration()\fR
will return the original DURATION.
.PP
On each \fIsubsequent\fR day of a multi-day event, \fBtrigdatetime()\fR
will return midnight on the day in question, and \fBtrigduration()\fR
will return the \fIremaining\fR duration. Consider this example:
.PP
.nf
#!/bin/sh
remind - 12 feb 1991 '*6' <<'EOF'
BANNER %
REM 1991-02-13 AT 16:00 DURATION 72:00 SATISFY 1
set a trigdatetime()
set b trigduration()
set c trigeventstart()
set d trigeventduration()
MSG now=[today()] dt=[a] dur=[b] estart=[c] edur=[d]%
EOF
.fi
.PP
The output is:
.PP
.nf
now=1991-02-12 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
now=1991-02-13 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
now=1991-02-14 dt=1991-02-14@00:00 dur=64:00 estart=1991-02-13@16:00 edur=72:00
now=1991-02-15 dt=1991-02-15@00:00 dur=40:00 estart=1991-02-13@16:00 edur=72:00
now=1991-02-16 dt=1991-02-16@00:00 dur=16:00 estart=1991-02-13@16:00 edur=72:00
now=1991-02-17 dt=1991-02-13@16:00 dur=72:00 estart=-1 edur=-1
.fi
.PP
As you see, the \fBtrigdatetime()\fR and \fBtrigduration()\fR functions
return the start time and duration of the \fIremaining\fR portion of
a multi-day event, whereas \fBtrigeventstart\fR and \fBtrigeventduration\fR
always return the original start and duration of the multi-day event. Note also
that the return value for expired reminders is not reliable; the fact
that \fBtrigeventstart\fR and \fBtrigeventduration\fR return -1 in that case
is an implementation artifact.
.PP
.B SELF-OVERLAPPING EVENTS
.PP
A multi-day event has the possibility of "overlapping itself". When this
happens, \fBRemind\fR prefers the \fIlater\fR event (only one copy of
an event is ever triggered for a given date.) Consider this example:
.PP
.nf
#!/bin/sh
remind - '*5' 10 Feb 1991 <<'EOF'
BANNER %
REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]%
EOF
.fi
.PP
The output is:
.PP
.nf
1991-02-10 1991-02-04@00:00 48:00
1991-02-11 1991-02-11@00:00 192:00
1991-02-12 1991-02-11@00:00 168:00
1991-02-13 1991-02-11@00:00 144:00
1991-02-14 1991-02-11@00:00 120:00
.fi
.PP
Although the event from 1991-02-04 still has 24 hours left on 1991-02-11,
the fresh occurrence on 1991-02-11 takes precedences and is the one that
is triggered.
.PP
I do not recommend constructing self-overlapping multi-day events.
.PP
.SH EXPRESSION PASTING
.PP
An extremely powerful feature of \fBRemind\fR is its macro capability,
@@ -2962,7 +3261,7 @@ three commands are equivalent:
o
You cannot use expression-pasting to determine the type (\fBMSG\fR,
\fBCAL\fR, etc.) of a \fBREM\fR command. You can paste expressions
before and after the \fBMSG\fR, etc keywords, but cannot do something like
before and after the \fBMSG\fR, etc. keywords, but cannot do something like
this:
.PP
.nf
@@ -3058,8 +3357,10 @@ to true if a corresponding \fBREM\fR command would trigger. Examples:
.PP
Note that the \fBIFTRIG\fR command computes a trigger date, which can
be retrieved with the \fBtrigdate()\fR function. You can use all of
the normal trigger components, such as \fBUNTIL\fR, \fIdelta\fR, etc in the
\fBIFTRIG\fR command.
the normal trigger components, such as \fBUNTIL\fR, \fIdelta\fR, etc. in the
\fBIFTRIG\fR command. However, you cannot use a type specifier such
as \fBCAL\fR, \fBMSG\fR or \fBSATISFY\fR; attempting to do so
yields a parse error.
.PP
.SH USER-DEFINED FUNCTIONS
.PP
@@ -3257,12 +3558,12 @@ ends. Otherwise, \fBRemind\fR computes the next trigger date, and re-tests
or non-null, or until the iteration limit specified with the \fB\-x\fR
command-line option is reached.
.PP
If \fIexpr\fR is not satisfied, then \fBtrigvalid()\fR is set to 0.
Otherwise, \fBtrigvalid()\fR is set to 1. In any event, no error message
is issued.
If \fIexpr\fR is not satisfied, then \fBtrigvalid()\fR is set to 0 and
the error message "Can't compute trigger" is issued. Otherwise,
\fBtrigvalid()\fR is set to 1.
.PP
This is really useful only if \fIexpr\fR involves a call to the
\fBtrigdate()\fR function; otherwise, \fIexpr\fR will not change as
\fBtrigdate()\fR or related functions; otherwise, \fIexpr\fR will not change as
\fBRemind\fR iterates.
.PP
An example of the usefulness of \fBSATISFY\fR: Suppose you wish to
@@ -3285,6 +3586,12 @@ more complicated sequence:
ENDIF
.fi
.PP
You can write the REM statement a little more concisely:
.PP
.nf
REM 13 SATISFY $Tw == 5
.fi
.PP
Let's see how this works. The \fBSATISFY\fR clause iterates through
all the 13ths of successive months, until a trigger date is found whose
day-of-week is Friday (== 5). If a valid date was found, we use the
@@ -3325,7 +3632,7 @@ However, when \fBRemind\fR gets around to calculating the trigger
for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
omitting Labour Day for 1993, and the "Mon AFTER" command
will not be triggered. (But see the description of \fBSCANFROM\fR
in the section "Details about Trigger Computation.")
in the section "DETAILS ABOUT TRIGGER COMPUTATION.")
.PP
It is probably best to stay away from computing \fBOMIT\fR
trigger dates unless you keep these pitfalls in mind.
@@ -3339,7 +3646,7 @@ follows:
.fi
.PP
Note that for this case only, the \fIexpr\fR after \fBSATISFY\fR
\fImust\fR be enclosed in braces. It must come after all the other
\fImust\fR be enclosed in square brackets. It must come after all the other
components of the trigger, and immediately before the \fBMSG\fR,
\fBRUN\fR, etc. keyword. If \fIexpr\fR cannot be satisfied, then
the reminder is not triggered.
@@ -3347,22 +3654,49 @@ the reminder is not triggered.
Thus, the "Friday the 13th" example can be expressed more compactly as:
.PP
.nf
REM 13 +2 SATISFY [wkdaynum(trigdate()) == 5] \\
MSG Friday the 13th is %b.
REM 13 +2 SATISFY [$Tw == 5] MSG Friday the 13th is %b.
.fi
.PP
And you can trigger a reminder on Mondays, Wednesdays and Thursdays
occurring on odd-numbered days of the month with the following:
.PP
.nf
REM Mon Wed Thu SATISFY [day(trigdate())%2] \\
MSG Here it is!!!
REM Mon Wed Thu SATISFY [$Td %2 ] MSG Here it is!!!
.fi
.PP
Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
.PP
.SH POSSIBLY-UNCOMPUTABLE TRIGGERS
.PP
Occasionally, you may wish to suppress the "Can't compute trigger" warnings
for reminders for which a trigger date cannot be compute. For example,
the following reminder is triggered on a Monday that is not a holiday
if the following Tuesday is a holiday:
.PP
.nf
REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
However, if there are no Mondays after today's date that satisfy the
condition, Remind will print the "Can't compute trigger" error. To
suppress this, use the \fBMAYBE-UNCOMPUTABLE\fR keyword:
.PP
.nf
REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
It's almost never appropriate to use \fBMAYBE-UNCOMPUTABLE\fR, but it is
provided for those rare occasions when it makes sense. If you use
\fBMAYBE-UNCOMPUTABLE\fR inside the \fBevaltrig()\fR function, then
untriggerable triggers return -1. For example:
.PP
.nf
SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT Mon")
.fi
.PP
will set a to -1.
.SH DEBUGGING REMINDER SCRIPTS
.PP
Although the command-line \fB\-d\fR option is useful for debugging, it
@@ -3476,11 +3810,11 @@ the body in the %"...%" sequence, only that portion is inserted. For
example, consider the following:
.PP
.nf
REM 6 Jan MSG %"David's birthday%" is %b
REM 6 Jan MSG %"Dianne's birthday%" is %b
.fi
.PP
In the normal mode, \fBRemind\fR would print "David's birthday is today"
on 6 January. However, in the calendar mode, only the text "David's birthday"
In the normal mode, \fBRemind\fR would print "Dianne's birthday is today"
on 6 January. However, in the calendar mode, only the text "Dianne's birthday"
is inserted into the box for 6 January.
.PP
If you explicitly use the %"...%" sequence in a \fBRUN\fR-type reminder,
@@ -3525,7 +3859,7 @@ iterations. On the next iteration, the commands are skipped, since
initialized has remained defined. Thus, time-consuming operations that
do not depend on the value of \fBtoday()\fR are done only once.
.PP
System variables (those whose names start with '$') are automatically
Most system variables (those whose names start with '$') are automatically
preserved between calendar iterations.
.PP
Note that for efficiency, \fBRemind\fR caches the reminder script
@@ -4114,7 +4448,7 @@ They are used only when piping data from a \fBremind \-p\fR line.
equivalent of MSG in \fBremind's\fR normal mode of operation.)
.PP
The various \fBSPECIAL\fRs recognized are particular for each
backend; however, there are three \fBSPECIAL\fRs that all backends
backend; however, there are four \fBSPECIAL\fRs that all backends
should attempt to support. They are currently supported by
\fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.
.PP
@@ -4177,9 +4511,12 @@ The rest of the line is the text to put in the calendar.
.PP
The COLOR special is "doubly special", because in its normal operating
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
Also, if you invoke \fBRemind\fR with \fB\-cc\fR..., then it approximates
Also, if you invoke \fBRemind\fR with \fB\-@\fR[\fIn\fR], then it approximates
SPECIAL COLOR reminders on your terminal.
.PP
See also the documentation of the \fB$DefaultColor\fR system variable
in the section "SYSTEM VARIABLES".
.PP
The \fBWEEK\fR special lets you place annotations such as the week
number in the calendar. For example, this would number each Monday
with the ISO 8601 week number. The week number is shown like this:
@@ -4332,6 +4669,18 @@ from 7 days before the current date. This ensures that Labour Day for
the current year will continue to be triggered until 7 days after it has
occurred. This allows you to safely use the AFTER keyword as shown.
.PP
As a special case, you can simply use a negative number after SCANFROM;
a negative numbner \-N is interpreted as N days before today. Thus,
the previous example could also be written like this:
.PP
.nf
# This form of SCANFROM requires Remind 03.01.17 or later.
REM Mon 1 Sept SCANFROM \-7 SATISFY 1
OMIT [trigdate()]
REM Mon AFTER MSG Hello
.fi
.PP
In general, use \fBSCANFROM\fR as shown for safe movable \fBOMITs\fR. The
amount you should scan back by (7 days in the example above) depends on
the number of possible consecutive \fBOMITted\fR days that may occur, and
@@ -4386,10 +4735,7 @@ Note that this behaviour is not true for
versions of \fBRemind\fR prior to 03.00.01.
.SH AUTHOR
.PP
Remind is now supported by Roaring Penguin Software
Inc. (http://www.roaringpenguin.com)
.PP
David F. Skoll <dfs@roaringpenguin.com> wrote \fBRemind\fR. The moon code
Dianne Skoll <dianne@skoll.ca> wrote \fBRemind\fR. The moon code
was copied largely unmodified from "moontool" by John Walker. The
sunrise and sunset functions use ideas from programs by Michael
Schwartz and Marc T. Kaufman. The Hebrew calendar support was taken

View File

@@ -1,4 +1,4 @@
.TH TKREMIND 1 "15 February 1998"
.TH TKREMIND 1 "1 January 2020"
.UC 4
.SH NAME
tkremind \- graphical front-end to Remind calendar program
@@ -104,7 +104,7 @@ edit the reminder, thereby gaining access to advanced features of
\fBRemind\fR's idioms for expressing different types of reminders.
.SH PRINTING
To print the current month's calender, click \fBPrint...\fR on the
To print the current month's calendar, click \fBPrint...\fR on the
main calendar window. This brings up the print dialog. Printing
either produces a PostScript file or sends PostScript to a UNIX command.
@@ -125,10 +125,11 @@ Select the appropriate paper size and orientation. Activate
be the normal case unless you have many reminders in a particular
day. (See the \fBRem2PS\fR documentation.)
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel.
Note that during printing, \fBRemind\fR is \fInot\fR called with
the \fB-itkremind=1\fR option, because it is operated in normal
PostScript-producing mode.
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Note
that during printing, \fBRemind\fR is called with the
\fB-itkremind=1\fR option and also an additional \fB-itkprint=1\fR
option.
.SH EDITING REMINDERS
@@ -210,7 +211,8 @@ background reminder pops up.
.TP
.B Feed popped-up reminder to command's standard input
If selected, feeds the text of the reminder to the command described
above.
above. The text of the reminder is prefixed by "HH:MM ", where HH:MM
is the time of the reminder.
.TP
.B E-mail reminders here if popup not dismissed
@@ -358,13 +360,9 @@ This line is emitted in response to a \fBSTATUS\fR command. The number
\fIn\fR is the number of reminders in the queue.
.SH AUTHOR
TkRemind is now supported by Roaring Penguin Software
Inc. (http://www.roaringpenguin.com)
.PP
TkRemind was written by David F. Skoll <dfs@roaringpenguin.com>.
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
\fBTkRemind\fR is Copyright 1996-1998 by David F. Skoll, Copyright
1999 by Roaring Penguin Software Inc.
\fBTkRemind\fR is Copyright 1996-2020 by Dianne Skoll.
.SH FILES

3
scripts/cm2rem.tcl Executable file → Normal file
View File

@@ -8,8 +8,7 @@
# files (version 3 only) to Remind format.
#
# This file is part of REMIND.
# Copyright (C) 1992-1998 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
#
#--------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -43,8 +43,10 @@ test: remind
.c.o:
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) $(LANGDEF) -I. -I$(srcdir) $<
rem2ps: rem2ps.o dynbuf.o
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o
$(REMINDOBJS): $(REMINDHDRS)
rem2ps: rem2ps.o dynbuf.o json.o
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
remind: $(REMINDOBJS)
@CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
@@ -72,23 +74,21 @@ clobber:
rm -f *.o *~ remind rem2ps test.out core *.bak
depend:
gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c
gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c json.c
# The next targets are not very useful to you. I use them to build
# distributions, etc.
# Build a tar file based on all files checked into git.
distro:
ln -s . ../remind-$(VERSION)
(cd ..; git ls-files | fgrep -v .gitignore | fgrep -v remind.php) | sed -e 's/^/remind-$(VERSION)\//' | xargs tar -C .. -cvf remind-$(VERSION).tar
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION).tar
gzip -f -v -9 remind-$(VERSION).tar
rm -f ../remind-$(VERSION)
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION).tar.gz
beta-tgz:
ln -s . ../remind-$(VERSION)-BETA-$(BETA)
(cd ..; git ls-files | fgrep -v .gitignore | fgrep -v remind.php) | sed -e 's/^/remind-$(VERSION)-BETA-$(BETA)\//' | xargs tar -C .. -cvf remind-$(VERSION)-BETA-$(BETA).tar
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)-BETA-$(BETA)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar
gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar
rm -f ../remind-$(VERSION)-BETA-$(BETA)
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION)-BETA-$(BETA).tar.gz
#---------------- Stuff after this added by "make depend" -----------------

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,7 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -37,7 +36,7 @@
/*---------------------------------------------------------------------*/
#define DEFAULT_PAGE {"Letter", 612, 792}
/* #define DEFAULT_PAGE {"A4", 595, 842} */
/*---------------------------------------------------------------------*/
/* DATESEP: The default date separator. Standard usage is '-'; */
/* others may prefer '/'. */
@@ -52,6 +51,13 @@
#define TIMESEP ':'
/* #define TIMESEP '.' */
/*---------------------------------------------------------------------*/
/* DATETIMESEP: The default datetime separator. Default is '@'; */
/* others may prefer 'T'. */
/*---------------------------------------------------------------------*/
#define DATETIMESEP '@'
/* #define DATETIMESEP '/' */
/*---------------------------------------------------------------------*/
/* ISOLATIN1: define it to 1 if you use the */
/* ISO 8859-1 character set instead of ASCII. */
@@ -140,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */
/*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16
#define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */
@@ -178,7 +184,7 @@
/*---------------------------------------------------------------------*/
/* How many attempts to resolve a weird date spec? */
/*---------------------------------------------------------------------*/
#define TRIG_ATTEMPTS 50
#define TRIG_ATTEMPTS 500
/*---------------------------------------------------------------------*/
/* How many global omits of the form YYYY MM DD do we handle? */
@@ -214,6 +220,9 @@
#define PSBEGIN "# rem2ps begin"
#define PSEND "# rem2ps end"
#define PSBEGIN2 "# rem2ps2 begin"
#define PSEND2 "# rem2ps2 end"
#ifdef BROKEN_PUTC
#define Putc SafePutc
#define PutChar SafePutChar

View File

@@ -6,8 +6,7 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -37,7 +36,7 @@
/*---------------------------------------------------------------------*/
#define DEFAULT_PAGE {"Letter", 612, 792}
/* #define DEFAULT_PAGE {"A4", 595, 842} */
/*---------------------------------------------------------------------*/
/* DATESEP: The default date separator. Standard usage is '-'; */
/* others may prefer '/'. */
@@ -52,6 +51,13 @@
#define TIMESEP ':'
/* #define TIMESEP '.' */
/*---------------------------------------------------------------------*/
/* DATETIMESEP: The default datetime separator. Default is '@'; */
/* others may prefer 'T'. */
/*---------------------------------------------------------------------*/
#define DATETIMESEP '@'
/* #define DATETIMESEP '/' */
/*---------------------------------------------------------------------*/
/* ISOLATIN1: define it to 1 if you use the */
/* ISO 8859-1 character set instead of ASCII. */
@@ -140,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */
/*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16
#define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */
@@ -214,6 +220,9 @@
#define PSBEGIN "# rem2ps begin"
#define PSEND "# rem2ps end"
#define PSBEGIN2 "# rem2ps2 begin"
#define PSEND2 "# rem2ps2 end"
#ifdef BROKEN_PUTC
#define Putc SafePutc
#define PutChar SafePutChar

View File

@@ -7,8 +7,7 @@
/* commands. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -19,9 +18,9 @@
#include <stdlib.h>
#include "types.h"
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
@@ -35,6 +34,17 @@ static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
static int ParsePriority (ParsePtr s, Trigger *t);
static int ParseUntil (ParsePtr s, Trigger *t);
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
static int ComputeTrigDuration(TimeTrig *t);
static int
ComputeTrigDuration(TimeTrig *t)
{
if (t->ttime == NO_TIME ||
t->duration == NO_TIME) {
return 0;
}
return (t->ttime + t->duration - 1) / MINUTES_PER_DAY;
}
/***************************************************************/
/* */
@@ -71,6 +81,9 @@ int DoRem(ParsePtr p)
PurgeEchoLine("%s\n", CurLine);
r=DoSatRemind(&trig, &tim, p);
if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig);
if (r == E_EXPIRED) return OK;
return r;
@@ -118,12 +131,15 @@ int DoRem(ParsePtr p)
}
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
if (PurgeMode) {
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
PurgeEchoLine("%s\n", CurLine);
}
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig);
return r;
}
@@ -201,10 +217,15 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->once = NO_ONCE;
trig->typ = NO_TYPE;
trig->scanfrom = NO_DATE;
trig->from = NO_DATE;
trig->priority = DefaultPrio;
trig->sched[0] = 0;
trig->warn[0] = 0;
trig->omitfunc[0] = 0;
trig->duration_days = 0;
trig->eventstart = NO_TIME;
trig->eventduration = NO_TIME;
trig->maybe_uncomputable = 0;
DBufInit(&(trig->tags));
trig->passthru[0] = 0;
tim->ttime = NO_TIME;
@@ -246,6 +267,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
tim->ttime = (tok.val % MINUTES_PER_DAY);
if (save_in_globals) {
LastTriggerTime = tim->ttime;
SaveLastTimeTrig(tim);
}
break;
@@ -261,6 +283,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->m = tok.val;
break;
case T_MaybeUncomputable:
trig->maybe_uncomputable = 1;
break;
case T_Skip:
DBufFree(&buf);
if (trig->skip != NO_SKIP) return E_SKIP_ERR;
@@ -277,6 +303,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
DBufFree(&buf);
r=ParseTimeTrig(s, tim, save_in_globals);
if (r) return r;
trig->duration_days = ComputeTrigDuration(tim);
break;
case T_Scanfrom:
@@ -373,6 +400,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
r=ParseToken(s, &buf);
if (r) return r;
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
/* An OMITFUNC counts as a nonconst_expr! */
s->expr_happened = 1;
s->nonconst_expr = 1;
DBufFree(&buf);
break;
@@ -397,7 +428,18 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
switch(tok.type) {
case T_Time:
case T_LongTime:
tim->duration = tok.val;
case T_Year:
case T_Day:
case T_Number:
if (tok.val != 0) {
tim->duration = tok.val;
} else {
tim->duration = NO_TIME;
}
if (save_in_globals) {
SaveLastTimeTrig(tim);
}
trig->duration_days = ComputeTrigDuration(tim);
break;
default:
return E_BAD_TIME;
@@ -447,16 +489,19 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
switch(tok.type) {
case T_Time:
DBufFree(&buf);
if (tim->ttime != NO_TIME) return E_TIME_TWICE;
tim->ttime = tok.val;
break;
case T_Delta:
DBufFree(&buf);
if (tim->delta != NO_DELTA) return E_DELTA_TWICE;
tim->delta = (tok.val > 0) ? tok.val : -tok.val;
break;
case T_Rep:
DBufFree(&buf);
if (tim->rep != NO_REP) return E_REP_TWICE;
tim->rep = tok.val;
break;
@@ -466,6 +511,7 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
/* Save trigger time in global variable */
if (save_in_globals) {
LastTriggerTime = tim->ttime;
SaveLastTimeTrig(tim);
}
PushToken(DBufValue(&buf), s);
DBufFree(&buf);
@@ -664,6 +710,30 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
FromJulian(tok.val, &y, &m, &d);
break;
case T_Back:
DBufFree(&buf);
if (type != SCANFROM_TYPE) {
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
return E_INCOMPLETE;
}
if (y != NO_YR) {
Eprint("%s: %s", word, ErrMsg[E_YR_TWICE]);
return E_YR_TWICE;
}
if (m != NO_MON) {
Eprint("%s: %s", word, ErrMsg[E_MON_TWICE]);
return E_MON_TWICE;
}
if (d != NO_DAY) {
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE;
}
if (tok.val < 0) {
tok.val = -tok.val;
}
FromJulian(JulianToday - tok.val, &y, &m, &d);
break;
default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
@@ -676,9 +746,12 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
}
t->scanfrom = Julian(y, m, d);
if (type == FROM_TYPE) {
t->from = t->scanfrom;
if (t->scanfrom < JulianToday) {
t->scanfrom = JulianToday;
}
} else {
t->from = NO_DATE;
}
PushToken(DBufValue(&buf), s);
@@ -704,20 +777,24 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
char const *s;
Value v;
int red = -1, green = -1, blue = -1;
int is_color = 0;
DBufInit(&buf);
DBufInit(&calRow);
DBufInit(&pre_buf);
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
if ((t->typ == PASSTHRU_TYPE && strcmp(t->passthru, "COLOR") && strcmp(t->passthru, "COLOUR")) ||
if ((t->typ == PASSTHRU_TYPE && StrCmpi(t->passthru, "COLOR") && StrCmpi(t->passthru, "COLOUR")) ||
t->typ == CAL_TYPE ||
t->typ == PS_TYPE ||
t->typ == PSF_TYPE)
return OK;
/* Handle COLOR types */
if (t->typ == PASSTHRU_TYPE && (!strcmp(t->passthru, "COLOR") || !strcmp(t->passthru, "COLOUR"))) {
if (t->typ == PASSTHRU_TYPE && (!StrCmpi(t->passthru, "COLOR") || !StrCmpi(t->passthru, "COLOUR"))) {
/* Strip off three tokens */
r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &red);
if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' ');
@@ -725,6 +802,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf);
if (r) return r;
r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &green);
if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' ');
@@ -732,6 +810,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf);
if (r) return r;
r = ParseToken(p, &buf);
sscanf(DBufValue(&buf), "%d", &blue);
if (!NextMode) {
DBufPuts(&pre_buf, DBufValue(&buf));
DBufPutc(&pre_buf, ' ');
@@ -751,10 +830,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf);
}
/* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
format. */
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
simple-calendar format. */
if (NextMode) {
if ( (r=DoSubst(p, &buf, t, tim, jul, CAL_MODE)) ) return r;
if ( (r=DoSubst(p, &buf, t, tim, jul, ADVANCE_MODE)) ) return r;
if (!DBufLen(&buf)) {
DBufFree(&buf);
DBufFree(&pre_buf);
@@ -815,6 +894,23 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
return OK;
}
/* Correct colors */
if (UseVTColors) {
if (red == -1 && green == -1 && blue == -1) {
if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) {
red = DefaultColorR;
green = DefaultColorG;
blue = DefaultColorB;
}
}
if (red >= 0 && green >= 0 && blue >= 0) {
is_color = 1;
if (red > 255) red = 255;
if (green > 255) green = 255;
if (blue > 255) blue = 255;
}
}
/* Put the substituted string into the substitution buffer */
/* Don't use msgprefix() on RUN-type reminders */
@@ -825,6 +921,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
r = EvalExpr(&s, &v, NULL);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf);
DestroyValue(v);
@@ -836,6 +935,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
}
}
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
if (t->typ != RUN_TYPE) {
if (UserFuncExists("msgsuffix") == 1) {
@@ -844,6 +946,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
r = EvalExpr(&s, &v, NULL);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
}
if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf);
DestroyValue(v);
@@ -855,6 +960,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
}
}
if (is_color) {
DBufPuts(&buf, Decolorize(red, green, blue));
}
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
if (DBufPutc(&buf, '\n') != OK) {
DBufFree(&buf);
@@ -889,7 +998,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
break;
case RUN_TYPE:
system(DBufValue(&buf));
System(DBufValue(&buf));
break;
default: /* Unknown/illegal type? */
@@ -993,21 +1102,35 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
/* Do the "satisfying..." remind calculation. */
/* */
/***************************************************************/
int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
{
int iter, jul, r;
int iter, jul, r, start;
Value v;
char const *s;
char const *t;
t = p->pos;
iter = 0;
jul = trig->scanfrom;
start = trig->scanfrom;
while (iter++ < MaxSatIter) {
jul = ComputeTrigger(jul, trig, &r, 1);
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
if (jul != start && trig->duration_days) {
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
} else if (jul == start) {
if (tt->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
if (tt->duration != NO_TIME) {
trig->eventduration = tt->duration;
}
}
SaveAllTriggerInfo(trig, tt, jul, tt->ttime, 1);
}
if (jul == -1) {
return E_EXPIRED;
}
@@ -1016,14 +1139,42 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
t = p->pos;
if (r) return r;
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
if (v.type == INT_TYPE && v.v.val) return OK;
if (v.type == STR_TYPE && *v.v.str) return OK;
if ((v.type == INT_TYPE && v.v.val) ||
(v.type == STR_TYPE && *v.v.str)) {
AdjustTriggerForDuration(trig->scanfrom, jul, trig, tt, 1);
if (DebugFlag & DB_PRTTRIG) {
int y, m, d;
FromJulian(LastTriggerDate, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
FileName, LineNo,
DayName[LastTriggerDate % 7],
d,
MonthName[m],
y);
if (tt->ttime != NO_TIME) {
fprintf(ErrFp, " AT %02d:%02d",
(tt->ttime / 60),
(tt->ttime % 60));
if (tt->duration != NO_TIME) {
fprintf(ErrFp, " DURATION %02d:%02d",
(tt->duration / 60),
(tt->duration % 60));
}
}
fprintf(ErrFp, "\n");
}
return OK;
}
p->pos = s;
jul++;
if (jul+trig->duration_days < start) {
start++;
} else {
start = jul+trig->duration_days+1;
}
}
p->pos = t;
LastTrigValid = 0;
return OK;
return E_CANT_TRIG;
}
/***************************************************************/
@@ -1117,7 +1268,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
}
r = OK;
system(DBufValue(&execBuffer));
System(DBufValue(&execBuffer));
finished:
DBufFree(&buf);

View File

@@ -6,8 +6,7 @@
/* reminders are triggered. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -19,9 +18,9 @@
#include <stdlib.h>
#include "types.h"
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#define UPPER(c) (islower(c) ? toupper(c) : (c))
@@ -645,10 +644,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break;
case '_':
if (mode != CAL_MODE && mode != ADVANCE_MODE && !MsgCommand)
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || (mode != CAL_MODE && mode != ADVANCE_MODE && !MsgCommand)) {
sprintf(s, "%s", NL);
else
} else {
sprintf(s, " ");
}
SHIP_OUT(s);
break;
@@ -657,8 +657,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break;
case '"':
if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
has_quote = 1;
if (PsCal != PSCAL_LEVEL3) {
if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
has_quote = 1;
} else {
if (DBufPutc(dbuf, '%') != OK) return E_NO_MEM;
if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
}
break;
default:

View File

@@ -6,8 +6,7 @@
/* buffers. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -151,7 +150,9 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
we can usually save some unnecessary copying */
*(dbuf->buffer) = 0;
fgets(dbuf->buffer, dbuf->allocatedLen, fp);
if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
return OK;
}
if (!*(dbuf->buffer)) return OK;
dbuf->len = strlen(dbuf->buffer);
l = dbuf->len - 1;
@@ -163,7 +164,7 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
while(busy) {
*tmp = 0;
fgets(tmp, 256, fp);
if (fgets(tmp, 256, fp) == NULL) return OK;
if (!*tmp) return OK;
l = strlen(tmp) - 1;
if (tmp[l] == '\n') {

View File

@@ -5,8 +5,7 @@
/* Declaration of functions for manipulating dynamic buffers */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,8 +5,7 @@
/* Error definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -119,7 +118,8 @@
#define E_CANT_CONVERT_TZ 99
#define E_NO_MATCHING_REMS 100
#define E_STRING_TOO_LONG 101
#define E_TIME_TWICE 102
#define E_DURATION_NO_AT 103
#ifdef MK_GLOBALS
#undef EXTERN
#define EXTERN
@@ -234,7 +234,9 @@ EXTERN char *ErrMsg[]
"Bad function in WARN clause",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
}
#endif /* MK_GLOBALS */
;

View File

@@ -5,8 +5,7 @@
/* This file contains routines to parse and evaluate */
/* expressions. */
/* */
/* Copyright 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -31,7 +30,6 @@
#define LE 4
#define NE 5
static char CoerceBuf[512];
extern int NumFuncs;
static int Multiply(void), Divide(void), Mod(void), Add(void),
@@ -494,6 +492,7 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
{
int len;
int h, m, r;
int ampm = 0;
if (*s == '\"') { /* It's a literal string "*/
len = strlen(s)-1;
@@ -534,7 +533,27 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
m += *s - '0';
s++;
}
/* Check for p[m] or a[m] */
if (*s == 'A' || *s == 'a' || *s == 'P' || *s == 'p') {
ampm = tolower(*s);
s++;
if (*s == 'm' || *s == 'M') {
s++;
}
}
if (*s || h>23 || m>59) return E_BAD_TIME;
if (ampm) {
if (h < 1 || h > 12) return E_BAD_TIME;
if (ampm == 'a') {
if (h == 12) {
h = 0;
}
} else if (ampm == 'p') {
if (h < 12) {
h += 12;
}
}
}
v->type = TIME_TYPE;
v->v.val = h*60 + m;
return OK;
@@ -579,6 +598,8 @@ int DoCoerce(char type, Value *v)
int h, d, m, y, i, k;
char const *s;
char coerce_buf[128];
/* Do nothing if value is already the right type */
if (type == v->type) return OK;
@@ -606,12 +627,12 @@ int DoCoerce(char type, Value *v)
}
case STR_TYPE:
switch(v->type) {
case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
case TIME_TYPE: sprintf(CoerceBuf, "%02d%c%02d", v->v.val / 60,
case INT_TYPE: sprintf(coerce_buf, "%d", v->v.val); break;
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
TimeSep, v->v.val % 60);
break;
case DATE_TYPE: FromJulian(v->v.val, &y, &m, &d);
sprintf(CoerceBuf, "%04d%c%02d%c%02d",
sprintf(coerce_buf, "%04d%c%02d%c%02d",
y, DateSep, m+1, DateSep, d);
break;
case DATETIME_TYPE:
@@ -620,13 +641,13 @@ int DoCoerce(char type, Value *v)
k = v->v.val % MINUTES_PER_DAY;
h = k / 60;
i = k % 60;
sprintf(CoerceBuf, "%04d%c%02d%c%02d@%02d%c%02d",
y, DateSep, m+1, DateSep, d, h, TimeSep, i);
sprintf(coerce_buf, "%04d%c%02d%c%02d%c%02d%c%02d",
y, DateSep, m+1, DateSep, d, DateTimeSep, h, TimeSep, i);
break;
default: return E_CANT_COERCE;
}
v->type = STR_TYPE;
v->v.str = StrDup(CoerceBuf);
v->v.str = StrDup(coerce_buf);
if (!v->v.str) {
v->type = ERR_TYPE;
return E_NO_MEM;
@@ -701,26 +722,12 @@ int DoCoerce(char type, Value *v)
return OK;
case STR_TYPE:
h = 0;
m = 0;
s = v->v.str;
if (!isdigit(*s)) return E_CANT_COERCE;
while (isdigit(*s)) {
h *= 10;
h += *s++ - '0';
}
if (*s != ':' && *s != '.' && *s != TimeSep)
return E_CANT_COERCE;
s++;
if (!isdigit(*s)) return E_CANT_COERCE;
while (isdigit(*s)) {
m *= 10;
m += *s++ - '0';
}
if (*s || h>23 || m>59) return E_CANT_COERCE;
if (ParseLiteralTime(&s, &i)) return E_CANT_COERCE;
if (*s) return E_CANT_COERCE;
v->type = TIME_TYPE;
free(v->v.str);
v->v.val = h*60+m;
v->v.val = i;
return OK;
default: return E_CANT_COERCE;
@@ -766,9 +773,9 @@ static int Add(void)
return OK;
}
/* If it's a datetime plus an int, add 'em */
if ((v1.type == DATETIME_TYPE && v2.type == INT_TYPE) ||
(v1.type == INT_TYPE && v2.type == DATETIME_TYPE)) {
/* If it's a datetime plus an int or a time, add 'em */
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
v1.v.val += v2.v.val;
if (v1.v.val < 0) return E_DATE_OVER;
v1.type = DATETIME_TYPE;
@@ -776,9 +783,11 @@ static int Add(void)
return OK;
}
/* If it's a time plus an int, add 'em mod MINUTES_PER_DAY */
/* If it's a time plus an int or a time plus a time,
add 'em mod MINUTES_PER_DAY */
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
(v1.type == INT_TYPE && v2.type == TIME_TYPE)) {
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
v1.v.val = (v1.v.val + v2.v.val) % MINUTES_PER_DAY;
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
v1.type = TIME_TYPE;
@@ -799,7 +808,7 @@ static int Add(void)
v3.type = STR_TYPE;
l1 = strlen(v1.v.str);
l2 = strlen(v2.v.str);
if (MaxStringLen && (l1 + l2 > MaxStringLen)) {
if (MaxStringLen && (l1 + l2 > (size_t) MaxStringLen)) {
DestroyValue(v1); DestroyValue(v2);
return E_STRING_TOO_LONG;
}
@@ -809,7 +818,7 @@ static int Add(void)
return E_NO_MEM;
}
strcpy(v3.v.str, v1.v.str);
strcat(v3.v.str, v2.v.str);
strcpy(v3.v.str+l1, v2.v.str);
DestroyValue(v1); DestroyValue(v2);
PushValStack(v3);
return OK;
@@ -852,8 +861,9 @@ static int Subtract(void)
return OK;
}
/* If it's a datetime minus an int, do subtraction, checking for underflow */
if (v1.type == DATETIME_TYPE && v2.type == INT_TYPE) {
/* If it's a datetime minus an int or a time, do subtraction,
* checking for underflow */
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
v1.v.val -= v2.v.val;
if (v1.v.val < 0) return E_DATE_OVER;
PushValStack(v1);
@@ -1193,7 +1203,7 @@ void PrintValue (Value *v, FILE *fp)
}
else if (v->type == DATETIME_TYPE) {
FromJulian(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
fprintf(fp, "%04d%c%02d%c%02d@%02d%c%02d", y, DateSep, m+1, DateSep, d,
fprintf(fp, "%04d%c%02d%c%02d%c%02d%c%02d", y, DateSep, m+1, DateSep, d, DateTimeSep,
(v->v.val % MINUTES_PER_DAY) / 60, TimeSep, (v->v.val % MINUTES_PER_DAY) % 60);
}
else fprintf(fp, "ERR");
@@ -1219,6 +1229,48 @@ int CopyValue(Value *dest, const Value *src)
return OK;
}
int ParseLiteralTime(char const **s, int *tim)
{
int h=0;
int m=0;
int ampm=0;
if (!isdigit(**s)) return E_BAD_TIME;
while(isdigit(**s)) {
h *= 10;
h += *(*s)++ - '0';
}
if (**s != ':' && **s != '.' && **s != TimeSep) return E_BAD_TIME;
(*s)++;
if (!isdigit(**s)) return E_BAD_TIME;
while(isdigit(**s)) {
m *= 10;
m += *(*s)++ - '0';
}
/* Check for p[m] or a[m] */
if (**s == 'A' || **s == 'a' || **s == 'P' || **s == 'p') {
ampm = tolower(**s);
(*s)++;
if (**s == 'm' || **s == 'M') {
(*s)++;
}
}
if (h>23 || m>59) return E_BAD_TIME;
if (ampm) {
if (h < 1 || h > 12) return E_BAD_TIME;
if (ampm == 'a') {
if (h == 12) {
h = 0;
}
} else if (ampm == 'p') {
if (h < 12) {
h += 12;
}
}
}
*tim = h * 60 + m;
return OK;
}
/***************************************************************/
/* */
/* ParseLiteralDate */
@@ -1230,10 +1282,9 @@ int CopyValue(Value *dest, const Value *src)
int ParseLiteralDate(char const **s, int *jul, int *tim)
{
int y, m, d;
int hour, min;
int r;
y=0; m=0; d=0;
hour=0; min=0;
*tim = NO_TIME;
if (!isdigit(**s)) return E_BAD_DATE;
@@ -1261,22 +1312,11 @@ int ParseLiteralDate(char const **s, int *jul, int *tim)
*jul = Julian(y, m, d);
/* Do we have a time part as well? */
if (**s == ' ' || **s == '@') {
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {
(*s)++;
while(isdigit(**s)) {
hour *= 10;
hour += *(*s)++ - '0';
}
if (**s != ':' && **s != '.' && **s != TimeSep) return E_BAD_TIME;
(*s)++;
while(isdigit(**s)) {
min *= 10;
min += *(*s)++ - '0';
}
if (hour > 23 || min > 59) return E_BAD_TIME;
*tim = hour * 60 + min;
r = ParseLiteralTime(s, tim);
if (r != OK) return r;
}
return OK;
}

View File

@@ -5,8 +5,7 @@
/* Contains a few definitions used by expression evaluator. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -7,8 +7,7 @@
/* files. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -181,6 +180,8 @@ int ReadLine(void)
static int ReadLineFromFile(void)
{
int l;
char copy_buffer[4096];
size_t n;
DynamicBuffer buf;
@@ -234,8 +235,25 @@ static int ReadLineFromFile(void)
DBufFree(&LineBuffer);
return E_NO_MEM;
}
FreshLine = 1;
DBufFree(&buf);
/* If the line is: __EOF__ treat it as end-of-file */
CurLine = DBufValue(&LineBuffer);
if (!strcmp(CurLine, "__EOF__")) {
if (PurgeMode && PurgeFP) {
PurgeEchoLine("%s\n", "__EOF__");
while ((n = fread(copy_buffer, 1, sizeof(copy_buffer), fp)) != 0) {
fwrite(copy_buffer, 1, n, PurgeFP);
}
if (PurgeFP != stdout) fclose(PurgeFP);
PurgeFP = NULL;
}
FCLOSE(fp);
DBufFree(&LineBuffer);
CurLine = DBufValue(&LineBuffer);
}
FreshLine = 1;
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
return OK;
}
@@ -348,12 +366,12 @@ static int CacheFile(char const *fname)
cl = NULL;
/* Create a file header */
cf = NEW(CachedFile);
cf->cache = NULL;
if (!cf) {
ShouldCache = 0;
FCLOSE(fp);
return E_NO_MEM;
}
cf->cache = NULL;
cf->filename = StrDup(fname);
if (!cf->filename) {
ShouldCache = 0;

View File

@@ -6,8 +6,7 @@
/* expressions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -54,90 +53,108 @@
#define RetVal (info->retval)
/* Function prototypes */
static int FCurrent (func_info *);
static int FNonomitted (func_info *);
static int FTimepart(func_info *);
static int FDatepart(func_info *);
static int FRealCurrent(func_info *);
static int FAbs (func_info *);
static int FAccess (func_info *);
static int FArgs (func_info *);
static int FAsc (func_info *);
static int FBaseyr (func_info *);
static int FChar (func_info *);
static int FChoose (func_info *);
static int FCoerce (func_info *);
static int FDate (func_info *);
static int FDateTime (func_info *);
static int FDay (func_info *);
static int FDaysinmon (func_info *);
static int FDefined (func_info *);
static int FDosubst (func_info *);
static int FEasterdate (func_info *);
static int FEvalTrig (func_info *);
static int FFiledate (func_info *);
static int FFiledatetime (func_info *);
static int FFiledir (func_info *);
static int FFilename (func_info *);
static int FGetenv (func_info *);
static int FHebdate (func_info *);
static int FHebday (func_info *);
static int FHebmon (func_info *);
static int FHebyear (func_info *);
static int FHour (func_info *);
static int FIif (func_info *);
static int FIndex (func_info *);
static int FIsdst (func_info *);
static int FIsomitted (func_info *);
static int FSlide (func_info *);
static int FLanguage (func_info *);
static int FMax (func_info *);
static int FMin (func_info *);
static int FMinute (func_info *);
static int FMinsfromutc (func_info *);
static int FMoondate (func_info *);
static int FMoondatetime (func_info *);
static int FMoonphase (func_info *);
static int FMoontime (func_info *);
static int FMon (func_info *);
static int FMonnum (func_info *);
static int FOrd (func_info *);
static int FOstype (func_info *);
static int FPlural (func_info *);
static int FSgn (func_info *);
static int FPsmoon (func_info *);
static int FPsshade (func_info *);
static int FShell (func_info *);
static int FStrlen (func_info *);
static int FSubstr (func_info *);
static int FDawn (func_info *);
static int FDusk (func_info *);
static int FSunset (func_info *);
static int FSunrise (func_info *);
static int FTime (func_info *);
static int FTrigdate (func_info *);
static int FTrigdatetime (func_info *);
static int FTrigtime (func_info *);
static int FTrigvalid (func_info *);
static int FTypeof (func_info *);
static int FUpper (func_info *);
static int FValue (func_info *);
static int FVersion (func_info *);
static int FWkday (func_info *);
static int FWkdaynum (func_info *);
static int FYear (func_info *);
static int FIsleap (func_info *);
static int FLower (func_info *);
static int FNow (func_info *);
static int FRealnow (func_info *);
static int FRealtoday (func_info *);
static int FToday (func_info *);
static int FTrigger (func_info *);
static int FTzconvert (func_info *);
static int FWeekno (func_info *);
static int CheckArgs (BuiltinFunc *f, int nargs);
static int CleanUpAfterFunc (func_info *);
static int SunStuff (int rise, double cosz, int jul);
static int FADawn (func_info *);
static int FADusk (func_info *);
static int FAbs (func_info *);
static int FAccess (func_info *);
static int FAmpm (func_info *);
static int FArgs (func_info *);
static int FAsc (func_info *);
static int FBaseyr (func_info *);
static int FChar (func_info *);
static int FChoose (func_info *);
static int FCoerce (func_info *);
static int FCurrent (func_info *);
static int FDate (func_info *);
static int FDateTime (func_info *);
static int FDatepart (func_info *);
static int FDawn (func_info *);
static int FDay (func_info *);
static int FDaysinmon (func_info *);
static int FDefined (func_info *);
static int FDosubst (func_info *);
static int FDusk (func_info *);
static int FEasterdate (func_info *);
static int FEvalTrig (func_info *);
static int FFiledate (func_info *);
static int FFiledatetime (func_info *);
static int FFiledir (func_info *);
static int FFilename (func_info *);
static int FGetenv (func_info *);
static int FHebdate (func_info *);
static int FHebday (func_info *);
static int FHebmon (func_info *);
static int FHebyear (func_info *);
static int FHour (func_info *);
static int FIif (func_info *);
static int FIndex (func_info *);
static int FIsdst (func_info *);
static int FIsleap (func_info *);
static int FIsomitted (func_info *);
static int FLanguage (func_info *);
static int FLower (func_info *);
static int FMax (func_info *);
static int FMin (func_info *);
static int FMinsfromutc (func_info *);
static int FMinute (func_info *);
static int FMon (func_info *);
static int FMonnum (func_info *);
static int FMoondate (func_info *);
static int FMoondatetime (func_info *);
static int FMoonphase (func_info *);
static int FMoontime (func_info *);
static int FNDawn (func_info *);
static int FNDusk (func_info *);
static int FNonomitted (func_info *);
static int FNow (func_info *);
static int FOrd (func_info *);
static int FOstype (func_info *);
static int FPlural (func_info *);
static int FPsmoon (func_info *);
static int FPsshade (func_info *);
static int FRealCurrent (func_info *);
static int FRealnow (func_info *);
static int FRealtoday (func_info *);
static int FSgn (func_info *);
static int FShell (func_info *);
static int FSlide (func_info *);
static int FStrlen (func_info *);
static int FSubstr (func_info *);
static int FSunrise (func_info *);
static int FSunset (func_info *);
static int FTime (func_info *);
static int FTimepart (func_info *);
static int FToday (func_info *);
static int FTrigback (func_info *);
static int FTrigdate (func_info *);
static int FTrigdatetime (func_info *);
static int FTrigdelta (func_info *);
static int FTrigduration (func_info *);
static int FTrigeventduration(func_info *);
static int FTrigeventstart (func_info *);
static int FTrigfrom (func_info *);
static int FTrigger (func_info *);
static int FTrigpriority (func_info *);
static int FTrigrep (func_info *);
static int FTrigscanfrom (func_info *);
static int FTrigtime (func_info *);
static int FTrigtimedelta (func_info *);
static int FTrigtimerep (func_info *);
static int FTriguntil (func_info *);
static int FTrigvalid (func_info *);
static int FTypeof (func_info *);
static int FTzconvert (func_info *);
static int FUpper (func_info *);
static int FValue (func_info *);
static int FVersion (func_info *);
static int FWeekno (func_info *);
static int FWkday (func_info *);
static int FWkdaynum (func_info *);
static int FYear (func_info *);
static int CleanUpAfterFunc (func_info *);
static int CheckArgs (BuiltinFunc *f, int nargs);
static int SunStuff (int rise, double cosz, int jul);
/* "Overload" the struct Operator definition */
#define NO_MAX 127
@@ -188,6 +205,9 @@ BuiltinFunc Func[] = {
{ "abs", 1, 1, 1, FAbs },
{ "access", 2, 2, 0, FAccess },
{ "adawn", 0, 1, 0, FADawn},
{ "adusk", 0, 1, 0, FADusk},
{ "ampm", 1, 3, 1, FAmpm },
{ "args", 1, 1, 0, FArgs },
{ "asc", 1, 1, 1, FAsc },
{ "baseyr", 0, 0, 1, FBaseyr },
@@ -233,6 +253,8 @@ BuiltinFunc Func[] = {
{ "moondatetime", 1, 3, 0, FMoondatetime },
{ "moonphase", 0, 2, 0, FMoonphase },
{ "moontime", 1, 3, 0, FMoontime },
{ "ndawn", 0, 1, 0, FNDawn},
{ "ndusk", 0, 1, 0, FNDusk},
{ "nonomitted", 2, NO_MAX, 0, FNonomitted },
{ "now", 0, 0, 0, FNow },
{ "ord", 1, 1, 1, FOrd },
@@ -253,10 +275,22 @@ BuiltinFunc Func[] = {
{ "time", 2, 2, 1, FTime },
{ "timepart", 1, 1, 1, FTimepart },
{ "today", 0, 0, 0, FToday },
{ "trigback", 0, 0, 0, FTrigback },
{ "trigdate", 0, 0, 0, FTrigdate },
{ "trigdatetime", 0, 0, 0, FTrigdatetime },
{ "trigdelta", 0, 0, 0, FTrigdelta },
{ "trigduration", 0, 0, 0, FTrigduration },
{ "trigeventduration", 0, 0, 0, FTrigeventduration },
{ "trigeventstart", 0, 0, 0, FTrigeventstart },
{ "trigfrom", 0, 0, 0, FTrigfrom },
{ "trigger", 1, 3, 0, FTrigger },
{ "trigpriority", 0, 0, 0, FTrigpriority },
{ "trigrep", 0, 0, 0, FTrigrep },
{ "trigscanfrom", 0, 0, 0, FTrigscanfrom },
{ "trigtime", 0, 0, 0, FTrigtime },
{ "trigtimedelta",0, 0, 0, FTrigtimedelta },
{ "trigtimerep", 0, 0, 0, FTrigtimerep },
{ "triguntil", 0, 0, 0, FTriguntil },
{ "trigvalid", 0, 0, 0, FTrigvalid },
{ "typeof", 1, 1, 1, FTypeof },
{ "tzconvert", 2, 3, 0, FTzconvert },
@@ -854,6 +888,76 @@ static int FSgn(func_info *info)
return OK;
}
/***************************************************************/
/* */
/* FAmpm - return a time as a string with "AM" or "PM" suffix */
/* */
/***************************************************************/
static int FAmpm(func_info *info)
{
int h, m;
int yr=0, mo=0, da=0;
char const *am = "AM";
char const *pm = "PM";
char const *ampm = NULL;
char outbuf[128];
if (ARG(0).type != DATETIME_TYPE && ARG(0).type != TIME_TYPE) {
return E_BAD_TYPE;
}
if (HASDATE(ARG(0))) {
FromJulian(DATEPART(ARG(0)), &yr, &mo, &da);
}
if (Nargs >= 2) {
ASSERT_TYPE(1, STR_TYPE);
am = ARGSTR(1);
if (Nargs >= 3) {
ASSERT_TYPE(2, STR_TYPE);
pm = ARGSTR(2);
}
}
h = TIMEPART(ARG(0)) / 60;
m = TIMEPART(ARG(0)) % 60;
if (h <= 11) {
/* AM */
if (h == 0) {
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c12%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "12%c%02d", TimeSep, m);
}
} else {
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
}
}
ampm = am;
} else {
if (h > 12) {
h -= 12;
}
if (ARG(0).type == DATETIME_TYPE) {
snprintf(outbuf, sizeof(outbuf), "%04d%c%02d%c%02d%c%d%c%02d", yr, DateSep, mo+1, DateSep, da, DateTimeSep, h, TimeSep, m);
} else {
snprintf(outbuf, sizeof(outbuf), "%d%c%02d", h, TimeSep, m);
}
ampm = pm;
}
RetVal.type = STR_TYPE;
RetVal.v.str = malloc(strlen(outbuf) + strlen(ampm) + 1);
if (!RetVal.v.str) {
RetVal.type = ERR_TYPE;
return E_NO_MEM;
}
strcpy(RetVal.v.str, outbuf);
strcat(RetVal.v.str, ampm);
return OK;
}
/***************************************************************/
/* */
/* FOrd - returns a string containing ordinal number. */
@@ -1130,6 +1234,120 @@ static int FTrigdate(func_info *info)
return OK;
}
static int FTrigback(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTrigger.back;
return OK;
}
static int FTrigdelta(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTrigger.delta;
return OK;
}
static int FTrigtimedelta(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTimeTrig.delta;
return OK;
}
static int FTrigtimerep(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTimeTrig.rep;
return OK;
}
static int FTrigeventduration(func_info *info)
{
if (LastTrigger.eventduration == NO_TIME) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = TIME_TYPE;
RETVAL = LastTrigger.eventduration;
}
return OK;
}
static int FTrigeventstart(func_info *info)
{
if (LastTrigger.eventstart == NO_TIME) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = DATETIME_TYPE;
RETVAL = LastTrigger.eventstart;
}
return OK;
}
static int FTrigduration(func_info *info)
{
if (LastTimeTrig.duration == NO_TIME) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = TIME_TYPE;
RETVAL = LastTimeTrig.duration;
}
return OK;
}
static int FTrigrep(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTrigger.rep;
return OK;
}
static int FTrigpriority(func_info *info)
{
RetVal.type = INT_TYPE;
RETVAL = LastTrigger.priority;
return OK;
}
static int FTriguntil(func_info *info)
{
if (LastTrigger.until == NO_UNTIL) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = DATE_TYPE;
RETVAL = LastTrigger.until;
}
return OK;
}
static int FTrigscanfrom(func_info *info)
{
if (LastTrigger.scanfrom == NO_DATE) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = DATE_TYPE;
RETVAL = LastTrigger.scanfrom;
}
return OK;
}
static int FTrigfrom(func_info *info)
{
if (LastTrigger.from == NO_DATE) {
RetVal.type = INT_TYPE;
RETVAL = -1;
} else {
RetVal.type = DATE_TYPE;
RETVAL = LastTrigger.from;
}
return OK;
}
static int FTrigvalid(func_info *info)
{
RetVal.type = INT_TYPE;
@@ -1873,14 +2091,11 @@ static int SunStuff(int rise, double cosz, int jul)
+ (double) LongSec / 3600.0;
latitude = DEGRAD * ((double) LatDeg + (double) LatMin / 60.0
+ (double) LatSec / 3600.0);
+ (double) LatSec / 3600.0);
FromJulian(jul, &year, &mon, &day);
if (rise > 1)
rise -= 2;
/* Following formula on page B6 exactly... */
t = (double) jul;
if (rise) {
@@ -1915,10 +2130,10 @@ static int SunStuff(int rise, double cosz, int jul)
/* Sine of sun's declination */
sinDelta = 0.39782 * sin(DEGRAD*L);
cosDelta = sqrt(1 - sinDelta*sinDelta);
/* Cosine of sun's local hour angle */
cosH = (cosz - sinDelta * sin(latitude)) / (cosDelta * cos(latitude));
if (cosH < -1.0) { /* Summer -- permanent daylight */
if (rise) return NO_TIME;
else return -NO_TIME;
@@ -1936,9 +2151,9 @@ static int SunStuff(int rise, double cosz, int jul)
if (T >= 24.0) T -= 24.0;
else if (T < 0.0) T+= 24.0;
UT = T + longdeg / 15.0;
local = UT + (double) mins / 60.0;
if (local < 0.0) local += 24.0;
@@ -1949,7 +2164,7 @@ static int SunStuff(int rise, double cosz, int jul)
hours = (int) local;
mins = (int) ((local - hours) * 60.0);
/* Sometimes, we get roundoff error. Check for "reasonableness" of
answer. */
if (rise) {
@@ -1970,19 +2185,30 @@ static int SunStuff(int rise, double cosz, int jul)
static int FSun(int rise, func_info *info)
{
int jul = JulianToday;
double cosz = -0.014543897; /* for sunrise and sunset */
/* Assignment below is not necessary, but it silences
a GCC warning about a possibly-uninitialized variable */
double cosz = 0.0;
int r;
if (rise == 0 || rise == 1) {
/* Sunrise and sunset : cos(90 degrees + 50 arcminutes) */
cosz = -0.01454389765158243;
} else if (rise == 2 || rise == 3) {
/* Civil twilight: cos(96 degrees) */
if (rise == 2 || rise == 3) {
cosz = -0.104528463268;
cosz = -0.10452846326765333;
} else if (rise == 4 || rise == 5) {
/* Nautical twilight: cos(102 degrees) */
cosz = -0.20791169081775912;
} else if (rise == 6 || rise == 7) {
/* Astronomical twilight: cos(108 degrees) */
cosz = -0.30901699437494734;
}
if (Nargs >= 1) {
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
jul = DATEPART(ARG(0));
}
r = SunStuff(rise, cosz, jul);
r = SunStuff(rise % 2, cosz, jul);
if (r == NO_TIME) {
RETVAL = 0;
RetVal.type = INT_TYPE;
@@ -2014,6 +2240,24 @@ static int FDusk(func_info *info)
return FSun(2, info);
}
static int FNDawn(func_info *info)
{
return FSun(5, info);
}
static int FNDusk(func_info *info)
{
return FSun(4, info);
}
static int FADawn(func_info *info)
{
return FSun(7, info);
}
static int FADusk(func_info *info)
{
return FSun(6, info);
}
/***************************************************************/
/* */
/* FFiledate */
@@ -2389,16 +2633,16 @@ static int tz_set_tz(char const *tz)
unsetenv("TZ");
r = 0;
} else {
r = setenv("TZ", tz, 1);
r = setenv("TZ", tz, 1);
}
tzset();
return r;
}
static int tz_convert(int year, int month, int day,
int hour, int minute,
char const *src_tz, char const *tgt_tz,
struct tm *tm)
int hour, int minute,
char const *src_tz, char const *tgt_tz,
struct tm *tm)
{
int r;
time_t t;
@@ -2419,28 +2663,28 @@ static int tz_convert(int year, int month, int day,
/* backup old TZ env var */
old_tz = getenv("TZ");
if (tgt_tz == NULL) {
tgt_tz = old_tz;
tgt_tz = old_tz;
}
/* set source TZ */
r = tz_set_tz(src_tz);
if (r == -1) {
return -1;
return -1;
}
/* create timestamp in UTC */
t = mktime(tm);
if (t == (time_t) -1) {
tz_set_tz(old_tz);
return -1;
tz_set_tz(old_tz);
return -1;
}
/* set target TZ */
r = tz_set_tz(tgt_tz);
if (r == -1) {
tz_set_tz(old_tz);
return -1;
tz_set_tz(old_tz);
return -1;
}
/* convert to target TZ */
@@ -2451,9 +2695,9 @@ static int tz_convert(int year, int month, int day,
/* return result */
if (res == NULL) {
return -1;
return -1;
} else {
return 1;
return 1;
}
}
@@ -2524,6 +2768,7 @@ FSlide(func_info *info)
} else {
while(amt) {
d--;
if (d < 0) return E_DATE_OVER;
r = IsOmitted(d, localomit, NULL,&omit);
if (r) return r;
if (!omit) amt++;
@@ -2664,13 +2909,17 @@ FEvalTrig(func_info *info)
return E_PARSE_ERR;
}
if (scanfrom == NO_DATE) {
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 0);
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
} else {
/* Hokey... */
if (trig.scanfrom != JulianToday) {
Eprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()");
}
jul = ComputeTrigger(scanfrom, &trig, &r, 0);
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
}
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = 0;
jul = -1;
}
FreeTrig(&trig);
if (r) return r;

View File

@@ -8,8 +8,7 @@
/* globals.h and err.h */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -7,8 +7,7 @@
/* MK_GLOBALS. Also contains useful macro definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -47,7 +46,7 @@ EXTERN INIT( int DoPrefixLineNo, 0);
EXTERN INIT( int MondayFirst, 0);
EXTERN INIT( int Iterations, 1);
EXTERN INIT( int PsCal, 0);
EXTERN INIT( int CalWidth, 80);
EXTERN INIT( int CalWidth, -1);
EXTERN INIT( int CalWeeks, 0);
EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0);
@@ -73,6 +72,10 @@ EXTERN INIT( int DontIssueAts, 0);
EXTERN INIT( int Daemon, 0);
EXTERN INIT( char DateSep, DATESEP);
EXTERN INIT( char TimeSep, TIMESEP);
EXTERN INIT( char DateTimeSep, DATETIMESEP);
EXTERN INIT( int DefaultColorR, -1);
EXTERN INIT( int DefaultColorB, -1);
EXTERN INIT( int DefaultColorG, -1);
EXTERN INIT( int SynthesizeTags, 0);
EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 150);
@@ -85,8 +88,10 @@ EXTERN FILE *ErrFp;
EXTERN INIT( FILE *PurgeFP, NULL);
EXTERN INIT( int NumIfs, 0);
EXTERN INIT( unsigned int IfFlags, 0);
EXTERN INIT( int LastTriggerDate, 0);
EXTERN INIT( int LastTrigValid, 0);
EXTERN Trigger LastTrigger;
EXTERN TimeTrig LastTimeTrig;
EXTERN INIT( int LastTriggerDate, 0);
EXTERN INIT( int LastTriggerTime, 0);
EXTERN INIT( int ShouldCache, 0);
EXTERN char const *CurLine;
@@ -98,6 +103,9 @@ EXTERN INIT( int CalPad, 1);
EXTERN INIT( int UseVTChars, 0);
EXTERN INIT( int UseUTF8Chars, 0);
EXTERN INIT( int UseVTColors, 0);
EXTERN INIT( int Use256Colors, 0);
EXTERN INIT( int UseTrueColors, 0);
EXTERN INIT( int TerminalBackground, TERMINAL_BACKGROUND_UNKNOWN);
/* Latitude and longitude */
EXTERN INIT( int LatDeg, LAT_DEG);

View File

@@ -5,8 +5,7 @@
/* Support for the Hebrew calendar */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/* Derived from code written by Amos Shapir in 1978; revised */
/* 1985. */
@@ -139,8 +138,8 @@ int DaysInHebYear(int y)
/***************************************************************/
char const *DaysInHebMonths(int ylen)
{
static char monlen[13] =
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29};
static char monlen[14] =
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29, 29};
if (ylen > 355) {

View File

@@ -7,8 +7,7 @@
/* in normal mode. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2011 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -24,6 +23,7 @@
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "types.h"
#include "protos.h"
@@ -39,6 +39,7 @@
* simple calendar format.
* -r = Disallow RUN mode
* -c[n] = Produce a calendar for n months (default = 1)
* -@[n,m] = Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
* -w[n,n,n] = Specify output device width, padding and spacing
* -s[n] = Produce calendar in "simple calendar" format
* -p[n] = Produce calendar in format compatible with rem2ps
@@ -136,7 +137,7 @@ void InitRemind(int argc, char const *argv[])
int InvokedAsRem = 0;
char const *s;
int weeks;
int x;
int jul;
#if defined(__APPLE__)
@@ -147,6 +148,17 @@ void InitRemind(int argc, char const *argv[])
jul = NO_DATE;
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
but clamp to [20, 500] */
if (isatty(STDOUT_FILENO)) {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
FormWidth = w.ws_col - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
/* Initialize global dynamic buffers */
DBufInit(&Banner);
DBufInit(&LineBuffer);
@@ -191,6 +203,7 @@ void InitRemind(int argc, char const *argv[])
/* Parse the command-line options */
i = 1;
while (i < argc) {
arg = argv[i];
if (*arg != '-') break; /* Exit the loop if it's not an option */
@@ -205,6 +218,27 @@ void InitRemind(int argc, char const *argv[])
while (*arg) {
switch(*arg++) {
case '@':
UseVTColors = 1;
if (*arg) {
PARSENUM(x, arg);
if (x == 1) {
Use256Colors = 1;
} else if (x == 2) {
UseTrueColors = 1;
}
}
if (*arg == ',') {
arg++;
PARSENUM(x, arg);
if (x == 0) {
TerminalBackground = TERMINAL_BACKGROUND_DARK;
} else if (x == 1) {
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
}
}
break;
case 'j':
case 'J':
PurgeMode = 1;
@@ -401,9 +435,21 @@ void InitRemind(int argc, char const *argv[])
case 'p':
case 'P':
DoSimpleCalendar = 1;
PsCal = 1;
if (*arg == 'a' || *arg == 'A') {
DoSimpleCalDelta = 1;
PsCal = PSCAL_LEVEL1;
while (*arg == 'a' || *arg == 'A' ||
*arg == 'p' || *arg == 'P') {
if (*arg == 'a' || *arg == 'A') {
DoSimpleCalDelta = 1;
} else if (*arg == 'p' || *arg == 'P') {
/* JSON interchange formats always include
file and line number info */
DoPrefixLineNo = 1;
if (PsCal == PSCAL_LEVEL1) {
PsCal = PSCAL_LEVEL2;
} else {
PsCal = PSCAL_LEVEL3;
}
}
arg++;
}
PARSENUM(CalMonths, arg);
@@ -419,7 +465,10 @@ void InitRemind(int argc, char const *argv[])
case 'W':
if (*arg != ',') {
PARSENUM(CalWidth, arg);
if (CalWidth < 71) CalWidth = 71;
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
}
if (*arg == ',') {
arg++;
@@ -586,7 +635,7 @@ void InitRemind(int argc, char const *argv[])
}
/* Figure out the offset from UTC */
if (CalculateUTC)
(void) CalcMinsFromUTC(JulianToday, SystemTime(1)/60,
(void) CalcMinsFromUTC(JulianToday, SystemTime(0)/60,
&MinsFromUTC, NULL);
}
@@ -600,8 +649,7 @@ void InitRemind(int argc, char const *argv[])
#ifndef L_USAGE_OVERRIDE
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "Copyright 1999-2011 Roaring Penguin Software Inc.\n");
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
@@ -609,6 +657,7 @@ void Usage(void)
fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
fprintf(ErrFp, " -r Disable RUN directives\n");
fprintf(ErrFp, " -@[n,m] Colorize COLOR reminders\n");
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");

1045
src/json.c Normal file

File diff suppressed because it is too large Load Diff

280
src/json.h Normal file
View File

@@ -0,0 +1,280 @@
/* vim: set et ts=3 sw=3 sts=3 ft=c:
*
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
* https://github.com/udp/json-parser
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _JSON_H
#define _JSON_H
#ifndef json_char
#define json_char char
#endif
#ifndef json_int_t
#ifndef _MSC_VER
#include <inttypes.h>
#define json_int_t int64_t
#else
#define json_int_t __int64
#endif
#endif
#include <stdlib.h>
#ifdef __cplusplus
#include <string.h>
extern "C"
{
#endif
typedef struct
{
unsigned long max_memory;
int settings;
/* Custom allocator support (leave null to use malloc/free)
*/
void * (* mem_alloc) (size_t, int zero, void * user_data);
void (* mem_free) (void *, void * user_data);
void * user_data; /* will be passed to mem_alloc and mem_free */
size_t value_extra; /* how much extra space to allocate for values? */
} json_settings;
#define json_enable_comments 0x01
typedef enum
{
json_none,
json_object,
json_array,
json_integer,
json_double,
json_string,
json_boolean,
json_null
} json_type;
extern const struct _json_value json_value_none;
typedef struct _json_object_entry
{
json_char * name;
unsigned int name_length;
struct _json_value * value;
} json_object_entry;
typedef struct _json_value
{
struct _json_value * parent;
json_type type;
union
{
int boolean;
json_int_t integer;
double dbl;
struct
{
unsigned int length;
json_char * ptr; /* null terminated */
} string;
struct
{
unsigned int length;
json_object_entry * values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
{ return values;
}
decltype(values) end () const
{ return values + length;
}
#endif
} object;
struct
{
unsigned int length;
struct _json_value ** values;
#if defined(__cplusplus) && __cplusplus >= 201103L
decltype(values) begin () const
{ return values;
}
decltype(values) end () const
{ return values + length;
}
#endif
} array;
} u;
union
{
struct _json_value * next_alloc;
void * object_mem;
} _reserved;
#ifdef JSON_TRACK_SOURCE
/* Location of the value in the source JSON
*/
unsigned int line, col;
#endif
/* Some C++ operator sugar */
#ifdef __cplusplus
public:
inline _json_value ()
{ memset (this, 0, sizeof (_json_value));
}
inline const struct _json_value &operator [] (int index) const
{
if (type != json_array || index < 0
|| ((unsigned int) index) >= u.array.length)
{
return json_value_none;
}
return *u.array.values [index];
}
inline const struct _json_value &operator [] (const char * index) const
{
if (type != json_object)
return json_value_none;
for (unsigned int i = 0; i < u.object.length; ++ i)
if (!strcmp (u.object.values [i].name, index))
return *u.object.values [i].value;
return json_value_none;
}
inline operator const char * () const
{
switch (type)
{
case json_string:
return u.string.ptr;
default:
return "";
};
}
inline operator json_int_t () const
{
switch (type)
{
case json_integer:
return u.integer;
case json_double:
return (json_int_t) u.dbl;
default:
return 0;
};
}
inline operator bool () const
{
if (type != json_boolean)
return false;
return u.boolean != 0;
}
inline operator double () const
{
switch (type)
{
case json_integer:
return (double) u.integer;
case json_double:
return u.dbl;
default:
return 0;
};
}
#endif
} json_value;
json_value * json_parse (const json_char * json,
size_t length);
#define json_error_max 128
json_value * json_parse_ex (json_settings * settings,
const json_char * json,
size_t length,
char * error);
void json_value_free (json_value *);
/* Not usually necessary, unless you used a custom mem_alloc and now want to
* use a custom mem_free.
*/
void json_value_free_ex (json_settings * settings,
json_value *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -5,14 +5,13 @@
/* Header file for language support for various languages. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
/* I'm chauvinistic and name each language with its English name... */
#define ENGLISH 0 /* original by David F. Skoll */
#define ENGLISH 0 /* original by Dianne Skoll */
#define GERMAN 1 /* translated by Wolfgang Thronicke */
#define DUTCH 2 /* translated by Willem Kasdorp and Erik-Jan Vens */
#define FINNISH 3 /* translated by Mikko Silvonen */
@@ -26,7 +25,7 @@
#define SPANISH 11 /* translated by Rafa Couto */
#define ICELANDIC 12 /* translated by Björn Davíðsson */
/* Add more languages here - but please e-mail dfs@roaringpenguin.com
/* Add more languages here - but please e-mail dianne@skoll.ca
to have your favorite language assigned a number. If you add a
language, please send me the header file, and permission to include
it in future releases of Remind. Note that you'll get no remuneration

View File

@@ -6,8 +6,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
/* */
/***************************************************************/

View File

@@ -6,13 +6,12 @@
/* */
/* Author: Willem Kasdorp */
/* */
/* Modified slightly by David Skoll */
/* Modified slightly by Dianne Skoll */
/* */
/* Further corrections by Erik-Jan Vens */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,8 +5,7 @@
/* Support for the English language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -11,8 +11,7 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -302,7 +301,9 @@ EXTERN char *ErrMsg[] =
"Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#elif IBMEXTENDED
"Ok",
@@ -406,7 +407,9 @@ EXTERN char *ErrMsg[] =
"Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else
"Ok",
@@ -510,7 +513,9 @@ EXTERN char *ErrMsg[] =
"Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif
@@ -522,8 +527,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
#endif

View File

@@ -8,10 +8,9 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Laurent Duperval and */
/* David F. Skoll. */
/* Dianne Skoll. */
/* */
/***************************************************************/
@@ -242,7 +241,9 @@ EXTERN char *ErrMsg[] =
"Fonction ill\351gale apr\350s WARN",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else /* ISOLATIN1 */
"Ok",
@@ -346,7 +347,9 @@ EXTERN char *ErrMsg[] =
"Fonction illegale apres WARN",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
@@ -356,8 +359,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif

View File

@@ -9,8 +9,7 @@
/* I don't speak German. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,8 +5,7 @@
/* Support for the Icelandic language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
/* */
/***************************************************************/

View File

@@ -7,8 +7,7 @@
/* This file is part of REMIND. */
/* It is Copyright (C) 1996 by Valerio Aimale */
/* */
/* Remind is copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,8 +6,7 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993 by Trygve Randen. */
/* Remind is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -9,8 +9,7 @@
/* Polish. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -281,7 +280,9 @@ EXTERN char *ErrMsg[] =
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else /* ISOLATIN1 */
"OK",
"Brakujacy ']'",
@@ -384,7 +385,9 @@ EXTERN char *ErrMsg[] =
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
@@ -394,8 +397,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif

View File

@@ -8,10 +8,9 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1996 by Marco Paganini and */
/* David F. Skoll. */
/* Dianne Skoll. */
/* */
/***************************************************************/
@@ -247,7 +246,9 @@ EXTERN char *ErrMsg[] =
"Funcao ilegal na clausula WARN",
"Can't convert between time zones",
"No files matching *.rem",
"String too long"
"String too long",
"Time specified twice",
"Cannot specify DURATION without specifying AT"
};
#endif /* MK_GLOBALS */
@@ -256,8 +257,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "(C) 1999-2000 Roaring Penguin Software Inc.\n");
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
#endif

View File

@@ -8,8 +8,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
/* */
/***************************************************************/

View File

@@ -7,8 +7,7 @@
/* Author: Rafa Couto <rafacouto@biogate.com> */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -42,7 +41,7 @@
#define L_JUL "Julio"
#define L_AUG "Agosto"
#define L_SEP "Septiembre"
#define L_OCT "Octuber"
#define L_OCT "Octubre"
#define L_NOV "Noviembre"
#define L_DEC "Diciembre"

View File

@@ -6,8 +6,7 @@
/* routines, etc. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2011 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -64,14 +63,16 @@ int main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
/* The very first thing to do is to set up ErrFp to be stderr */
/* The very first thing to do is to set up ErrFp to be stderr */
ErrFp = stderr;
/* Set up global vars */
/* Set up global vars */
ArgC = argc;
ArgV = (char const **) argv;
InitRemind(argc, (char const **) argv);
ClearLastTriggers();
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
ProduceCalendar();
return 0;
@@ -126,10 +127,7 @@ int main(int argc, char *argv[])
}
}
if (Iterations) {
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
NumTriggered = 0;
PerIterationInit();
JulianToday++;
}
}
@@ -147,6 +145,19 @@ void PurgeEchoLine(char const *fmt, ...)
}
void
PerIterationInit(void)
{
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
DefaultColorR = -1;
DefaultColorG = -1;
DefaultColorB = -1;
NumTriggered = 0;
ClearLastTriggers();
}
/***************************************************************/
/* */
/* DoReminders */
@@ -714,7 +725,7 @@ int DoIf(ParsePtr p)
int r;
unsigned syndrome;
if (NumIfs >= IF_NEST) return E_NESTED_IF;
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
else {
@@ -795,13 +806,20 @@ int DoIfTrig(ParsePtr p)
int jul;
if (NumIfs >= IF_NEST) return E_NESTED_IF;
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
else {
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
if (!Hush || r != E_RUN_DISABLED) {
Eprint("%s", ErrMsg[r]);
}
}
syndrome = IF_TRUE | BEFORE_ELSE;
}
else {
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
syndrome = IF_TRUE | BEFORE_ELSE;
@@ -1303,6 +1321,7 @@ void UTCToLocal(int utcdate, int utctime, int *locdate, int *loctime)
void SigIntHandler(int d)
{
UNUSED(d);
signal(SIGINT, SigIntHandler);
GotSigInt();
exit(0);
@@ -1322,3 +1341,67 @@ FreeTrig(Trigger *t)
{
DBufFree(&(t->tags));
}
void
ClearLastTriggers(void)
{
LastTrigger.expired = 0;
LastTrigger.wd = NO_WD;
LastTrigger.d = NO_DAY;
LastTrigger.m = NO_MON;
LastTrigger.y = NO_YR;
LastTrigger.back = NO_BACK;
LastTrigger.delta = NO_DELTA;
LastTrigger.rep = NO_REP;
LastTrigger.localomit = NO_WD;
LastTrigger.skip = NO_SKIP;
LastTrigger.until = NO_UNTIL;
LastTrigger.typ = NO_TYPE;
LastTrigger.once = NO_ONCE;
LastTrigger.scanfrom = NO_DATE;
LastTrigger.from = NO_DATE;
LastTrigger.priority = DefaultPrio;
LastTrigger.sched[0] = 0;
LastTrigger.warn[0] = 0;
LastTrigger.omitfunc[0] = 0;
LastTrigger.passthru[0] = 0;
LastTimeTrig.ttime = NO_TIME;
LastTimeTrig.delta = NO_DELTA;
LastTimeTrig.rep = NO_REP;
LastTimeTrig.duration = NO_TIME;
}
void
SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid)
{
SaveLastTrigger(t);
SaveLastTimeTrig(tt);
LastTriggerDate = trigdate;
LastTriggerTime = trigtime;
LastTrigValid = valid;
}
void
SaveLastTrigger(Trigger const *t)
{
memcpy(&LastTrigger, t, sizeof(LastTrigger));
DBufInit(&(LastTrigger.tags));
}
void
SaveLastTimeTrig(TimeTrig const *t)
{
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
}
/* Wrapper to ignore warnings about ignoring return value of system() */
void
System(char const *cmd)
{
int r;
r = system(cmd);
if (r == 0) {
r = 1;
}
}

View File

@@ -141,7 +141,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
MD5Transform(ctx->buf, (uint32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5

View File

@@ -5,8 +5,7 @@
/* Calculations for figuring out moon phases. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,8 +6,7 @@
/* the data structures for OMITted dates. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -454,6 +453,7 @@ DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
end = Julian(yend, mend, dend);
if (end < start) {
Eprint("Warning: Swapping dates on OMIT ... THROUGH ... line");
tmp = start;
start = end;
end = tmp;

View File

@@ -5,11 +5,13 @@
/* Function Prototypes. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
/* Suppress unused variable warnings */
#define UNUSED(x) (void) x
/* Define a string assignment macro - be careful!!! */
#define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); }
@@ -35,6 +37,7 @@ int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
int ParseLiteralDate (char const **s, int *jul, int *tim);
int ParseLiteralTime (char const **s, int *tim);
int EvalExpr (char const **e, Value *v, ParsePtr p);
int DoCoerce (char type, Value *v);
void PrintValue (Value *v, FILE *fp);
@@ -86,7 +89,10 @@ void HandleQueuedReminders (void);
char const *FindInitialToken (Token *tok, char const *s);
void FindToken (char const *s, Token *tok);
void FindNumericToken (char const *s, Token *t);
int ComputeTrigger (int today, Trigger *trig, int *err, int save_in_globals);
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals, int duration_days);
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt);
char *StrnCpy (char *dest, char const *source, int n);
int StrMatch (char const *s1, char const *s2, int n);
int StrinCmp (char const *s1, char const *s2, int n);
@@ -103,7 +109,7 @@ void DumpVarTable (void);
void DestroyVars (int all);
int PreserveVar (char const *name);
int DoPreserve (Parser *p);
int DoSatRemind (Trigger *trig, TimeTrig *tim, ParsePtr p);
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
int DoMsgCommand (char const *cmd, char const *msg);
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
unsigned int HashVal (char const *str);
@@ -140,3 +146,18 @@ void PurgeEchoLine(char const *fmt, ...);
void FreeTrig(Trigger *t);
void AppendTag(DynamicBuffer *buf, char const *s);
char const *SynthesizeTag(void);
void ClearLastTriggers(void);
void SaveLastTrigger(Trigger const *t);
void SaveLastTimeTrig(TimeTrig const *t);
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
void PerIterationInit(void);
char const *Decolorize(int r, int g, int b);
char const *Colorize(int r, int g, int b);
void PrintJSONString(char const *s);
void PrintJSONKeyPairInt(char const *name, int val);
void PrintJSONKeyPairString(char const *name, char const *val);
void PrintJSONKeyPairDate(char const *name, int jul);
void PrintJSONKeyPairDateTime(char const *name, int dt);
void PrintJSONKeyPairTime(char const *name, int t);
void System(char const *cmd);

View File

@@ -5,8 +5,7 @@
/* Queue up reminders for subsequent execution. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -28,9 +27,9 @@
#include <stdlib.h>
#include <unistd.h>
#include "types.h"
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
@@ -44,6 +43,7 @@ typedef struct queuedrem {
char passthru[PASSTHRU_LEN+1];
char sched[VAR_NAME_LEN+1];
DynamicBuffer tags;
Trigger t;
TimeTrig tt;
} QueuedRem;
@@ -92,6 +92,8 @@ int QueueReminder(ParsePtr p, Trigger *trig,
qelem->typ = trig->typ;
strcpy(qelem->passthru, trig->passthru);
qelem->tt = *tim;
qelem->t = *trig;
DBufInit(&(qelem->t.tags));
qelem->next = QueueHead;
qelem->RunDisabled = RunDisabled;
qelem->ntrig = 0;
@@ -152,7 +154,7 @@ void HandleQueuedReminders(void)
/* Initialize the queue - initialize all the entries time of issue */
while (q) {
q->tt.nexttime = (int) (SystemTime(0)/60 - 1);
q->tt.nexttime = (int) (SystemTime(1)/60 - 1);
q->tt.nexttime = CalculateNextTime(q);
q = q->next;
}
@@ -169,25 +171,24 @@ void HandleQueuedReminders(void)
if (Daemon && !q) {
if (Daemon < 0) {
/* Sleep until midnight */
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(0);
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
} else {
TimeToSleep = 60*Daemon;
}
} else {
TimeToSleep = q->tt.nexttime * 60L - SystemTime(0);
TimeToSleep = q->tt.nexttime * 60L - SystemTime(1);
}
while (TimeToSleep > 0L) {
SleepTime = TimeToSleep;
if (Daemon > 0 && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
if (Daemon > 0 && SleepTime > (unsigned int) 60*Daemon) SleepTime = 60*Daemon;
/* Wake up once a minute to recalibrate sleep time in
case of laptop hibernation */
if (Daemon <= 0) {
if (SleepTime > 60) {
SleepTime = 60;
}
/* Wake up on the next exact minute */
SleepTime = 60 - (SystemTime(1)%60);
}
if (Daemon >= 0) {
@@ -210,12 +211,12 @@ void HandleQueuedReminders(void)
if (Daemon && !q) {
if (Daemon < 0) {
/* Sleep until midnight */
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(0);
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
} else {
TimeToSleep = 60*Daemon;
}
} else {
TimeToSleep = q->tt.nexttime * 60L - SystemTime(0);
TimeToSleep = q->tt.nexttime * 60L - SystemTime(1);
}
}
@@ -225,7 +226,7 @@ void HandleQueuedReminders(void)
changed or a laptop awakes from hibernation.
However, DO triger if tt.nexttime == tt.ttime so all
queued reminders are triggered at least once. */
if ((SystemTime(0) - (q->tt.nexttime * 60) <= 60) ||
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
(q->tt.nexttime == q->tt.ttime)) {
/* Trigger the reminder */
CreateParser(q->text, &p);
@@ -235,7 +236,7 @@ void HandleQueuedReminders(void)
if (Daemon < 0) {
printf("NOTE reminder %s",
SimpleTime(q->tt.ttime));
printf("%s", SimpleTime(SystemTime(0)/60));
printf("%s", SimpleTime(SystemTime(1)/60));
if (!*DBufValue(&q->tags)) {
printf("*\n");
} else {
@@ -245,9 +246,7 @@ void HandleQueuedReminders(void)
/* Set up global variables so some functions like trigdate()
and trigtime() work correctly */
LastTriggerDate = JulianToday;
LastTriggerTime = q->tt.ttime;
LastTrigValid = 1;
SaveAllTriggerInfo(&(q->t), &(q->tt), JulianToday, q->tt.ttime, 1);
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
if (Daemon < 0) {
printf("NOTE endreminder\n");
@@ -449,6 +448,70 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
}
}
/* Dump the queue in JSON format */
static void
json_queue(QueuedRem const *q)
{
int done = 0;
printf("[");
while(q) {
if (q->tt.nexttime == NO_TIME) {
q = q->next;
continue;
}
if (done) {
printf(",");
}
done = 1;
printf("{");
switch(q->typ) {
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
case RUN_TYPE: PrintJSONKeyPairString("type", "RUN_TYPE"); break;
case CAL_TYPE: PrintJSONKeyPairString("type", "CAL_TYPE"); break;
case SAT_TYPE: PrintJSONKeyPairString("type", "SAT_TYPE"); break;
case PS_TYPE: PrintJSONKeyPairString("type", "PS_TYPE"); break;
case PSF_TYPE: PrintJSONKeyPairString("type", "PSF_TYPE"); break;
case MSF_TYPE: PrintJSONKeyPairString("type", "MSF_TYPE"); break;
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
default: PrintJSONKeyPairString("type", "?"); break;
}
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
PrintJSONKeyPairInt("ntrig", q->ntrig);
PrintJSONKeyPairTime("ttime", q->tt.ttime);
PrintJSONKeyPairTime("nextttime", q->tt.nexttime);
PrintJSONKeyPairInt("delta", q->tt.delta);
if (q->tt.rep != NO_TIME) {
PrintJSONKeyPairInt("rep", q->tt.rep);
}
if (q->tt.duration != NO_TIME) {
PrintJSONKeyPairInt("duration", q->tt.duration);
}
if (q->passthru[0]) {
PrintJSONKeyPairString("passthru", q->passthru);
}
if (q->sched[0]) {
PrintJSONKeyPairString("sched", q->sched);
}
if (DBufLen(&(q->tags))) {
PrintJSONKeyPairString("tags", DBufValue(&(q->tags)));
}
/* Last one is a special case - no trailing comma */
printf("\"");
PrintJSONString("body");
printf("\":\"");
if (q->text) {
PrintJSONString(q->text);
} else {
PrintJSONString("");
}
printf("\"}");
q = q->next;
}
printf("]\n");
}
/***************************************************************/
/* */
/* DaemonWait */
@@ -506,6 +569,38 @@ static void DaemonWait(unsigned int sleeptime)
}
printf("NOTE queued %d\n", nqueued);
fflush(stdout);
} else if (!strcmp(cmdLine, "QUEUE\n")) {
printf("NOTE queue\n");
QueuedRem *q = QueueHead;
while (q) {
if (q->tt.nexttime != NO_TIME) {
switch (q->typ) {
case NO_TYPE: printf("NO_TYPE "); break;
case MSG_TYPE: printf("MSG_TYPE "); break;
case RUN_TYPE: printf("RUN_TYPE "); break;
case CAL_TYPE: printf("CAL_TYPE "); break;
case SAT_TYPE: printf("SAT_TYPE "); break;
case PS_TYPE: printf("PS_TYPE "); break;
case PSF_TYPE: printf("PSF_TYPE "); break;
case MSF_TYPE: printf("MSF_TYPE "); break;
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE "); break;
default: printf("? "); break;
}
printf("RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
printf("%s %s %s\n",
(q->passthru[0] ? q->passthru : "*"),
(q->sched[0] ? q->sched : "*"),
q->text ? q->text : "NULL");
}
q = q->next;
}
printf("NOTE endqueue\n");
fflush(stdout);
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
printf("NOTE JSONQUEUE\n");
json_queue(QueueHead);
printf("NOTE ENDJSONQUEUE\n");
fflush(stdout);
} else if (!strcmp(cmdLine, "REREAD\n")) {
printf("NOTE reread\n");
fflush(stdout);

View File

@@ -5,8 +5,7 @@
/* Print a PostScript calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -21,6 +20,7 @@
#include <unistd.h>
#include <stdlib.h>
#include "rem2ps.h"
#include "json.h"
#define NEW(type) (malloc(sizeof(type)))
@@ -31,6 +31,7 @@
#define SPECIAL_COLOR 4
#define SPECIAL_WEEK 5
#define SPECIAL_SHADE 6
#define SPECIAL_UNKNOWN 7
/* Array holding how specials sort */
static int SpecialSortOrder[] = {
@@ -47,6 +48,7 @@ typedef struct calentry {
struct calentry *next;
int special;
char *entry;
int daynum;
} CalEntry;
typedef struct {
@@ -63,7 +65,7 @@ char const *SmallCalLoc[] = {
"sbt",
};
#define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0]))
#define NUMSMALL ((int) (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0])))
char const *SmallLocation;
int SmallCol1, SmallCol2;
@@ -138,6 +140,172 @@ void WriteOneEntry (CalEntry *c);
void GetSmallLocations (void);
char const *EatToken(char const *in, char *out, int maxlen);
/***************************************************************/
/* */
/* StrCmpi */
/* */
/* Compare strings, case insensitive. */
/* */
/***************************************************************/
int StrCmpi(char const *s1, char const *s2)
{
int r;
while (*s1 && *s2) {
r = toupper(*s1) - toupper(*s2);
if (r) return r;
s1++;
s2++;
}
return toupper(*s1) - toupper(*s2);
}
/***************************************************************/
/* */
/* Parse the new-style JSON intermediate format */
/* */
/***************************************************************/
static CalEntry *
JSONToCalEntry(DynamicBuffer *buf)
{
CalEntry *c;
json_value *val;
val = json_parse(DBufValue(buf), DBufLen(buf));
if (!val) {
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
exit(1);
}
if (val->type != json_object) {
fprintf(stderr, "Expecting JSON object; found `%s'\n",
DBufValue(buf));
exit(1);
}
c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
c->next = NULL;
c->special = SPECIAL_NORMAL;
int got_date = 0, got_body = 0;
size_t i;
for (i=0; i<val->u.object.length; i++) {
char const *nm = val->u.object.values[i].name;
json_value *v = val->u.object.values[i].value;
char const *s;
if (!strcmp(nm, "date")) {
if (v->type == json_string) {
s = v->u.string.ptr;
c->daynum = (s[8] - '0') * 10 + s[9] - '0';
got_date = 1;
}
} else if (!strcmp(nm, "body")) {
if (v->type == json_string) {
s = v->u.string.ptr;
c->entry = malloc(strlen(s)+1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, s);
got_body = 1;
}
} else if (!strcmp(nm, "passthru")) {
if (v->type == json_string) {
s = v->u.string.ptr;
if (!StrCmpi(s, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!StrCmpi(s, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!StrCmpi(s, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!StrCmpi(s, "WEEK")) {
c->special = SPECIAL_WEEK;
} else if (!StrCmpi(s, "PSFile")) {
c->special = SPECIAL_PSFILE;
} else if (!StrCmpi(s, "COLOUR") ||
!StrCmpi(s, "COLOR")) {
c->special = SPECIAL_COLOR;
} else {
c->special = SPECIAL_UNKNOWN;
}
}
}
}
json_value_free(val);
if (!got_body || !got_date) {
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
exit(1);
}
return c;
}
/***************************************************************/
/* */
/* Parse the old-style REM2PS intermediate format */
/* */
/***************************************************************/
static CalEntry *
TextToCalEntry(DynamicBuffer *buf)
{
char const *startOfBody;
char passthru[PASSTHRU_LEN+1];
CalEntry *c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
c->next = NULL;
c->special = SPECIAL_NORMAL;
c->daynum = (DBufValue(buf)[8] - '0') * 10 + DBufValue(buf)[9] - '0';
/* Skip the tag, duration and time */
startOfBody = DBufValue(buf)+10;
/* Eat the passthru */
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
/* Eat the tag */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the duration */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the time */
startOfBody = EatToken(startOfBody, NULL, 0);
c->entry = malloc(strlen(startOfBody) + 1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, startOfBody);
/* Save the type of SPECIAL */
if (!StrCmpi(passthru, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!StrCmpi(passthru, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!StrCmpi(passthru, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!StrCmpi(passthru, "WEEK")) {
c->special = SPECIAL_WEEK;
} else if (!StrCmpi(passthru, "PSFile")) {
c->special = SPECIAL_PSFILE;
} else if (!StrCmpi(passthru, "COLOUR") ||
!StrCmpi(passthru, "COLOR")) {
c->special = SPECIAL_COLOR;
} else if (StrCmpi(passthru, "*")) {
c->special = SPECIAL_UNKNOWN;
}
return c;
}
/***************************************************************/
/* */
/* MAIN PROGRAM */
@@ -155,13 +323,20 @@ int main(int argc, char *argv[])
Usage("Input should not come from a terminal");
}
int first_line = 1;
/* Search for a valid input file */
while (!feof(stdin)) {
DBufGets(&buf, stdin);
if (!strcmp(DBufValue(&buf), PSBEGIN)) {
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
exit(1);
}
first_line = 0;
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
if (!validfile) {
if (Verbose) {
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-1998 by David F. Skoll\n\n", VERSION);
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
fprintf(stderr, "Generating PostScript calendar\n");
}
}
@@ -192,10 +367,7 @@ void DoPsCal(void)
int days, wkday, prevdays, nextdays;
int sfirst;
int i;
int is_ps;
int firstcol;
char const *startOfBody;
char passthru[PASSTHRU_LEN+1];
DynamicBuffer buf;
CalEntry *c, *d, *p;
@@ -231,6 +403,7 @@ void DoPsCal(void)
printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2],
year[2], year[3], validfile);
printf("%%%%PageBoundingBox: 0 0 %d %d\n", CurPage->xsize, CurPage->ysize);
/* Emit PostScript to do the heading */
if (!PortraitMode) printf("90 rotate 0 XSIZE neg translate\n");
@@ -273,80 +446,48 @@ void DoPsCal(void)
}
DBufGets(&buf, stdin);
if (!strcmp(DBufValue(&buf), PSEND)) {
if (!strcmp(DBufValue(&buf), PSEND) ||
!strcmp(DBufValue(&buf), PSEND2)) {
DBufFree(&buf);
break;
}
/* Ignore lines beginning with '#' */
if (DBufValue(&buf)[0] == '#') {
DBufFree(&buf);
continue;
}
/* Read the day number - a bit of a hack! */
DayNum = (DBufValue(&buf)[8] - '0') * 10 + DBufValue(&buf)[9] - '0';
if (DayNum != CurDay) {
for(; CurDay<DayNum; CurDay++) {
if (DBufValue(&buf)[0] == '{') {
/* Starts with '{', so assume new-style JSON format */
c = JSONToCalEntry(&buf);
} else {
/* Assume it's the old-style rem2ps intermediate format */
c = TextToCalEntry(&buf);
}
/* If it's an unknown special, ignore */
if (c->special == SPECIAL_UNKNOWN) {
DBufFree(&buf);
free(c);
c = NULL;
continue;
}
if (c->daynum != CurDay) {
for(; CurDay<c->daynum; CurDay++) {
WriteCalEntry();
WkDayNum = (WkDayNum + 1) % 7;
}
}
/* Add the text */
c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
c->next = NULL;
c->special = SPECIAL_NORMAL;
/* Skip the tag, duration and time */
startOfBody = DBufValue(&buf)+10;
/* Eat the passthru */
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
/* Eat the tag */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the duration */
startOfBody = EatToken(startOfBody, NULL, 0);
/* Eat the time */
startOfBody = EatToken(startOfBody, NULL, 0);
is_ps = 0;
if (!strcmp(passthru, "PostScript") ||
!strcmp(passthru, "PSFile") ||
!strcmp(passthru, "MOON") ||
!strcmp(passthru, "WEEK") ||
!strcmp(passthru, "SHADE")) {
is_ps = 1;
}
c->entry = malloc(strlen(startOfBody) + 1);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry, startOfBody);
if (is_ps) {
/* Save the type of SPECIAL */
if (!strcmp(passthru, "PostScript")) {
c->special = SPECIAL_POSTSCRIPT;
} else if (!strcmp(passthru, "SHADE")) {
c->special = SPECIAL_SHADE;
} else if (!strcmp(passthru, "MOON")) {
c->special = SPECIAL_MOON;
} else if (!strcmp(passthru, "WEEK")) {
c->special = SPECIAL_WEEK;
if (c->special == SPECIAL_POSTSCRIPT ||
c->special == SPECIAL_SHADE ||
c->special == SPECIAL_MOON ||
c->special == SPECIAL_WEEK ||
c->special == SPECIAL_PSFILE) {
if (!PsEntries[c->daynum]) {
PsEntries[c->daynum] = c;
} else {
c->special = SPECIAL_PSFILE;
}
if (!PsEntries[DayNum]) {
PsEntries[DayNum] = c;
} else {
d = PsEntries[DayNum];
d = PsEntries[c->daynum];
p = NULL;
/* Slot it into the right place */
while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) {
@@ -360,14 +501,12 @@ void DoPsCal(void)
if (p) {
p->next = c;
} else {
PsEntries[DayNum] = c;
PsEntries[c->daynum] = c;
}
c->next = d;
}
}
} else if (!strcmp(passthru, "*") ||
!strcmp(passthru, "COLOUR") ||
!strcmp(passthru, "COLOR")) {
} else {
/* Put on linked list */
if (!CurEntries) {
CurEntries = c;
@@ -376,10 +515,6 @@ void DoPsCal(void)
while(d->next) d = d->next;
d->next = c;
}
if (!strcmp(passthru, "COLOR") ||
!strcmp(passthru, "COLOUR")) {
c->special = SPECIAL_COLOR;
}
}
}
for(; CurDay<=days; CurDay++) {
@@ -670,7 +805,8 @@ void Init(int argc, char *argv[])
char const *s;
char const *t;
int i=1;
int j;
size_t j;
int k;
int offset;
PortraitMode = 1;
@@ -799,13 +935,13 @@ void Init(int argc, char *argv[])
case 'i': UseISO = 1; break;
case 'c': j=(*s);
if (!j) {
case 'c': k=(*s);
if (!k) {
SmallLocation = SmallCalLoc[0];
} else {
j -= '0';
if (j>=0 && j<NUMSMALL) {
SmallLocation = SmallCalLoc[j];
k -= '0';
if (k>=0 && k<NUMSMALL) {
SmallLocation = SmallCalLoc[k];
} else {
SmallLocation = SmallCalLoc[0];
}

View File

@@ -5,16 +5,15 @@
/* Define the PostScript prologue */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
char *PSProlog1[] =
{
"% This file was produced by Remind and Rem2PS, written by",
"% David F. Skoll.",
"% Remind and Rem2PS are Copyright 1992-1997 David F. Skoll.",
"% Dianne Skoll.",
"% Remind and Rem2PS are Copyright 1992-2020 Dianne Skoll.",
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",

View File

@@ -5,8 +5,7 @@
/* Routines for sorting reminders by trigger date */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -151,7 +150,7 @@ void IssueSortedReminders(void)
break;
case RUN_TYPE:
system(cur->text);
System(cur->text);
break;
}

View File

@@ -6,8 +6,7 @@
/* classifying the tokens parsed. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -68,6 +67,7 @@ Token TokArray[] = {
{ "june", 3, T_Month, 5 },
{ "march", 3, T_Month, 2 },
{ "may", 3, T_Month, 4 },
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
{ "monday", 3, T_WkDay, 0 },
{ "msf", 3, T_RemType, MSF_TYPE },
{ "msg", 3, T_RemType, MSG_TYPE },
@@ -229,11 +229,11 @@ void FindToken(char const *s, Token *tok)
/* If language is other than English, search the DayNames[] and MonthNames[]
array. */
#if LANG != ENGLISH
for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
if (l >= NonEnglishToks[r].MinLen &&
!TokStrCmp(&NonEnglishToks[r], s)) {
tok->type = NonEnglishToks[r].type;
tok->val = NonEnglishToks[r].val;
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
if (l >= NonEnglishToks[x].MinLen &&
!TokStrCmp(&NonEnglishToks[x], s)) {
tok->type = NonEnglishToks[x].type;
tok->val = NonEnglishToks[x].val;
return;
}
}
@@ -258,6 +258,7 @@ void FindNumericToken(char const *s, Token *t)
{
int mult = 1, hour, min;
char const *s_orig = s;
int ampm = 0;
t->type = T_Illegal;
t->val = 0;
@@ -285,10 +286,6 @@ void FindNumericToken(char const *s, Token *t)
like Jan 6, 1998 */
if (*s == ',') {
s++;
/* Special hack - convert years between 90 and
99 to 1990 and 1999 */
if (t->val >= 90 && t->val <= 99) t->val += 1900;
/* Classify the number we've got */
if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
@@ -300,7 +297,29 @@ void FindNumericToken(char const *s, Token *t)
s++;
hour = t->val;
PARSENUM(min, s);
if (*s || min > 59) return; /* Illegal time */
if (min > 59) return; /* Illegal time */
/* Check for p[m] or a[m] */
if (*s == 'A' || *s == 'a' || *s == 'P' || *s == 'p') {
ampm = tolower(*s);
s++;
if (*s == 'm' || *s == 'M') {
s++;
}
}
if (*s) return; /* Illegal time */
if (ampm) {
if (hour < 1 || hour > 12) return;
if (ampm == 'a') {
if (hour == 12) {
hour = 0;
}
} else if (ampm == 'p') {
if (hour < 12) {
hour += 12;
}
}
}
t->val = hour*60 + min; /* Convert to minutes past midnight */
if (hour <= 23) {
t->type = T_Time;

View File

@@ -5,8 +5,7 @@
/* Routines for figuring out the trigger date of a reminder */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -409,6 +408,57 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
return simple;
}
int
AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals)
{
int y, m, d;
/* If we have an AT, save the original event start */
if (tim->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
if (tim->duration != NO_TIME) {
trig->eventduration = tim->duration;
}
}
/* Now potentially adjust */
if (r < today && r + trig->duration_days >= today) {
/* Adjust duration down */
tim->duration -= (today - r) * MINUTES_PER_DAY;
tim->duration += tim->ttime;
/* Start at midnight */
tim->ttime = 0;
/* Change trigger date to today */
r = today;
if (DebugFlag & DB_PRTTRIG) {
FromJulian(r, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
FileName, LineNo,
DayName[r % 7],
d,
MonthName[m],
y);
if (tim->ttime != NO_TIME) {
fprintf(ErrFp, " AT %02d:%02d",
(tim->ttime / 60),
(tim->ttime % 60));
if (tim->duration != NO_TIME) {
fprintf(ErrFp, " DURATION %02d:%02d",
(tim->duration / 60),
(tim->duration % 60));
}
}
fprintf(ErrFp, "\n");
}
}
if (save_in_globals) {
SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
}
return r;
}
/***************************************************************/
/* */
/* ComputeTrigger */
@@ -417,10 +467,49 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* today's date. */
/* */
/***************************************************************/
int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
int *err, int save_in_globals)
{
int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, 0);
if (*err != OK) {
return r;
}
if (r == today) {
if (tim->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
if (tim->duration != NO_TIME) {
trig->eventduration = tim->duration;
}
}
if (save_in_globals) {
SaveAllTriggerInfo(trig, tim, r, tim->ttime, 1);
}
return r;
}
if (trig->duration_days) {
r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals, trig->duration_days);
if (*err != OK) {
return r;
}
}
r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals);
return r;
}
/***************************************************************/
/* */
/* ComputeTriggerNoAdjustDuration */
/* */
/* Compute a trigger, but do NOT adjust the time trigger */
/* duration. */
/* */
/***************************************************************/
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
int *err, int save_in_globals, int duration_days)
{
int nattempts = 0,
start = today,
start = today - duration_days,
nextstart = 0,
y, m, d, omit,
result;
@@ -430,15 +519,25 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
LastTrigValid = 0;
}
/* Assume everything works */
/* Assume everything works */
*err = OK;
/* But check for obvious problems... */
/* But check for obvious problems... */
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
*err = E_2MANY_LOCALOMIT;
return -1;
}
if (start < 0) {
*err = E_DATE_OVER;
return -1;
}
if (tim->duration != NO_TIME && tim->ttime == NO_TIME) {
*err = E_DURATION_NO_AT;
return -1;
}
if (trig->rep != NO_REP &&
(trig->d == NO_DAY ||
trig->m == NO_MON ||
@@ -449,6 +548,11 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
}
/* Save the trigger */
if (save_in_globals) {
SaveLastTrigger(trig);
}
while (nattempts++ < TRIG_ATTEMPTS) {
result = GetNextTriggerDate(trig, start, err, &nextstart);
@@ -470,7 +574,9 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
} else {
omit = 0;
}
if (result >= today &&
/** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */
if (result+duration_days >= today &&
(trig->skip != SKIP_SKIP || !omit)) {
if (save_in_globals) {
LastTriggerDate = result; /* Save in global var */
@@ -478,12 +584,23 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
}
if (DebugFlag & DB_PRTTRIG) {
FromJulian(result, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
FileName, LineNo,
DayName[result % 7],
d,
MonthName[m],
y);
if (tim->ttime != NO_TIME) {
fprintf(ErrFp, " AT %02d:%02d",
(tim->ttime / 60),
(tim->ttime % 60));
if (tim->duration != NO_TIME) {
fprintf(ErrFp, " DURATION %02d:%02d",
(tim->duration / 60),
(tim->duration % 60));
}
}
fprintf(ErrFp, "\n");
}
return result;
}
@@ -536,3 +653,41 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
*err = E_CANT_TRIG;
return -1;
}
/***************************************************************/
/* */
/* ComputeScanStart */
/* */
/* Figure out where to start scan from by examining SCANFROM */
/* and DURATION */
/* */
/***************************************************************/
int
ComputeScanStart(int today, Trigger *trig, TimeTrig *tt)
{
int minutes, days;
/* If we don't have a time/duration, just use scanfrom */
if (tt->ttime == NO_TIME ||
tt->duration == NO_TIME) {
if (trig->scanfrom == NO_DATE) {
return today;
}
return trig->scanfrom;
}
/* Calculate time-based SCANFROM */
minutes = tt->ttime + tt->duration - 1;
/* Figure out how many days to scan backwards from */
days = minutes / MINUTES_PER_DAY;
if (trig->scanfrom != NO_DATE) {
if (trig->scanfrom <= today - days) {
return trig->scanfrom;
} else {
return today - days;
}
}
return today - days;
}

View File

@@ -5,8 +5,7 @@
/* Type definitions all dumped here. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -69,7 +68,12 @@ typedef struct {
int typ;
int once;
int scanfrom;
int from;
int priority;
int duration_days; /* Duration converted to days to search */
int eventstart; /* Original event start (datetime) */
int eventduration; /* Original event duration (minutes) */
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
@@ -88,16 +92,16 @@ typedef struct {
/* The parse pointer */
typedef struct {
char isnested; /* Is it a nested expression? */
char allownested;
DynamicBuffer pushedToken; /* Pushed-back token */
char const *text; /* Start of text */
char const *pos; /* Current position */
char const *etext; /* Substituted text */
char const *epos; /* Position in substituted text */
DynamicBuffer pushedToken; /* Pushed-back token */
char const *tokenPushed; /* NULL if no pushed-back token */
char expr_happened; /* Did we encounter an [expression] ? */
char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
unsigned char isnested; /* Is it a nested expression? */
unsigned char allownested;
unsigned char expr_happened; /* Did we encounter an [expression] ? */
unsigned char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
} Parser;
typedef Parser *ParsePtr; /* Pointer to parser structure */
@@ -168,7 +172,8 @@ enum TokTypes
T_Duration,
T_LongTime,
T_OmitFunc,
T_Through
T_Through,
T_MaybeUncomputable
};
/* The structure of a token */
@@ -213,3 +218,18 @@ typedef struct {
/* Flags for FROM / SCANFROM */
#define SCANFROM_TYPE 0
#define FROM_TYPE 1
/* PS Calendar levels */
/* Original interchange format */
#define PSCAL_LEVEL1 1
/* Line-by-line JSON */
#define PSCAL_LEVEL2 2
/* Pure JSON */
#define PSCAL_LEVEL3 3
#define TERMINAL_BACKGROUND_UNKNOWN 0
#define TERMINAL_BACKGROUND_DARK 1
#define TERMINAL_BACKGROUND_LIGHT 2

View File

@@ -6,8 +6,7 @@
/* functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -65,6 +64,7 @@ int DoFset(ParsePtr p)
int c;
UserFunc *func;
Var *v;
int orig_namelen;
DynamicBuffer buf;
DBufInit(&buf);
@@ -75,6 +75,7 @@ int DoFset(ParsePtr p)
DBufFree(&buf);
return E_BAD_ID;
}
orig_namelen = buf.len;
/* Should be followed by '(' */
c = ParseNonSpaceChar(p, &r, 0);
@@ -95,9 +96,8 @@ int DoFset(ParsePtr p)
StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN);
DBufFree(&buf);
if (!Hush) {
if (FindFunc(DBufValue(&buf), Func, NumFuncs)) {
Eprint("%s: `%s'", ErrMsg[E_REDEF_FUNC],
DBufValue(&buf));
if (FindFunc(func->name, Func, NumFuncs)) {
Eprint("%s: `%s'", ErrMsg[E_REDEF_FUNC], func->name);
}
}
func->locals = NULL;
@@ -119,6 +119,7 @@ int DoFset(ParsePtr p)
if ( (r=ParseIdentifier(p, &buf)) ) return r;
if (*DBufValue(&buf) == '$') {
DBufFree(&buf);
DestroyUserFunc(func);
return E_BAD_ID;
}
v = NEW(Var);
@@ -165,6 +166,10 @@ int DoFset(ParsePtr p)
/* Add the function definition */
FSet(func);
if (orig_namelen > VAR_NAME_LEN) {
Eprint("Warning: Function name `%s...' truncated to `%s'",
func->name, func->name);
}
return OK;
}
@@ -274,7 +279,7 @@ int CallUserFunc(char const *name, int nargs, ParsePtr p)
}
return E_RECURSIVE;
}
/* Check number of args */
if (nargs != f->nargs) {
if (DebugFlag &DB_PRTEXPR) {

View File

@@ -5,8 +5,7 @@
/* Useful utility functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,8 +6,7 @@
/* user- and system-defined variables. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2007 by Roaring Penguin Software Inc. */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -38,6 +37,7 @@ typedef int (*SysVarFunc)(int, Value *);
static int trig_date_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = DATE_TYPE;
if (!LastTrigValid) {
val->v.val = 0;
@@ -49,6 +49,7 @@ static int trig_date_func(int do_set, Value *val)
static int trig_day_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
val->v.val = -1;
@@ -63,6 +64,7 @@ static int trig_day_func(int do_set, Value *val)
static int trig_mon_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
val->v.val = -1;
@@ -77,6 +79,7 @@ static int trig_mon_func(int do_set, Value *val)
static int trig_year_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
if (!LastTrigValid) {
val->v.val = -1;
@@ -91,6 +94,7 @@ static int trig_year_func(int do_set, Value *val)
static int trig_wday_func(int do_set, Value *val)
{
val->type = INT_TYPE;
UNUSED(do_set);
if (!LastTrigValid) {
val->v.val = -1;
return OK;
@@ -102,6 +106,7 @@ static int trig_wday_func(int do_set, Value *val)
static int today_date_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = DATE_TYPE;
val->v.val = JulianToday;
return OK;
@@ -109,6 +114,7 @@ static int today_date_func(int do_set, Value *val)
static int today_day_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
val->v.val = d;
@@ -118,6 +124,7 @@ static int today_day_func(int do_set, Value *val)
static int today_mon_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
val->v.val = m+1;
@@ -127,6 +134,7 @@ static int today_mon_func(int do_set, Value *val)
static int today_year_func(int do_set, Value *val)
{
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
val->v.val = y;
@@ -135,11 +143,70 @@ static int today_year_func(int do_set, Value *val)
static int today_wday_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = INT_TYPE;
val->v.val = (JulianToday + 1) % 7;
return OK;
}
static int datetime_sep_func(int do_set, Value *val)
{
if (!do_set) {
val->v.str = malloc(2);
if (!val->v.str) return E_NO_MEM;
val->v.str[0] = DateTimeSep;
val->v.str[1] = 0;
val->type = STR_TYPE;
return OK;
}
if (val->type != STR_TYPE) return E_BAD_TYPE;
if (strcmp(val->v.str, "T") &&
strcmp(val->v.str, "@")) {
return E_BAD_TYPE;
}
DateTimeSep = val->v.str[0];
return OK;
}
static int default_color_func(int do_set, Value *val)
{
int col_r, col_g, col_b;
if (!do_set) {
/* 12 = strlen("255 255 255\0") */
val->v.str = malloc(12);
if (!val->v.str) return E_NO_MEM;
snprintf(val->v.str, 12, "%d %d %d",
DefaultColorR,
DefaultColorG,
DefaultColorB
);
val->type = STR_TYPE;
return OK;
}
if (val->type != STR_TYPE) return E_BAD_TYPE;
if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) {
return E_BAD_TYPE;
}
/* They either all have to be -1, or all between 0 and 255 */
if (col_r == -1 && col_g == -1 && col_b == -1) {
DefaultColorR = -1;
DefaultColorG = -1;
DefaultColorB = -1;
return OK;
}
if (col_r < 0) return E_2LOW;
if (col_r > 255) return E_2HIGH;
if (col_g < 0) return E_2LOW;
if (col_g > 255) return E_2HIGH;
if (col_b < 0) return E_2LOW;
if (col_b > 255) return E_2HIGH;
DefaultColorR = col_r;
DefaultColorG = col_g;
DefaultColorB = col_b;
return OK;
}
static int date_sep_func(int do_set, Value *val)
{
if (!do_set) {
@@ -342,6 +409,10 @@ int DoSet (Parser *p)
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
else r = SetVar(DBufValue(&buf), &v);
if (buf.len > VAR_NAME_LEN) {
Eprint("Warning: Variable name `%.*s...' truncated to `%.*s'",
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
}
DBufFree(&buf);
return r;
}
@@ -404,17 +475,17 @@ int DoDump(ParsePtr p)
DumpVarTable();
return OK;
}
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
while(1) {
if (*DBufValue(&buf) == '$') {
DumpSysVarByName(DBufValue(&buf)+1);
} else {
v = FindVar(DBufValue(&buf), 0);
DBufValue(&buf)[VAR_NAME_LEN] = 0;
if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN,
if (!v) fprintf(ErrFp, "%s %s\n",
DBufValue(&buf), UNDEF);
else {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n");
}
@@ -442,12 +513,12 @@ void DumpVarTable(void)
register Var *v;
register int i;
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
for (i=0; i<VAR_HASH_SIZE; i++) {
v = VHashTbl[i];
while(v) {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n");
v = v->next;
@@ -575,6 +646,8 @@ static SysVar SysVarArr[] = {
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999},
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
@@ -584,7 +657,7 @@ static SysVar SysVarArr[] = {
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 132 },
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500 },
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
@@ -729,7 +802,7 @@ static SysVar *FindSysVar(char const *name)
/***************************************************************/
void DumpSysVarByName(char const *name)
{
int i;
size_t i;
SysVar *v;
if (!name || !*name) {
@@ -757,8 +830,12 @@ static void DumpSysVar(char const *name, const SysVar *v)
if (!v && !name) return; /* Shouldn't happen... */
buffer[0]='$'; buffer[1] = 0;
if (name && strlen(name) > VAR_NAME_LEN) {
fprintf(ErrFp, "$%s: Name too long\n", name);
return;
}
if (name) strcat(buffer, name); else strcat(buffer, v->name);
fprintf(ErrFp, "%*s ", VAR_NAME_LEN+1, buffer);
fprintf(ErrFp, "%16s ", buffer);
if (v) {
if (v->type == SPECIAL_TYPE) {
Value val;

8
sync-to-dianne-git Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
cd /home/dfs/Software/Remind.git || exit 1
rm -f .git/COMMIT_EDITMSG .git/*~
git update-server-info && cd .git && rsync --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
exit $?

View File

@@ -28,3 +28,5 @@ REM Fri SPECIAL SHADE 255 204 204
REM Sat SPECIAL SHADE 204 255 204
REM Sun SPECIAL SHADE 204 204 255
# This should be ignored by rem2ps
REM SPECIAL HTML <b>FOO</b>

View File

@@ -7,8 +7,7 @@
# in the build directory.
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 David F. Skoll
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 Dianne Skoll
# ---------------------------------------------------------------------------
DIR=`dirname $0`
@@ -80,6 +79,7 @@ rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
../src/remind -pp ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
# The sun tests can fail due to math roundoff error changing the times
# by a minute...
@@ -100,7 +100,198 @@ REM 1 Jan 2012 AT 10:00 MSG 10am: Should show up
MSG [$DontTrigAts]
EOF
# An OMITFUNC should indicate nonconst_expr
../src/remind -pp - 1 jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
REM Mon OMITFUNC foo MSG bar
EOF
# Test default color
../src/remind -ppp - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
REM 2 MSG Normal
SET $DefaultColor "255 0 0"
REM 3 MSG Red
SET $DefaultColor "-1 -1 -1"
REM 4 MSG Normal
# Should give an error
SET $DefaultColor "256 0 0"
EOF
# Test -@ option
../src/remind -w,0,0 -@0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@0,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@0,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@0,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@1,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@1,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2,0
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
../src/remind -w,0,0 -@2,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
rem 1 SPECIAL COLOR 0 0 0 BLACK
rem 2 SPECIAL COLOR 0 0 65 BLUE
rem 3 SPECIAL COLOR 0 65 0 GREEN
rem 4 SPECIAL COLOR 0 65 65 CYAN
rem 5 msg -@2,1
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
rem 18 SPECIAL COLOR 65 65 65 WHITE
rem 8 SPECIAL COLOR 0 0 0 BLACK
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED"

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,16 @@
#
# ./test-rem # From WITHIN Remind source directory!
# Should issue a warning
fset year(x) 1
# Don't evaluate SATISFY expressions if reminder has expired
REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
# bad AT
REM AT 0:00 0:01 0:02 MSG foo
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
fset _h(x, y) trigger(hebdate(x,y))
@@ -166,6 +172,10 @@ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
OMIT [trigger(trigdate())]
REM Fri after MSG 16 Feb 1991
CLEAR-OMIT-CONTEXT
REM Fri SCANFROM -7 SATISFY 1
OMIT [trigger(trigdate())]
REM Fri after MSG 16 Feb 1991
CLEAR-OMIT-CONTEXT
# Test omitfunc
fset _ofunc(x) (day(x) < 7 || day(x) % 2)
@@ -303,9 +313,231 @@ set a082 slide('1991-03-01', 7, "Sat", "Sun")
set a083 slide('1991-04-01', -7, "Sat")
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 MSG foo
set a086 trigback()
set a087 trigdelta()
set a088 trigrep()
set a089 triguntil()
set a090 trigscanfrom()
set a091 trigfrom()
set a092 trigpriority()
set a093 trigtimedelta()
set a094 trigtimerep()
set a095 trigduration()
REM Mon Wed FROM 2010-09-03 ++3 --4 MSG foo
set a096 trigback()
set a097 trigdelta()
set a098 trigrep()
set a099 triguntil()
set a100 trigscanfrom()
set a101 trigfrom()
set a102 trigpriority()
set a103 trigtimedelta()
set a104 trigtimerep()
set a105 trigduration()
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 AT 14:41 +15 *2 DURATION 213 MSG foo
set a106 trigback()
set a107 trigdelta()
set a108 trigrep()
set a109 triguntil()
set a110 trigscanfrom()
set a111 trigfrom()
set a112 trigpriority()
set a113 trigtimedelta()
set a114 trigtimerep()
set a115 trigduration()
REM Mon Wed FROM 2010-09-03 ++3 --4 AT 14:44 MSG foo
set a116 trigback()
set a117 trigdelta()
set a118 trigrep()
set a119 triguntil()
set a120 trigscanfrom()
set a121 trigfrom()
set a122 trigpriority()
set a123 trigtimedelta()
set a124 trigtimerep()
set a125 trigduration()
# Test adding TIME+TIME and DATETIME+TIME
set a126 11:00 + 3:00
set a127 23:00 + 5:30
set a128 '2018-02-03@10:00' + 6:45
set a129 23:30 + '2019-02-02@16:44'
# Multi-day reminder
REM 13 AT 16:00 DURATION 72:00 MSG 72-hour event
set a130 trigdate()
set a131 trigtime()
set a132 trigdatetime()
set a133 trigduration()
set a134 trigeventstart()
set a135 trigeventduration()
# These will issue errors
REM Mon OMIT Mon SKIP MSG Never ever ever...
REM Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
# These will just silently not trigger
REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
dump
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OMIT 2010-09-03 THROUGH 2010-09-15
OMIT December 25 MSG X
# Next should give a parse error
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
OMIT DUMP
# Regression test for bugfix in Hebrew calendar Adar jahrzeit
[_i(14, "Adar", today(), 5761)] MSG Purim
# Regression test for bug found by Larry Hynes
REM SATISFY [day(trigdate()-25) == 14] MSG Foo
# Check combo of SATISFY and long-duration events
REM 14 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 8:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 8:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 32:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 32:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
REM 14 AT 16:00 DURATION 40:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
# This is now an error
REM DURATION 15:00 MSG Should fail... need AT if you have DURATION.
# Parsing of AM/PM times
REM AT 0:00am MSG foo 0a
REM AT 1:00AM MSG foo 1a
REM AT 2:00am MSG foo 2a
REM AT 3:00AM MSG foo 3a
REM AT 4:00am MSG foo 4a
REM AT 5:00AM MSG foo 5a
REM AT 6:00am MSG foo 6a
REM AT 7:00AM MSG foo 7a
REM AT 8:00am MSG foo 8a
REM AT 9:00AM MSG foo 9a
REM AT 10:00am MSG foo 10a
REM AT 11:00AM MSG foo 11a
REM AT 12:00am MSG foo 12a
REM AT 13:00AM MSG foo 13a
REM AT 0:00pm MSG foo 0p
REM AT 1:00PM MSG foo 1p
REM AT 2:00pm MSG foo 2p
REM AT 3:00PM MSG foo 3p
REM AT 4:00pm MSG foo 4p
REM AT 5:00PM MSG foo 5p
REM AT 6:00pm MSG foo 6p
REM AT 7:00PM MSG foo 7p
REM AT 8:00pm MSG foo 8p
REM AT 9:00PM MSG foo 9p
REM AT 10:00pm MSG foo 10p
REM AT 11:00PM MSG foo 11p
REM AT 12:00pm MSG foo 12p
REM AT 13:00PM MSG foo 13p
DEBUG +x
SET x 0:00am + 0
SET x 1:00AM + 0
SET x 2:00am + 0
SET x 3:00AM + 0
SET x 4:00am + 0
SET x 5:00AM + 0
SET x 6:00am + 0
SET x 7:00AM + 0
SET x 8:00am + 0
SET x 9:00AM + 0
SET x 10:00am + 0
SET x 11:00AM + 0
SET x 12:00am + 0
SET x 13:00AM + 0
SET x 0:00pm + 0
SET x 1:00PM + 0
SET x 2:00pm + 0
SET x 3:00PM + 0
SET x 4:00pm + 0
SET x 5:00PM + 0
SET x 6:00pm + 0
SET x 7:00PM + 0
SET x 8:00pm + 0
SET x 9:00PM + 0
SET x 10:00pm + 0
SET x 11:00PM + 0
SET x 12:00pm + 0
SET x 13:00PM + 0
SET x '2015-02-03@0:00am' + 0
SET x '2015-02-03@1:00AM' + 0
SET x '2015-02-03@2:00am' + 0
SET x '2015-02-03@3:00AM' + 0
SET x '2015-02-03@4:00am' + 0
SET x '2015-02-03@5:00AM' + 0
SET x '2015-02-03@6:00am' + 0
SET x '2015-02-03@7:00AM' + 0
SET x '2015-02-03@8:00am' + 0
SET x '2015-02-03@9:00AM' + 0
SET x '2015-02-03@10:00am' + 0
SET x '2015-02-03@11:00AM' + 0
SET x '2015-02-03@12:00am' + 0
SET x '2015-02-03@13:00AM' + 0
SET x '2015-02-03@0:00pm' + 0
SET x '2015-02-03@1:00PM' + 0
SET x '2015-02-03@2:00pm' + 0
SET x '2015-02-03@3:00PM' + 0
SET x '2015-02-03@4:00pm' + 0
SET x '2015-02-03@5:00PM' + 0
SET x '2015-02-03@6:00pm' + 0
SET x '2015-02-03@7:00PM' + 0
SET x '2015-02-03@8:00pm' + 0
SET x '2015-02-03@9:00PM' + 0
SET x '2015-02-03@10:00pm' + 0
SET x '2015-02-03@11:00PM' + 0
SET x '2015-02-03@12:00pm' + 0
SET x '2015-02-03@13:00PM' + 0
# Test the ampm function
set x ampm(0:12) + ""
set x ampm(1:12) + ""
set x ampm(2:12) + ""
set x ampm(3:12) + ""
set x ampm(4:12) + ""
set x ampm(5:12) + ""
set x ampm(6:12) + ""
set x ampm(7:12) + ""
set x ampm(8:12) + ""
set x ampm(9:12) + ""
set x ampm(10:12) + ""
set x ampm(11:12) + ""
set x ampm(12:12) + ""
set x ampm(13:12) + ""
set x ampm(14:12) + ""
set x ampm(15:12) + ""
set x ampm(16:12) + ""
set x ampm(17:12) + ""
set x ampm(18:12) + ""
set x ampm(19:12) + ""
set x ampm(20:12) + ""
set x ampm(21:12) + ""
set x ampm(22:12) + ""
set x ampm(23:12) + ""
# Coerce with am/pm
set x coerce("TIME", "12:45am")
set x coerce("TIME", "12:45")
set x coerce("TIME", "1:45pm")
set x coerce("DATETIME", "2020-05-05@12:45am")
set x coerce("DATETIME", "2020-05-05@12:45")
set x coerce("DATETIME", "2020-05-05@1:45pm")
# Don't want Remind to queue reminders
EXIT
__EOF__
REM This line should not even be seen
And you can put whatever you like here.
[+f=asdfasdasde3ir0a]

View File

@@ -11,8 +11,7 @@
# Use the output to verify your translations.
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 David F. Skoll
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 Dianne Skoll
#
# ---------------------------------------------------------------------------

4
tests/utf-8.rem Normal file
View File

@@ -0,0 +1,4 @@
MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
Wed MSG With tabs and spaces

View File

@@ -1,7 +1,6 @@
# Makefile.in for installing WWW server calendar scripts
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2007 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
# The complete path to where the scripts actually live, as seen by
# the UNIX operating system.
@@ -70,6 +69,7 @@ install:
sed $(SEDSCRIPT) < moon.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/moon.rem
sed $(SEDSCRIPT) < sunrise.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
sed $(SEDSCRIPT) < sunset.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunset.rem
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
@@ -77,6 +77,7 @@ install:
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunset.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)

View File

@@ -9,7 +9,7 @@ only tested it with Linux running NCSA's httpd and Apache's httpd, but
it should work on any UNIX web server.
To install it, you need the Remind package, available via ftp from
ftp://ftp.doe.carleton.ca/pub/remind-3.0. You should install Remind,
https://dianne.skoll.ca/projects/remind/ You should install Remind,
setting the lattitude, longitude, location and time zone as appropriate
for your machine.
@@ -38,12 +38,8 @@ where "what" is one of:
hebps -- get a PostScript calendar with Jewish holidays.
hebhtml -- get an HTML version of the above (requires Perl.)
(Visit http://www.doe.carleton.ca/~dfs/ for previews.)
All of these links will be set up in a sample HTML document
called "calendar.html" and installed in the HTMLDIR you specified
in the Makefile.
4) Enjoy!

View File

@@ -10,4 +10,4 @@ You may have to edit the "#!/usr/bin/perl" line to reflect the
location of your Perl interpreter.
--
David F. Skoll
Dianne Skoll

5
www/blank.rem Normal file
View File

@@ -0,0 +1,5 @@
[moondate(0)] SPECIAL MOON 0
[moondate(1)] SPECIAL MOON 1
[moondate(2)] SPECIAL MOON 2
[moondate(3)] SPECIAL MOON 3
REM Monday SPECIAL WEEK (W[weekno()])

3
www/cal_dispatch-DIST Executable file → Normal file
View File

@@ -1,8 +1,7 @@
#!/bin/sh
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
# CAL_DISPATCH -- Shell script for CGI directory to dispatch calendar
# commands.

View File

@@ -22,7 +22,7 @@ PostScript Calendar with Jewish Holidays</a> (Approximately 35 kB)<P>
<a HREF="%CGIDIR%/cal_dispatch?hebhtml">
HTML Calendar with Jewish Holidays</a>
<HR>
<a HREF="http://www.roaringpenguin.com/remind">
<a HREF="https://dianne.skoll.ca/projects/remind">
Get the Remind software</a> that provides this service.<P>
</BODY>

5
www/calps Executable file → Normal file
View File

@@ -2,11 +2,10 @@
# PostScript calendar shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo "Content-type: application/postscript"
echo
$REMIND -p /dev/null | $REM2PS -e -c3 -l
$REMIND -p $DIR/blank.rem | $REM2PS -e -c3 -l
exit 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 360 B

3
www/hebdate Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# Hebrew date shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo Content-type: text/html
echo ""

View File

@@ -1,8 +1,7 @@
# Hebrew date reminder file
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
BANNER %
IF !$PSCAL
@@ -24,12 +23,14 @@ ENDIF
# dates were obtained from "The First Jewish Catalog" by Richard Siegel #
# and Michael and Sharon Strassfeld, published by the Jewish Publication #
# Society of America. The Reform version of the calendar was guessed #
# at by David Skoll based on experience. Additional corrections were #
# at by Dianne Skoll based on experience. Additional corrections were #
# made from the paper "Calendrical Calculations" by Nachum Dershowitz #
# and Edward M. Reingold. Any further corrections are welcome. #
# #
##########################################################################
SET n $NumTrig
# --- HERE ARE THE JEWISH HOLIDAYS ---
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
# you get the Diaspora versions of Jewish holidays
@@ -139,6 +140,10 @@ ENDIF
fset msgprefix(x) ""
IF $NumTrig > n
REM SPECIAL SHADE 224 224 255
ENDIF
# Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here!
@@ -166,7 +171,7 @@ ELSE
[trigger(moondate(2))] SPECIAL MOON 2
[trigger(moondate(3))] SPECIAL MOON 3
REM PS Border Border moveto /DayFont findfont 10 scalefont setfont ([hebday(today())] [hebmon(today())]) show
REM SPECIAL HTML <P><FONT SIZE=-1>[hebday(today())] [hebmon(today())]</FONT></P>
REM SPECIAL HTML <P>[hebday(today())] [hebmon(today())]</P>
ENDIF

3
www/hebhtml Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# HTML calendar shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo "Content-Type: text/html"
echo ""

3
www/hebps Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# Hebrew PostScript calendar shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
# Figure out the month: If day <= 20, use this month; otherwise, use
# next month.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 361 B

3
www/moon Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# Moon shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo Content-type: text/html
echo

View File

@@ -1,8 +1,7 @@
# File for giving moon phase info.
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
set now now()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

After

Width:  |  Height:  |  Size: 317 B

34
www/rem2html Executable file → Normal file
View File

@@ -4,10 +4,11 @@ use strict;
use warnings;
use Getopt::Long;
use JSON::Any;
my %Options;
my $rem2html_version = '2.0';
my $rem2html_version = '2.1';
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
@@ -84,7 +85,7 @@ Insert I<html_text> right before the E<lt>/bodyE<gt> tag.
=head1 AUTHOR
rem2html was written by David F. Skoll with much inspiration from an
rem2html was written by Dianne Skoll with much inspiration from an
earlier version by Don Schwarz.
=cut
@@ -191,7 +192,7 @@ sub parse_input
my $found_data = 0;
while(<STDIN>) {
chomp;
last if /^\# rem2ps begin$/;
last if /^\# rem2ps2? begin$/;
}
my $line;
@@ -228,13 +229,29 @@ sub parse_input
}
while(<STDIN>) {
chomp;
last if /^\# rem2ps end$/;
last if /^\# rem2ps2? end$/;
next if /^\#/;
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
my ($y, $m, $d, $special, $tag, $duration, $time, $body) =
($1, $2, $3, $4, $5, $6, $7, $8);
my ($y, $m, $d, $special, $tag, $duration, $time, $body);
if (m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/) {
($y, $m, $d, $special, $tag, $duration, $time, $body) =
($1, $2, $3, $4, $5, $6, $7, $8);
} elsif (/\{/) {
my $obj = JSON::Any->jsonToObj($_);
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
$y = $1;
$m = $2;
$d = $3;
$special = $obj->{passthru} || '*';
$tag = $obj->{tags} || '*';
$duration = $obj->{duration} || '*';
$time = $obj->{time} || '*';
$body = $obj->{body};
} else {
next;
}
my $d1 = $d;
$d1 =~ s/^0+//;
$special = uc($special);
if ($special eq 'HTML') {
push(@{$days->[$d]}, $body);
} elsif ($special eq 'HTMLCLASS') {
@@ -256,6 +273,9 @@ sub parse_input
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)/) {
$shades->[$d] = sprintf("#%02X%02X%02X",
($1 % 256), ($2 % 256), ($3 % 256));
} elsif ($body =~ /(\d+)/) {
$shades->[$d] = sprintf("#%02X%02X%02X",
($1 % 256), ($1 % 256), ($1 % 256));
}
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {

3
www/sunrise Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# Sunrise shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo Content-type: text/html
echo

3
www/sunrise.rem-DIST Executable file → Normal file
View File

@@ -1,8 +1,7 @@
# File for giving sunrise info
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
set now now()

3
www/sunset Executable file → Normal file
View File

@@ -2,8 +2,7 @@
# Sunset shell script
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
echo Content-type: text/html
echo

View File

@@ -1,8 +1,7 @@
# File for giving sunset info
#
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
# Copyright (C) 1992-2018 by Dianne Skoll
set now now()