Compare commits

..

167 Commits

Author SHA1 Message Date
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
73 changed files with 6325 additions and 618 deletions

1
.gitignore vendored
View File

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

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

2
configure vendored
View File

@@ -3991,7 +3991,7 @@ _ACEOF
fi
done
VERSION=03.01.17
VERSION=03.03.00
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"

View File

@@ -75,6 +75,6 @@ if test "$GCC" = yes; then
fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
VERSION=03.01.17
VERSION=03.03.00
AC_SUBST(VERSION)
AC_OUTPUT(src/Makefile www/Makefile src/version.h)

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,7 +93,7 @@ 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 -------------

View File

@@ -1,5 +1,82 @@
CHANGES TO REMIND
* 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.

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

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,6 +402,247 @@ 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 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
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

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
@@ -46,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:
@@ -72,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
@@ -106,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
@@ -448,7 +489,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
@@ -1033,17 +1075,17 @@ 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:
.PP
.nf
REM 5 March 1999 AT 13:00 DURATION 1:30 MSG Meeting
.fi
.PP
Note that \fIduration\fR is specified in hours and minutes.
Note that \fIduration\fR is specified in hours and minutes. If you
specify a duration of 00:00, then \fBRemind\fR behaves exactly as if
no \fBDURATION\fR at all had been present.
.PP
.SH THE SUBSTITUTION FILTER
.PP
@@ -1709,7 +1751,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.
@@ -1718,6 +1765,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.
@@ -1751,9 +1803,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 >=
@@ -1883,6 +1937,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
@@ -1986,6 +2056,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.
@@ -2791,10 +2865,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
@@ -2827,9 +2968,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
@@ -2909,6 +3052,99 @@ 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 \fIearlier\fR event (only one copy of
an event is ever triggered for a given date.) Consider this example:
.PP
.nf
#!/bin/sh
remind - '*4' 11 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-11 1991-02-04@00:00 24: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 1991-02-11 is a Monday (which should cause the event to be
triggered, the 8-day-long event that started on 1991-02-04 \fIhas not
finished yet\fR, so that is the one that is triggered. The next day,
the event starting on 1991-02-04 \fIhas\fR finished, so the 1991-02-11
event triggers, with a remaining duration of 168:00, or 7 days.
.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,
@@ -2984,7 +3220,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
@@ -3080,8 +3316,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
@@ -3279,12 +3517,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
@@ -3307,6 +3545,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
@@ -3361,7 +3605,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.
@@ -3369,16 +3613,14 @@ 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
@@ -3547,7 +3789,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
@@ -4136,7 +4378,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
@@ -4199,9 +4441,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:

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
@@ -360,7 +360,7 @@ This line is emitted in response to a \fBSTATUS\fR command. The number
.SH AUTHOR
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
\fBTkRemind\fR is Copyright 1996-2018 by Dianne Skoll.
\fBTkRemind\fR is Copyright 1996-2020 by Dianne Skoll.
.SH FILES

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,7 +74,7 @@ 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.
@@ -86,6 +88,7 @@ distro:
beta-tgz:
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar
gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION)-BETA-$(BETA).tar.gz
#---------------- Stuff after this added by "make depend" -----------------

View File

@@ -5,7 +5,7 @@
/* The code for generating a calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -16,6 +16,8 @@
#include <ctype.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#ifdef REM_USE_WCHAR
#include <wctype.h>
@@ -31,10 +33,11 @@
/* Data structures used by the calendar */
typedef struct cal_entry {
struct cal_entry *next;
char const *text;
char *text;
char *raw_text;
char const *pos;
#ifdef REM_USE_WCHAR
wchar_t const *wc_text;
wchar_t *wc_text;
wchar_t const *wc_pos;
#endif
int is_color;
@@ -44,8 +47,12 @@ typedef struct cal_entry {
DynamicBuffer tags;
char passthru[PASSTHRU_LEN+1];
int duration;
char const *filename;
char *filename;
int lineno;
Trigger trig;
TimeTrig tt;
int nonconst_expr;
int if_depth;
} CalEntry;
/* Line-drawing sequences */
@@ -132,13 +139,92 @@ static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
static struct line_drawing *linestruct;
#define DRAW(x) fputs(linestruct->x, stdout)
struct xterm256_colors {
int r;
int g;
int b;
};
/* Xterm support 256 different colors, numbered from 0 to 255. The following
table is a list of the [r, g, b] components of each Xterm color. The
data was obtained from https://jonasjacek.github.io/colors/ */
static struct xterm256_colors XTerm256Colors[] =
{
{ 0, 0, 0}, {128, 0, 0}, { 0, 128, 0}, {128, 128, 0},
{ 0, 0, 128}, {128, 0, 128}, { 0, 128, 128}, {192, 192, 192},
{128, 128, 128}, {255, 0, 0}, { 0, 255, 0}, {255, 255, 0},
{ 0, 0, 255}, {255, 0, 255}, { 0, 255, 255}, {255, 255, 255},
{ 0, 0, 0}, { 0, 0, 95}, { 0, 0, 135}, { 0, 0, 175},
{ 0, 0, 215}, { 0, 0, 255}, { 0, 95, 0}, { 0, 95, 95},
{ 0, 95, 135}, { 0, 95, 175}, { 0, 95, 215}, { 0, 95, 255},
{ 0, 135, 0}, { 0, 135, 95}, { 0, 135, 135}, { 0, 135, 175},
{ 0, 135, 215}, { 0, 135, 255}, { 0, 175, 0}, { 0, 175, 95},
{ 0, 175, 135}, { 0, 175, 175}, { 0, 175, 215}, { 0, 175, 255},
{ 0, 215, 0}, { 0, 215, 95}, { 0, 215, 135}, { 0, 215, 175},
{ 0, 215, 215}, { 0, 215, 255}, { 0, 255, 0}, { 0, 255, 95},
{ 0, 255, 135}, { 0, 255, 175}, { 0, 255, 215}, { 0, 255, 255},
{ 95, 0, 0}, { 95, 0, 95}, { 95, 0, 135}, { 95, 0, 175},
{ 95, 0, 215}, { 95, 0, 255}, { 95, 95, 0}, { 95, 95, 95},
{ 95, 95, 135}, { 95, 95, 175}, { 95, 95, 215}, { 95, 95, 255},
{ 95, 135, 0}, { 95, 135, 95}, { 95, 135, 135}, { 95, 135, 175},
{ 95, 135, 215}, { 95, 135, 255}, { 95, 175, 0}, { 95, 175, 95},
{ 95, 175, 135}, { 95, 175, 175}, { 95, 175, 215}, { 95, 175, 255},
{ 95, 215, 0}, { 95, 215, 95}, { 95, 215, 135}, { 95, 215, 175},
{ 95, 215, 215}, { 95, 215, 255}, { 95, 255, 0}, { 95, 255, 95},
{ 95, 255, 135}, { 95, 255, 175}, { 95, 255, 215}, { 95, 255, 255},
{135, 0, 0}, {135, 0, 95}, {135, 0, 135}, {135, 0, 175},
{135, 0, 215}, {135, 0, 255}, {135, 95, 0}, {135, 95, 95},
{135, 95, 135}, {135, 95, 175}, {135, 95, 215}, {135, 95, 255},
{135, 135, 0}, {135, 135, 95}, {135, 135, 135}, {135, 135, 175},
{135, 135, 215}, {135, 135, 255}, {135, 175, 0}, {135, 175, 95},
{135, 175, 135}, {135, 175, 175}, {135, 175, 215}, {135, 175, 255},
{135, 215, 0}, {135, 215, 95}, {135, 215, 135}, {135, 215, 175},
{135, 215, 215}, {135, 215, 255}, {135, 255, 0}, {135, 255, 95},
{135, 255, 135}, {135, 255, 175}, {135, 255, 215}, {135, 255, 255},
{175, 0, 0}, {175, 0, 95}, {175, 0, 135}, {175, 0, 175},
{175, 0, 215}, {175, 0, 255}, {175, 95, 0}, {175, 95, 95},
{175, 95, 135}, {175, 95, 175}, {175, 95, 215}, {175, 95, 255},
{175, 135, 0}, {175, 135, 95}, {175, 135, 135}, {175, 135, 175},
{175, 135, 215}, {175, 135, 255}, {175, 175, 0}, {175, 175, 95},
{175, 175, 135}, {175, 175, 175}, {175, 175, 215}, {175, 175, 255},
{175, 215, 0}, {175, 215, 95}, {175, 215, 135}, {175, 215, 175},
{175, 215, 215}, {175, 215, 255}, {175, 255, 0}, {175, 255, 95},
{175, 255, 135}, {175, 255, 175}, {175, 255, 215}, {175, 255, 255},
{215, 0, 0}, {215, 0, 95}, {215, 0, 135}, {215, 0, 175},
{215, 0, 215}, {215, 0, 255}, {215, 95, 0}, {215, 95, 95},
{215, 95, 135}, {215, 95, 175}, {215, 95, 215}, {215, 95, 255},
{215, 135, 0}, {215, 135, 95}, {215, 135, 135}, {215, 135, 175},
{215, 135, 215}, {215, 135, 255}, {215, 175, 0}, {215, 175, 95},
{215, 175, 135}, {215, 175, 175}, {215, 175, 215}, {215, 175, 255},
{215, 215, 0}, {215, 215, 95}, {215, 215, 135}, {215, 215, 175},
{215, 215, 215}, {215, 215, 255}, {215, 255, 0}, {215, 255, 95},
{215, 255, 135}, {215, 255, 175}, {215, 255, 215}, {215, 255, 255},
{255, 0, 0}, {255, 0, 95}, {255, 0, 135}, {255, 0, 175},
{255, 0, 215}, {255, 0, 255}, {255, 95, 0}, {255, 95, 95},
{255, 95, 135}, {255, 95, 175}, {255, 95, 215}, {255, 95, 255},
{255, 135, 0}, {255, 135, 95}, {255, 135, 135}, {255, 135, 175},
{255, 135, 215}, {255, 135, 255}, {255, 175, 0}, {255, 175, 95},
{255, 175, 135}, {255, 175, 175}, {255, 175, 215}, {255, 175, 255},
{255, 215, 0}, {255, 215, 95}, {255, 215, 135}, {255, 215, 175},
{255, 215, 215}, {255, 215, 255}, {255, 255, 0}, {255, 255, 95},
{255, 255, 135}, {255, 255, 175}, {255, 255, 215}, {255, 255, 255},
{ 8, 8, 8}, { 18, 18, 18}, { 28, 28, 28}, { 38, 38, 38},
{ 48, 48, 48}, { 58, 58, 58}, { 68, 68, 68}, { 78, 78, 78},
{ 88, 88, 88}, { 98, 98, 98}, {108, 108, 108}, {118, 118, 118},
{128, 128, 128}, {138, 138, 138}, {148, 148, 148}, {158, 158, 158},
{168, 168, 168}, {178, 178, 178}, {188, 188, 188}, {198, 198, 198},
{208, 208, 208}, {218, 218, 218}, {228, 228, 228}, {238, 238, 238}
};
/* Global variables */
static CalEntry *CalColumn[7];
static int ColSpaces;
static void Colorize(CalEntry const *e);
static void Decolorize(void);
static int DidAMonth;
static int DidADay;
static void ColorizeEntry(CalEntry const *e);
static void SortCol (CalEntry **col);
static void DoCalendarOneWeek (int nleft);
static void DoCalendarOneMonth (void);
@@ -159,6 +245,76 @@ static void WriteBottomCalLine (void);
static void WriteIntermediateCalLine (void);
static void WriteCalDays (void);
static void PrintJSONString(char const *s)
{
while (*s) {
switch(*s) {
case '\b': printf("\\b"); break;
case '\f': printf("\\f"); break;
case '\n': printf("\\n"); break;
case '\r': printf("\\r"); break;
case '\t': printf("\\t"); break;
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
default: printf("%c", *s);
}
s++;
}
}
static void PrintJSONKeyPairInt(char const *name, int val)
{
printf("\"");
PrintJSONString(name);
printf("\":%d, ", val);
}
static void PrintJSONKeyPairString(char const *name, char const *val)
{
/* If value is blank, skip it! */
if (!val || !*val) {
return;
}
printf("\"");
PrintJSONString(name);
printf("\":\"");
PrintJSONString(val);
printf("\", ");
}
static void PrintJSONKeyPairDate(char const *name, int jul)
{
int y, m, d;
if (jul == NO_DATE) {
/* Skip it! */
return;
}
FromJulian(jul, &y, &m, &d);
printf("\"");
PrintJSONString(name);
printf("\":\"%04d-%02d-%02d\", ", y, m+1, d);
}
static void PrintJSONKeyPairDateTime(char const *name, int dt)
{
int y, m, d, h, i, k;
if (dt == NO_TIME) {
/* Skip it! */
return;
}
i = dt / MINUTES_PER_DAY;
FromJulian(i, &y, &m, &d);
k = dt % MINUTES_PER_DAY;
h = k / 60;
i = k % 60;
printf("\"");
PrintJSONString(name);
printf("\":\"%04d-%02d-%02dT%02d:%02d\", ", y, m+1, d, h, i);
}
#ifdef REM_USE_WCHAR
static void PutWideChar(wchar_t const wc)
{
@@ -202,26 +358,146 @@ static void goff(void)
printf("%s", linestruct->graphics_off);
}
static void Decolorize(void)
static void
ClampColor(int *r, int *g, int *b)
{
printf("%s", "\x1B[0m");
if (TerminalBackground == TERMINAL_BACKGROUND_UNKNOWN) {
/* No special clamping if terminal background is unknown */
return;
}
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
if (*r <= 64 && *g <= 64 && *b <= 64) {
int max = *r;
double factor;
if (*g > max) max = *g;
if (*b > max) max = *b;
if (max == 0) {
*r = 65;
*g = 65;
*b = 65;
return;
}
factor = 65.0 / (double) max;
*r = (int) (factor * (double) *r);
*g = (int) (factor * (double) *g);
*b = (int) (factor * (double) *b);
}
return;
}
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
if (*r > 191 && *g > 191 && *b > 191) {
int min = *r;
if (*g < min) min = *g;
if (*b < min) min = *b;
double factor = 192.0 / (double) min;
*r = (int) (factor * (double) *r);
*g = (int) (factor * (double) *g);
*b = (int) (factor * (double) *b);
}
}
}
static void Colorize(CalEntry const *e)
char const *
Decolorize(int r, int g, int b)
{
int bright = 0;
int r, g, b;
if (e->r > 128 || e->g > 128 || e->b > 128) {
bright = 1;
}
if (e->r > 64) r = 1;
else r = 0;
if (e->g > 64) g = 1;
else g = 0;
if (e->b > 64) b = 1;
else b = 0;
if (!strcmp(Colorize(r, g, b), "")) {
return "";
}
return "\x1B[0m";
}
printf("%s", VT100Colors[bright][r][g][b]);
static char const *
Colorize256(int r, int g, int b)
{
static char buf[40];
int best = -1;
int best_dist = 0;
int dist;
struct xterm256_colors *cur;
size_t i;
ClampColor(&r, &g, &b);
for (i=0; i<(sizeof(XTerm256Colors) / sizeof(XTerm256Colors[0])); i++) {
cur = &XTerm256Colors[i];
dist = ((r - cur->r) * (r - cur->r)) +
((b - cur->b) * (b - cur->b)) +
((g - cur->g) * (g - cur->g));
if (best == -1 || dist < best_dist) {
best_dist = dist;
best = (int) i;
}
}
cur = &XTerm256Colors[best];
sprintf(buf, "\x1B[38;5;%dm", best);
return buf;
}
static char const *
ColorizeTrue(int r, int g, int b)
{
static char buf[40];
ClampColor(&r, &g, &b);
sprintf(buf, "\x1B[38;2;%d;%d;%dm", r, g, b);
return buf;
}
char const *
Colorize(int r, int g, int b)
{
int bright = 0;
if (UseTrueColors) {
return ColorizeTrue(r, g, b);
}
if (Use256Colors) {
return Colorize256(r, g, b);
}
if (r > 128 || g > 128 || b > 128) {
bright = 1;
}
if (r > 64) r = 1;
else r = 0;
if (g > 64) g = 1;
else g = 0;
if (b > 64) b = 1;
else b = 0;
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
/* Convert black-on-black to grey */
if (!r && !g && !b) return VT100Colors[1][0][0][0];
}
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
/* Convert white-on-white to grey */
if (r && g && b) return VT100Colors[1][0][0][0];
}
return VT100Colors[bright][r][g][b];
}
static void ColorizeEntry(CalEntry const *e)
{
printf("%s", Colorize(e->r, e->g, e->b));
}
static int
ComputeCalWidth(int x)
{
struct winsize w;
if (x >= 71) {
/* Has been set with -w option */
return x;
}
if (!isatty(STDOUT_FILENO)) {
/* Output is not a TTY... assume 80 */
return 80;
}
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) {
return 80;
}
if (w.ws_col < 71) {
return 80;
}
return w.ws_col;
}
/***************************************************************/
@@ -244,14 +520,25 @@ void ProduceCalendar(void)
}
ShouldCache = 1;
CalWidth = ComputeCalWidth(CalWidth);
ColSpaces = (CalWidth - 9) / 7;
CalWidth = 7*ColSpaces + 8;
if (CalMonths) {
FromJulian(JulianToday, &y, &m, &d);
JulianToday = Julian(y, m, 1);
while (CalMonths--)
DidAMonth = 0;
if (PsCal == PSCAL_LEVEL3) {
printf("[\n");
}
while (CalMonths--) {
DoCalendarOneMonth();
DidAMonth = 1;
}
if (PsCal == PSCAL_LEVEL3) {
printf("\n]\n");
}
return;
} else {
if (MondayFirst) JulianToday -= (JulianToday%7);
@@ -373,30 +660,74 @@ static void DoCalendarOneMonth(void)
if (!DoSimpleCalendar) WriteCalHeader();
DidADay = 0;
if (PsCal) {
FromJulian(JulianToday, &y, &m, &d);
printf("%s\n", PSBEGIN);
printf("%s %d %d %d %d\n",
MonthName[m], y, DaysInMonth(m, y), (JulianToday+1) % 7,
MondayFirst);
printf("%s %s %s %s %s %s %s\n",
DayName[6], DayName[0], DayName[1], DayName[2],
DayName[3], DayName[4], DayName[5]);
if (PsCal == PSCAL_LEVEL1) {
printf("%s\n", PSBEGIN);
} else if (PsCal == PSCAL_LEVEL2) {
printf("%s\n", PSBEGIN2);
} else {
if (DidAMonth) {
printf(",\n");
}
printf("{\n");
}
if (PsCal < PSCAL_LEVEL3) {
printf("%s %d %d %d %d\n",
MonthName[m], y, DaysInMonth(m, y), (JulianToday+1) % 7,
MondayFirst);
printf("%s %s %s %s %s %s %s\n",
DayName[6], DayName[0], DayName[1], DayName[2],
DayName[3], DayName[4], DayName[5]);
} else {
PrintJSONKeyPairString("monthname", MonthName[m]);
PrintJSONKeyPairInt("year", y);
PrintJSONKeyPairInt("daysinmonth", DaysInMonth(m, y));
PrintJSONKeyPairInt("firstwkday", (JulianToday+1) % 7);
PrintJSONKeyPairInt("mondayfirst", MondayFirst);
printf("\"daynames\":[\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"],",
DayName[6], DayName[0], DayName[1], DayName[2],
DayName[3], DayName[4], DayName[5]);
}
mm = m-1;
if (mm<0) {
mm = 11; yy = y-1;
} else yy=y;
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
if (PsCal < PSCAL_LEVEL3) {
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
} else {
PrintJSONKeyPairString("prevmonthname", MonthName[mm]);
PrintJSONKeyPairInt("daysinprevmonth", DaysInMonth(mm, yy));
PrintJSONKeyPairInt("prevmonthyear", yy);
}
mm = m+1;
if (mm>11) {
mm = 0; yy = y+1;
} else yy=y;
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
if (PsCal < PSCAL_LEVEL3) {
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
} else {
PrintJSONKeyPairString("nextmonthname", MonthName[mm]);
PrintJSONKeyPairInt("daysinnextmonth", DaysInMonth(mm, yy));
PrintJSONKeyPairInt("nextmonthyear", yy);
printf("\"entries\":[\n");
}
}
while (WriteCalendarRow()) continue;
if (PsCal) printf("%s\n", PSEND);
if (PsCal == PSCAL_LEVEL1) {
printf("%s\n", PSEND);
} else if (PsCal == PSCAL_LEVEL2) {
printf("%s\n", PSEND2);
} else if (PsCal == PSCAL_LEVEL3){
if (DidADay) {
printf("\n");
}
printf("]\n}");
}
if (!DoSimpleCalendar) WriteCalTrailer();
}
@@ -631,9 +962,10 @@ static int WriteOneColLine(int col)
if (!*ws && e->next) {
PrintLeft("", ColSpaces, ' ');
CalColumn[col] = e->next;
free((void *)e->text);
free((void *)e->filename);
if (e->wc_text) free((void *)e->wc_text);
free(e->text);
free(e->raw_text);
free(e->filename);
if (e->wc_text) free(e->wc_text);
free(e);
return 1;
}
@@ -647,7 +979,7 @@ static int WriteOneColLine(int col)
/* Colorize reminder if necessary */
if (UseVTColors && e->is_color) {
Colorize(e);
ColorizeEntry(e);
}
/* If we couldn't find a space char, print what we have. */
@@ -669,7 +1001,7 @@ static int WriteOneColLine(int col)
/* Decolorize reminder if necessary */
if (UseVTColors && e->is_color) {
Decolorize();
printf("%s", Decolorize(e->r, e->g, e->b));
}
/* Flesh out the rest of the column */
@@ -681,9 +1013,10 @@ static int WriteOneColLine(int col)
/* If done, free memory if no next entry. */
if (!*ws && !e->next) {
CalColumn[col] = e->next;
free((void *)e->text);
free((void *)e->filename);
if (e->wc_text) free((void *)e->wc_text);
free(e->text);
free(e->raw_text);
free(e->filename);
if (e->wc_text) free(e->wc_text);
free(e);
} else {
e->wc_pos = ws;
@@ -699,11 +1032,12 @@ static int WriteOneColLine(int col)
if (!*s && e->next) {
PrintLeft("", ColSpaces, ' ');
CalColumn[col] = e->next;
free((void *)e->text);
free((void *)e->filename);
free(e->text);
free(e->filename);
#ifdef REM_USE_WCHAR
if (e->wc_text) free((void *)e->wc_text);
if (e->wc_text) free(e->wc_text);
#endif
free(e->raw_text);
free(e);
return 1;
}
@@ -717,7 +1051,7 @@ static int WriteOneColLine(int col)
/* Colorize reminder if necessary */
if (UseVTColors && e->is_color) {
Colorize(e);
ColorizeEntry(e);
}
/* If we couldn't find a space char, print what we have. */
@@ -739,7 +1073,7 @@ static int WriteOneColLine(int col)
/* Decolorize reminder if necessary */
if (UseVTColors && e->is_color) {
Decolorize();
printf("%s", Decolorize(e->r, e->g, e->b));
}
/* Flesh out the rest of the column */
@@ -751,11 +1085,12 @@ static int WriteOneColLine(int col)
/* If done, free memory if no next entry. */
if (!*s && !e->next) {
CalColumn[col] = e->next;
free((void *)e->text);
free((void *)e->filename);
free(e->text);
free(e->filename);
#ifdef REM_USE_WCHAR
if (e->wc_text) free((void *)e->wc_text);
if (e->wc_text) free(e->wc_text);
#endif
free(e->raw_text);
free(e);
} else {
e->pos = s;
@@ -781,10 +1116,7 @@ static void GenerateCalEntries(int col)
Parser p;
/* Do some initialization first... */
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
NumTriggered = 0;
PerIterationInit();
r=IncludeFile(InitialFile);
if (r) {
@@ -930,14 +1262,16 @@ static int DoCalRem(ParsePtr p, int col)
CalEntry *CurCol = CalColumn[col];
CalEntry *e;
char const *s, *s2;
DynamicBuffer buf, obuf, pre_buf;
DynamicBuffer buf, obuf, pre_buf, raw_buf;
Token tok;
int nonconst_expr = 0;
int is_color, col_r, col_g, col_b;
is_color = 0;
DBufInit(&buf);
DBufInit(&pre_buf);
DBufInit(&raw_buf);
/* Parse the trigger date and time */
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
@@ -945,6 +1279,20 @@ static int DoCalRem(ParsePtr p, int col)
return r;
}
if (trig.typ == MSG_TYPE ||
trig.typ == CAL_TYPE ||
trig.typ == MSF_TYPE) {
is_color = (
DefaultColorR != -1
&& DefaultColorG != -1
&& DefaultColorB != -1);
if (is_color) {
col_r = DefaultColorR;
col_g = DefaultColorG;
col_b = DefaultColorB;
}
}
/* Don't include timed reminders in calendar if -a option supplied. */
if (DontIssueAts && tim.ttime != NO_TIME) {
FreeTrig(&trig);
@@ -955,7 +1303,7 @@ static int DoCalRem(ParsePtr p, int col)
return E_EOLN;
}
if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, p);
r=DoSatRemind(&trig, &tim, p);
if (r) {
FreeTrig(&trig);
if (r == E_EXPIRED) return OK;
@@ -999,13 +1347,15 @@ static int DoCalRem(ParsePtr p, int col)
}
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
FreeTrig(&trig);
return r;
}
}
/* Save nonconst_expr flag */
nonconst_expr = p->nonconst_expr;
/* Convert PS and PSF to PASSTHRU */
if (trig.typ == PS_TYPE) {
strcpy(trig.passthru, "PostScript");
@@ -1014,13 +1364,27 @@ static int DoCalRem(ParsePtr p, int col)
strcpy(trig.passthru, "PSFile");
trig.typ = PASSTHRU_TYPE;
}
/* If it's a plain reminder but we have a default color, add the
three colors to the prebuf and change passthru to "COLOR" */
if (trig.typ == MSG_TYPE ||
trig.typ == CAL_TYPE ||
trig.typ == MSF_TYPE) {
if (PsCal && is_color) {
char cbuf[24];
sprintf(cbuf, "%d %d %d ", col_r, col_g, col_b);
DBufPuts(&pre_buf, cbuf);
strcpy(trig.passthru, "COLOR");
/* Don't change trig.typ or next if() will trigger! */
}
}
if (trig.typ == PASSTHRU_TYPE) {
if (!PsCal && strcmp(trig.passthru, "COLOR") && strcmp(trig.passthru, "COLOUR")) {
if (!PsCal && StrCmpi(trig.passthru, "COLOR") && StrCmpi(trig.passthru, "COLOUR")) {
FreeTrig(&trig);
return OK;
}
if (!strcmp(trig.passthru, "COLOR") ||
!strcmp(trig.passthru, "COLOUR")) {
if (!StrCmpi(trig.passthru, "COLOR") ||
!StrCmpi(trig.passthru, "COLOUR")) {
is_color = 1;
/* Strip off the three color numbers */
DBufFree(&buf);
@@ -1069,20 +1433,31 @@ static int DoCalRem(ParsePtr p, int col)
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
NumTriggered++;
/* The parse_ptr should not be nested, but just in case... */
if (!p->isnested) {
if (DBufPuts(&raw_buf, p->pos) != OK) {
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
}
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
/* Suppress time if it's not today or if it's a non-COLOR special */
if (jul != JulianToday ||
(trig.typ == PASSTHRU_TYPE &&
strcmp(trig.passthru, "COLOUR") &&
strcmp(trig.passthru, "COLOR"))) {
StrCmpi(trig.passthru, "COLOUR") &&
StrCmpi(trig.passthru, "COLOR"))) {
if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) {
DBufFree(&obuf);
DBufFree(&raw_buf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
} else {
if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) {
DBufFree(&raw_buf);
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
@@ -1100,6 +1475,7 @@ static int DoCalRem(ParsePtr p, int col)
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(&obuf, v.v.str) != OK) {
DestroyValue(v);
DBufFree(&raw_buf);
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
@@ -1121,12 +1497,14 @@ static int DoCalRem(ParsePtr p, int col)
if (r) {
DBufFree(&pre_buf);
DBufFree(&obuf);
DBufFree(&raw_buf);
FreeTrig(&trig);
return r;
}
if (DBufLen(&obuf) <= oldLen) {
DBufFree(&obuf);
DBufFree(&pre_buf);
DBufFree(&raw_buf);
FreeTrig(&trig);
return OK;
}
@@ -1140,6 +1518,7 @@ static int DoCalRem(ParsePtr p, int col)
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(&obuf, v.v.str) != OK) {
DestroyValue(v);
DBufFree(&raw_buf);
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
@@ -1156,10 +1535,15 @@ static int DoCalRem(ParsePtr p, int col)
e = NEW(CalEntry);
if (!e) {
DBufFree(&obuf);
DBufFree(&raw_buf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
e->nonconst_expr = nonconst_expr;
e->if_depth = NumIfs;
e->trig = trig;
e->tt = tim;
#ifdef REM_USE_WCHAR
e->wc_pos = NULL;
e->wc_text = NULL;
@@ -1169,9 +1553,13 @@ static int DoCalRem(ParsePtr p, int col)
e->g = col_g;
e->b = col_b;
e->text = StrDup(s);
e->raw_text = StrDup(DBufValue(&raw_buf));
DBufFree(&raw_buf);
DBufFree(&obuf);
DBufFree(&pre_buf);
if (!e->text) {
if (!e->text || !e->raw_text) {
if (e->text) free(e->text);
if (e->raw_text) free(e->raw_text);
free(e);
FreeTrig(&trig);
return E_NO_MEM;
@@ -1189,12 +1577,14 @@ static int DoCalRem(ParsePtr p, int col)
e->priority = trig.priority;
e->filename = StrDup(FileName);
if(!e->filename) {
if (e->text) free(e->text);
if (e->raw_text) free(e->raw_text);
free(e);
return E_NO_MEM;
}
e->lineno = LineNo;
if (trig.typ == PASSTHRU_TYPE) {
if (trig.typ == PASSTHRU_TYPE || is_color) {
StrnCpy(e->passthru, trig.passthru, PASSTHRU_LEN);
} else {
e->passthru[0] = 0;
@@ -1212,23 +1602,8 @@ static int DoCalRem(ParsePtr p, int col)
return OK;
}
/***************************************************************/
/* */
/* WriteSimpleEntries */
/* */
/* Write entries in 'simple calendar' format. */
/* */
/***************************************************************/
static void WriteSimpleEntries(int col, int jul)
static void WriteSimpleEntryProtocol1(CalEntry *e)
{
CalEntry *e = CalColumn[col];
CalEntry *n;
int y, m, d;
FromJulian(jul, &y, &m, &d);
while(e) {
if (DoPrefixLineNo) printf("# fileinfo %d %s\n", e->lineno, e->filename);
printf("%04d/%02d/%02d", y, m+1, d);
if (e->passthru[0]) {
printf(" %s", e->passthru);
} else {
@@ -1250,10 +1625,186 @@ static void WriteSimpleEntries(int col, int jul)
printf("* ");
}
printf("%s\n", e->text);
free((void *)e->text);
free((void *)e->filename);
}
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
{
int done = 0;
if (DoPrefixLineNo) {
PrintJSONKeyPairString("filename", e->filename);
PrintJSONKeyPairInt("lineno", e->lineno);
}
PrintJSONKeyPairString("passthru", e->passthru);
PrintJSONKeyPairString("tags", DBufValue(&(e->tags)));
if (e->duration != NO_TIME) {
PrintJSONKeyPairInt("duration", e->duration);
}
if (e->time != NO_TIME) {
PrintJSONKeyPairInt("time", e->time);
if (e->tt.delta) {
PrintJSONKeyPairInt("tdelta", e->tt.delta);
}
if (e->tt.rep) {
PrintJSONKeyPairInt("trep", e->tt.rep);
}
}
if (e->trig.eventduration != NO_TIME) {
PrintJSONKeyPairInt("eventduration", e->trig.eventduration);
}
/* wd is an array of days from 0=monday to 6=sunday.
We convert to array of strings */
if (e->trig.wd != NO_WD) {
printf("\"wd\":[");
done = 0;
int i;
for (i=0; i<7; i++) {
if (e->trig.wd & (1 << i)) {
if (done) {
printf(",");
}
done = 1;
printf("\"%s\"", EnglishDayName[i]);
}
}
printf("], ");
}
if (e->trig.d != NO_DAY) {
PrintJSONKeyPairInt("d", e->trig.d);
}
if (e->trig.m != NO_MON) {
PrintJSONKeyPairInt("m", e->trig.m+1);
}
if (e->trig.y != NO_YR) {
PrintJSONKeyPairInt("y", e->trig.y);
}
PrintJSONKeyPairDateTime("eventstart", e->trig.eventstart);
if (e->trig.back) {
PrintJSONKeyPairInt("back", e->trig.back);
}
if (e->trig.delta) {
PrintJSONKeyPairInt("delta", e->trig.delta);
}
if (e->trig.rep) {
PrintJSONKeyPairInt("rep", e->trig.rep);
}
if (e->nonconst_expr) {
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
}
if (e->if_depth) {
PrintJSONKeyPairInt("if_depth", e->if_depth);
}
switch(e->trig.skip) {
case SKIP_SKIP:
PrintJSONKeyPairString("skip", "SKIP");
break;
case BEFORE_SKIP:
PrintJSONKeyPairString("skip", "BEFORE");
break;
case AFTER_SKIP:
PrintJSONKeyPairString("skip", "AFTER");
break;
}
/* Local omit is an array of days from 0=monday to 6=sunday.
We convert to array of strings */
if (e->trig.localomit != NO_WD) {
printf("\"localomit\":[");
done = 0;
int i;
for (i=0; i<7; i++) {
if (e->trig.localomit & (1 << i)) {
if (done) {
printf(",");
}
done = 1;
printf("\"%s\"", EnglishDayName[i]);
}
}
printf("], ");
}
PrintJSONKeyPairDate("until", e->trig.until);
if (e->trig.once != NO_ONCE) {
PrintJSONKeyPairInt("once", e->trig.once);
}
if (e->trig.scanfrom != today) {
PrintJSONKeyPairDate("scanfrom", e->trig.scanfrom);
}
PrintJSONKeyPairDate("from", e->trig.from);
PrintJSONKeyPairInt("priority", e->trig.priority);
if (e->is_color) {
PrintJSONKeyPairInt("r", e->r);
PrintJSONKeyPairInt("g", e->g);
PrintJSONKeyPairInt("b", e->b);
} else if (!StrCmpi(e->passthru, "SHADE")) {
int r, g, b, n;
n = sscanf(e->text, "%d %d %d", &r, &g, &b);
if (n < 3) {
g = r;
b = r;
}
if (r < 0) r = 0;
else if (r > 255) r = 255;
if (g < 0) g = 0;
else if (g > 255) g = 255;
if (b < 0) b = 0;
else if (b > 255) b = 255;
PrintJSONKeyPairInt("r", r);
PrintJSONKeyPairInt("g", g);
PrintJSONKeyPairInt("b", b);
}
/* Only print rawbody if it differs from body */
if (strcmp(e->raw_text, e->text)) {
PrintJSONKeyPairString("rawbody", e->raw_text);
}
printf("\"body\":\"");
PrintJSONString(e->text);
printf("\"");
}
/***************************************************************/
/* */
/* WriteSimpleEntries */
/* */
/* Write entries in 'simple calendar' format. */
/* */
/***************************************************************/
static void WriteSimpleEntries(int col, int jul)
{
CalEntry *e = CalColumn[col];
CalEntry *n;
int y, m, d;
FromJulian(jul, &y, &m, &d);
while(e) {
if (DoPrefixLineNo) {
if (PsCal != PSCAL_LEVEL2 && PsCal != PSCAL_LEVEL3) {
printf("# fileinfo %d %s\n", e->lineno, e->filename);
}
}
if (PsCal >= PSCAL_LEVEL2) {
if (PsCal == PSCAL_LEVEL3) {
if (DidADay) {
printf(",\n");
}
}
DidADay = 1;
printf("{\"date\":\"%04d-%02d-%02d\", ", y, m+1, d);
WriteSimpleEntryProtocol2(e, jul);
printf("}");
if (PsCal != PSCAL_LEVEL3) {
printf("\n");
}
} else {
printf("%04d/%02d/%02d", y, m+1, d);
WriteSimpleEntryProtocol1(e);
}
free(e->text);
free(e->raw_text);
free(e->filename);
#ifdef REM_USE_WCHAR
if (e->wc_text) free((void *)e->wc_text);
if (e->wc_text) free(e->wc_text);
#endif
n = e->next;
free(e);
@@ -1530,6 +2081,8 @@ char const *SynthesizeTag(void)
unsigned char buf[16];
static char out[128];
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) FileName, strlen(FileName));
MD5Update(&ctx, (unsigned char *) &LineNo, sizeof(LineNo));
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
MD5Final(buf, &ctx);
sprintf(out, "__syn__%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",

View File

@@ -6,7 +6,7 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -220,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,7 +6,7 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -220,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,7 +7,7 @@
/* commands. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -18,9 +18,9 @@
#include <stdlib.h>
#include "types.h"
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
@@ -34,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;
}
/***************************************************************/
/* */
@@ -68,7 +79,7 @@ int DoRem(ParsePtr p)
if (trig.typ == SAT_TYPE) {
PurgeEchoLine("%s\n", "#!P: Cannot purge SATISFY-type reminders");
PurgeEchoLine("%s\n", CurLine);
r=DoSatRemind(&trig, p);
r=DoSatRemind(&trig, &tim, p);
if (r) {
FreeTrig(&trig);
if (r == E_EXPIRED) return OK;
@@ -117,7 +128,7 @@ 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]);
@@ -200,10 +211,14 @@ 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;
DBufInit(&(trig->tags));
trig->passthru[0] = 0;
tim->ttime = NO_TIME;
@@ -245,6 +260,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;
@@ -276,6 +292,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:
@@ -372,6 +389,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;
@@ -396,7 +417,15 @@ 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;
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;
@@ -468,6 +497,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);
@@ -702,9 +732,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);
@@ -730,20 +763,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, ' ');
@@ -751,6 +788,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, ' ');
@@ -758,6 +796,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, ' ');
@@ -841,6 +880,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 */
@@ -851,6 +907,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);
@@ -862,6 +921,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) {
@@ -870,6 +932,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);
@@ -881,6 +946,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);
@@ -1019,18 +1088,18 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
/* Do the "satisfying..." remind calculation. */
/* */
/***************************************************************/
int DoSatRemind(Trigger *trig, 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);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
@@ -1042,14 +1111,42 @@ int DoSatRemind(Trigger *trig, 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;
}
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* reminders are triggered. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -18,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))
@@ -656,8 +656,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,7 +6,7 @@
/* buffers. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,7 +5,7 @@
/* Declaration of functions for manipulating dynamic buffers */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,7 +5,7 @@
/* Error definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -119,6 +119,7 @@
#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 +235,8 @@ EXTERN char *ErrMsg[]
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
}
#endif /* MK_GLOBALS */
;

View File

@@ -5,7 +5,7 @@
/* This file contains routines to parse and evaluate */
/* expressions. */
/* */
/* Copyright 1992-2018 by Dianne Skoll */
/* Copyright 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -30,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),
@@ -578,6 +577,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;
@@ -605,12 +606,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:
@@ -619,13 +620,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%c%02d%c%02d",
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;
@@ -765,9 +766,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;
@@ -775,9 +776,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;
@@ -808,7 +811,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;
@@ -851,8 +854,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);

View File

@@ -5,7 +5,7 @@
/* Contains a few definitions used by expression evaluator. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -7,7 +7,7 @@
/* files. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* expressions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -53,94 +53,107 @@
#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 FADawn (func_info *);
static int FADusk (func_info *);
static int FNDawn (func_info *);
static int FNDusk (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 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
@@ -260,10 +273,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 },
@@ -1137,6 +1162,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;
@@ -1880,7 +2019,7 @@ 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);
@@ -1919,10 +2058,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;
@@ -1940,9 +2079,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;
@@ -1953,7 +2092,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) {
@@ -2422,16 +2561,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;
@@ -2452,28 +2591,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 */
@@ -2484,9 +2623,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;
}
}
@@ -2557,6 +2696,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++;
@@ -2697,13 +2837,13 @@ 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);
}
FreeTrig(&trig);
if (r) return r;

View File

@@ -8,7 +8,7 @@
/* globals.h and err.h */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -7,7 +7,7 @@
/* MK_GLOBALS. Also contains useful macro definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -46,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 +73,9 @@ 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,7 +5,7 @@
/* Support for the Hebrew calendar */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/* Derived from code written by Amos Shapir in 1978; revised */
/* 1985. */

View File

@@ -7,7 +7,7 @@
/* in normal mode. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2019 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -38,6 +38,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
@@ -135,7 +136,7 @@ void InitRemind(int argc, char const *argv[])
int InvokedAsRem = 0;
char const *s;
int weeks;
int x;
int jul;
#if defined(__APPLE__)
@@ -190,6 +191,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 */
@@ -204,6 +206,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;
@@ -400,9 +423,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);
@@ -418,7 +453,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++;
@@ -599,7 +637,7 @@ void InitRemind(int argc, char const *argv[])
#ifndef L_USAGE_OVERRIDE
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2019 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
@@ -607,6 +645,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,7 +5,7 @@
/* Header file for language support for various languages. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
/* */
/***************************************************************/

View File

@@ -11,7 +11,7 @@
/* Further corrections by Erik-Jan Vens */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,7 +5,7 @@
/* Support for the English language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -11,7 +11,7 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -302,7 +302,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#elif IBMEXTENDED
"Ok",
@@ -407,7 +408,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else
"Ok",
@@ -512,7 +514,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif
@@ -524,7 +527,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
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,7 +8,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Laurent Duperval and */
/* Dianne Skoll. */
/* */
@@ -242,7 +242,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else /* ISOLATIN1 */
"Ok",
@@ -347,7 +348,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
@@ -357,7 +359,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
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,7 +9,7 @@
/* I don't speak German. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,7 +5,7 @@
/* Support for the Icelandic language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
/* */
/***************************************************************/

View File

@@ -7,7 +7,7 @@
/* This file is part of REMIND. */
/* It is Copyright (C) 1996 by Valerio Aimale */
/* */
/* Remind is copyright (C) 1992-2018 by Dianne Skoll */
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993 by Trygve Randen. */
/* Remind is Copyright (C) 1992-2018 by Dianne Skoll */
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -9,7 +9,7 @@
/* Polish. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -281,7 +281,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#else /* ISOLATIN1 */
"OK",
"Brakujacy ']'",
@@ -385,7 +386,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
@@ -395,7 +397,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
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,7 +8,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1996 by Marco Paganini and */
/* Dianne Skoll. */
/* */
@@ -247,7 +247,8 @@ EXTERN char *ErrMsg[] =
"Can't convert between time zones",
"No files matching *.rem",
"String too long",
"Time specified twice"
"Time specified twice",
"Cannot specify DURATION without specifying AT"
};
#endif /* MK_GLOBALS */
@@ -256,7 +257,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
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

@@ -1,4 +1,4 @@
!/***************************************************************/
/***************************************************************/
/* */
/* ROMANIAN.H */
/* */
@@ -8,7 +8,7 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
/* */
/***************************************************************/

View File

@@ -7,7 +7,7 @@
/* Author: Rafa Couto <rafacouto@biogate.com> */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* routines, etc. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -63,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;
@@ -125,10 +127,7 @@ int main(int argc, char *argv[])
}
}
if (Iterations) {
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
NumTriggered = 0;
PerIterationInit();
JulianToday++;
}
}
@@ -146,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 */
@@ -799,8 +811,13 @@ int DoIfTrig(ParsePtr p)
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 (!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;
@@ -1322,3 +1339,46 @@ 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
SaveLastTrigger(Trigger const *t)
{
memcpy(&LastTrigger, t, sizeof(LastTrigger));
DBufInit(&(LastTrigger.tags));
}
void
SaveLastTimeTrig(TimeTrig const *t)
{
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
}

View File

@@ -5,7 +5,7 @@
/* Calculations for figuring out moon phases. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* the data structures for OMITted dates. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -5,7 +5,7 @@
/* Function Prototypes. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -88,7 +88,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 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);
@@ -105,7 +108,7 @@ void DumpVarTable (void);
void DestroyVars (int all);
int PreserveVar (char const *name);
int DoPreserve (Parser *p);
int DoSatRemind (Trigger *trig, 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);
@@ -142,3 +145,9 @@ 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 PerIterationInit(void);
char const *Decolorize(int r, int g, int b);
char const *Colorize(int r, int g, int b);

View File

@@ -5,7 +5,7 @@
/* Queue up reminders for subsequent execution. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -27,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"
@@ -43,6 +43,7 @@ typedef struct queuedrem {
char passthru[PASSTHRU_LEN+1];
char sched[VAR_NAME_LEN+1];
DynamicBuffer tags;
Trigger t;
TimeTrig tt;
} QueuedRem;
@@ -91,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;
@@ -246,6 +249,8 @@ void HandleQueuedReminders(void)
LastTriggerDate = JulianToday;
LastTriggerTime = q->tt.ttime;
LastTrigValid = 1;
SaveLastTrigger(&(q->t));
SaveLastTimeTrig(&(q->tt));
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
if (Daemon < 0) {
printf("NOTE endreminder\n");

View File

@@ -5,7 +5,7 @@
/* Print a PostScript calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <stdlib.h>
#include "rem2ps.h"
#include "json.h"
#define NEW(type) (malloc(sizeof(type)))
@@ -30,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[] = {
@@ -46,6 +48,7 @@ typedef struct calentry {
struct calentry *next;
int special;
char *entry;
int daynum;
} CalEntry;
typedef struct {
@@ -137,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 */
@@ -154,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 Dianne Skoll\n\n", VERSION);
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
fprintf(stderr, "Generating PostScript calendar\n");
}
}
@@ -191,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;
@@ -230,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");
@@ -272,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])) {
@@ -359,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;
@@ -375,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++) {

View File

@@ -5,7 +5,7 @@
/* Define the PostScript prologue */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -13,7 +13,7 @@ char *PSProlog1[] =
{
"% This file was produced by Remind and Rem2PS, written by",
"% Dianne Skoll.",
"% Remind and Rem2PS are Copyright 1992-1997 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,7 +5,7 @@
/* Routines for sorting reminders by trigger date */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* classifying the tokens parsed. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -228,11 +228,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;
}
}

View File

@@ -5,7 +5,7 @@
/* Routines for figuring out the trigger date of a reminder */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -408,6 +408,61 @@ 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) {
LastTriggerTime = tim->ttime;
SaveLastTimeTrig(tim);
SaveLastTrigger(trig);
LastTriggerDate = r;
LastTrigValid = 1;
}
return r;
}
/***************************************************************/
/* */
/* ComputeTrigger */
@@ -416,10 +471,30 @@ 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);
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 nattempts = 0,
start = today,
start = today - trig->duration_days,
nextstart = 0,
y, m, d, omit,
result;
@@ -429,15 +504,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 ||
@@ -448,6 +533,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);
@@ -469,7 +559,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+trig->duration_days >= today &&
(trig->skip != SKIP_SKIP || !omit)) {
if (save_in_globals) {
LastTriggerDate = result; /* Save in global var */
@@ -477,12 +569,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;
}
@@ -535,3 +638,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,7 +5,7 @@
/* Type definitions all dumped here. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -68,7 +68,11 @@ 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) */
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
@@ -87,16 +91,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 */
@@ -212,3 +216,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,7 +6,7 @@
/* functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -64,6 +64,7 @@ int DoFset(ParsePtr p)
int c;
UserFunc *func;
Var *v;
int orig_namelen;
DynamicBuffer buf;
DBufInit(&buf);
@@ -74,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);
@@ -164,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;
}

View File

@@ -5,7 +5,7 @@
/* Useful utility functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/

View File

@@ -6,7 +6,7 @@
/* user- and system-defined variables. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2018 by Dianne Skoll */
/* Copyright (C) 1992-2020 by Dianne Skoll */
/* */
/***************************************************************/
@@ -168,6 +168,45 @@ static int datetime_sep_func(int do_set, Value *val)
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) {
@@ -370,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;
}
@@ -604,6 +647,7 @@ static SysVar SysVarArr[] = {
{"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 },

View File

@@ -1,7 +1,7 @@
#!/bin/sh
cd /home/dfs/Software/Remind.git || exit 1
rm -f .git/COMMIT_EDITMSG
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

@@ -79,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...
@@ -99,6 +100,194 @@ 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
cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then

File diff suppressed because it is too large Load Diff

View File

@@ -313,6 +313,69 @@ 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 3:33 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()
dump
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OMIT 2010-09-03 THROUGH 2010-09-15
@@ -322,6 +385,18 @@ 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
# 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.
__EOF__
REM This line should not even be seen
And you can put whatever you like here.

View File

@@ -69,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)
@@ -76,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!

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()])

View File

@@ -7,5 +7,5 @@
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: 379 B

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 360 B

View File

@@ -29,6 +29,8 @@ ENDIF
# #
##########################################################################
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
@@ -138,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!
@@ -165,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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

After

Width:  |  Height:  |  Size: 317 B

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);
@@ -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') {