Compare commits

...

239 Commits

Author SHA1 Message Date
Dianne Skoll
e345eb15f2 Update verison to 04.02.02 2023-01-01 16:54:23 -05:00
Dianne Skoll
e8b2872a87 Update docs 2023-01-01 16:52:52 -05:00
Dianne Skoll
2f196e3c9f Update copyright year. :) 2022-12-30 13:43:28 -05:00
Dianne Skoll
839b844a10 Correct some comments. 2022-12-26 16:26:07 -05:00
Dianne Skoll
0cea410529 Add a bunch of: "SPDX-License-Identifier: GPL-2.0-only" comments. 2022-12-26 14:24:33 -05:00
Dianne Skoll
90397ece64 Mark soleq as non-constant. 2022-12-26 11:54:24 -05:00
Dianne Skoll
0b95fc290c Tweak. 2022-12-25 10:01:18 -05:00
Dianne Skoll
9a4e8b6070 Better sorting. 2022-12-25 09:37:22 -05:00
Dianne Skoll
924fd16ade More pleaseing alignment. :) 2022-12-23 17:07:54 -05:00
Dianne Skoll
0815fe19cc Align astro output. 2022-12-23 15:43:09 -05:00
Dianne Skoll
7f445e1b66 Add more emojis 2022-12-23 13:56:00 -05:00
Dianne Skoll
31afc60af4 Set latitude and longitude in astro 2022-12-23 13:40:32 -05:00
Dianne Skoll
9d34a8aa42 Set $Latitude in astro 2022-12-23 13:39:19 -05:00
Dianne Skoll
91325ff489 Update "astro" example to include equinoxes and solstices. 2022-12-23 13:28:11 -05:00
Dianne Skoll
1f99d6df59 More docs on NOQUEUE 2022-12-23 13:06:58 -05:00
Dianne Skoll
8a608a06b8 Tweak man page. 2022-12-23 11:51:01 -05:00
Dianne Skoll
bb34474e59 Document return value of soleq() 2022-12-23 11:38:59 -05:00
Dianne Skoll
029c054489 Document soleq() and NOQUEUE. 2022-12-23 11:37:27 -05:00
Dianne Skoll
01400d0672 Test the one-arg form of soleq() 2022-12-23 11:14:49 -05:00
Dianne Skoll
a1eafb2c89 Add NOQUEUE modifier; reverse order of args to soleq and make second arg optional (defaults to today()) 2022-12-23 11:04:18 -05:00
Dianne Skoll
af88e393f9 Reverse oreder of soleq args. 2022-12-23 10:56:13 -05:00
Dianne Skoll
3a250ce765 Don't make tests depend on date they are run. 2022-12-22 22:12:14 -05:00
Dianne Skoll
d651ac40a8 Update comments. 2022-12-22 22:01:54 -05:00
Dianne Skoll
653324e220 Add include/seasons.rem 2022-12-22 21:51:45 -05:00
Dianne Skoll
e5c6703eaa Add function for solstice/equinox calculations. 2022-12-22 21:44:49 -05:00
Dianne Skoll
1596d9c76a Better comments. 2022-12-21 13:41:25 -05:00
Dianne Skoll
4aacf74e25 More renaming of jul -> dse 2022-12-21 13:35:12 -05:00
Dianne Skoll
ae58bc7c11 Better message. 2022-12-21 13:15:05 -05:00
Dianne Skoll
387125d983 Start fixing terminology: Julian becomes DSE
Remind's so-called "Julian" date is not a true Julian date.
It's really the number of days since the Remind Epoch, so rename
to DSE (Days Since Epoch)
2022-12-21 13:14:00 -05:00
Dianne Skoll
aa5f9297b2 Add tests for handling world-writable dirs and files. 2022-12-20 10:38:28 -05:00
Dianne Skoll
8c4a7e766f Don't read world-writable directories 2022-12-20 10:26:47 -05:00
Dianne Skoll
d7f32d3901 Better error indication if something goes wrong in ShowTodaysReminders. 2022-12-20 09:45:16 -05:00
Dianne Skoll
d4f09e2a31 Fix typo 2022-12-15 10:37:28 -05:00
Dianne Skoll
8b5fe4f2a0 Update WHATSNEW for 04.02.01 release. 2022-12-15 09:34:02 -05:00
Dianne Skoll
98fc4a917f Bump version to 04.02.01 2022-12-15 09:24:30 -05:00
Dianne Skoll
e633530a36 Fix stray %" 2022-11-15 08:24:52 -05:00
Dianne Skoll
bfea9915b9 Remove unnecessary %"...%" markers. 2022-11-14 12:37:17 -05:00
Clément Bœsch
d68ed6e75d Add French holidays courtesy of Clément Bœsch 2022-11-14 12:20:43 -05:00
Dianne Skoll
a22631d768 Document need for Noto Fonts in TkRemind. 2022-11-01 13:40:44 -04:00
Dianne Skoll
552bf84e33 Make test *not* depend on the current date... *sigh*. 2022-10-24 09:41:40 -04:00
Dianne Skoll
28d0251093 If we use "-m" in ExtraRemindArgs, set $MondayFirst in tkremind
Patch courtesy of Luís Henriques
2022-10-24 09:35:27 -04:00
Dianne Skoll
f3d969f658 Make sure we print the banner on each iteration of a command-line '*rep' 2022-10-20 18:21:57 -04:00
Dianne Skoll
2afe95d090 Fix typo in comment. 2022-10-18 17:25:59 -04:00
Dianne Skoll
3692a6b265 Avoid ambiguous local<->UTC conversions right around when the clocks change. 2022-10-17 09:58:32 -04:00
Dianne Skoll
8fc19358bb Double-up on "%" in a printf formatting string. 2022-10-17 08:29:38 -04:00
Dianne Skoll
c8f9773d83 Speed up FindFunc. 2022-10-14 13:53:50 -04:00
Dianne Skoll
e1091db82f Don't try to use -ffat-lto-objects with clang 2022-10-14 13:31:57 -04:00
Dianne Skoll
9f8ed13434 Remove a whole lot of unused / dead code. 2022-10-14 13:26:56 -04:00
Dianne Skoll
914f03d5eb Fix bad comment. 2022-10-14 11:45:04 -04:00
Dianne Skoll
a801f6d4ce Token names are already lower-case. 2022-10-14 11:43:36 -04:00
Dianne Skoll
fde5a7b4ca Can use strcmp rather than StrCmpI in FindOperator since they are not alphabetic 2022-10-14 11:41:11 -04:00
Dianne Skoll
0e1fff6339 Update WHATSNEW for release. 2022-10-14 11:06:27 -04:00
Dianne Skoll
60fdeac2e9 Add RPM dependencies. 2022-10-14 11:02:51 -04:00
Dianne Skoll
3b3f10d448 Document prereqs on Gentoo and Arch Linux. 2022-10-14 10:53:35 -04:00
Dianne Skoll
48a4314dd2 Remove "validate" field from system variables. It was never used. 2022-10-14 10:42:05 -04:00
Dianne Skoll
9beff3a24a Tweak demo 2022-10-13 15:36:26 -04:00
Dianne Skoll
1ef90c7a61 Fix comments. 2022-10-13 13:55:09 -04:00
Dianne Skoll
5c886d181e Make overline clearer. 2022-10-13 13:54:06 -04:00
Dianne Skoll
da4d830163 More effects. 2022-10-13 13:53:10 -04:00
Dianne Skoll
c7abb7986c Add ansitext demo 2022-10-13 13:51:51 -04:00
Dianne Skoll
5a3b3d8a06 Add standard include file with various ANSI text attribute-changing sequences. 2022-10-13 10:42:28 -04:00
Dianne Skoll
127cee03df Add gmon.out to gitignore 2022-10-13 10:42:12 -04:00
Dianne Skoll
7455748d54 Eliminate compiler warning. 2022-10-13 08:28:09 -04:00
Dianne Skoll
e278d0e768 Fix typo 2022-10-12 20:13:47 -04:00
Dianne Skoll
a5acc12239 Try a ridiculously long line to excercise dynamic-buffer resizing 2022-10-12 20:11:23 -04:00
Dianne Skoll
a25afb9771 Fix ancient logic error in dynamic buffer code. 2022-10-12 19:38:18 -04:00
Dianne Skoll
6252a472b5 Get rid of useless macro. 2022-10-12 19:21:35 -04:00
Dianne Skoll
dbe4c662c1 Add the "FUNSET" command to delete user-defined functions. 2022-10-12 14:12:13 -04:00
Dianne Skoll
b77a261c87 Add Jewish holidays to the list of standard holiday files. 2022-10-12 14:05:55 -04:00
Dianne Skoll
351c54cc50 Print today. 2022-10-12 13:48:15 -04:00
Dianne Skoll
72d0b13ad5 Make the CI setup run "make all" to catch possible errors compiling the Perl modules. 2022-10-12 11:32:37 -04:00
Dianne Skoll
bea2a6541c Fix docs. 2022-10-12 10:20:20 -04:00
Dianne Skoll
5258e98f54 Add translations for various astronomical events in German localization, courtesy of Gunther Reißig. 2022-10-12 08:39:02 -04:00
Dianne Skoll
af9d42721c Separate Sun from Moon output. 2022-10-11 15:44:19 -04:00
Dianne Skoll
8ed43f5c3e Update WHATSNEW 2022-10-11 14:19:32 -04:00
Dianne Skoll
ec02a87c2b Fix some bugs in US holidays. 2022-10-11 14:19:00 -04:00
Dianne Skoll
6c2ec04d40 Visual tweaks. 2022-10-11 13:57:00 -04:00
Dianne Skoll
9f91cdf0b9 Update WHATSNEW. 2022-10-11 13:23:55 -04:00
Dianne Skoll
8ada68ce54 Add the "columns(str)" variant. 2022-10-11 13:18:44 -04:00
Dianne Skoll
d7975634af Update WHATSNEW 2022-10-11 11:56:41 -04:00
Dianne Skoll
87be68fecf Document rows() and columns() 2022-10-11 11:54:52 -04:00
Dianne Skoll
b42d5fd412 Add rows() and columns() built-in function. 2022-10-11 11:52:35 -04:00
Dianne Skoll
603228b944 Update prerequisite list. 2022-10-11 10:41:57 -04:00
Dianne Skoll
c62f676813 Diagnose unterminated %{...} sequence 2022-10-11 10:35:31 -04:00
Dianne Skoll
c7654c27a6 Update WHATSNEW. 2022-10-11 09:16:04 -04:00
Dianne Skoll
b00bf05fea Add test for %{custom} substitution. 2022-10-11 09:14:47 -04:00
Dianne Skoll
29bd07d4ef Document %{name} substitution sequences. 2022-10-11 09:11:12 -04:00
Dianne Skoll
b7047da89e Allow user-defined substitutions of the form: %{name} or %*{name} that call subst_name. 2022-10-11 09:07:08 -04:00
Dianne Skoll
f26334e25f Add doc about %_ to insert a blank line if $AddBlankLines is 0. 2022-10-11 08:31:13 -04:00
Dianne Skoll
b80bc5f788 Test that ending a reminder with %_ does add a blank line. 2022-10-11 08:30:17 -04:00
Dianne Skoll
91549e18ce Make use of $AddBlankLines 2022-10-10 22:52:48 -04:00
Dianne Skoll
07fd975935 Add the $AddBlankLines system variable. 2022-10-10 22:49:28 -04:00
Dianne Skoll
f9d968cf68 Fix CI script. 2022-10-10 17:31:14 -04:00
Dianne Skoll
6a7e696a60 Minor doc tweak 2022-10-10 17:17:31 -04:00
Dianne Skoll
6734fae1db Update docs/WHATSNEW 2022-10-10 17:15:21 -04:00
Dianne Skoll
481fbc20a1 Bump version to 04.02.00 2022-10-10 17:05:00 -04:00
Dianne Skoll
3c120bf561 Avoid compiler warning. 2022-10-10 17:04:51 -04:00
Dianne Skoll
ee65e04974 Top-level test does not depend on top-level all. 2022-10-10 17:04:35 -04:00
Dianne Skoll
4ee6bb0eca Add test for embedded %_ in MSF reminders. 2022-10-10 11:12:47 -04:00
Dianne Skoll
b9839421f2 make "MSF" correctly wrap UTF-8 text. 2022-10-10 11:05:38 -04:00
Dianne Skoll
67601507fa More robust handling of ANSI color escape sequences. 2022-10-09 22:00:06 -04:00
Dianne Skoll
c2e5534462 Make "REM ... MSF ..." handle ANSI color escape sequences correctly. 2022-10-09 21:55:09 -04:00
Dianne Skoll
f4ea3af6fc Update test output. 2022-10-09 21:32:04 -04:00
Dianne Skoll
e0998a3991 Implement trigtags() 2022-10-09 21:31:24 -04:00
Dianne Skoll
d67e580d0a More tweaks 2022-10-09 18:24:49 -04:00
Dianne Skoll
d6ce54eea4 Tweak astro example script. 2022-10-09 18:22:56 -04:00
Dianne Skoll
8b9ec43029 Add "astro" example script. 2022-10-09 18:21:03 -04:00
Dianne Skoll
9d68134f0f Make PrintValue escape only byte values < 32 2022-10-09 17:53:40 -04:00
Dianne Skoll
3d91371870 Correct and clarify man page. 2022-10-09 17:53:21 -04:00
Dianne Skoll
d1c0ef63b0 Fix inconsistency in man page. 2022-10-09 17:34:09 -04:00
Dianne Skoll
2a59da61e1 Update man page. 2022-10-09 13:40:21 -04:00
Dianne Skoll
2bc5e21627 Document ansicolor and the new color-related special variables. 2022-10-09 13:36:41 -04:00
Dianne Skoll
7d77bfd12a Add tests for invalid ansicolor() calls. 2022-10-09 13:10:28 -04:00
Dianne Skoll
0ff589c288 Merge branch 'utf8' into 'master'
Convert files to UTF-8
2022-10-09 17:02:45 +00:00
Dianne Skoll
f3cca092be Add tests for ansicolors function and new $Use...Colors variables. 2022-10-09 12:59:52 -04:00
Dianne Skoll
7218d55f08 Add $TerminalBackground special variable. 2022-10-09 12:40:48 -04:00
Dianne Skoll
ec72c74016 Add $Use256Colors, $UseBGVTColors, $UseTrueColors and $UseVTColors special variables. 2022-10-09 12:16:33 -04:00
Dianne Skoll
c946f08235 Fix spelling error. 2022-10-07 18:55:07 -04:00
Dianne Skoll
a8543ac349 Fix regression test. 2022-10-06 17:53:01 -04:00
Dianne Skoll
dd3c0e14ed Make wording more consistent. 2022-10-06 17:52:19 -04:00
Dianne Skoll
a2bc0acd3c Use English day names in "OMIT DUMP" 2022-10-06 15:20:37 -04:00
Dianne Skoll
a34266741a Clarify that we use the union of globally- and locally-omitted weekdays. 2022-10-06 08:40:05 -04:00
Dianne Skoll
dedb9766c9 Make a SATISFY-type reminder with ADDOMIT but no MSG actually add to the omits.
Previously, something like: REM 1 May ADDOMIT SATISFY 1
would not add to the global OMIT list.
2022-10-06 08:35:50 -04:00
Dianne Skoll
aedd759f50 Tweak wording. 2022-10-05 16:39:18 -04:00
Dianne Skoll
a24c2f6905 Refactor code. 2022-10-05 16:36:08 -04:00
Dianne Skoll
fac31a10b8 Add the timezone() built-in function. 2022-10-05 16:28:38 -04:00
Dianne Skoll
fba9f139ed Add global OMIT of the form:
OMIT wkday [wkday...]

For example:  OMIT Saturday Sunday
2022-10-05 14:12:53 -04:00
Dianne Skoll
588d9debe8 Simplify American Independence Day example. 2022-10-05 11:12:21 -04:00
Dianne Skoll
805c2e0c69 Implement the utctolocal and localtoutc functions. 2022-10-04 16:23:45 -04:00
Dianne Skoll
2c2b1440b3 Make tests work in non-utf-8 locale. 2022-09-27 21:49:33 -04:00
Jochen Sprickerhof
6973f62d74 Convert files to UTF-8 2022-09-26 20:03:05 +02:00
Dianne Skoll
f547c1e714 Update release notes. 2022-09-26 12:08:49 -04:00
Dianne Skoll
f8ea124b1f Add OS error message if we can't open file. 2022-09-24 10:57:32 -04:00
Dianne Skoll
820e2aec4d Document that "-wcol" also sets $FormWidth 2022-09-24 10:48:43 -04:00
Dianne Skoll
01ce6b2d8f Clamp min CalWidth at 71. 2022-09-24 10:40:04 -04:00
Dianne Skoll
b39e0eab7e Get rid of ComputeCalWidth - it's obsolete 2022-09-24 10:39:05 -04:00
Dianne Skoll
d6fc451d74 Refactor code. 2022-09-24 10:34:05 -04:00
Dianne Skoll
ac91556fc2 Make '-wn' initialize FormWidth as well. 2022-09-24 10:29:23 -04:00
Dianne Skoll
ccf639efe6 Make '-wt' accept FormWidth as well as CalWidth 2022-09-24 10:27:19 -04:00
Dianne Skoll
a8aa3b328b Add "-wt" option to size calendar according to terminal window. 2022-09-24 10:26:06 -04:00
Dianne Skoll
74a3b3e73d Yet more doc fixes. 2022-09-24 09:56:16 -04:00
Dianne Skoll
c0e68b57ea Fix pod 2022-09-24 09:53:11 -04:00
Dianne Skoll
0ad4ea26eb Properly set version and release date in man pages for rem2html and rem2pdf 2022-09-24 09:50:15 -04:00
Dianne Skoll
ea7aafaf5e Refactor code to reduce copy-paste coding. 2022-09-24 09:16:50 -04:00
Dianne Skoll
18043080ba Properly detect missing quote after escape sequence. 2022-09-23 20:42:57 -04:00
Dianne Skoll
7cd8cf3a77 Dump strings more sensibly in PrintValue. 2022-09-23 19:10:36 -04:00
Dianne Skoll
21da52ec36 Update unit tests. 2022-09-23 19:05:51 -04:00
Dianne Skoll
7a0c164843 Dump strings more sensibly. 2022-09-23 19:05:26 -04:00
Dianne Skoll
5cf4961f19 More clarification. 2022-09-23 08:38:00 -04:00
Dianne Skoll
68926d145b Fix innacuracy in how string constants are described. 2022-09-23 08:32:12 -04:00
Dianne Skoll
fdc3e4d23d Update WHATSNEW 2022-09-22 15:00:30 -04:00
Dianne Skoll
f179c837e1 Update regression tests. 2022-09-22 08:56:58 -04:00
Dianne Skoll
740bb44956 Don't consider IFTRIG true if we could not compute a trigger date.
Bug noted by Gunther Reißig
2022-09-22 08:48:19 -04:00
Dianne Skoll
5b953769fe Obey $DefaultColor in a SATISFY-type reminder.
Bug found by Gunther Reißig.
2022-09-22 08:37:37 -04:00
Dianne Skoll
1ae00ce778 No need to reset NumTriggered. 2022-09-21 19:11:30 -04:00
Dianne Skoll
a01e05c1db Fix bug introduced in commit 98c5bf511e:
Don't print a banner when issuing a queued reminder.
2022-09-21 18:17:25 -04:00
Dianne Skoll
63fb3e99f3 Make "test" depend on "all" rather than just "remind" 2022-09-19 13:56:11 -04:00
Dianne Skoll
6cf7f5d2d8 Merge branch 'add_ci' into 'master'
Add ci

See merge request dskoll/remind!2
2022-09-19 17:54:45 +00:00
Jochen Sprickerhof
316eb43303 Add Gitlab CI 2022-09-19 19:51:15 +02:00
Dianne Skoll
576112a39a Merge branch 'drop_fgrep' into 'master'
Replace deprecated fgrep by grep

See merge request dskoll/remind!1
2022-09-19 17:50:03 +00:00
Jochen Sprickerhof
6607223abb Replace deprecated fgrep by grep -F 2022-09-19 19:49:20 +02:00
Dianne Skoll
9e85b1932d Mark today in bold iff "remind -c" color output is enabled. 2022-09-19 11:32:10 -04:00
Dianne Skoll
4ba7f5b1f2 Only embolden today if stdout is a tty 2022-09-19 10:44:21 -04:00
Dianne Skoll
fc93ae890a Allow NULL pointers to be supplied to FromJulian if we are not interested in specific values 2022-09-17 23:04:34 -04:00
Dianne Skoll
8051d01945 Document change in Makefile install/install-stripped targets. 2022-09-17 09:07:27 -04:00
Dianne Skoll
63430c59f7 Make "make install" *not* strip debugging symbols; add "make install-stripped" target to strip them. 2022-09-17 09:04:45 -04:00
Dianne Skoll
c646bfc63f Make today's date bold in -c mode. 2022-09-16 21:01:10 -04:00
Dianne Skoll
58dea8f69b Support greyscale version of SHADE. 2022-09-16 20:44:59 -04:00
Dianne Skoll
f1c82dcb37 Update docs; bump version to 04.01.00. 2022-09-16 19:54:04 -04:00
Dianne Skoll
b984b66819 Put a space before the "***" representing today in -c mode. 2022-09-16 16:15:01 -04:00
Dianne Skoll
44bdae302b Allow 2 (=TERMINAL_BACKGROUND_UNKNOWN) for m in -@n,m,b 2022-09-16 15:58:51 -04:00
Dianne Skoll
8eb6b250fb Add support for the WEEK speical. 2022-09-16 15:08:53 -04:00
Dianne Skoll
d838c41bf2 Add tests for stdout() function. 2022-09-16 14:14:06 -04:00
Dianne Skoll
f9dbf36496 Don't backgroundize the row with day numbers. 2022-09-16 13:53:33 -04:00
Dianne Skoll
fe1427db28 Finalize support for SPECIAL SHADE in "remind -c" 2022-09-16 13:50:23 -04:00
Dianne Skoll
2621ad5604 Tweak calendar column-to-day handling. 2022-09-16 13:43:20 -04:00
Dianne Skoll
efecf2e1ea Make "remind -c" optionally support the SPECIAL SHADE 2022-09-16 11:41:18 -04:00
Dianne Skoll
8666e6357e Start working on support for SHADE in remind -c output. 2022-09-16 08:42:20 -04:00
Dianne Skoll
ae7069c9cb Gotta use the right sscanf format. :( 2022-09-15 18:43:58 -04:00
Dianne Skoll
0c6ab3e607 Properly parse args to MOON special 2022-09-15 18:37:46 -04:00
Dianne Skoll
17d6a60c0a Fix moon-phase-in-terminal printing and add tests. 2022-09-15 18:23:03 -04:00
Dianne Skoll
e3e0a541dc Print moon phases in terminal if terminal supports UTF-8 2022-09-15 18:18:05 -04:00
Jochen Sprickerhof
712aa08fbc make test depend on all 2022-09-08 16:32:04 +02:00
Dianne Skoll
98c5bf511e Print banner prior to first MSG-type reminder. 2022-09-06 09:14:55 -04:00
Dianne Skoll
1f9281628f Add home page to rem2pdf.1 and rem2html.1 2022-08-27 11:21:24 -04:00
Dianne Skoll
8fb15aed17 Do a sanity-check to make sure we pick up a release date. 2022-08-27 10:26:51 -04:00
Dianne Skoll
a24c3a8542 Remove generated man pages when running "make clean" 2022-08-27 10:24:29 -04:00
Dianne Skoll
8f8059e3f3 Generate man files from *.in versions to include release date and version number. 2022-08-27 10:22:31 -04:00
Dianne Skoll
24bb462199 Rename *.1 to *.1.in 2022-08-27 10:14:16 -04:00
Dianne Skoll
38e914f171 Get release date. 2022-08-27 10:06:02 -04:00
Dianne Skoll
4a02c54e8d Add home page to man pages. 2022-08-26 16:33:39 -04:00
Dianne Skoll
5fe169438a Document behavior of DO and filedir() with respect to symbolic links. 2022-08-22 09:19:30 -04:00
Dianne Skoll
a7ef6e851a Fix error in Makefile - remove duplicate clean: definition 2022-08-21 10:24:30 -04:00
Dianne Skoll
4d57b9d0aa Pass CFLAGS at link-time
Thanks to Zoltan Puskas for suggestion.
2022-08-21 10:23:16 -04:00
Dianne Skoll
5a7452d9f6 Add install-nostripped top-level target.
Thanks to Zoltan Puskas for suggestion.
2022-08-21 10:22:58 -04:00
Dianne Skoll
3916887aff Update change log. 2022-08-16 09:24:51 -04:00
Dianne Skoll
f84f59fa91 Bump version to 04.00.03. 2022-08-15 14:48:59 -04:00
Dianne Skoll
1032f8908e Don't create mysterious files named '&1' when creating new reminders. Sigh. 2022-08-11 11:32:59 -04:00
Dianne Skoll
6c2e8fc608 Document calendar_body and plain_body. 2022-08-08 11:49:06 -04:00
Dianne Skoll
012e527fb5 Fix parsing of old-style output. 2022-08-06 12:06:09 -04:00
Dianne Skoll
62198c9807 Use the new calendar_body/plain_body fields. 2022-08-06 11:54:32 -04:00
Dianne Skoll
de95224d62 Use new calendar_body / plain_body elements. 2022-08-06 11:49:35 -04:00
Dianne Skoll
be374a0464 Update test suite for new JSON output. 2022-08-06 09:09:06 -04:00
Dianne Skoll
fe9b3186d7 Add plain_body and calendar_body keys to JSON output. 2022-08-06 09:06:54 -04:00
Dianne Skoll
8405ea6c53 Add note about how to kill remind in queue mode. 2022-08-06 08:34:16 -04:00
Dianne Skoll
4274d05e10 Fix man page typo 2022-08-05 22:09:36 -04:00
Dianne Skoll
4e80ce1159 Don't make SIGINT kill a background process; don't call printf from a signal-handler; use sigaction instead of signal 2022-08-05 22:04:44 -04:00
Dianne Skoll
52f473f2af Update .gitignore 2022-08-04 10:34:45 -04:00
Dianne Skoll
1d6ca51bf9 Update docs. 2022-08-02 14:58:15 -04:00
Dianne Skoll
e662d0b3dd Bump version to 04.00.02 2022-08-02 14:51:00 -04:00
Dianne Skoll
b910d557d1 Document new form of OMIT command. 2022-07-27 15:16:23 -04:00
Dianne Skoll
a4ad0a9e97 Rename error constant. 2022-07-27 15:06:04 -04:00
Dianne Skoll
07f67e7dd7 Better error messages 2022-07-27 15:03:48 -04:00
Dianne Skoll
d6575773fb Don't let THROUGH date be before START date in OMIT. 2022-07-27 14:55:34 -04:00
Dianne Skoll
ac1303886e Add another test. 2022-07-27 14:47:11 -04:00
Dianne Skoll
1569992184 Add test for more flexible OMIT 2022-07-27 14:43:54 -04:00
Dianne Skoll
55a1f1d746 Implement more flexible OMIT. We can do things like:
OMIT May       - equivalent to "OMIT May 1" ... "OMIT May 31"
    OMIT Nov 20 THROUGH Dec 4
    OMIT Apr THROUGH May
    OMIT 2023-12-25 THROUGH 2024-01-06
2022-07-27 14:39:43 -04:00
Dianne Skoll
ef7742a3cc Add GitHub README 2022-07-19 10:12:46 -04:00
Dianne Skoll
ef48c2020b Fix typo 2022-07-12 20:44:57 -04:00
Dianne Skoll
6dcb25073b Make $T behave as documented: If trigger date is not valid, should return 0. 2022-07-04 14:23:39 -04:00
Dianne Skoll
4824b07ec8 Document inotifywait 2022-07-03 19:47:06 -04:00
Dianne Skoll
a8f1228fb7 Update TkRemind man page. 2022-07-03 19:13:05 -04:00
Dianne Skoll
80e51d1d0f Make calendar with 6 rows in a month handle resizing properly.
Fixes https://github.com/dfskoll/remind/issues/1
2022-07-01 16:45:25 -04:00
Dianne Skoll
80e30638a5 Update changelog 2022-06-03 16:22:19 -04:00
Dianne Skoll
dd2fc30364 Add test for $SuppressLRM 2022-05-29 17:28:45 -04:00
Dianne Skoll
a5865fb5fe Add $SuppressLRM system variable; bump version to 04.00.01. 2022-05-27 12:22:26 -04:00
Dianne Skoll
aca2f28341 Add liberapay button. 2022-05-19 13:58:03 -04:00
Dianne Skoll
7a3f5f7ac9 Add github action to run tests. 2022-05-19 09:46:32 -04:00
Dianne Skoll
1731710ef2 Minor reformatting of source. 2022-05-19 09:01:11 -04:00
Dianne Skoll
dc2a8f48bf Update man page. 2022-04-07 11:53:20 -04:00
Dianne Skoll
5e16179bfa Update docs for 04.04.00 release. 2022-04-04 09:36:08 -04:00
Dianne Skoll
a7c1bc81b2 Remove a bug from man page. 2022-04-03 12:59:25 -04:00
Dianne Skoll
5f5ec8ef19 More intelligent handling of --prefix wrt ExtUtils::MakeMaker. 2022-04-03 12:23:28 -04:00
Dianne Skoll
712ff56792 Update docs 2022-04-01 12:11:04 -04:00
Dianne Skoll
99af1f964c Fix bug that broke "-m" option to tkreminder. 2022-04-01 12:08:25 -04:00
Dianne Skoll
de5d1347e5 Make the operator stack static 2022-03-26 19:05:18 -04:00
Dianne Skoll
5e07fbde6d Fix formatting. 2022-03-26 18:03:31 -04:00
Dianne Skoll
c523c7f3b3 Allow a subst_N or subst_Nx function to return 0 to indicate "use the normal substitution" 2022-03-26 18:02:39 -04:00
Dianne Skoll
6b3c6b0ec7 Fix a couple of typos. 2022-03-26 10:11:17 -04:00
106 changed files with 7067 additions and 1851 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
liberapay: dskoll

7
.github/README.md vendored Normal file
View File

@@ -0,0 +1,7 @@
# Remind has moved
For various reasons, I have decided to move Remind off GitHub. This repo
will be archived. To create merge requests or issues, please visit
Remind's new home at https://salsa.debian.org/dskoll/remind
-- Dianne Skoll

29
.github/workflows/github-action.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
# language: bash
---
name: Remind unit tests
on:
push
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout Remind
uses: actions/checkout@v2
- name: Add test user
run: |
sudo adduser --home /home/testuser --gecos 'Test User' --disabled-password testuser
- name: Fix ownership
run: |
sudo chown -R testuser .
- name: Build
run: |
sudo su -c './configure && make' testuser
- name: Run Tests
run: |
sudo su -c 'make test' testuser
- name: Fix up permissions so GitHub does not complain
run: |
sudo chmod -R a+rwX .

6
.gitignore vendored
View File

@@ -10,6 +10,10 @@ autom4te.cache
blib/
config.log
config.status
man/rem.1
man/rem2ps.1
man/remind.1
man/tkremind.1
pm_to_blib
rem2html/Makefile
rem2html/rem2html.1
@@ -17,6 +21,7 @@ rem2pdf/Makefile.PL
rem2pdf/Makefile.old
rem2pdf/Makefile.top
rem2pdf/bin/rem2pdf
set-irc-topic
src/*.tar.gz*
src/Makefile
src/config.h
@@ -26,3 +31,4 @@ src/test-*.out
src/version.h
tests/test.out
www/Makefile
gmon.out

13
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,13 @@
tests:
image: 'debian:stable-slim'
before_script:
- apt update && apt-get -y install gcc make
- useradd --create-home testuser
- chown -R testuser .
- chmod -R go-w .
script:
- LANG=C.UTF-8 su testuser -c './configure && make all && make test'
artifacts:
when: always
paths:
- tests/test.out

View File

@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
1. REMIND refers to the entire set of files and documentation in the
REMIND package.
2. REMIND is Copyright 1992-2022 Dianne Skoll, except where noted in
2. REMIND is Copyright 1992-2023 Dianne Skoll, except where noted in
individual files.
3. DISTRIBUTION AND USE

View File

@@ -1,4 +1,5 @@
# Top-level Makefile for Remind.
# SPDX-License-Identifier: GPL-2.0-only
all: src/Makefile
@echo ""
@@ -12,20 +13,33 @@ all: src/Makefile
@$(MAKE) -C rem2pdf -f Makefile.top
install:
@echo ""
@echo "*********************"
@echo "* *"
@echo "* Installing REMIND *"
@echo "* *"
@echo "*********************"
@echo "**********************************"
@echo "* *"
@echo "* Installing REMIND (unstripped) *"
@echo "* *"
@echo "**********************************"
@echo ""
@$(MAKE) -C src install
@$(MAKE) -C rem2html install
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
clean:
find . -name '*~' -exec rm {} \;
-rm man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1
-$(MAKE) -C src clean
-$(MAKE) -C rem2pdf clean
install-stripped:
@echo ""
@echo "********************************"
@echo "* *"
@echo "* Installing REMIND (stripped) *"
@echo "* *"
@echo "**********************************"
@echo ""
@$(MAKE) -C src install-stripped
@$(MAKE) -C rem2html install
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
test:
@$(MAKE) -C src -s test

40
README
View File

@@ -34,5 +34,45 @@ If you do NOT have Tcl/Tk or are NOT running X Windows:
5) Type: "make install" -- you may need to be root to do this.
PREREQUISITES:
--------------
Remind and rem2ps have no prerequisites beyond the standard C library and
the standard math library.
Rem2HTML requires the JSON::MaybeXS Perl module.
Rem2PDF requires the JSON::MaybeXS, Pango and Cairo Perl modules.
- On Debian-like systems, these prerequisites may be installed with:
apt install libjson-maybexs-perl libpango-perl libcairo-perl
- On RPM-based systems, you need perl-Pango, perl-Cairo and perl-JSON-MaybeXS
- On Gentoo, you need dev-perl/Pango, dev-perl/Cairo and dev-perl/JSON-MaybeXS.
- On Arch linux, you need pango-perl, cairo-perl and perl-json-maybexs
TkRemind requires Tcl/Tk and the tcllib library.
- On Debian-like systems, install with:
apt install tcl tk tcllib
- On RPM-based systems, you need tcl, tk and tcllib
- On Arch Linux, you need tk and tcllib. The latter is available at
https://aur.archlinux.org/packages/tcllib
If the little arrows for "Previous Month" and "Next Month" do not display
correctly in TkRemind, you may need to install the Noto Fonts. Install
all of your distribution's Nonto Font-related packages.
- On Debian-like systems, install with:
apt install fonts-noto-core fonts-noto-color-emoji \
fonts-noto-extra fonts-noto-ui-core fonts-noto-ui-extra
==========================================================================
Contact info: mailto:dianne@skoll.ca
Home page: https://dianne.skoll.ca/projects/remind/

View File

@@ -1,5 +1,6 @@
#!/bin/sh
# -*-Mode: TCL;-*-
# SPDX-License-Identifier: GPL-2.0-only
#--------------------------------------------------------------
# BUILD.TK

32
configure vendored
View File

@@ -622,6 +622,7 @@ ac_includes_default="\
ac_header_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
RELEASE_DATE
PERLARTIFACTS
VERSION
EGREP
@@ -3974,7 +3975,14 @@ fi
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
# Check for link-time optimization support
for f in -flto=auto -ffat-lto-objects; do
f=-flto=auto
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
$as_echo_n "checking whether $CC supports $f... " >&6; }
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$CFLAGS $f"
f=-ffat-lto-objects
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
$as_echo_n "checking whether $CC supports $f... " >&6; }
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
@@ -3985,7 +3993,10 @@ $as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
done
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test "$ac_cv_perlartifacts" = "yes" ; then
@@ -3994,6 +4005,14 @@ else
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
fi
RELEASE_DATE=`grep '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]' docs/WHATSNEW | head -n 1 | awk '{print $NF}'`
# Sanity-check release date
echo "$RELEASE_DATE" | grep '^....-..-..$' > /dev/null 2>&1
if test "$?" != 0 ; then
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
exit 1
fi
for ac_func in setenv unsetenv glob mbstowcs setlocale initgroups
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -4006,11 +4025,12 @@ _ACEOF
fi
done
VERSION=04.00.00
VERSION=04.02.02
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf"
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -4710,6 +4730,10 @@ do
"rem2pdf/Makefile.PL") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.PL" ;;
"rem2pdf/Makefile.top") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.top" ;;
"rem2pdf/bin/rem2pdf") CONFIG_FILES="$CONFIG_FILES rem2pdf/bin/rem2pdf" ;;
"man/rem.1") CONFIG_FILES="$CONFIG_FILES man/rem.1" ;;
"man/rem2ps.1") CONFIG_FILES="$CONFIG_FILES man/rem2ps.1" ;;
"man/remind.1") CONFIG_FILES="$CONFIG_FILES man/remind.1" ;;
"man/tkremind.1") CONFIG_FILES="$CONFIG_FILES man/tkremind.1" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View File

@@ -47,7 +47,12 @@ AC_HEADER_TIME
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
# Check for link-time optimization support
for f in -flto=auto -ffat-lto-objects; do
f=-flto=auto
AC_MSG_CHECKING([whether $CC supports $f])
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
AC_MSG_RESULT([yes])
CFLAGS="$CFLAGS $f"
f=-ffat-lto-objects
AC_MSG_CHECKING([whether $CC supports $f])
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
AC_MSG_RESULT([yes])
@@ -55,7 +60,9 @@ if test "$GCC" = yes; then
else
AC_MSG_RESULT([no])
fi
done
else
AC_MSG_RESULT([no])
fi
fi
if test "$ac_cv_perlartifacts" = "yes" ; then
@@ -64,10 +71,19 @@ else
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
fi
RELEASE_DATE=`grep '[[0-9]][[0-9]][[0-9]][[0-9]]-[[0-9]][[0-9]]-[[0-9]][[0-9]]' docs/WHATSNEW | head -n 1 | awk '{print $NF}'`
# Sanity-check release date
echo "$RELEASE_DATE" | grep '^....-..-..$' > /dev/null 2>&1
if test "$?" != 0 ; then
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
exit 1
fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
VERSION=04.00.00
VERSION=04.02.02
AC_SUBST(VERSION)
AC_SUBST(PERL)
AC_SUBST(PERLARTIFACTS)
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf)
AC_SUBST(RELEASE_DATE)
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1)
chmod a+x rem2pdf/bin/rem2pdf

View File

@@ -1,6 +1,213 @@
CHANGES TO REMIND
* VERSION 4.0 Patch 0 - 2022-??-??
* VERSION 4.2 Patch 2 - 2023-01-01
- NEW FEATURE: Remind: Add the NOQUEUE modifier to the REM statement for
explicitly telling Remind not to queue a timed reminder.
- NEW FEATURE: Remind: Add soleq() function to return the DATETIME of
solstices and equinoxes. See $SysInclude/seasons.rem for an example
of how to use the function.
- MINOR IMPROVEMENT: Update examples/astro to include solstices and equinoxes.
- BUG FIX: TkRemind: Provide better error indication if showing today's
reminders fails on startup.
- BUG FIX: Remind: Refuse to read world-writable directories.
- BUG FIX: Tests depended on the actual date of the test run. This has
been fixed.
- INTERNAL CHANGE: Remind: Change inappropriately-named "Julian" variables
to "DSE" (= Days Since Epoch) since they weren't really holding true
Julian dates.
- INTERNAL CHANGE: Add "SPDX-License-Identifier" tags to most files.
* VERSION 4.2 Patch 1 - 2022-12-15
- MINOR IMPROVEMENT: TkRemind: If "Extra Remind Options" contains -m, make
TkRemind start the calendar with Monday instead of Sunday.
- MINOR IMPROVEMENT: Sample files: Add French holidays courtesy of
Clément Bœsch.
- MINOR IMPROVEMENT: A few performance fixes, likely not even noticeable in
most cases.
- MINOR FIXES: Fix misleading comments in the source code.
- MINOR FIX: Remove a bunch of dead code in the moon-phase routines.
- MINOR FIX: Remove unnecessary %"...%" markers in holidays/us.rem
- MINOR FIX: Don't use the -ffat-lto-objects command-line option if we're
compiling with Clang.
- MINOR FIX: Remind: Fix a broken printf-format string (need to double up on %
to get a literal % in the output.)
- BUG FIX: Make test suite pass regardless of the date on which it is run.
D'oh!!!
- BUG FIX: Make sure the banner gets printed each time through a "*N"
command-line option loop.
* VERSION 4.2 Patch 0 - 2022-10-14
- NEW FEATURE: remind: Allow weekdays to be globally-omitted. For example:
OMIT Saturday Sunday
globally-omits all Saturdays and Sundays.
- NEW FEATURE: remind: Add ansicolor() built-in function to make it easier
to colorize reminders on the terminal. Suggested by Tim Chase.
- NEW FEATURE: remind: Add several special variables related to the color
mode: $UseVTColors, $UseBGVTColors, $Use256Colors, $UseTrueColors and
$TerminalBackground. Based on a suggestion by Tim Chase.
- NEW FEATURE: remind: Add utctolocal() and localtoutc() built-in functions.
- NEW FEATURE: remind: Add timezone() built-in function.
- NEW FEATURE: remind: Add trigtags() function per suggestion from Tim Chase.
- NEW FEATURE: remind: The $AddBlankLines system variable controls whether or
not a blank line is added after each reminder.
- NEW FEATURE: remind: The built-in functions columns() and rows() return the
width and height of the terminal (in character positions) respectively.
- NEW FEATURE: remind: The built-in function columns("string") returns the
number of columns occupied by "string" on the terminal, taking into account
double-width Unicode characters and zero-width ANSI escape sequences.
- NEW FEATURE: remind: You can add custom substitution sequences of the form
%{name} or %*{name} that end up calling the function subst_name and using
its return value as the replacement for the substitution sequence.
- NEW FEATURE: remind: Add the FUNSET command to undefine a user-defined
function.
- NEW FILES: Add standard include files holidays/jewish.rem and
ansitext.rem (the latter defines standard ANSI escape codes for
changing text attributes such as bold, underline, etc.)
- NEW EXAMPLES: add examples/alignmemt.rem, examples/ansitext and
examples/astro
- BUG FIX: remind: Make MSF correctly format UTF-8 text and text with
embedded ANSI color-changing codes.
- BUG FIX: remind: Make ADDOMIT actually work correctly in a SATISFY-type
REM command. Bug found by Gunther Reißig
- BUG FIX: Convert documentation files and src/lang.h to UTF-8. Patch
from Jochen Sprickerhof.
- BUG FIX: Fix tests in non-UTF-8 locales.
- BUG FIX: Fix a few problems with the include/holidays/us.rem file.
- BUG FIX: remind: Fix an ancient logic error in DBufPutc that hurt
performance.
- MINOR IMPROVEMENT: Clean up code and remove some dead code.
* VERSION 4.1 Patch 0 - 2022-09-25
- NEW FEATURE: remind: "remind -c" now supports the MOON special, printing
the moon phases in the calendar if the locale supports UTF-8 encoding.
- NEW FEATURE: remind: "remind -c" now supports the SHADE special. Works
best with the 256-color extended XTerm palette or 24-bit true-color
terminal escape sequences.
- NEW FEATURE: remind: "remind -c" now supports the WEEK special.
- NEW FEATURE: remind: The new "stdout()" function returns a string describing
where stdout is going. Examples of return values are "TTY" if remind's
output is going to terminal, "FILE" if it's redirected to a plain file,
or "PIPE" if it's going to a pipe. See the man page for all the details.
- NEW FEATURE: Add the "-wt" option to set the calendar width to the terminal
width even if standard output is a pipe. Useful for situations like this:
remind -wt -c .reminders | less -R
- CHANGE: "make install" now no longer strips debugging symbols from the
remind and rem2ps executables. Use "make install-stripped" if you want
them stripped.
- CHANGE: remind: "remind -c" highlights today's date in bold, if
colors are enabled.
- CHANGE: Dump string values with control characters escaped.
- DOCUMENTATION FIX: Document behavior of DO and filedir() with respect
to symbolic links.
- DOCUMENTATION FIX: Add home page link to man pages. Suggested by Ian! D.
Allen.
- DOCUMENTATION FIX: Make date in man pages actually be the release date.
Include Remind version in man pages. Also suggested by Ian! D. Allen.
- DOCUMENTATION FIX: Fix inaccuracy in how string constants were documented.
- BUG FIX: Makefiles: Pass CFLAGS at link-time so link-time optimization
actually happens. Pointed out by Zoltan Puskas.
- BUG FIX: If the first REM command to trigger was a RUN command, the banner
would not print. This has been fixed.
- BUG FIX: replace deprecated 'fgrep' with 'grep -F' (Jochen Sprickerhof)
- BUG FIX: make "make test" depend on "make all" (Jochen Sprickerhof)
- BUG FIX: make "REM ... SATISFY ... MSG foo" respect $DefaultColor. Bug
reported by Gunther Reißig.
- BUG FIX: Don't consider IFTRIG true if we could not compute a trigger date.
Bug noted by Gunther Reißig.
* VERSION 4.0 Patch 3 - 2022-08-16
- IMPROVEMENT: remind: add plain_body and calendar_body JSON keys in -pp...
output.
- BUG FIX: tkremind: Don't create empty files called '&1' when creating
a new reminder.
- BUG FIX: remind: Don't call signal-unsafe functions from signal handler
* VERSION 4.0 Patch 2 - 2022-08-02
- IMPROVEMENT: remind: Allow more forms of OMIT as per Ian! D. Allen's request:
OMIT Month [THROUGH Month]
OMIT Day Month [THROUGH Day Month]
OMIT Day Month Year [THROUGH Day Month Year]
- BUG FIX: Make $T behave as documented, exactly like trigdate(). $T would
return '1989-12-31' rather than 0 if the trigger date was not valid.
- BUG FIX: TkRemind: Fix resizing bug for a calendar with 6 rows.
- DOCUMENTATION IMPROVEMENT: Improve TkRemind documentation; document use
of inotifywait if available.
* VERSION 4.0 Patch 1 - 2022-06-03
- IMPROVEMENT: Add $SuppressLRM system variable to suppress the UTF-8
Left-to-Right mark in "remind -c" output.
- DOCUMENTATION FIX: Document the "q" sub-option to the "-p" option.
* VERSION 4.0 Patch 0 - 2022-04-04
- MAJOR NEW FEATURE: remind: Remind output can effectively be
translated into other languages at run-time. A number of system
@@ -30,6 +237,11 @@ CHANGES TO REMIND
This causes Remind *not* to remove the %"...%" marker sequence from
remind bodies.
- BUG FIX: rem2pdf: Make rem2pdf respect the --prefix ./configure flag.
Loosely based on patch by Jonathan Kamens.
- BUG FIX: tkremind: Fix the "-m" flag, which was broken in 03.04.00.
- BUG FIX: Fix the overflow-detection functions so they work with link-time
optimization. The previous versions would be optimized away.
@@ -1029,7 +1241,7 @@ CHANGES TO REMIND
- Fixed dates for Yom Hazikaron and Yom Ha'atzmaut if 5 Iyar falls on a
Saturday. (Hebrew calendar fix.)
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
+ BUG FIXES
@@ -1176,7 +1388,7 @@ CHANGES TO REMIND
- Made parser _very_ forgiving -- the type of reminder now defaults
to MSG. This lets you have lines in the reminder file like this:
Feb 9, 1998 Meeting with Joe.
Feb 9, 1998 Meeting with Joe.
But I don't recommend abusing it. It's mostly to ease migration from
UNIX calendar(1) files.
@@ -1706,7 +1918,7 @@ CHANGES TO REMIND
of Mikko Silvonen.
- Changed the date conversion routines to greatly speed up conversion from
Julian to yyyy/mm/dd form.
Days-since-epoch to yyyy/mm/dd form.
+ BUG FIXES:
@@ -1767,7 +1979,7 @@ CHANGES TO REMIND
- Removed identifiers in the C source beginning with "_" to conform
to ANSI practice.
- Fixed a bug in the -u option which resulted in environment variables
SHELL and USER not being set correctly. Also made -u set the LOGNAME
environment variable.
@@ -1840,7 +2052,7 @@ CHANGES TO REMIND
- Fixed all the source files to include "config.h" first.
- Changed the way triggers are calculated so that trigger dates are
- Changed the way triggers are calculated so that trigger dates are
always valid if year, month and day are specified, and there is no
UNTIL clause. See MAN page section "DETAILS ABOUT TRIGVALID()."
@@ -1982,6 +2194,3 @@ CHANGES TO REMIND
* Version 1.0
- never publicly released.

19
examples/alignment.rem Normal file
View File

@@ -0,0 +1,19 @@
# Demo the columns() function
#
# Run as: remind -@2 alignment.rem
# SPDX-License-Identifier: GPL-2.0-only
SET $AddBlankLines 0
BANNER %
FSET center(x) pad("", " ", (columns() - columns(x))/2) + x
FSET right(x) pad("", " ", columns() - columns(x)) + x
MSG This is left-aligned.
MSG [ansicolor(0,255,0)]This is also left-aligned.[ansicolor("")]
MSG [center("This is centered.")]
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
msg [right("This is right-aligned.")]
msg [ansicolor(255,0,0) + right("This is also right-aligned. 🌕 🌕 🌕") + ansicolor("")]

36
examples/ansitext Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/sh
#
# A little demo script that displays ANSI text attributes
# Not all attributes work on all terminals... your mileage may vary.
# SPDX-License-Identifier: GPL-2.0-only
remind -@2 - <<'EOF'
SET $AddBlankLines 0
BANNER %
INCLUDE [$SysInclude]/ansitext.rem
MSG This file shows off some ANSI text attributes and colors.
MSG Not all attributes work on all terminals.%_
MSG This is [ansi_bold]bold.[ansi_normal]
MSG This is [ansi_faint]faint.[ansi_normal]
MSG This is [ansi_italic]italic.[ansi_normal]
MSG This is [ansi_underline]underline.[ansi_normal]
MSG This is [ansi_underline2]underline2.[ansi_normal]%_
MSG This is [ansi_reverse]reverse.[ansi_normal]%_
MSG This is [ansi_strikeout]strikeout.[ansi_normal]%_
MSG This is [ansi_overline]overline.[ansi_normal]%_
MSG This is [ansicolor(255,0,0)]red.[ansicolor("")]
MSG This is [ansicolor(0,255,0)]green.[ansicolor("")]
MSG This is [ansicolor(0,0,255)]blue.[ansicolor("")]
MSG This is [ansicolor(255,255,0)]yellow.[ansicolor("")]
MSG This is [ansicolor(255,0,255)]magenta.[ansicolor("")]
MSG This is [ansicolor(0,255,255)]cyan.[ansicolor("")]%_
# You can combine attributes
MSG This is [ansicolor(0,255,0)][ansicolor(0,0,96,1)][ansi_italic][ansi_bold]Green-Bold-Italic-on-Blue[ansi_normal][ansicolor("")]
EOF
exit 0

70
examples/astro Executable file
View File

@@ -0,0 +1,70 @@
#!/bin/sh
#
# A little demo script that displays astronomical events
#
# Best used in a UTF-8 environment.
# SPDX-License-Identifier: GPL-2.0-only
# Set this variable to 1 if your terminal has a dark background or 0 if
# it: light.
bg_dark=1
# Set your latitude and longitude correctly for Sunrise/Sunset/Equinox/Solstice
#
# The values below are for Ottawa, Ontario, Canada
latitude="45.420556"
longitude="-75.689722"
remind -g -ibg_dark="$bg_dark" "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
BANNER %
INCLUDE [$SysInclude]/ansitext.rem
MSG Today is [ansi_bold][$T][ansi_normal], being the [ord($T-date(year($T),1,1)+1)] day of [year($T)].%_
IF bg_dark
SPECIAL COLOR 255 255 0 Sunrise: 🌅 [sunrise()] today and [sunrise($T+1)] tomorrow
SPECIAL COLOR 255 128 0 Sunset: 🌇 [sunset()] today and [sunset($T+1)] tomorrow%_
ENDIF
EOF
remind -g -ibg_dark="$bg_dark" "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
BANNER %
IF bg_dark
REM [moondatetime(0)] +60 SPECIAL COLOR 255 255 0 New moon: 🌑 [$T] %3 (%b)
REM [moondatetime(1)] +60 SPECIAL COLOR 255 255 128 First Quarter: 🌓 [$T] %3 (%b)
REM [moondatetime(2)] +60 SPECIAL COLOR 255 255 255 Full moon: 🌕 [$T] %3 (%b)
REM [moondatetime(3)] +60 SPECIAL COLOR 255 255 128 Last Quarter: 🌗 [$T] %3 (%b)
ELSE
SPECIAL COLOR 128 128 0 Sunrise: 🌅 [sunrise()] today and [sunrise($T+1)] tomorrow
SPECIAL COLOR 128 32 0 Sunset: 🌇 [sunset()] today and [sunset($T+1)] tomorrow%_
REM [moondatetime(0)] +60 SPECIAL COLOR 128 128 0 New moon: 🌑 [$T] %3 (%b)
REM [moondatetime(1)] +60 SPECIAL COLOR 128 128 64 First Quarter: 🌓 [$T] %3 (%b)
REM [moondatetime(2)] +60 SPECIAL COLOR 0 0 0 Full moon: 🌕 [$T] %3 (%b)
REM [moondatetime(3)] +60 SPECIAL COLOR 128 128 64 Last Quarter: 🌗 [$T] %3 (%b)
ENDIF
EOF
echo ""
remind -g -ibg_dark="$bg_dark" "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
SET $AddBlankLines 0
BANNER %
IF $LatDeg >= 0
REM [soleq(0)] +366 MSG Next Vernal Equinox: 🌼 [$T] %3 (%b)
REM [soleq(1)] +366 MSG Next Summer Solstice: 😎 [$T] %3 (%b)
REM [soleq(2)] +366 MSG Next Autumnal Equinox: 🍂 [$T] %3 (%b)
REM [soleq(3)] +366 MSG Next Winter Solstice: ❄️ [$T] %3 (%b)
ELSE
REM [soleq(0)] +366 MSG Next Autumnal Equinox: 🍂 [$T] %3 (%b)
REM [soleq(1)] +366 MSG Next Winter Solstice: ❄️ [$T] %3 (%b)
REM [soleq(2)] +366 MSG Next Vernal Equinox: 🌼 [$T] %3 (%b)
REM [soleq(3)] +366 MSG Next Summer Solstice: 😎 [$T] %3 (%b)
ENDIF
EOF

View File

@@ -16,7 +16,8 @@
# "#PSSTUFF" for nifty PostScript examples #
# #
# This file is part of REMIND. #
# Copyright (C) 1992-2022 Dianne Skoll #
# Copyright (C) 1992-2023 Dianne Skoll #
# SPDX-License-Identifier: GPL-2.0-only
# #
#############################################################################
@@ -77,16 +78,16 @@ REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
############################################################################
# If it falls on a Saturday, bump to previous Friday
REM 4 July OMIT SAT SCANFROM -1 BEFORE ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
REM 3 JULY SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Independence day (observed)
# If it falls on a Sunday, bump to following Monday
REM 4 July OMIT SUN SCANFROM -7 AFTER ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
REM 5 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Independence day (observed)
# If it falls on Sat or Sun, note the actual day
REM 4 July SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
# Otherwise observed and actual is on the 4th
REM 4 July OMIT SAT SUN SKIP SCANFROM -7 ADDOMIT MSG Independence Day
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw >= 1 && $Tw <= 5] MSG Independence Day
##########################################################################
# #

35
include/ansitext.rem Normal file
View File

@@ -0,0 +1,35 @@
# Global variables for various ANSI escape-code sequences
# Not all sequences are supported by all terminals.
# This file is part of REMIND
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# SPDX-License-Identifier: GPL-2.0-only
if !defined("ansi_bold")
# Disable ANSI attributes in calandar mode
if $CalMode
set ansi_normal ""
set ansi_bold ""
set ansi_faint ""
set ansi_italic ""
set ansi_underline ""
set ansi_reverse ""
set ansi_strikeout ""
set ansi_underline2 ""
set ansi_overline ""
else
set ansi_normal char(27) + "[0m"
set ansi_bold char(27) + "[1m"
set ansi_faint char(27) + "[2m"
set ansi_italic char(27) + "[3m"
set ansi_underline char(27) + "[4m"
set ansi_reverse char(27) + "[7m"
set ansi_strikeout char(27) + "[9m"
set ansi_underline2 char(27) + "[21m"
set ansi_overline char(27) + "[53m"
endif
preserve ansi_normal ansi_bold ansi_faint ansi_italic ansi_underline2 ansi_reverse ansi_strikeout ansi_underline2 ansi_overline
endif
# Example: REM MSG I must [ansi_bold]emphasize[ansi_normal] \
# the [ansi_italic]severity[ansi_normal] of the situation!

View File

@@ -1,4 +1,5 @@
# Canadian holidays
# SPDX-License-Identifier: GPL-2.0-only
OMIT 1 Jan MSG New Year's Day

20
include/holidays/fr.rem Normal file
View File

@@ -0,0 +1,20 @@
#
# France Holidays
#
# Source: Article L3133-1
# https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006072050/LEGISCTA000006178007/2016-08-10/
#
SET easter EASTERDATE($Uy)
REM Jan 1 MSG %"Jour de l'an%"
REM [easter+1] MSG %"Lundi de Pâques%"
REM May 1 MSG %"Fête du Travail%"
REM May 8 MSG %"Victoire des alliés%"
REM [easter+39] MSG %"Jeudi de l'Ascension%"
REM [easter+50] MSG %"Lundi de Pentecôte%"
REM Jul 14 MSG %"Fête nationale%"
REM Aug 15 MSG %"Assomption%"
REM Nov 1 MSG %"La Toussaint%"
REM Nov 11 MSG %"Armistice%"
REM Dec 25 MSG %"Noël%"

112
include/holidays/jewish.rem Normal file
View File

@@ -0,0 +1,112 @@
# Major Jewish Holidays
# SPDX-License-Identifier: GPL-2.0-only
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
# you get the Diaspora versions of Jewish holidays
SET InIsrael value("InIsrael", 0)
# Set the variable Reform to 1 if you want the Reform version of the
# Jewish calendar. Otherwise, you get the traditional version
SET Reform value("Reform", 0)
# Convenient function definition to save typing
FSET _h(x, y) HEBDATE(x,y)
FSET _h2(x, y) HEBDATE(x, y, $U-7)
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
FSET _BackTwoFri(x, y) IIF(WKDAYNUM(_h2(x,y))!=5, _h2(x,y), _h2(x,y)-2)
FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
# Default values in case InIsrael and Reform are not set
SET InIsrael VALUE("InIsrael", 0)
SET Reform VALUE("Reform", 0)
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
# No RH-2 or Tzom Gedalia in Reform
IF !Reform
[_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
[_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
ENDIF
[_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
[_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
IF !InIsrael
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
ENDIF
[_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
IF InIsrael
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
ELSE
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
ENDIF
# Because Kislev can change length, we must be more careful about Chanukah
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%"
[_chan(4)] MSG %"Chanukah 4%"
[_chan(5)] MSG %"Chanukah 5%"
[_chan(6)] MSG %"Chanukah 6%"
[_chan(7)] MSG %"Chanukah 7%"
[_chan(8)] MSG %"Chanukah 8%"
# Not sure about Reform's position on the next one.
IF !Reform
# 10 Tevet will never be a Saturday, so whether or not to
# move it is moot. (Thanks to Art Werschulz.)
[_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
ENDIF
[_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
[_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
IF WKDAYNUM(_h2(13, "Adar")) != 6
REM [_h2(13, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
ELSE
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
ENDIF
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
IF !InIsrael
[_h(16, "Nisan")] MSG %"Pesach 2%"
ENDIF
[_h(21, "Nisan")] MSG %"Pesach 7%"
IF !InIsrael && !Reform
[_h(22, "Nisan")] MSG %"Pesach 8%"
ENDIF
[_h(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
[_BackTwoFri(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
[_BackTwoSat(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
# Not sure about Reform's position on Lag B'Omer
IF !Reform
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
ENDIF
[_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
[_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
IF !InIsrael && !Reform
[_h(7, "Sivan")] MSG %"Shavuot 2%"
ENDIF
# Fairly sure Reform Jews don't observe the next two
IF !Reform
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
# fall on a Saturday
[_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
[_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
ENDIF
# Clean up
FUNSET _h _h2 _PastSat _BackTwoFri _BackTwoSat _chan

View File

@@ -1,49 +1,55 @@
# US holidays
# This file is part of REMIND.
# Copyright (C) 1992-2022 Dianne Skoll
# Copyright (C) 1992-2023 Dianne Skoll
# SPDX-License-Identifier: GPL-2.0-only
REM [easterdate($Uy)-46] MSG %"Ash Wednesday%"
REM [easterdate($Uy)-7] MSG %"Palm Sunday%"
OMIT [easterdate($Uy)-2] MSG %"Good Friday%"
REM [easterdate($Uy)-46] MSG Ash Wednesday
REM [easterdate($Uy)-7] MSG Palm Sunday
OMIT [easterdate($Uy)-2] MSG Good Friday
OMIT [easterdate($Uy)] MSG %"Easter%" Sunday
REM [easterdate($Uy)+39] MSG %"Ascension Day%"
REM [easterdate($Uy)+49] MSG %"Pentecost%"
REM [easterdate($Uy)+39] MSG Ascension Day
REM [easterdate($Uy)+49] MSG Pentecost
# Some holidays are omitted, some are not. You may want to change
# which ones are omitted.
OMIT Jan 1 MSG %"New Year's Day%"
OMIT Jan 1 MSG New Year's Day
REM Third Monday in Jan MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's Day%"
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's Day%"
REM Feb 2 MSG Ground Hog Day
REM Feb 14 MSG Valentine's Day
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG President's Day
REM Mar 17 MSG St. Patrick's Day
# The DST rules are accurate for most locations in
# North America
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Last Sunday in October ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
# These are accurate for most places in North America
REM MAYBE-UNCOMPUTABLE Sun November SATISFY [isdst($T) != isdst($T+1)] MSG Daylight Saving Time Ends
REM MAYBE-UNCOMPUTABLE Sun March SATISFY [isdst($T) != isdst($T+1)] MSG Daylight Saving Time Starts
REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
REM May 5 MSG %"Cinco de Mayo%"
REM First Sat in May MSG %"Kentucky Derby%"
REM Second Sun in May MSG %"Mother's Day%"
REM Third Sat in May MSG %"Armed Forces Day%"
REM Last Monday in May SCANFROM -7 ADDOMIT MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%"
REM Third Sun in June MSG %"Father's Day%"
REM First Mon in Sep SCANFROM -7 ADDOMIT MSG %"Labor Day%"
REM Second Mon in Oct MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%"
REM May 5 MSG Cinco de Mayo
REM First Sat in May MSG Kentucky Derby
REM Second Sun in May MSG Mother's Day
REM Third Sat in May MSG Armed Forces Day
REM Last Monday in May SCANFROM -7 ADDOMIT MSG Memorial Day
REM Jun 14 MSG Flag Day
REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
REM Last Thu in Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
REM Dec 24 MSG %"Christmas Eve%"
REM July 4 SCANFROM -7 ADDOMIT MSG Independence Day
REM July 3 SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Independence Day (observed)
REM July 5 SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Independence Day (observed)
REM Third Sun in June MSG Father's Day
REM First Mon in Sep SCANFROM -7 ADDOMIT MSG Labor Day
REM Second Mon in Oct MSG Columbus Day / Indigenous Peoples' Day
REM Nov 11 MSG Veterans Day
REM Oct 30 MSG Mischief Night
REM Oct 31 MSG Halloween
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG Election Day
REM Thu 22 Nov SCANFROM -7 ADDOMIT MSG Thanksgiving Day
REM Fri 23 Nov SCANFROM -7 ADDOMIT MSG Thanksgiving (cont.)
REM Dec 24 MSG Christmas Eve
OMIT Dec 25 MSG %"Christmas%" Day

View File

@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
SET autolang getenv("LC_ALL")
IF autolang == ""
SET autolang getenv("LANGUAGE")

View File

@@ -1,6 +1,6 @@
# Support for the Danish language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Mogens Lynnerup.
SET $Sunday "Søndag"

View File

@@ -1,6 +1,6 @@
# Support for the German language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Wolfgang Thronicke
# Day names
@@ -61,3 +61,29 @@ FSET subst_gx(alt, d, t) iif(alt, subst_g_alt(d), $On + " " + subst_g_alt(d))
FSET subst_ux(alt, d, t) subst_ax(alt, d, t)
FSET subst_vx(alt, d, t) subst_gx(alt, d, t)
FSET subst_p(alt, d, t) iif(d == today()+1, "", "en")
# Localization of various astronomical events
# Perihelion
SET earthseasons_Perihelion_str "Perihel"
# Vernal equinox
SET earthseasons_EquinoxMar_str "Frühlingsanfang"
# Summer solstice
SET earthseasons_SolsticeJun_str "Sommeranfang"
# Aphelion
SET earthseasons_Aphelion_str "Aphel"
# Autumnal Equinox
SET earthseasons_EquinoxSep_str "Herbstanfang"
# Winter Solstice
SET earthseasons_SolsticeDec_str "Winteranfang"
# Daylight saving time starts
SET daylightST_starts_str "Beginn Sommerzeit"
# Daylight saving time ends
SET daylightST_ends_str "Ende Sommerzeit"

View File

@@ -1,4 +1,4 @@
# Support for the English language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# Nothing to do for English since it is the default.

View File

@@ -1,6 +1,6 @@
# Support for the Spanish language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
SET $Sunday "Domingo"

View File

@@ -1,6 +1,6 @@
# Support for the Finnish language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Mikko Silvonen
SET $Sunday "sunnuntai"

View File

@@ -1,6 +1,6 @@
# Support for the French language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Laurent Duperval
SET $Sunday "dimanche"

View File

@@ -1,6 +1,6 @@
# Support for the Icelanding language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
SET $Sunday "sunnudagur"

View File

@@ -1,6 +1,6 @@
# Support for the Italian language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Valerio Aimale
SET $Sunday "Domenica"

View File

@@ -1,6 +1,6 @@
# Support for the Dutch language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
SET $Sunday "zondag"

View File

@@ -1,6 +1,6 @@
# Support for the Norwegian language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Trygve Randen
SET $Sunday "Søndag"

View File

@@ -1,6 +1,6 @@
# Support for the Polish language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Jerzy Sobczyk
SET $Sunday "Niedziela"

View File

@@ -1,6 +1,6 @@
# Support for the (Brazilian) Portuguese language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Marco Paganini
SET $Sunday "domingo"

View File

@@ -1,6 +1,6 @@
# Support for the Romanian language.
# This file is part of REMIND.
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
# This file is derived from a translation by Liviu Daia
SET $Sunday "Duminică"

16
include/seasons.rem Normal file
View File

@@ -0,0 +1,16 @@
# Equinoxes and solstices
# SPDX-License-Identifier: GPL-2.0-only
IF $LatDeg >= 0
# Northern Hemisphere
REM NOQUEUE [soleq(0)] MSG %"Vernal Equinox%" is %3.
REM NOQUEUE [soleq(1)] MSG %"Summer Solstice%" is %3.
REM NOQUEUE [soleq(2)] MSG %"Autumnal Equinox%" is %3.
REM NOQUEUE [soleq(3)] MSG %"Winter Solstice%" is %3.
ELSE
# Southern Hemisphere
REM NOQUEUE [soleq(0)] MSG %"Autumnal Equinox%" is %3.
REM NOQUEUE [soleq(1)] MSG %"Winter Solstice%" is %3.
REM NOQUEUE [soleq(2)] MSG %"Vernal Equinox%" is %3.
REM NOQUEUE [soleq(3)] MSG %"Summer Solstice%" is %3.
ENDIF

View File

@@ -1,4 +1,4 @@
.TH REM 1 "14 March 2022"
.TH REM 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
.UC 4
.SH NAME
rem \- Invoke Remind with a default filename
@@ -16,5 +16,7 @@ the filename $HOME/.reminders
.PP
.SH AUTHOR
Remind was written by Dianne Skoll <dianne@skoll.ca>
.SH HOME PAGE
https://dianne.skoll.ca/projects/remind/
.SH SEE ALSO
\fBremind\fR

View File

@@ -1,4 +1,4 @@
.TH REM2PS 1 "14 March 2022"
.TH REM2PS 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
.UC 4
.SH NAME
rem2ps \- draw a PostScript calendar from Remind output
@@ -586,6 +586,18 @@ For a SHADE or COLOR special, the blue color component.
.B body \fIbody\fR
The body of the reminder to issue. Always present.
.TP
.B calendar_body \fIbody\fR
The text appropriate to include in a calendar. Only present if the
original body contains %"...%" sequences and the "q" modifier was used
with Remind's "-pp..." flag.
.TP
.B plain_body \fIbody\fR
The "plain" body of the reminder with any %"...%" sequences removed.
If your back-end is designed to draw a calendar, then it should
use the \fBcalendar_body\fR if present. If not, then it
should use the \fBplain_body\fR if present, and if not, then it
should fall back on the \fBbody\fR.
.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
@@ -674,6 +686,8 @@ resulting PostScript output will probably not work.
You should ensure that the values you supply for margin widths are sensible.
If they are too big for the media size, \fBRem2ps\fR will not complain,
but again, the PostScript output will probably not work.
.SH HOME PAGE
https://dianne.skoll.ca/projects/remind/
.SH SEE ALSO
\fBremind\fR, \fBrem2pdf\fR, \fBrem2html\fR, \fBtkremind\fR.

View File

@@ -1,4 +1,4 @@
.TH REMIND 1 "14 March 2022"
.TH REMIND 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
.UC 4
.SH NAME
remind \- a sophisticated reminder service
@@ -78,18 +78,18 @@ display.
.B 'c'
causes \fBRemind\fR to use VT100 escape sequences to approximate
SPECIAL COLOR reminders. Note that this flag is kept for
backwards-compatibility; you should use the \fB\-@\fI[n][,m]\fR
backwards-compatibility; you should use the \fB\-@\fI[n][,m][,b]\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".
.B \-@\fR[\fIn\fR][,\fIm\fR][,\fIb\fR]
Tells \fBRemind\fR to approximate SPECIAL COLOR and SHADE 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
@@ -99,23 +99,53 @@ 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
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.
is supplied, or it is supplied as \fIm\fR=2, 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.
.PP
If the optional \fIb\fR parameter is supplied following a comma, then
\fIb=0\fR tells \fBRemind\fR to ignore SPECIAL SHADE reminders (the
default) and \fIb=1\fR tells \fBRemind\fR to respect SPECIAL SHADE
reminders by emitting VT100 escape codes to color the background of the
calendar cell. Note that SHADE does not work well unless you are
using the extended 256-color palette (\fIn\fR=1) or the true
24-bit colors (\fIn\fR=2). Note that for calendar cells that are
shaded, the clamping mechanism described earlier for \fIm=0\fR or
\fIm=1\fR is skipped; it is assumed that if you set \fIboth\fR the
foreground color of a reminder and the background color of a cell,
then you know what you are doing.
.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. 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.
columns in the output device. If \fIcol\fR is not specified, or is
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. If
\fIcol\fR is specified as the letter \fBt\fR, then \fBRemind\fR
attempts to get the width of the \fB/dev/tty\fR terminal device. This
is useful, for example, if you pipe calendar output into \fBless\fR;
even though standard output is a pipe, you want the calendar to be
sized correctly for your terminal window:
.RS
.PP
.nf
remind -c -wt .reminders | less
.fi
.RE
.RS
.PP
Note that the value of \fIcol\fR is also used to set the system variable
$FormWidth, which is initialized to \fIcol\fR - 8. See "SYSTEM VARIABLES"
for details.
.PP
\fIPad\fR specifies how many lines
to use to "pad" empty calendar boxes. This defaults to 5. If you
@@ -141,7 +171,7 @@ 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][\fBp\fR][\fBp\fR]\fIn\fR
.B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR][\fBq\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, and various
@@ -156,7 +186,9 @@ by the reminder's \fIdelta\fR. If you follow the \fBp\fR with another
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.
format, again documented in \fBrem2ps(1)\fR. If you include a \fBq\fR
letter with this option, then the normal calendar-mode substitution filter
is disabled and the %"...%" sequences are preserved in the output.
.RS
.PP
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
@@ -378,7 +410,7 @@ information.
.SH REMINDER FILES
.PP
\fBRemind\fR uses scripts to control its operation. You can use any
text editor capable of creating plain ASCII files to create a
text editor capable of creating plain-text files to create a
\fBRemind\fR script. The commands inside a script can range from the
very simple and almost immediately understandable:
.PP
@@ -432,6 +464,7 @@ Its syntax is:
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
[\fBOMIT\fR \fIomit_list\fR]
[\fBADDOMIT\fR]
[\fBNOQUEUE\fR]
[\fBOMITFUNC\fR \fIomit_function\fR]
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
[\fBSCHED\fR \fIsched_function\fR]
@@ -563,6 +596,7 @@ The trigger date for a specific run is simply the current system date.
present. The reminder is triggered on the specified day of each month.
The trigger date for a particular run is the closest such day to the
current system date. For example:
.PP
.nf
REM 1 MSG First of every month.
REM 31 MSG 31st of every month that has 31 days.
@@ -572,6 +606,7 @@ current system date. For example:
.I month
present. The reminder is triggered every day of the specified month.
Example:
.PP
.nf
REM Feb MSG Every day in February
.fi
@@ -581,6 +616,7 @@ Example:
and
.I month
present. Examples:
.PP
.nf
REM 6 Jan MSG Every 6th of January
REM Feb 29 MSG Every 29th of February
@@ -589,6 +625,7 @@ present. Examples:
5. Only
.I year
present. Example:
.PP
.nf
REM 1991 MSG Every day in 1991
.fi
@@ -598,6 +635,7 @@ present. Example:
and
.I day
present. Examples:
.PP
.nf
REM 1 1990 MSG 1st of every month in 1990
REM 1992 23 MSG 23rd of every month in 1992
@@ -608,6 +646,7 @@ present. Examples:
and
.I month
present. Examples:
.PP
.nf
REM Feb 1991 MSG Every day in Feb 1991
REM 1992 September MSG Every day in Sept 1992
@@ -618,6 +657,7 @@ present. Examples:
and
.I day
present. Examples:
.PP
.nf
REM 8 Jan 1991 MSG 8th January 1991.
REM 1992 March 9 MSG 9th March 1992.
@@ -626,6 +666,7 @@ present. Examples:
9.
.I weekday
only. Examples:
.PP
.nf
REM Sat MSG Every Saturday
REM Mon Tue Wed Thu Fri MSG Every working day
@@ -637,6 +678,7 @@ only. Examples:
and
.I day
present. Examples:
.PP
.nf
REM Sat 1 MSG First Saturday of every month
REM Mon Tue Wed Thu Fri 15 \\
@@ -648,6 +690,7 @@ present. Examples:
and
.I month
present. Examples:
.PP
.nf
REM Mon March MSG Every Monday in March
REM Mon Tue Wed Thu Fri Feb MSG Every working day in February
@@ -658,6 +701,7 @@ present. Examples:
and
.I day
present. Examples:
.PP
.nf
REM Mon 1 March MSG First Monday in March
REM Sat Sun 15 July MSG First Sat or Sun on or after 15 July
@@ -668,6 +712,7 @@ present. Examples:
and
.I year
present. Example:
.PP
.nf
REM Sat Sun 1991 MSG Every Saturday and Sunday in 1991
.fi
@@ -677,6 +722,7 @@ present. Example:
and
.I year
present. Examples:
.PP
.nf
REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990
REM Mon Tue Wed Thu Fri 1 1990 \\
@@ -688,6 +734,7 @@ present. Examples:
and
.I year
present. Example:
.PP
.nf
REM Mon Wed 1991 Feb MSG Every Mon and Wed in Feb 1991.
.fi
@@ -697,6 +744,7 @@ present. Example:
and
.I year
present. Example:
.PP
.nf
REM Mon Tue Wed Thu Fri 28 Oct 1990 \\
MSG 1st working day on or after 28 October 1990.
@@ -957,6 +1005,18 @@ also. See "The OMIT command" for more details.)
By comparison, if we had used "\-\-1", the reminder would be triggered on
the last day of the month, regardless of the \fBOMIT\fR.
.PP
If you locally omit weekdays but also have globally-omitted weekdays, then
the list of ommitted weekdays is the union of the two. Consider this
example:
.PP
.nf
OMIT Sat Sun
REM 15 OMIT Fri Sat MSG Whatever
.fi
.PP
In the REM command, the effective list of omitted weekdays will
be Friday, Saturday and Sunday.
.PP
.B COMPUTED LOCAL OMITS
.PP
The \fBOMITFUNC\fR phrase of the \fBREM\fR command allows you to
@@ -1041,7 +1101,11 @@ for a timed reminder is the same as the current system date, the
reminder is queued for later activation. When \fBRemind\fR has
finished processing the reminder file, it puts itself in the
background, and activates timed reminders when the system time reached
the specified time.
the specified time. Note that if you use the \fBNOQUEUE\fR modifier
in the \fBREM\fR command, then this queueing and background activation
is \fInot\fR performed. \fBNOQUEUE\fR is useful if you want a time
to be associated with a reminder (eg, in the calendar) but are not
interested in a popup reminder happening at the specified time.
.PP
If the trigger date is \fInot\fR the same as the system date, the reminder
@@ -1130,7 +1194,8 @@ tags; see their documentation for details.
.PP
The \fBTAG\fR keyword is followed by a tag consisting of up to
48 characters. You can have as many TAG clauses as you like in
a given REM statement.
a given REM statement. A tag can contain any character except for
whitespace and a comma.
.PP
If you supply the \fB\-y\fR option to \fBRemind\fR, then any
reminder that lacks a \fBTAG\fR will have one synthesized. The
@@ -1466,7 +1531,8 @@ Notes:
o
.B Remind
normally prints a blank line after each reminder; if the last character
of the body is "%", the blank line will not be printed.
of the body is "%", the blank line will not be printed. You can globally
suppress the extra blank lines by setting \fB$AddBlankLines\fR to 0.
.TP
o
Substitutions a, b, c, e, f, g, h, i, j, k, l, u and v all are replaced
@@ -1515,11 +1581,15 @@ In addition to being a keyword in the \fBREM\fR command,
\fBOMIT\fR is a command in its own right. Its syntax is:
.PP
.RS
\fBOMIT\fR \fIday\fR \fImonth\fR [\fIyear\fR]
\fBOMIT\fR \fIweekday\fR [\fIweekday\fR...]
.PP
or:
.PP
\fBOMIT\fR \fIday1\fR \fImonth1\fR \fIyear1\fR \fBTHROUGH\fR \fIday2\fR \fImonth2\fR \fIyear2\fR
\fBOMIT\fR [\fIday\fR] \fImonth\fR [\fIyear\fR]
.PP
or:
.PP
\fBOMIT\fR [\fIday1\fR] \fImonth1\fR [\fIyear1\fR] \fBTHROUGH\fR [\fIday2\fR] \fImonth2\fR [\fIyear2\fR]
.RE
.PP
The \fBOMIT\fR command is used to "globally" omit certain days
@@ -1528,12 +1598,23 @@ The \fBOMIT\fR command is used to "globally" omit certain days
"\-\-" and "\+\+" forms. Some examples:
.PP
.nf
OMIT 1 Jan
OMIT 7 Sep 1992
OMIT Saturday Sunday
OMIT 1 Jan
OMIT 7 Sep 1992
OMIT 15 Jan THROUGH 14 Feb
OMIT May # Equivalent to OMIT May 1 THROUGH May 31
OMIT 25 Dec THROUGH 4 Jan
OMIT 2023-05-03 THROUGH 2023-05-12
OMIT Jun THROUGH July # Equivalent to OMIT Jun 1 THROUGH July 31
.fi
.PP
The first example specifies a holiday that occurs on the same date each
year - New Year's Day. The second example specifies a holiday that
The first example omits every Saturday and Sunday. This is useful for
reminders that shouldn't trigger on weekends.
.PP
The second example specifies a holiday that occurs on the same date each
year - New Year's Day.
.PP
The third example specifies a holiday that
changes each year - Labour Day. For these types of holidays, you
must create an \fBOMIT\fR command for each year. (Later, in the
description of expressions and some of the more advanced features of
@@ -1561,9 +1642,7 @@ equivalent:
.fi
.PP
The \fBTHROUGH\fR keyword lets you conveniently OMIT a range of days.
The starting and ending points must be fully-specified (ie, they must
include day, month and year.). For example, the following sequences
are equivalent:
For example, the following sequences are equivalent:
.PP
.nf
OMIT 3 Jan 2011
@@ -1575,12 +1654,28 @@ are equivalent:
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
.fi
.PP
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command:
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command as
long as both dates are fully specified
.PP
.nf
OMIT 6 Sep 2010 THROUGH 10 Sep 2010 MSG Vacation
.fi
.PP
If you use a THROUGH clause, then either the year must be supplied before
and after the THROUGH, or it must be missing before and after the THROUGH.
The following are legal:
.PP
.nf
OMIT 25 Dec THROUGH 6 Jan
OMIT 25 Dec 2024 THROUGH 6 Jan 2025
.fi
.PP
But the following are not:
.PP
.nf
OMIT 25 Dec THROUGH 6 Jan 2025
OMIT 25 Dec 2024 THROUGH 6 Jan
.nf
.PP
You can debug your global OMITs with the following command:
.PP
@@ -1689,6 +1784,12 @@ Arguably, the \fBINCLUDE\fR command should have worked the way \fBDO\fR
does right from the start, but changing it would have broken
backward-compatibility, hence the introduction of \fBDO\fR.
.PP
Note that if the currently-processing reminders file was specified as
a symbolic link to a file that is not in the same directory as the
symbolic link itself, \fBDO\fR will fail. \fBRemind\fR does \fInot\fR
resolve the real path of symbolic links, so you should avoid using
symbolic links to files.
.PP
.SH THE RUN COMMAND
.PP
If you include other files in your reminder script, you may not always
@@ -1883,12 +1984,16 @@ The following examples illustrate constants in \fBRemind\fR expressions:
12, 36, \-10, 0, 1209
.TP
.B STRING constants
"Hello there", "This is a test", "\\n\\gosd\\w", ""
"Hello there", "This is a test", "\\nHello\\tThere", ""
.PP
.RS
Note that the empty string is represented by "", and that
backslashes in a string are \fInot\fR interpreted specially, as in they are
in C.
Note that the empty string is represented by "". Remind supports
the escape sequences "\\a", "\\b", "\\f", "\\n", "\\r", "\\t"
and "\\v" which have the same meanings as their counterparts in C.
To include a quote in a string, use "\\"". Any other character
preceded by a backslash is inserted into the string as-is, but the
backslash itself is removed. To include a backslash in a string,
use "\\\\".
.RE
.TP
.B TIME constants
@@ -2175,6 +2280,16 @@ The following system variables are defined. Those marked
"read-only" cannot be changed with the \fBSET\fR command.
All system variables hold values of type \fBINT\fR, unless otherwise
specified.
.TP
.B $AddBlankLines
If set to 1 (the default), then \fBRemind\fR normally prints a blank
line after the banner and each reminder. (This can be suppressed by
ending the reminder or banner with a single percent sign.) If
$AddBlankLines is set to 0, then Remind does not print the blank line.
In this case, ending a reminder with % has no effect. If you \fIdo\fR
want a blank line after a reminder, end it with \fB%_\fR to insert a
newline.
.TP
.B $CalcUTC
If 1 (the default), then \fBRemind\fR uses C library functions
@@ -2323,9 +2438,10 @@ the decimal point must be a period (".").
.PP
For example, the coordinates of the Statue of Liberty in New York City
are approximately set by:
.PP
.nf
SET $Latitude "40.68933"
SET $Longitude "-74.04454"
SET $Latitude "40.68933"
SET $Longitude "-74.04454"
.fi
.RE
.TP
@@ -2441,11 +2557,25 @@ order, or 2 if sorting by time in descending order.
The number of spaces by which all lines (except the first) of an
\fBMSF\fR-type reminder should be indented. The default is 0.
.TP
.B $SuppressLRM
Normally, when Remind is run with the \fB\-c\fR option in a UTF-8 locale,
it emits a left-to-right mark sequence after printing day names or
reminders. Some terminals render this incorrectly, so you can use:
.RS
.PP
.nf
SET $SuppressLRM 1
.fi
.PP
at the top of your reminder file to suppress the LRM sequences, or you
can invoke Remind with the option \fB'\-i$SuppressLRM=1'\fR.
.RE
.TP
.B $SysInclude (read-only, STRING type)
A directory path containing standard reminder scripts. Currently,
Remind ships with some standard holiday files and language packs.
The value of \fB$SysInclude\fR is likely to be something like
"/usr/share/remind" or "/usr/local/share/remind"
The value of \fB$SysInclude\fR is "@prefix@/share/remind" on
this installation.
.TP
.B $T (read-only, DATE type)
Exactly equivalent to \fBtrigdate()\fR. (See BUILT-IN FUNCTIONS.)
@@ -2485,6 +2615,23 @@ Equivalent to \fBwkdaynum(today())\fR.
.TP
.B $Uy (read-only)
Equivalent to \fByear(today())\fR.
.TP
.B $UseVTColors (read-only)
Set to 1 if the \fB\-@\fR or \fB\-cc\fR options were used; 0 otherwise.
.TP
.B $UseBGVTColors (read-only)
Set to 1 if the \fB\-@,,1\fR option was used; 0 otherwise.
.TP
.B $Use256Colors (read-only)
Set to 1 if the \fB\-@1\fR option was used; 0 otherwise.
.TP
.B $UseTrueColors (read-only)
Set to 1 if the \fB\-@2\fR option was used; 0 otherwise.
.TP
.B $TerminalBackground (read-only)
Returns -1 if the terminal background color was not specified,
0 if it was specified as dark with the \fB\-@,0\fR option or
1 if it was specified as light with the \fB\-@,1\fR option.
.PP
Note: If any of the calendar modes are in effect, then the
values of $Daemon, $DontFork, $DontTrigAts, $DontQueue, $HushMode,
@@ -2547,6 +2694,60 @@ $TimeSep and $DateTimeSep when formatting its output. For example:
.PP
.RE
.TP
.B ansicolor(i_red, i_green, i_blue [,i_bg [,i_clamp]])
Returns a \fBSTRING\fR that contains an ANSI escape sequence for changing
the terminal text color. The parameters \fIred\fR, \fIgreen\fR and \fIblue\fR
are integers from 0 to 255 specifying the value of the respective color
component. As a special case, all three values can be -1, in which case
the ANSI sequence "ESC[0m" is returned, which resets all text attributes
to normal.
.RS
.PP
The string returned by \fBansicolor\fR depends on the color mode that
\fBRemind\fR is running in, as specified by the \fB\-@\fR option. If color
mode is not enabled, then \fBansicolor\fR always returns the empty string.
Otherwise, it returns the escape sequence that best approximates the color
according to the \fB\-@\fR color mode.
.PP
The optional \fIbg\fR argument is either 0 or 1. If 0 (the default), then
the foreground color is set. If 1, then the background color is set. Note
that setting the background color only works in 256-color or true-color
mode.
.PP
The optional \fIclamp\fR argument is either 0 or 1. If 0 (the default),
then colors are not adjusted based on the terminal background color. If
1, then \fBRemind\fR attempts to adjust dark or bright colors so they have
enough contrast to be visible in the terminal.
.PP
The first three arguments may alternatively be specified as a string
consisting of three space-separated numbers, as in this example: "128 128 0"
.PP
As a special case, \fBansicolor("")\fR is equivalent to
\fBansicolor(-1,-1,-1)\fR and returns the ANSI sequence to reset all text
attributes to normal.
.PP
Note that inserting ANSI color sequences in calendar mode \fIwill
produce garbled results\fR. Therefore, we recommend defining
functions such as the ones below that return the empty string in
calendar mode:
.PP
.nf
IF $CalMode
FSET fg(r,g,b) ""
FSET bg(r,g,b) ""
ELSE
FSET fg(r,g,b) ansicolor(r,g,b)
FSET bg(r,g,b) ansicolor(r,g,b,1)
ENDIF
REM [fg(255,0,0)][bg(64,64,64)]Red on Gray[fg(-1,-1,-1)] in normal mode
REM SPECIAL COLOR 0 255 0 Green in normal and calendar mode
.fi
.PP
If you use the \fBansicolor\fR function, don't forget to reset the color
back to normal with \fBansicolor(-1,-1,-1)\fR or subsequent reminders
will continue to be colored.
.RE
.TP
.B args(s_fname)
Returns the number of arguments expected by the user-defined function
\fIfname\fR, or \-1 if no such user-defined function exists. Note that
@@ -2557,7 +2758,10 @@ available only in versions of \fBRemind\fR from 03.00.04 and up.
.TP
.B asc(s_string)
Returns an \fBINT\fR that is the ASCII code of the first character
in \fIstring\fR. As a special case, \fBasc("")\fR returns 0.
in \fIstring\fR. As a special case, \fBasc("")\fR returns 0. For UTF-8
strings, this will return the UTF-8 byte with which the string
begins, which is not likely to be very useful (and may indeed be negative
on machines where \fBchar\fR is a signed type.)
.TP
.B baseyr()
Returns the "base year" that was compiled into \fBRemind\fR (normally
@@ -2566,14 +2770,10 @@ Returns the "base year" that was compiled into \fBRemind\fR (normally
.TP
.B char(i_i1 [,i_i2...])
This function can take any number of \fBINT\fR arguments. It returns
a \fBSTRING\fR consisting of the characters specified by the arguments.
Note that none of the arguments can be 0, unless there is only one
a \fBSTRING\fR consisting of the bytes specified by the arguments.
It is easy to create invalid UTF-8 sequences; \fBchar\fR does not check
for this. Note that none of the arguments can be 0, unless there is only one
argument. As a special case, \fBchar(0)\fR returns "".
.PP
.RS
Note that because \fBRemind\fR does not support escaping of characters
in strings, the only way to get a double-quote in a string is to use
\fBchar(34)\fR.
.RE
.TP
.B choose(i_index, x_arg1 [,x_arg2...])
@@ -2632,6 +2832,22 @@ arguments are converted using the reverse of procedures described
above. A \fBSTRING\fR \fIarg\fR is converted by parsing it as an
integer.
.RE
.TP
.B columns([s_arg])
If called with no arguments, \fBcolumns()\fR behaves as follows:
If standard output is a TTY, returns the width of the terminal in columns.
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
the terminal size. If this fails, returns -1.
.RS
.PP
If called with a single string argument, \fBcolumns(str)\fR returns
the number of columns \fBstr\fR will occupy if printed to a terminal.
ANSI color-changing sequences occupy zero columns whereas some Unicode
characters occupy two columns. \fBcolumns(str)\fR takes all of that
into account. Note that if Remind was compiled without Unicode support,
\fBcolumns(str)\fR returns a type mismatch error.
.RE
.TP
.B current()
Returns the current date and time as a DATETIME object. This may be the
@@ -2780,6 +2996,13 @@ This includes the file "stuff" in the same directory as the
current file being processed. Note that this workaround is
no longer necessary because \fBDO stuff\fR will achieve the
same goal.
.PP
Note that if the currently-processing reminders file was specified as
a symbolic link, then \fBfiledir()\fR returns the directory containing
the symbolic link and \fInot\fR the directory containing the target
of the symbolic link. You should avoid using
symbolic links to files unless both the symbolic link and its target
happen to be in the same directory.
.RE
.TP
.B filename()
@@ -2872,6 +3095,10 @@ other languages, this function will return the English name of the
language (e.g. "German") Note that \fBlanguage()\fR is not available
in versions of \fBRemind\fR prior to 03.00.02.
.TP
.B localtoutc(q_datetime)
Given a \fBDATETIME\fR object interpreted in the local time zone, return
a \fBDATETIME\fR object that expresses the same time in UTC.
.TP
.B lower(s_string)
Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR
converted to lower-case.
@@ -3048,6 +3275,7 @@ be right-padded.
.RS
.PP
Here are some examples:
.PP
.nf
pad(3, "0", 2) --> "03"
pad(465, "0", 2) --> "465"
@@ -3142,6 +3370,11 @@ Returns the date as provided by the operating system. This is in contrast to
\fBRemind\fR's concept of "today", which may be changed if it is running
in calendar mode, or if a date has been supplied on the command line.
.TP
.B rows()
If standard output is a TTY, returns the height of the terminal in rows.
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
the terminal size. If this fails, returns -1.
.TP
.B sgn(i_num)
Returns \-1 if \fInum\fR is negative, 1 if \fInum\fR is positive,
and 0 if \fInum\fR is zero.
@@ -3203,9 +3436,46 @@ May 16 and 17. You can go backwards, too, so:
takes \fIa\fR back to 2009-05-13.
.RE
.TP
.B soleq(i_which [, dqi_start])
The \fBsoleq\fR function computes solstices and equinoxes. The \fIwhich\fR
parameter ranges from 0 to 3, and specifies which event we are interested
in: 0 is the March equinox; 1 is the June solstice; 2 is the September
equinox and 3 is the December solstice.
.RS
.PP
The optional \fIstart\fR parameter can either be an integer specifying the
year of the event we are interested in, or a \fBDATE\fR or \fBDATETIME\fR
object; if the latter, then \fBsoleq\fR returns the first event on or
after the date part of the \fIstart\fR parameter (it ignores the time
component if \fIstart\fR is a \fBDATETIME\fR.) If \fIstart\fR is
not supplied, then it defaults to \fBtoday()\fR.
.PP
The return value of \fBsoleq()\fR is a \fBDATETIME\fR object specifying
the date and time of the solstice or equinox in the local time zone. It
should be accurate to within 3 minues or so in the worst case.
.PP
See the included file \fB$SysInclude/seasons.rem\fR for examples of how
to use \fBsoleq()\fR.
.RE
.TP
.B stdout()
Returns a string representing where Remind's standard output is going.
The return values are one of the following: "TTY" if standard-output
is a terminal, "BLOCKDEV" if it is a block device (very unlikely),
"CHARDEV" if it is a character device (eg, /dev/null), "DIR" if it
is a directory (very unlikely), "PIPE" if it is a pipe or FIFO,
"SYMLINK" if it is a symlink (very unlikely), "SOCKET" if it is a
socket, or "UNKNOWN" if it could not be determined.
.RS
.PP
The purpose of \fBstdout()\fR is mostly to distinguish between TTY
and non-TTY output; you may wish to change or disable colors if the
output is not going to a TTY.
.RE
.TP
.B strlen(s_str)
Returns the length of \fIstr\fR. If the length of \fIstr\fR is too large
to represent as an integers, emits a "Number too high" error.
to represent as an integer, emits a "Number too high" error.
.TP
.B substr(s_str, i_start [,i_end])
Returns a \fBSTRING\fR consisting of all characters in \fIstr\fR from
@@ -3245,6 +3515,12 @@ Creates a \fBTIME\fR with the hour and minute components specified by
Returns a \fBTIME\fR object representing the time portion of
\fIdatetime\fR.
.TP
.B timezone([dq_datetime])
Returns a string representing the local time zone name of the given
\fBDATETIME\fR. If no argument is supplied, \fBRemind\fR uses the
value of \fBcurrent()\fR. If a \fBDATE\fR rather than \fBDATETIME\fR
is supplied, \fBRemind\fR uses a time part of 00:00.
.TP
.B today()
Returns \fBRemind\fR's notion of "today." This may be the actual system
date, or a date supplied on the command line, or the date of the
@@ -3266,6 +3542,7 @@ non-zero trigger date.
\fBIFTRIG\fR. For example, if you have meetings every Monday in
June and July, and you want warnings 3 days in advance, you
could use:
.PP
.nf
REM [trig("Mon Jun +3", "Mon July +3")] +3 MSG Meeting %b
.fi
@@ -3470,6 +3747,12 @@ returns "30 November 1994 AT 22:00" for EST, which is 5 hours behind UTC.
The value for your time zone may differ.
.RE
.TP
.B trigtags()
Returns a comma-separated list of the TAGs associated with the most recent
\fBREM\fR command that was triggered. Returns the empty string if there
were no TAGs. If there are multiple tags, they are each separated by
a single comma, not a comma and a space.
.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,
@@ -3511,6 +3794,11 @@ values. Here is an example:
Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR
converted to upper-case.
.TP
.B utctolocal(q_datetime)
Given a \fBDATETIME\fR object interpreted in UTC, return a
\fBDATETIME\fR object that expresses the same time in the local time
zone.
.TP
.B value(s_varname [,x_default])
Returns the value of the specified variable. For example, value("X"+"Y")
returns the value of variable XY, if it is defined. If XY is not defined,
@@ -3524,7 +3812,7 @@ defined, and the value of XY if it is defined.
.TP
.B version()
Returns a string specifying the version of \fBRemind\fR. For version
03.00.04, returns "03.00.04". It is guaranteed that as new versions of
@VERSION@, returns "@VERSION@". It is guaranteed that as new versions of
\fBRemind\fR are released, the value returned by \fBversion()\fR will
strictly increase, according to the rules for string ordering.
.TP
@@ -3857,13 +4145,13 @@ Notes:
.TP
o
If you access a variable in \fIexpr\fR that is not in the list of arguments,
the "global" value (if any) is used.
the global value (if any) is used.
.TP
o
Function and parameter names are significant only to 12 characters.
Function and parameter names are significant to 64 characters.
.TP
o
The \fBvalue()\fR function \fIalways\fR accesses the "global" value of a
The \fBvalue()\fR function \fIalways\fR accesses the global value of a
variable, even if it has the same name as an argument. For example:
.RS
.PP
@@ -3891,6 +4179,19 @@ with future versions of \fBRemind\fR (which may define more built-in
functions), you may wish to name all user-defined functions beginning
with an underscore.
.PP
To delete a user-defined function, use \fBFUNSET\fR. This takes a
space-separated list of user-defined functions to delete. For
example, after the command:
.PP
.nf
FUNSET myfunc1 otherfunc thirdfunc
.fi
.PP
it is guaranteed that no user-defined functions named myfunc1, otherfunc
or thirdfunc will exist. \fBRemind\fR does not issue an error if you
try to \fBFUNSET\fR a nonexistent user-defined function; it simply
does nothing in that case.
.PP
.SH PRECISE SCHEDULING
.PP
The \fBWARN\fR keyword allows precise control over advance warning in
@@ -4772,25 +5073,26 @@ This function is passed a single integer, namely a day of the month from
turn it into an ordinal number. In English, for example, the function
might return "st", "nd", "rd" or "th", depending on \fId\fR.
.TP
.B subst_N(alt, date, time)
.B subst_\fIN\fR\fB(alt, date, time)\fR
This is actually a \fIfamily\fR of functions, where \fIN\fR is a letter
or number. This function \fIcompletely overrides\fR the substitution
sequence "%X". The three arguments are an integer \fIalt\fR which,
sequence "%N". The three arguments are an integer \fIalt\fR which,
if non-zero, indicates that the alternate-mode substitution sequence
"%*X" was encountered; \fIdate\fR which is the trigger date of the
"%*N" was encountered; \fIdate\fR which is the trigger date of the
reminder and \fItime\fR which is the trigger time.
.TP
.B subst_Nx(alt, date, time)
.B subst_\fIN\fR\fBx(alt, date, time)\fR
Again, this is a \fIfamily\fR of functions. It is similar to the
\fBsubst_x\fR family except it is only called if \fIdate\fR is two or
\fBsubst_\fIN\fR family except it is only called if \fIdate\fR is two or
more days away from \fItoday()\fR. This is useful if you don't want to
override the "today" or "tomorrow" output for most substitution sequences.
.PP
Here's an example of how you might customize your substitution filter.
Suppose you want to change the "%b" sequence to substitute "the day
after tomorrow" for an event two days from now. You could do this:
.PP
.nf
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", \
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", \\
"in " + (d-today()) + " days' time")
REM [today()+3] ++3 MSG Event 1 is %b%
REM [today()+2] ++3 MSG Event 2 is %b%
@@ -4799,6 +5101,7 @@ after tomorrow" for an event two days from now. You could do this:
.fi
.PP
The output of this script is:
.PP
.nf
Event 1 is in 3 days' time
Event 2 is the day after tomorrow
@@ -4811,6 +5114,26 @@ time", and note also that the "tomorrow" and "today" events used the
normal substitution---\fBsubst_bx\fR is not called for trigger days of
today or tomorrow.
.PP
As a special case, if a \fBsubst_Nx\fB or \fBsubst_N\fR function
returns the integer zero, then the normal substitution mechanism is
used. Therefore, the previous example could have been written more simply
as:
.PP
.nf
FSET subst_bx(a,d,t) iif(d==today()+2, "the day after tomorrow", 0)
.fi
.PP
You can define your own substitution sequences in addition to the built-in
ones as follows: If you define a function named \fBsubst_\fIname\fB(alt, date, time)\fR, then the sequence \fB%{name}\fR calls the function with \fBalt\fR
set to 0 and \fBdate\fR and \fRtime\fR to the trigger date and time,
respectively. The \fB%{name}\fR sequence is replaced with whatever the
function returns. The sequence \fB%*{name}\fR is similar, but calls
the function with \fBalt\fR set to 1.
.PP
If you use a \fB%{name}\fR sequence and the function \fBsubst_\fIname\fR is
not defined or returns an error, then \fB%{name}\fR is replaced with the
empty string.
.PP
.SH LANGUAGE PACKS
.PP
\fBRemind\fR ships with a number of language packs, which are simply reminder
@@ -4823,12 +5146,14 @@ pl.rem (Polish), pt.rem (Portuguese) and ro.rem (Romanian).
.PP
To use a language pack (in this example, de.rem), simply place this at
the top of your reminders file:
.PP
.nf
INCLUDE [$SysInclude]/lang/de.rem
.fi
.PP
If you want \fBRemind\fR to try to find the language pack appropriate
for your locale settings, use:
.PP
.nf
INCLUDE [$SysInclude]/lang/auto.rem
.fi
@@ -5043,10 +5368,12 @@ should attempt to support. They are currently supported by
.PP
The \fBSHADE\fR special replaces the \fBpsshade()\fR function.
Use it like this:
.PP
.nf
REM Sat Sun SPECIAL SHADE 128
REM Mon SPECIAL SHADE 255 0 0
.fi
.PP
The \fBSHADE\fR keyword is followed by either one or three numbers,
from 0 to 255. If one number is supplied, it is interpreted as
a grey-scale value from black (0) to white (255). If three numbers
@@ -5057,14 +5384,17 @@ in calendars produced by \fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.)
.PP
The \fBMOON\fR special replaces the \fBpsmoon()\fR function. Use it
like this:
.PP
.nf
REM [moondate(0)] SPECIAL MOON 0
REM [moondate(1)] SPECIAL MOON 1
REM [moondate(2)] SPECIAL MOON 2
REM [moondate(3)] SPECIAL MOON 3
.fi
.PP
These draw little moons on the various calendars. The complete syntax
of the \fBMOON\fR special is as follows:
.PP
.nf
... SPECIAL MOON phase moonsize fontsize msg
.fi
@@ -5085,12 +5415,12 @@ and \fIfontsize\fR; the other backends use fixed sizes.
.PP
The \fBCOLOR\fR special lets you place colored reminders in the
calendar. Use it like this:
.PP
.nf
REM ... SPECIAL COLOR 255 0 0 This is a bright red reminder
REM ... SPECIAL COLOR 0 128 0 This is a dark green reminder
.fi
.PP
You can spell COLOR either the American way ("COLOR") or the British
way ("COLOUR"). This manual will use the American way.
@@ -5111,11 +5441,11 @@ number in the calendar. For example, this would number each Monday
with the ISO 8601 week number. The week number is shown like this:
"(W\fIn\fR)" in this example, but you can put whatever text you like
after the WEEK keyword.
.PP
.nf
REM Monday SPECIAL WEEK (W[weekno()])
.fi
.PP
.SH MISCELLANEOUS
.PP
.B COMMAND ABBREVIATIONS
@@ -5373,9 +5703,6 @@ are not implemented as read-only system variables.
.PP
Hebrew dates in \fBRemind\fR change at midnight instead of sunset.
.PP
Language should be selectable at run-time, not compile-time. Don't
expect this to happen soon!
.PP
\fBRemind\fR has some built-in limits (for example, number of global
\fBOMIT\fRs.)
.PP
@@ -5390,7 +5717,8 @@ Almanac Office, USNO.
.PP
Richard Siegel and Michael and Sharon Strassfeld, \fIThe First Jewish
Catalog\fR, Jewish Publication Society of America.
.PP
.SH HOME PAGE
https://dianne.skoll.ca/projects/remind/
.SH SEE ALSO
.PP
\fBrem\fR(1), \fBrem2ps\fR(1), \fBrem2pdf\fR(1), \fBtkremind\fR(1), \fBrem2html\fR(1)

View File

@@ -1,4 +1,4 @@
.TH TKREMIND 1 "14 March 2022"
.TH TKREMIND 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
.UC 4
.SH NAME
tkremind \- graphical front-end to Remind calendar program
@@ -18,13 +18,13 @@ as well as the tcllib extension. It also requires a \fBwish\fR
binary. If you are using Tcl/Tk 8.5, you may also need either the Img
or the tkpng extension to handle PNG images.
.SH OPTIONS
\fBTkRemind\fR itself has no options. However, it passes certain options
on to \fBRemind\fR. The options it passes are
\fB\-b\fR, \fB\-g\fR, \fB\-x\fR, \fB\-i\fR and \fB\-m\fR.
See the \fBRemind\fR man page for details about the options.
Note that \fBTkRemind\fR will respect the \fB\-m\fR and
\fB\-b1\fR options and adjust its appearance accordingly.
.SH COMMAND-LINE OPTIONS
\fBTkRemind\fR itself has no command-line options. However, it passes
certain options on to \fBRemind\fR. The options it passes are
\fB\-b\fR, \fB\-g\fR, \fB\-x\fR, \fB\-i\fR and \fB\-m\fR. See the
\fBRemind\fR man page for details about the options. Note that
\fBTkRemind\fR will respect the \fB\-m\fR and \fB\-b1\fR options and
adjust its appearance accordingly.
\fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders.
It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file
@@ -44,8 +44,14 @@ include the line:
.PP
\fIConfig_file\fR is the file in which \fBTkRemind\fR stores
its options. If it is omitted, it defaults to \fI$HOME/.tkremindrt\fR.
its options. If it is omitted, it defaults to \fI$HOME/.config/tkremindrc\fR.
.PP
If \fB$HOME/.reminders\fR is a \fIdirectory\fR, then \fBTkRemind\fR defaults to
reading \fB$HOME/.reminders\fR and writing new reminders to
\fB$HOME/.reminders/100-tkremind.rem\fR. If you want to keep your
reminders in a directory \fB$HOME/.reminders\fR, you should create that
directory before starting \fBTkRemind\fR.
.SH THE CALENDAR WINDOW
When you start \fBTkRemind\fR, it displays a calendar for the current
month, with today's date highlighted. Reminders are filled into each
@@ -274,7 +280,7 @@ Similar to Change entry font, but applies to calendar heading
.PP
Once you've configured the options the way you like them,
press \fBApply Options\fR to put them into effect, \fBSave Options\fR
to put them into effect and save them in $HOME/.tkremindrc, or
to put them into effect and save them in $HOME/.config/tkremindrc, or
\fBCancel\fR to cancel any changes you made.
.SH KEYBOARD SHORTCUTS
@@ -293,6 +299,19 @@ Next Month
.B Home
Today
.SH IMMEDIATE UPDATES
If you are running \fBTkRemind\fR on Linux and have the
\fBinotifywait\fR program installed (part of the \fBinotify-tools\fR
or similar package), then \fBTkRemind\fR redraws the calendar window
\fIimmediately\fR if \fB$HOME/.reminders\fR changes (or, if it is a
directory, any files in that directory change.)
.PP
This lets \fBTkRemind\fR react immediately to hand-edited reminders or
to reminder files that are imported from another calendar system (for example,
you may have a cron job that periodically imports your Google Calendar
entries into Remind format.)
.SH ODDS AND ENDS
\fBTkRemind\fR performs some basic consistency checks when you add or
preview a reminder. However, if you edit a reminder in the previewer,
@@ -323,8 +342,7 @@ You can use this to activate certain reminders in different ways
for \fBTkRemind\fR (for example).
.PP
\fBTkRemind\fR uses tags to keep track of reminders in the
script file. It also places special comments in the reminder
file to store additional state. You can certainly mix
script file. You can certainly mix
"hand-crafted" reminders with reminders created by \fBTkRemind\fR
if you are aware of the following rules and limitations:
.TP
@@ -334,15 +352,16 @@ where \fInnn\fR is a number. You should not use such \fBTAG\fRs
in hand-crafted reminders.
.TP
o
Do not edit lines starting with "# TKTAGnnn", "# TKEND", or any
lines in between. You can move such lines, but be careful to move
them as a single block.
.TP
o
Hand-crafted reminders cannot be edited with \fBTkRemind\fR, and
for hand-crafted timed reminders, you will not be presented with
the "Don't remind me again" option when they pop up.
.PP
However, rather than mixing hand-edited files with \fBTkRemind\fR-generated
ones, it is better to make \fB$HOME/.reminders\fR a directory and keep
your hand-edited files in a separate \fB*.rem\fR file than \fBTkRemind\fR's
\fB100-tkremind.rem\fR file.
.SH SERVER MODE
\fBRemind\fR has a special mode for interacting with programs like
@@ -400,14 +419,16 @@ 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-2020 by Dianne Skoll.
\fBTkRemind\fR is Copyright 1996-2023 by Dianne Skoll.
.SH FILES
$HOME/.reminders -- default reminder file.
$HOME/.reminders -- default reminder file or directory.
$HOME/.tkremindrc -- \fBTkRemind\fR saved options.
$HOME/.config/tkremindrc -- \fBTkRemind\fR saved options.
.SH HOME PAGE
https://dianne.skoll.ca/projects/remind/
.SH SEE ALSO
\fBremind\fR, \fBrem2ps\fR, \fBrem2pdf\fR, \fBrem2html\fR

View File

@@ -19,7 +19,7 @@ install:
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
done; \
pod2man rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
pod2man --center "VERSION @VERSION@" --date "@RELEASE_DATE@" rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
exit 1;

View File

@@ -1,4 +1,5 @@
#!perl
# SPDX-License-Identifier: GPL-2.0-only
use strict;
use warnings;
@@ -130,6 +131,10 @@ today's date, add the following reminder to your reminders file:
rem2html was written by Dianne Skoll with much inspiration from an
earlier version by Don Schwarz.
=head1 HOME PAGE
L<https://dianne.skoll.ca/projects/remind/>
=head1 SEE ALSO
B<remind>, B<rem2ps>, B<rem2pdf>, B<tkremind>

View File

@@ -1,4 +1,15 @@
use ExtUtils::MakeMaker;
{
# Override pod2man options
package MY;
sub manifypods {
my ($self,%attribs) = @_;
my $result = $self->SUPER::manifypods(%attribs);
$result =~ s/^(POD2MAN_EXE\s*=\s*)(.+)$/$1$2 --center 'VERSION @VERSION@' --date '@RELEASE_DATE@'/m;
return $result;
}
}
WriteMakefile(
NAME => 'Remind::PDF',
AUTHOR => q{Dianne Skoll <dianne@skoll.ca>},

View File

@@ -33,10 +33,16 @@ install:
$(MAKE) install DESTDIR=$(DESTDIR) "INSTALL_BASE=$(INSTALL_BASE)" && exit 0; \
elif test "$(prefix)" = "/usr" ; then \
$(MAKE) install DESTDIR=$(DESTDIR) INSTALLDIRS=vendor && exit 0; \
else \
elif test "$(prefix)" = "/usr/local" ; then \
$(MAKE) install DESTDIR=$(DESTDIR) && exit 0; \
else \
$(MAKE) install DESTDIR=$(DESTDIR) "INSTALL_BASE=$(prefix)" && exit 0; \
fi; \
exit 1;
Makefile: Makefile.PL
$(PERL) Makefile.PL @PERLARTIFACTS@ INSTALL_BASE=$(INSTALL_BASE) || true
if test "$(prefix)" != "/usr" -a "$(prefix)" != "/usr/local" -a "$(INSTALL_BASE)" = "" ; then \
$(PERL) Makefile.PL @PERLARTIFACTS@ INSTALL_BASE=$(prefix) || true;\
else \
$(PERL) Makefile.PL @PERLARTIFACTS@ INSTALL_BASE=$(INSTALL_BASE) || true;\
fi

View File

@@ -1,6 +1,8 @@
#!@PERL@
# SPDX-License-Identifier: GPL-2.0-only
use strict;
use warnings;
use lib '@prefix@/lib/perl5';
use Encode;
use Cairo;
@@ -442,14 +444,14 @@ B<-p>, B<-pp> or B<-ppp> options into B<rem2pdf>. The PDF output
will be sent to standard output. So for example, to print a 12-month
calendar for the year 2030, use:
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c=3 | lpr
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c3 | lpr
You can concatenate multiple B<remind> runs. For example, the following
will produce a PDF calendar for January through March of 2023, and
June of 2023 (for a total of four pages);
(remind -pp3 Jan 2023 /dev/null ; \
remind -p June 2023 /dev/null) | rem2pdf -e -l -c=3 > cal.pdf
(remind -pp3 /dev/null Jan 2023 ; \
remind -pp /dev/null June 2023) | rem2pdf -e -l -c3 > cal.pdf
=head1 FORMATTED TEXT
@@ -503,6 +505,10 @@ of each calendar box:
B<Rem2PDF> was written by Dianne Skoll <dianne@skoll.ca>
=head1 HOME PAGE
L<https://dianne.skoll.ca/projects/remind/>
=head1 SEE ALSO
B<remind>, B<rem2ps>, B<rem2html>, B<tkremind>

View File

@@ -1,4 +1,5 @@
package Remind::PDF;
# SPDX-License-Identifier: GPL-2.0-only
use strict;
use warnings;
@@ -227,14 +228,16 @@ sub parse_oldstyle_line
if ($hash->{passthru}) {
if ($hash->{passthru} =~ /^(shade|color|colour)$/i) {
if ($hash->{body} =~ /^\s*(\d+)\s+(\d+)\s+(\d+)/) {
if ($hash->{body} =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)/) {
$hash->{r} = $1;
$hash->{g} = $2;
$hash->{b} = $3;
} elsif ($hash->{body} =~ /^\s*(\d+)/) {
$hash->{body} = $4;
} elsif ($hash->{body} =~ /^\s*(\d+)\s*(.*)/) {
$hash->{r} = $1;
$hash->{g} = $1;
$hash->{b} = $1;
$hash->{body} = $2;
}
}
}
@@ -285,7 +288,7 @@ sub read_one_month_pp
Given a hashref C<$hash> consisting of one entry parsed
from the "remind -p" stream and a C<$specials_accepted> hash,
return 1 if we should include this entry in the calendar or
0 if mot.
0 if not.
=cut
sub accept_special

View File

@@ -1,4 +1,5 @@
package Remind::PDF::Entry;
# SPDX-License-Identifier: GPL-2.0-only
use strict;
use warnings;
@@ -76,7 +77,15 @@ sub render
$layout->set_width(1024 * ($x2 - $x1 - 2 * $settings->{border_size}));
$layout->set_wrap('word-char');
$layout->set_text(Encode::decode('UTF-8', $self->{body}));
my $body;
if (exists($self->{calendar_body})) {
$body = $self->{calendar_body};
} elsif (exists($self->{plain_body})) {
$body = $self->{plain_body};
} else {
$body = $self->{body};
}
$layout->set_text(Encode::decode('UTF-8', $body));
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
$layout->set_font_description($desc);
my ($wid, $h) = $layout->get_pixel_size();
@@ -233,11 +242,9 @@ sub _adjust
package Remind::PDF::Entry::color;
use base 'Remind::PDF::Entry';
# Strip the RGB prefix from body
# Nothing to do for COLOR-type reminder
sub _adjust
{
my ($self) = @_;
$self->{body} =~ s/^\d+\s+\d+\s+\d+\s+//;
}
package Remind::PDF::Entry::postscript;

View File

@@ -1,5 +1,6 @@
#!/bin/sh
# -*-Mode: TCL;-*-
# SPDX-License-Identifier: GPL-2.0-only
#--------------------------------------------------------------
# TKREMIND
@@ -7,7 +8,7 @@
# A cheesy graphical front/back end for Remind using Tcl/Tk
#
# This file is part of REMIND.
# Copyright (C) 1992-2022 Dianne Skoll
# Copyright (C) 1992-2023 Dianne Skoll
#
#--------------------------------------------------------------
@@ -457,6 +458,7 @@ proc CreateCalFrame { w dayNames } {
# Figure out reasonable height for text frames
global SetFontsWorked
global Option
global MondayFirst
set h [winfo screenheight .]
if {$h <= 480} {
if {$SetFontsWorked} {
@@ -470,7 +472,6 @@ proc CreateCalFrame { w dayNames } {
set h 5
}
global MondayFirst
frame $w -background $Option(LineColor)
for {set i 0} {$i < 7} {incr i} {
if {$MondayFirst} {
@@ -547,7 +548,9 @@ proc ConfigureCalFrame { w firstDay numDays } {
$w.t$i configure -state disabled -takefocus 0
}
for {set i $first} {$i <= $last} {incr i} {
set row [expr ($i/7)+1]
grid $w.f$i
grid rowconfigure $w $row -weight 1
pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
raise $w.l$i
@@ -581,7 +584,7 @@ proc ConfigureCalFrame { w firstDay numDays } {
pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
raise $w.l$i
raise $w.t$i
grid rowconfigure $w [expr $row+1] -weight 1
grid rowconfigure $w $row -weight 1
}
$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
$w.l$i configure -state disabled
@@ -953,6 +956,7 @@ proc WriteOptionsToFile {} {
#***********************************************************************
proc LoadOptions {} {
global Option ConfigFile
global MondayFirst
set problem [catch {set f [open "$ConfigFile" "r"]}]
if {$problem} {
return
@@ -972,6 +976,9 @@ proc LoadOptions {} {
set Option($key) $val
}
close $f
if {[regexp -- {-m.*} $Option(ExtraRemindArgs)]} {
set MondayFirst 1
}
font configure CalboxFont {*}$Option(CalboxFont)
font configure HeadingFont {*}$Option(HeadingFont)
}
@@ -1010,7 +1017,7 @@ proc ConfigureCalWindow { month year firstDay numDays } {
proc FillCalWindow {} {
set FileName ""
set LineNo 0
global DayNames CurYear CurMonth MonthNames CommandLine Option TagToObj RemindErrors
global DayNames CurYear CurMonth MonthNames CommandLine Option TagToObj RemindErrors MondayFirst
array unset TagToObj
@@ -1049,7 +1056,12 @@ proc FillCalWindow {} {
# Update the day names in the calendar window
for {set i 0} {$i < 7} {incr i} {
.cal.day$i configure -text [lindex $DayNames $i]
if {$MondayFirst} {
set index [expr ($i+1)%7]
} else {
set index $i
}
.cal.day$i configure -text [lindex $DayNames $index]
}
set offset [CalEntryOffset $firstWkday]
@@ -1084,8 +1096,13 @@ proc FillCalWindow {} {
} else {
set tag "*"
}
set stuff [dict get $obj body]
if {[dict exists $obj calendar_body]} {
set stuff [dict get $obj calendar_body]
} elseif {[dict exists $obj plain_body]} {
set stuff [dict get $obj plain_body]
} else {
set stuff [dict get $obj body]
}
set day [string trimleft $day 0]
set n [expr $day+$offset]
set month [string trimleft $month 0]
@@ -1109,30 +1126,31 @@ proc FillCalWindow {} {
}
"COLOUR" -
"COLOR" {
if {[regexp {^ *([0-9]+) +([0-9]+) +([0-9]+) +(.*)$} $stuff all r g b rest]} {
if {$r > 255} {
set r 255
} elseif {$r < 0} {
set r 0
}
if {$g > 255} {
set g 255
} elseif {$g < 0} {
set g 0
}
if {$b > 255} {
set b 255
} elseif {$b < 0} {
set b 0
}
set color [format "%02X%02X%02X" $r $g $b]
set extratags "clr$color"
.cal.t$n configure -state normal
.cal.t$n tag configure $extratags -foreground "#$color"
.cal.t$n configure -state disabled -takefocus 0
set stuff $rest
set type "COLOR"
}
set r [dict get $obj r]
set g [dict get $obj g]
set b [dict get $obj b]
if {$r > 255} {
set r 255
} elseif {$r < 0} {
set r 0
}
if {$g > 255} {
set g 255
} elseif {$g < 0} {
set g 0
}
if {$b > 255} {
set b 255
} elseif {$b < 0} {
set b 0
}
set color [format "%02X%02X%02X" $r $g $b]
set extratags "clr$color"
.cal.t$n configure -state normal
.cal.t$n tag configure $extratags -foreground "#$color"
.cal.t$n configure -state disabled -takefocus 0
set stuff $stuff
set type "COLOR"
}
}
if { $type != "*" && $type != "COLOR" && $type != "COLOUR"} {
@@ -2099,7 +2117,7 @@ proc CreateReminder {w} {
# Check it out!
global Remind
set f [open "|$Remind -arq -e - 2>&1" r+]
set f [open "|$Remind -arq -e - 2>@1" r+]
puts $f "BANNER %"
puts $f "$rem MSG %"
puts $f "MSG %_%_%_%_"
@@ -3806,13 +3824,19 @@ proc ShowTodaysReminders {} {
append cmdline "-b1 "
}
append cmdline $Option(ExtraRemindArgs);
append cmdline " $ReminderFile 2>/dev/null"
append cmdline " $ReminderFile 2>@1"
set f [open $cmdline r]
while {[gets $f line] >= 0} {
append stuff "$line\n"
}
close $f
$w.text insert end $stuff
if {[catch { close $f } err]} {
$w.text insert end "Error running Remind\n\n"
$w.text insert end $stuff
$w.text insert end "\n"
$w.text insert end $err
} else {
$w.text insert end $stuff
}
$w.text configure -state disabled
}
@@ -3900,7 +3924,7 @@ proc InotifyReadable { fp } {
catch { set num [gets $fp line] }
if {$num < 0} {
catch { exec kill [pid $fp] }
close $fp
catch { close $fp }
return
}
ScheduleUpdateForChanges

View File

@@ -36,7 +36,7 @@ REMINDOBJS= $(REMINDSRCS:.c=.o)
all: remind rem2ps
test: remind
test: all
@sh ../tests/test-rem
.c.o:
@@ -45,12 +45,12 @@ test: remind
$(REMINDOBJS): $(REMINDHDRS)
rem2ps: rem2ps.o dynbuf.o json.o
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
@CC@ @CFLAGS@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
remind: $(REMINDOBJS)
@CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
@CC@ @CFLAGS@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
install-nostripped: all
install: all
-mkdir -p $(DESTDIR)$(bindir) || true
for prog in $(PROGS) $(SCRIPTS) ; do \
$(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir) || exit 1; \
@@ -64,7 +64,7 @@ install-nostripped: all
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
install: install-nostripped
install-stripped: install
strip $(DESTDIR)$(bindir)/remind || true
strip $(DESTDIR)$(bindir)/rem2ps || true

View File

@@ -5,11 +5,12 @@
/* The code for generating a calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#include "config.h"
#include "custom.h"
@@ -147,6 +148,47 @@ static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
}
};
static char *VT100BGColors[2][2][2] /* [R][G][B] */ = {
{
{
/* 0, 0, 0 = Black */ "\x1B[0;40m",
/* 0, 0, 1 = Blue */ "\x1B[0;44m"
},
{
/* 0, 1, 0 = Green */ "\x1B[0;42m",
/* 0, 1, 1 = Cyan */ "\x1B[0;46m"
}
},
{
{
/* 1, 0, 0 = Red */ "\x1B[0;41m",
/* 1, 0, 1 = Magenta */ "\x1B[0;45m"
},
{
/* 1, 1, 0 = Yellow */ "\x1B[0;43m",
/* 1, 1, 1 = White */ "\x1B[0;47m"
}
}
};
/* Moon phase icons in UTF-8 */
static char const *moonphase_emojis[] = {
"\xF0\x9F\x8C\x91",
"\xF0\x9F\x8C\x93",
"\xF0\x9F\x8C\x95",
"\xF0\x9F\x8C\x97"
};
/* Moon phases for each day 1-31, up to 32 chars per moon-phase string
including termination \0 */
static char moons[32][32];
/* Week indicators */
static char weeks[32][32];
/* Background colors of each day 1-31, rgb */
static int bgcolor[32][3];
static struct line_drawing *linestruct;
#define DRAW(x) fputs(linestruct->x, stdout)
@@ -229,13 +271,14 @@ static struct xterm256_colors XTerm256Colors[] =
/* Global variables */
static CalEntry *CalColumn[7];
static int ColToDay[7];
static int ColSpaces;
static int DidAMonth;
static int DidADay;
static void ColorizeEntry(CalEntry const *e);
static void ColorizeEntry(CalEntry const *e, int clamp);
static void SortCol (CalEntry **col);
static void DoCalendarOneWeek (int nleft);
static void DoCalendarOneMonth (void);
@@ -244,21 +287,65 @@ static void WriteWeekHeaderLine (void);
static void WritePostHeaderLine (void);
static void PrintLeft (char const *s, int width, char pad);
static void PrintCentered (char const *s, int width, char *pad);
static int WriteOneCalLine (void);
static int WriteOneCalLine (int dse, int wd);
static int WriteOneColLine (int col);
static void GenerateCalEntries (int col);
static void WriteCalHeader (void);
static void WriteCalTrailer (void);
static int DoCalRem (ParsePtr p, int col);
static void WriteSimpleEntries (int col, int jul);
static void WriteSimpleEntries (int col, int dse);
static void WriteTopCalLine (void);
static void WriteBottomCalLine (void);
static void WriteIntermediateCalLine (void);
static void WriteCalDays (void);
static int
DayOf(int dse)
{
int d;
FromDSE(dse, NULL, NULL, &d);
return d;
}
static void
Backgroundize(int d)
{
if (d < 1 || d > 31) {
return;
}
if (!UseBGVTColors) {
return;
}
if (bgcolor[d][0] < 0) {
return;
}
printf("%s", Colorize(bgcolor[d][0], bgcolor[d][1], bgcolor[d][2], 1, 0));
}
static void
UnBackgroundize(int d)
{
if (d < 1 || d > 31) {
return;
}
if (!UseBGVTColors) {
return;
}
if (bgcolor[d][0] < 0) {
return;
}
printf("%s", Decolorize());
}
static void
send_lrm(void)
{
/* Don't send LRM if SuppressLRM is set */
if (SuppressLRM) {
return;
}
/* Send a lrm control sequence if UseUTF8Chars is enabled
or char encoding is UTF-8
*/
@@ -289,6 +376,19 @@ despace(char const *s)
return buf;
}
void PrintJSONChar(char c) {
switch(c) {
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", c);
}
}
void PrintJSONString(char const *s)
{
while (*s) {
@@ -327,14 +427,14 @@ void PrintJSONKeyPairString(char const *name, char const *val)
printf("\",");
}
void PrintJSONKeyPairDate(char const *name, int jul)
void PrintJSONKeyPairDate(char const *name, int dse)
{
int y, m, d;
if (jul == NO_DATE) {
if (dse == NO_DATE) {
/* Skip it! */
return;
}
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
printf("\"");
PrintJSONString(name);
printf("\":\"%04d-%02d-%02d\",", y, m+1, d);
@@ -349,7 +449,7 @@ void PrintJSONKeyPairDateTime(char const *name, int dt)
return;
}
i = dt / MINUTES_PER_DAY;
FromJulian(i, &y, &m, &d);
FromDSE(i, &y, &m, &d);
k = dt % MINUTES_PER_DAY;
h = k / 60;
i = k % 60;
@@ -375,7 +475,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
}
#ifdef REM_USE_WCHAR
static void PutWideChar(wchar_t const wc)
void PutWideChar(wchar_t const wc)
{
char buf[MB_CUR_MAX+1];
int len;
@@ -493,16 +593,13 @@ ClampColor(int *r, int *g, int *b)
}
char const *
Decolorize(int r, int g, int b)
Decolorize(void)
{
if (!strcmp(Colorize(r, g, b), "")) {
return "";
}
return "\x1B[0m";
}
static char const *
Colorize256(int r, int g, int b)
Colorize256(int r, int g, int b, int bg, int clamp)
{
static char buf[40];
int best = -1;
@@ -511,7 +608,9 @@ Colorize256(int r, int g, int b)
struct xterm256_colors *cur;
size_t i;
ClampColor(&r, &g, &b);
if (clamp) {
ClampColor(&r, &g, &b);
}
for (i=0; i<(sizeof(XTerm256Colors) / sizeof(XTerm256Colors[0])); i++) {
cur = &XTerm256Colors[i];
dist = ((r - cur->r) * (r - cur->r)) +
@@ -523,31 +622,42 @@ Colorize256(int r, int g, int b)
}
}
cur = &XTerm256Colors[best];
sprintf(buf, "\x1B[38;5;%dm", best);
if (bg) {
sprintf(buf, "\x1B[48;5;%dm", best);
} else {
sprintf(buf, "\x1B[38;5;%dm", best);
}
return buf;
}
static char const *
ColorizeTrue(int r, int g, int b)
ColorizeTrue(int r, int g, int b, int bg, int clamp)
{
static char buf[40];
ClampColor(&r, &g, &b);
sprintf(buf, "\x1B[38;2;%d;%d;%dm", r, g, b);
if (clamp) {
ClampColor(&r, &g, &b);
}
if (bg) {
sprintf(buf, "\x1B[48;2;%d;%d;%dm", r, g, b);
} else {
sprintf(buf, "\x1B[38;2;%d;%d;%dm", r, g, b);
}
return buf;
}
char const *
Colorize(int r, int g, int b)
Colorize(int r, int g, int b, int bg, int clamp)
{
int bright = 0;
if (UseTrueColors) {
return ColorizeTrue(r, g, b);
return ColorizeTrue(r, g, b, bg, clamp);
}
if (Use256Colors) {
return Colorize256(r, g, b);
return Colorize256(r, g, b, bg, clamp);
}
if (r > 128 || g > 128 || b > 128) {
bright = 1;
}
@@ -558,43 +668,112 @@ Colorize(int r, int g, int b)
if (b > 64) b = 1;
else b = 0;
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_DARK && !bg) {
/* Convert black-on-black to grey */
if (!r && !g && !b) return VT100Colors[1][0][0][0];
}
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_LIGHT && !bg) {
/* Convert white-on-white to grey */
if (r && g && b) return VT100Colors[1][0][0][0];
}
return VT100Colors[bright][r][g][b];
if (bg) {
return VT100BGColors[r][g][b];
} else {
return VT100Colors[bright][r][g][b];
}
}
static void ColorizeEntry(CalEntry const *e)
static void ColorizeEntry(CalEntry const *e, int clamp)
{
printf("%s", Colorize(e->r, e->g, e->b));
printf("%s", Colorize(e->r, e->g, e->b, 0, clamp));
}
static int
ComputeCalWidth(int x)
static void
InitMoonsAndShades(void)
{
struct winsize w;
if (x >= 71) {
/* Has been set with -w option */
return x;
int i;
/* Initialize the moon array */
if (encoding_is_utf8) {
for (i=0; i<=31; i++) {
moons[i][0] = 0;
}
}
if (!isatty(STDOUT_FILENO)) {
/* Output is not a TTY... assume 80 */
return 80;
/* Clear SHADEs */
if (UseBGVTColors) {
for (i=0; i<=31; i++) {
bgcolor[i][0] = -1;
bgcolor[i][1] = -1;
bgcolor[i][2] = -1;
}
}
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) {
return 80;
/* Clear weeks */
for(i=0; i<=31; i++) {
weeks[i][0] = 0;
}
if (w.ws_col < 71) {
return 71;
}
return w.ws_col;
}
static void
SetShadeEntry(int dse, char const *shade)
{
int y, m, d;
int r, g, b;
/* Don't bother if we're not doing SHADE specials */
if (!UseBGVTColors) {
return;
}
if (sscanf(shade, "%d %d %d", &r, &g, &b) != 3) {
if (sscanf(shade, "%d", &r) != 1) {
return;
}
g = r;
b = r;
}
if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 || b > 255) {
return;
}
FromDSE(dse, &y, &m, &d);
bgcolor[d][0] = r;
bgcolor[d][1] = g;
bgcolor[d][2] = b;
}
static void
SetMoonEntry(int dse, char const *moon)
{
int phase;
int y, m, d;
char msg[28];
/* Don't bother unless it's utf-8 */
if (!encoding_is_utf8) {
return;
}
msg[0] = 0;
if (sscanf(moon, "%d %*d %*d %27[^\x01]", &phase, msg) < 4) {
if (sscanf(moon, "%d", &phase) != 1) {
/* Malformed MOON special; ignore */
fprintf(stderr, "Oops 1\n");
return;
}
}
if (phase < 0 || phase > 3) {
/* Bad phase */
fprintf(stderr, "Oops 2\n");
return;
}
FromDSE(dse, &y, &m, &d);
if (msg[0]) {
snprintf(moons[d], sizeof(moons[d]), "%s %s", moonphase_emojis[phase], msg);
} else {
snprintf(moons[d], sizeof(moons[d]), "%s", moonphase_emojis[phase]);
}
}
/***************************************************************/
/* */
/* ProduceCalendar */
@@ -623,15 +802,13 @@ void ProduceCalendar(void)
}
ShouldCache = 1;
CalWidth = ComputeCalWidth(CalWidth);
ColSpaces = (CalWidth - 9) / 7;
CalWidth = 7*ColSpaces + 8;
/* Run the file once to get potentially-overridden day names */
if (CalMonths) {
FromJulian(JulianToday, &y, &m, &d);
JulianToday = Julian(y, m, 1);
FromDSE(DSEToday, &y, &m, &d);
DSEToday = DSE(y, m, 1);
GenerateCalEntries(-1);
DidAMonth = 0;
if (PsCal == PSCAL_LEVEL3) {
@@ -646,8 +823,8 @@ void ProduceCalendar(void)
}
return;
} else {
if (MondayFirst) JulianToday -= (JulianToday%7);
else JulianToday -= ((JulianToday+1)%7);
if (MondayFirst) DSEToday -= (DSEToday%7);
else DSEToday -= ((DSEToday+1)%7);
GenerateCalEntries(-1);
@@ -675,22 +852,26 @@ static void DoCalendarOneWeek(int nleft)
int y, m, d, done, i, l, wd;
char buf[128];
int LinesWritten = 0;
int OrigJul = JulianToday;
int OrigDse = DSEToday;
InitMoonsAndShades();
/* Fill in the column entries */
for (i=0; i<7; i++) {
ColToDay[i] = DayOf(DSEToday);
GenerateCalEntries(i);
JulianToday++;
DSEToday++;
}
/* Output the entries */
/* Figure out weekday of first column */
if (MondayFirst) wd = DSEToday % 7;
else wd = (DSEToday + 1) % 7;
/* Output the entries */
/* If it's "Simple Calendar" format, do it simply... */
if (DoSimpleCalendar) {
if (MondayFirst) wd = JulianToday % 7;
else wd = (JulianToday + 1) % 7;
for (i=0; i<7; i++) {
WriteSimpleEntries(i, OrigJul+i-wd);
WriteSimpleEntries(i, OrigDse+i-wd);
}
return;
}
@@ -700,13 +881,33 @@ static void DoCalendarOneWeek(int nleft)
DRAW(tb);
goff();
for (i=0; i<7; i++) {
FromJulian(OrigJul+i, &y, &m, &d);
FromDSE(OrigDse+i, &y, &m, &d);
char const *mon = get_month_name(m);
snprintf(buf, sizeof(buf), "%d %s ", d, get_month_abbrev(mon));
if (OrigJul+i == RealToday)
PrintLeft(buf, ColSpaces, '*');
else
if (moons[d][0]) {
if (weeks[d][0]) {
snprintf(buf, sizeof(buf), "%d %s %s %s ", d, get_month_abbrev(mon), weeks[d], moons[d]);
} else {
snprintf(buf, sizeof(buf), "%d %s %s ", d, get_month_abbrev(mon), moons[d]);
}
} else {
if (weeks[d][0]) {
snprintf(buf, sizeof(buf), "%d %s %s ", d, get_month_abbrev(mon), weeks[d]);
} else {
snprintf(buf, sizeof(buf), "%d %s ", d, get_month_abbrev(mon));
}
}
if (OrigDse+i == RealToday) {
if (UseVTColors) {
printf("\x1B[1m"); /* Bold */
}
PrintLeft(buf, ColSpaces-1, '*');
if (UseVTColors) {
printf("\x1B[0m"); /* Normal */
}
putchar(' ');
} else {
PrintLeft(buf, ColSpaces, ' ');
}
gon();
DRAW(tb);
goff();
@@ -717,7 +918,10 @@ static void DoCalendarOneWeek(int nleft)
DRAW(tb);
goff();
for (i=0; i<7; i++) {
d = ColToDay[i];
Backgroundize(d);
PrintLeft("", ColSpaces, ' ');
UnBackgroundize(d);
gon();
DRAW(tb);
goff();
@@ -728,7 +932,7 @@ static void DoCalendarOneWeek(int nleft)
/* Write the body lines */
done = 0;
while (!done) {
done = WriteOneCalLine();
done = WriteOneCalLine(OrigDse, wd);
LinesWritten++;
}
@@ -738,7 +942,10 @@ static void DoCalendarOneWeek(int nleft)
DRAW(tb);
goff();
for (i=0; i<7; i++) {
d = ColToDay[i];
Backgroundize(d);
PrintLeft("", ColSpaces, ' ');
UnBackgroundize(d);
gon();
DRAW(tb);
goff();
@@ -765,12 +972,14 @@ static void DoCalendarOneMonth(void)
{
int y, m, d, mm, yy, i, j;
InitMoonsAndShades();
if (!DoSimpleCalendar) WriteCalHeader();
DidADay = 0;
if (PsCal) {
FromJulian(JulianToday, &y, &m, &d);
FromDSE(DSEToday, &y, &m, &d);
if (PsCal == PSCAL_LEVEL1) {
printf("%s\n", PSBEGIN);
} else if (PsCal == PSCAL_LEVEL2) {
@@ -783,7 +992,7 @@ static void DoCalendarOneMonth(void)
}
if (PsCal < PSCAL_LEVEL3) {
printf("%s %d %d %d %d\n",
despace(get_month_name(m)), y, DaysInMonth(m, y), (JulianToday+1) % 7,
despace(get_month_name(m)), y, DaysInMonth(m, y), (DSEToday+1) % 7,
MondayFirst);
for (i=0; i<7; i++) {
j=(i+6)%7;
@@ -798,7 +1007,7 @@ static void DoCalendarOneMonth(void)
PrintJSONKeyPairString("monthname", get_month_name(m));
PrintJSONKeyPairInt("year", y);
PrintJSONKeyPairInt("daysinmonth", DaysInMonth(m, y));
PrintJSONKeyPairInt("firstwkday", (JulianToday+1) % 7);
PrintJSONKeyPairInt("firstwkday", (DSEToday+1) % 7);
PrintJSONKeyPairInt("mondayfirst", MondayFirst);
printf("\"daynames\":[\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"],",
get_day_name(6), get_day_name(0), get_day_name(1), get_day_name(2),
@@ -856,20 +1065,25 @@ static int WriteCalendarRow(void)
int y, m, d, wd, i, l;
int done;
char buf[81];
int OrigJul = JulianToday;
int OrigDse = DSEToday;
int LinesWritten = 0;
int moreleft;
/* Get the date of the first day */
FromJulian(JulianToday, &y, &m, &d);
if (!MondayFirst) wd = (JulianToday + 1) % 7;
else wd = JulianToday % 7;
FromDSE(DSEToday, &y, &m, &d);
if (!MondayFirst) wd = (DSEToday + 1) % 7;
else wd = DSEToday % 7;
for (i=0; i<7; i++) {
ColToDay[i] = 0;
}
/* Fill in the column entries */
for (i=wd; i<7; i++) {
if (d+i-wd > DaysInMonth(m, y)) break;
GenerateCalEntries(i);
JulianToday++;
ColToDay[i] = DayOf(DSEToday);
DSEToday++;
}
/* Output the entries */
@@ -877,7 +1091,7 @@ static int WriteCalendarRow(void)
/* If it's "Simple Calendar" format, do it simply... */
if (DoSimpleCalendar) {
for (i=wd; i<7 && d+i-wd<=DaysInMonth(m, y); i++) {
WriteSimpleEntries(i, OrigJul+i-wd);
WriteSimpleEntries(i, OrigDse+i-wd);
}
return (d+7-wd <= DaysInMonth(m, y));
}
@@ -891,9 +1105,27 @@ static int WriteCalendarRow(void)
if (i < wd || d+i-wd>DaysInMonth(m, y))
PrintLeft("", ColSpaces, ' ');
else {
sprintf(buf, "%d ", d+i-wd);
if (Julian(y, m, d+i-wd) == RealToday) {
if (moons[d+i-wd][0]) {
if (weeks[d+i-wd][0]) {
snprintf(buf, sizeof(buf), "%d %s %s ", d+i-wd, weeks[d+i-wd], moons[d+i-wd]);
} else {
snprintf(buf, sizeof(buf), "%d %s ", d+i-wd, moons[d+i-wd]);
}
} else {
if (weeks[d+i-wd][0]) {
snprintf(buf, sizeof(buf), "%d %s ", d+i-wd, weeks[d+i-wd]);
} else {
snprintf(buf, sizeof(buf), "%d ", d+i-wd);
}
}
if (DSE(y, m, d+i-wd) == RealToday) {
if (UseVTColors) {
printf("\x1B[1m"); /* Bold */
}
PrintLeft(buf, ColSpaces-1, '*');
if (UseVTColors) {
printf("\x1B[0m"); /* Normal */
}
putchar(' ');
} else {
PrintLeft(buf, ColSpaces, ' ');
@@ -909,7 +1141,9 @@ static int WriteCalendarRow(void)
DRAW(tb);
goff();
for (i=0; i<7; i++) {
Backgroundize(ColToDay[i]);
PrintLeft("", ColSpaces, ' ');
UnBackgroundize(ColToDay[i]);
gon();
DRAW(tb);
goff();
@@ -920,7 +1154,7 @@ static int WriteCalendarRow(void)
/* Write the body lines */
done = 0;
while (!done) {
done = WriteOneCalLine();
done = WriteOneCalLine(OrigDse, wd);
LinesWritten++;
}
@@ -930,7 +1164,9 @@ static int WriteCalendarRow(void)
DRAW(tb);
goff();
for (i=0; i<7; i++) {
Backgroundize(ColToDay[i]);
PrintLeft("", ColSpaces, ' ');
UnBackgroundize(ColToDay[i]);
gon();
DRAW(tb);
goff();
@@ -1101,19 +1337,25 @@ static void PrintCentered(char const *s, int width, char *pad)
/* Write a single line. */
/* */
/***************************************************************/
static int WriteOneCalLine(void)
static int WriteOneCalLine(int start_dse, int wd)
{
int done = 1, i;
int y, m, d;
gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) {
FromDSE(start_dse+i, &y, &m, &d);
d -= wd;
if (CalColumn[i]) {
Backgroundize(ColToDay[i]);
if (WriteOneColLine(i)) done = 0;
} else {
Backgroundize(ColToDay[i]);
PrintCentered("", ColSpaces, " ");
}
UnBackgroundize(ColToDay[i]);
gon();
DRAW(tb);
goff();
@@ -1142,9 +1384,12 @@ static int WriteOneColLine(int col)
wchar_t const *wspace;
int width;
#endif
int clamp = 1;
int numwritten = 0;
int d = ColToDay[col];
if (d && UseBGVTColors && bgcolor[d][0] != -1) {
clamp = 0;
}
/* Print as many characters as possible within the column */
#ifdef REM_USE_WCHAR
if (e->wc_text) {
@@ -1187,7 +1432,7 @@ static int WriteOneColLine(int col)
/* Colorize reminder if necessary */
if (UseVTColors && e->is_color) {
ColorizeEntry(e);
ColorizeEntry(e, clamp);
}
/* If we couldn't find a space char, print what we have. */
@@ -1224,9 +1469,10 @@ static int WriteOneColLine(int col)
}
}
/* Decolorize reminder if necessary */
/* Decolorize reminder if necessary, but keep any SHADE */
if (UseVTColors && e->is_color) {
printf("%s", Decolorize(e->r, e->g, e->b));
printf("%s", Decolorize());
Backgroundize(d);
}
/* Possibly send lrm control sequence */
@@ -1279,7 +1525,7 @@ static int WriteOneColLine(int col)
/* Colorize reminder if necessary */
if (UseVTColors && e->is_color) {
ColorizeEntry(e);
ColorizeEntry(e, clamp);
}
/* If we couldn't find a space char, print what we have. */
@@ -1307,9 +1553,10 @@ static int WriteOneColLine(int col)
}
}
/* Decolorize reminder if necessary */
/* Decolorize reminder if necessary, but keep SHADE */
if (UseVTColors && e->is_color) {
printf("%s", Decolorize(e->r, e->g, e->b));
printf("%s", Decolorize());
Backgroundize(d);
}
/* Flesh out the rest of the column */
@@ -1403,6 +1650,7 @@ static void GenerateCalEntries(int col)
case T_Exit: DoExit(&p); break;
case T_Set: r=DoSet(&p); break;
case T_Fset: r=DoFset(&p); break;
case T_Funset: r=DoFunset(&p); break;
case T_UnSet: r=DoUnset(&p); break;
case T_Clr: r=DoClear(&p); break;
case T_Flush: r=DoFlush(&p); break;
@@ -1455,7 +1703,7 @@ static void WriteCalHeader(void)
char buf[80];
int y, m, d;
FromJulian(JulianToday, &y, &m, &d);
FromDSE(DSEToday, &y, &m, &d);
sprintf(buf, "%s %d", get_month_name(m), y);
WriteTopCalLine();
@@ -1498,7 +1746,7 @@ static int DoCalRem(ParsePtr p, int col)
TimeTrig tim;
Value v;
int r, err;
int jul;
int dse;
CalEntry *CurCol;
CalEntry *e;
char const *s, *s2;
@@ -1583,14 +1831,27 @@ static int DoCalRem(ParsePtr p, int col)
DBufFree(&buf);
}
trig.typ = tok.val;
jul = LastTriggerDate;
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;
}
}
dse = LastTriggerDate;
if (!LastTrigValid) {
FreeTrig(&trig);
return OK;
}
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
@@ -1602,7 +1863,7 @@ static int DoCalRem(ParsePtr p, int col)
/* Add to global OMITs if so indicated */
if (trig.addomit) {
r = AddGlobalOmit(jul);
r = AddGlobalOmit(dse);
if (r) {
FreeTrig(&trig);
return r;
@@ -1646,10 +1907,49 @@ static int DoCalRem(ParsePtr p, int col)
}
}
if (trig.typ == PASSTHRU_TYPE) {
if (!PsCal && StrCmpi(trig.passthru, "COLOR") && StrCmpi(trig.passthru, "COLOUR")) {
if (!PsCal && !StrCmpi(trig.passthru, "SHADE")) {
if (dse == DSEToday) {
DBufInit(&obuf);
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
if (r) {
DBufFree(&obuf);
FreeTrig(&trig);
return r;
}
SetShadeEntry(dse, DBufValue(&obuf));
DBufFree(&obuf);
}
}
if (!PsCal && !StrCmpi(trig.passthru, "WEEK")) {
if (dse == DSEToday) {
DBufInit(&obuf);
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
if (r) {
DBufFree(&obuf);
FreeTrig(&trig);
return r;
}
sscanf(DBufValue(&obuf), "%31[^\x01]", weeks[DayOf(dse)]);
DBufFree(&obuf);
}
}
if (!PsCal && StrCmpi(trig.passthru, "COLOR") && StrCmpi(trig.passthru, "COLOUR") && StrCmpi(trig.passthru, "MOON")) {
FreeTrig(&trig);
return OK;
}
if (!PsCal && !StrCmpi(trig.passthru, "MOON")) {
if (dse == DSEToday) {
DBufInit(&obuf);
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
if (r) {
DBufFree(&obuf);
FreeTrig(&trig);
return r;
}
SetMoonEntry(dse, DBufValue(&obuf));
DBufFree(&obuf);
}
}
if (!StrCmpi(trig.passthru, "COLOR") ||
!StrCmpi(trig.passthru, "COLOUR")) {
is_color = 1;
@@ -1695,9 +1995,9 @@ static int DoCalRem(ParsePtr p, int col)
/* If trigger date == today, add it to the current entry */
DBufInit(&obuf);
if ((jul == JulianToday) ||
if ((dse == DSEToday) ||
(DoSimpleCalDelta &&
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
ShouldTriggerReminder(&trig, &tim, dse, &err))) {
NumTriggered++;
/* The parse_ptr should not be nested, but just in case... */
@@ -1711,7 +2011,7 @@ static int DoCalRem(ParsePtr p, int col)
}
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
/* Suppress time if it's not today or if it's a non-COLOR special */
if (jul != JulianToday ||
if (dse != DSEToday ||
(trig.typ == PASSTHRU_TYPE &&
StrCmpi(trig.passthru, "COLOUR") &&
StrCmpi(trig.passthru, "COLOR"))) {
@@ -1756,10 +2056,10 @@ static int DoCalRem(ParsePtr p, int col)
/* In -sa mode, run in ADVANCE mode if we're triggering
* before the actual date */
if (jul != JulianToday) {
r = DoSubst(p, &obuf, &trig, &tim, jul, ADVANCE_MODE);
if (dse != DSEToday) {
r = DoSubst(p, &obuf, &trig, &tim, dse, ADVANCE_MODE);
} else {
r = DoSubst(p, &obuf, &trig, &tim, jul, CAL_MODE);
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
}
if (r) {
DBufFree(&pre_buf);
@@ -1860,7 +2160,7 @@ static int DoCalRem(ParsePtr p, int col)
e->passthru[0] = 0;
}
e->pos = e->text;
if (jul == JulianToday) {
if (dse == DSEToday) {
e->time = tim.ttime;
} else {
e->time = NO_TIME;
@@ -1908,6 +2208,7 @@ static void WriteSimpleEntryProtocol1(CalEntry *e)
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
{
int done = 0;
char const *s;
if (DoPrefixLineNo) {
PrintJSONKeyPairString("filename", e->filename);
PrintJSONKeyPairInt("lineno", e->lineno);
@@ -2034,6 +2335,45 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
if (strcmp(e->raw_text, e->text)) {
PrintJSONKeyPairString("rawbody", e->raw_text);
}
/* Figure out calendar_body and plain_body */
if (DontSuppressQuoteMarkers) {
s = strstr(e->text, "%\"");
if (s) {
s += 2;
printf("\"calendar_body\":\"");
while (*s) {
if (*s == '%' && *(s+1) == '"') {
break;
}
PrintJSONChar(*s);
s++;
}
printf("\",");
}
}
s = strstr(e->text, "%\"");
if (s || e->is_color) {
printf("\"plain_body\":\"");
s = e->text;
if (e->is_color) {
while(*s && !isspace(*s)) s++;
while(*s && isspace(*s)) s++;
while(*s && !isspace(*s)) s++;
while(*s && isspace(*s)) s++;
while(*s && !isspace(*s)) s++;
while(*s && isspace(*s)) s++;
}
while(*s) {
if (*s == '%' && *(s+1) == '"') {
s += 2;
continue;
}
PrintJSONChar(*s);
s++;
}
printf("\",");
}
printf("\"body\":\"");
PrintJSONString(e->text);
printf("\"");
@@ -2046,13 +2386,13 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
/* Write entries in 'simple calendar' format. */
/* */
/***************************************************************/
static void WriteSimpleEntries(int col, int jul)
static void WriteSimpleEntries(int col, int dse)
{
CalEntry *e = CalColumn[col];
CalEntry *n;
int y, m, d;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
while(e) {
if (DoPrefixLineNo) {
if (PsCal != PSCAL_LEVEL2 && PsCal != PSCAL_LEVEL3) {
@@ -2067,7 +2407,7 @@ static void WriteSimpleEntries(int col, int jul)
}
DidADay = 1;
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
WriteSimpleEntryProtocol2(e, jul);
WriteSimpleEntryProtocol2(e, dse);
printf("}");
if (PsCal != PSCAL_LEVEL3) {
printf("\n");

View File

@@ -6,7 +6,8 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -6,7 +6,8 @@
/* which you can customize. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -7,7 +7,8 @@
/* commands. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -29,7 +30,7 @@ static int ParseLocalOmit (ParsePtr s, Trigger *t);
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
static int ParsePriority (ParsePtr s, Trigger *t);
static int ParseUntil (ParsePtr s, Trigger *t, int type);
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
static int ComputeTrigDuration(TimeTrig *t);
static int
@@ -55,7 +56,7 @@ int DoRem(ParsePtr p)
Trigger trig;
TimeTrig tim;
int r, err;
int jul;
int dse;
DynamicBuffer buf;
Token tok;
@@ -96,9 +97,13 @@ int DoRem(ParsePtr p)
FindToken(DBufValue(&buf), &tok);
DBufFree(&buf);
if (tok.type == T_Empty || tok.type == T_Comment) {
r = OK;
if (trig.addomit) {
r = AddGlobalOmit(LastTriggerDate);
}
DBufFree(&buf);
FreeTrig(&trig);
return OK;
return r;
}
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
DBufFree(&buf);
@@ -120,14 +125,14 @@ int DoRem(ParsePtr p)
DBufFree(&buf);
}
trig.typ = tok.val;
jul = LastTriggerDate;
dse = LastTriggerDate;
if (!LastTrigValid || PurgeMode) {
FreeTrig(&trig);
return OK;
}
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
if (PurgeMode) {
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
@@ -143,14 +148,14 @@ int DoRem(ParsePtr p)
/* Add to global OMITs if so indicated */
if (trig.addomit) {
r = AddGlobalOmit(jul);
r = AddGlobalOmit(dse);
if (r) {
FreeTrig(&trig);
return r;
}
}
if (PurgeMode) {
if (trig.expired || jul < JulianToday) {
if (trig.expired || dse < DSEToday) {
if (p->expr_happened) {
if (p->nonconst_expr) {
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
@@ -170,10 +175,10 @@ int DoRem(ParsePtr p)
}
/* Queue the reminder, if necessary */
if (jul == JulianToday &&
if (dse == DSEToday &&
!(!IgnoreOnce &&
trig.once != NO_ONCE &&
FileAccessDate == JulianToday))
FileAccessDate == DSEToday))
QueueReminder(p, &trig, &tim, trig.sched);
/* If we're in daemon mode, do nothing over here */
if (Daemon) {
@@ -182,8 +187,8 @@ int DoRem(ParsePtr p)
}
r = OK;
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
if ( (r=TriggerReminder(p, &trig, &tim, dse)) ) {
FreeTrig(&trig);
return r;
}
@@ -230,6 +235,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->skip = NO_SKIP;
trig->once = NO_ONCE;
trig->addomit = 0;
trig->noqueue = 0;
trig->typ = NO_TYPE;
trig->scanfrom = NO_DATE;
trig->from = NO_DATE;
@@ -287,7 +293,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
if (trig->d != NO_DAY) return E_DAY_TWICE;
if (trig->m != NO_MON) return E_MON_TWICE;
if (trig->y != NO_YR) return E_YR_TWICE;
FromJulian(tok.val, &y, &m, &d);
FromDSE(tok.val, &y, &m, &d);
trig->y = y;
trig->m = m;
trig->d = d;
@@ -298,7 +304,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
if (trig->d != NO_DAY) return E_DAY_TWICE;
if (trig->m != NO_MON) return E_MON_TWICE;
if (trig->y != NO_YR) return E_YR_TWICE;
FromJulian(tok.val / MINUTES_PER_DAY, &y, &m, &d);
FromDSE(tok.val / MINUTES_PER_DAY, &y, &m, &d);
trig->y = y;
trig->m = m;
trig->d = d;
@@ -431,6 +437,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->addomit = 1;
break;
case T_NoQueue:
DBufFree(&buf);
trig->noqueue = 1;
break;
case T_Omit:
DBufFree(&buf);
if (trig->omitfunc[0]) {
@@ -470,7 +481,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
case T_Tag:
r = ParseToken(s, &buf);
if (r) return r;
if (strchr(DBufValue(&buf), ',')) {
DBufFree(&buf);
return E_PARSE_ERR;
}
AppendTag(&(trig->tags), DBufValue(&buf));
DBufFree(&buf);
break;
case T_Duration:
@@ -543,7 +559,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
/* Check for some warning conditions */
if (!s->nonconst_expr) {
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
if (Julian(trig->y, trig->m, trig->d) > trig->until) {
if (DSE(trig->y, trig->m, trig->d) > trig->until) {
Wprint("Warning: UNTIL/THROUGH date earlier than start date");
}
}
@@ -564,7 +580,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
/* Set scanfrom to default if not set explicitly */
if (trig->scanfrom == NO_DATE) {
trig->scanfrom = JulianToday;
trig->scanfrom = DSEToday;
}
return OK;
@@ -723,7 +739,7 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
Eprint("%s: %s", which, ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE;
}
FromJulian(tok.val, &y, &m, &d);
FromDSE(tok.val, &y, &m, &d);
break;
default:
@@ -736,7 +752,7 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
DBufFree(&buf);
return E_BAD_DATE;
}
t->until = Julian(y, m, d);
t->until = DSE(y, m, d);
PushToken(DBufValue(&buf), s);
DBufFree(&buf);
return OK;
@@ -815,7 +831,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE;
}
FromJulian(tok.val, &y, &m, &d);
FromDSE(tok.val, &y, &m, &d);
break;
case T_Back:
@@ -839,7 +855,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
if (tok.val < 0) {
tok.val = -tok.val;
}
FromJulian(JulianToday - tok.val, &y, &m, &d);
FromDSE(DSEToday - tok.val, &y, &m, &d);
break;
default:
@@ -852,11 +868,11 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
DBufFree(&buf);
return E_BAD_DATE;
}
t->scanfrom = Julian(y, m, d);
t->scanfrom = DSE(y, m, d);
if (type == FROM_TYPE) {
t->from = t->scanfrom;
if (t->scanfrom < JulianToday) {
t->scanfrom = JulianToday;
if (t->scanfrom < DSEToday) {
t->scanfrom = DSEToday;
}
} else {
t->from = NO_DATE;
@@ -868,6 +884,8 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
}
}
}
/***************************************************************/
/* */
/* TriggerReminder */
@@ -875,7 +893,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
/* Trigger the reminder if it's a RUN or MSG type. */
/* */
/***************************************************************/
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse)
{
int r, y, m, d;
char PrioExpr[VAR_NAME_LEN+25];
@@ -929,25 +947,26 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
}
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
&& !NumTriggered && !NextMode && !MsgCommand) {
&& !DidMsgReminder && !NextMode && !MsgCommand) {
DidMsgReminder = 1;
if (!DoSubstFromString(DBufValue(&Banner), &buf,
JulianToday, NO_TIME) &&
DSEToday, NO_TIME) &&
DBufLen(&buf)) {
printf("%s\n", DBufValue(&buf));
}
printf("%s\n", DBufValue(&buf));
}
DBufFree(&buf);
}
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
simple-calendar format. */
if (NextMode) {
if ( (r=DoSubst(p, &buf, t, tim, jul, ADVANCE_MODE)) ) return r;
if ( (r=DoSubst(p, &buf, t, tim, dse, ADVANCE_MODE)) ) return r;
if (!DBufLen(&buf)) {
DBufFree(&buf);
DBufFree(&pre_buf);
return OK;
}
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
sprintf(tmpBuf, "%04d/%02d/%02d ", y, m+1, d);
if (DBufPuts(&calRow, tmpBuf) != OK) {
DBufFree(&calRow);
@@ -1030,7 +1049,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
}
if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf);
@@ -1044,9 +1063,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
}
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
}
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
if ( (r=DoSubst(p, &buf, t, tim, dse, NORMAL_MODE)) ) return r;
if (t->typ != RUN_TYPE) {
if (UserFuncExists("msgsuffix") == 1) {
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
@@ -1055,7 +1074,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
if (is_color) {
DBufPuts(&buf, Colorize(red, green, blue));
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
}
if (DBufPuts(&buf, v.v.str) != OK) {
DBufFree(&buf);
@@ -1069,7 +1088,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
}
if (is_color) {
DBufPuts(&buf, Decolorize(red, green, blue));
DBufPuts(&buf, Decolorize());
}
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
@@ -1081,7 +1100,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
/* If we are sorting, just queue it up in the sort buffer */
if (SortByDate) {
if (InsertIntoSortBuffer(jul, tim->ttime, DBufValue(&buf),
if (InsertIntoSortBuffer(dse, tim->ttime, DBufValue(&buf),
t->typ, t->priority) == OK) {
DBufFree(&buf);
NumTriggered++;
@@ -1128,20 +1147,20 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
/* triggered. Sets *err non-zero in event of an error. */
/* */
/***************************************************************/
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
{
int r, omit;
*err = 0;
/* Handle the ONCE modifier in the reminder. */
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == DSEToday)
return 0;
if (jul < JulianToday) return 0;
if (dse < DSEToday) return 0;
/* Don't trigger timed reminders if DontIssueAts is true, and if the
reminder is for today */
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) {
if (dse == DSEToday && DontIssueAts && tim->ttime != NO_TIME) {
if (DontIssueAts > 1) {
/* If two or more -a options, then *DO* issue ats that are in the
future */
@@ -1155,7 +1174,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
/* Don't trigger "old" timed reminders */
/*** REMOVED...
if (jul == JulianToday &&
if (dse == DSEToday &&
tim->ttime != NO_TIME &&
tim->ttime < SystemTime(0) / 60) return 0;
*** ...UNTIL HERE */
@@ -1166,28 +1185,28 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
/* If there's a "warn" function, it overrides any deltas */
if (t->warn[0] != 0) {
if (DeltaOffset) {
if (jul <= JulianToday + DeltaOffset) {
if (dse <= DSEToday + DeltaOffset) {
return 1;
}
}
return ShouldTriggerBasedOnWarn(t, jul, err);
return ShouldTriggerBasedOnWarn(t, dse, err);
}
/* Move back by delta days, if any */
if (t->delta != NO_DELTA) {
if (t->delta < 0)
jul = jul + t->delta;
dse = dse + t->delta;
else {
int iter = 0;
int max = MaxSatIter;
r = t->delta;
if (max < r*2) max = r*2;
while(iter++ < max) {
if (!r || (jul <= JulianToday)) {
if (!r || (dse <= DSEToday)) {
break;
}
jul--;
*err = IsOmitted(jul, t->localomit, t->omitfunc, &omit);
dse--;
*err = IsOmitted(dse, t->localomit, t->omitfunc, &omit);
if (*err) return 0;
if (!omit) r--;
}
@@ -1200,7 +1219,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
}
/* Should we trigger the reminder? */
return (jul <= JulianToday + DeltaOffset);
return (dse <= DSEToday + DeltaOffset);
}
/***************************************************************/
@@ -1212,7 +1231,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
/***************************************************************/
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
{
int iter, jul, r, start;
int iter, dse, r, start;
Value v;
char const *s;
char const *t;
@@ -1221,25 +1240,25 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
iter = 0;
start = trig->scanfrom;
while (iter++ < MaxSatIter) {
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
if (jul != start && trig->duration_days) {
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
if (dse != start && trig->duration_days) {
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
} else if (jul == start) {
} else if (dse == start) {
if (tt->ttime != NO_TIME) {
trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
if (tt->duration != NO_TIME) {
trig->eventduration = tt->duration;
}
}
SaveAllTriggerInfo(trig, tt, jul, tt->ttime, 1);
SaveAllTriggerInfo(trig, tt, dse, tt->ttime, 1);
}
if (jul == -1) {
if (dse == -1) {
return E_EXPIRED;
}
s = p->pos;
@@ -1249,10 +1268,10 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
if ((v.type == INT_TYPE && v.v.val) ||
(v.type == STR_TYPE && *v.v.str)) {
AdjustTriggerForDuration(trig->scanfrom, jul, trig, tt, 1);
AdjustTriggerForDuration(trig->scanfrom, dse, trig, tt, 1);
if (DebugFlag & DB_PRTTRIG) {
int y, m, d;
FromJulian(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
FileName, LineNo,
get_day_name(LastTriggerDate % 7),
@@ -1274,10 +1293,10 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
return OK;
}
p->pos = s;
if (jul+trig->duration_days < start) {
if (dse+trig->duration_days < start) {
start++;
} else {
start = jul+trig->duration_days+1;
start = dse+trig->duration_days+1;
}
}
p->pos = t;
@@ -1384,7 +1403,7 @@ finished:
/* function. */
/* */
/***************************************************************/
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
static int ShouldTriggerBasedOnWarn(Trigger *t, int dse, int *err)
{
char buffer[VAR_NAME_LEN+32];
int i;
@@ -1396,7 +1415,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
/* If no proper function exists, barf... */
if (UserFuncExists(t->warn) != 1) {
Eprint("%s: `%s'", ErrMsg[M_BAD_WARN_FUNC], t->warn);
return (jul == JulianToday);
return (dse == DSEToday);
}
for (i=1; ; i++) {
sprintf(buffer, "%s(%d)", t->warn, i);
@@ -1405,28 +1424,28 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
if (r) {
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
t->warn, ErrMsg[r]);
return (jul == JulianToday);
return (dse == DSEToday);
}
if (v.type != INT_TYPE) {
DestroyValue(v);
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
t->warn, ErrMsg[E_BAD_TYPE]);
return (jul == JulianToday);
return (dse == DSEToday);
}
/* If absolute value of return is not monotonically
decreasing, exit */
if (i > 1 && abs(v.v.val) >= lastReturnVal) {
return (jul == JulianToday);
return (dse == DSEToday);
}
lastReturnVal = abs(v.v.val);
/* Positive values: Just subtract. Negative values:
skip omitted days. */
if (v.v.val >= 0) {
if (JulianToday + v.v.val == jul) return 1;
if (DSEToday + v.v.val == dse) return 1;
} else {
int j = jul;
int j = dse;
int iter = 0;
int max = MaxSatIter;
if (max < v.v.val * 2) max = v.v.val*2;
@@ -1443,7 +1462,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
return 0;
}
if (j == JulianToday) return 1;
if (j == DSEToday) return 1;
}
}
}

View File

@@ -6,7 +6,8 @@
/* reminders are triggered. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -42,15 +43,16 @@
/* If mode==ADVANCE_MODE, ignore %" but don't add newline */
/* */
/***************************************************************/
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode)
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
{
int diff = jul - JulianToday;
int diff = dse - DSEToday;
int curtime = SystemTime(0) / 60;
int err, done;
int c;
int d, m, y;
int tim = tt->ttime;
int h, min, hh, ch, cmin, chh;
int i;
char const *pm, *cpm;
int tdiff, adiff, mdiff, hdiff;
char const *mplu, *hplu, *when, *plu;
@@ -68,7 +70,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
int r;
Value v;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
if (tim == NO_TIME) tim = curtime;
tdiff = tim - curtime;
@@ -190,8 +192,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
}
if (c == '\n') continue;
if (!c) {
if (mode != CAL_MODE && mode != ADVANCE_MODE &&
t->typ != RUN_TYPE && !MsgCommand) {
if (AddBlankLines &&
mode != CAL_MODE &&
mode != ADVANCE_MODE &&
t->typ != RUN_TYPE &&
!MsgCommand) {
if (DBufPutc(dbuf, '\n') != OK) return E_NO_MEM;
}
break;
@@ -221,11 +226,32 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
break;
}
}
done = 0;
snprintf(uf, sizeof(uf), "subst_%c", c);
if (UserFuncExists(uf) == 3) {
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
c, altmode ? 1 : 0, y, m+1, d, h, min);
if (c == '{') {
i = 0;
ss = s + snprintf(s, sizeof(s), "subst_");
while (1) {
c = ParseChar(p, &err, 0);
if (err) {
DBufFree(dbuf);
return err;
}
if (c == '}' || !c) {
break;
}
if (i < 64) {
*ss++ = c;
*ss = 0;
i++;
}
}
if (!c) {
Wprint("Warning: Unterminated %%{...} substitution sequence");
}
if (UserFuncExists(s) != 3) {
continue;
}
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
altmode ? 1 : 0, y, m+1, d, h, min);
expr = (char const *) s;
r = EvalExpr(&expr, &v, NULL);
if (r == OK) {
@@ -236,7 +262,28 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
}
}
DestroyValue(v);
continue;
}
continue;
}
done = 0;
snprintf(uf, sizeof(uf), "subst_%c", c);
if (UserFuncExists(uf) == 3) {
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
c, altmode ? 1 : 0, y, m+1, d, h, min);
expr = (char const *) s;
r = EvalExpr(&expr, &v, NULL);
if (r == OK) {
if (v.type != INT_TYPE || v.v.val != 0) {
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(dbuf, v.v.str) != OK) {
DestroyValue(v);
return E_NO_MEM;
}
}
DestroyValue(v);
continue;
}
DestroyValue(v);
} else {
Eprint("%s", ErrMsg[r]);
}
@@ -301,14 +348,17 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
expr = (char const *) s;
r = EvalExpr(&expr, &v, NULL);
if (r == OK) {
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(dbuf, v.v.str) != OK) {
DestroyValue(v);
return E_NO_MEM;
if (v.type != INT_TYPE || v.v.val != 0) {
if (!DoCoerce(STR_TYPE, &v)) {
if (DBufPuts(dbuf, v.v.str) != OK) {
DestroyValue(v);
return E_NO_MEM;
}
}
DestroyValue(v);
continue;
}
DestroyValue(v);
continue;
} else {
Eprint("%s", ErrMsg[r]);
}
@@ -321,10 +371,10 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_A_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %d %s, %d", get_day_name(jul%7), d,
snprintf(s, sizeof(s), "%s, %d %s, %d", get_day_name(dse%7), d,
get_month_name(m), y);
} else {
snprintf(s, sizeof(s), "%s %s, %d %s, %d", DynamicOn, get_day_name(jul%7), d,
snprintf(s, sizeof(s), "%s %s, %d %s, %d", DynamicOn, get_day_name(dse%7), d,
get_month_name(m), y);
}
#endif
@@ -345,9 +395,9 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_C_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s", get_day_name(jul%7));
snprintf(s, sizeof(s), "%s", get_day_name(dse%7));
} else {
snprintf(s, sizeof(s), "%s %s", DynamicOn, get_day_name(jul%7));
snprintf(s, sizeof(s), "%s %s", DynamicOn, get_day_name(dse%7));
}
#endif
SHIP_OUT(s);
@@ -395,9 +445,9 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_G_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %d %s", get_day_name(jul%7), d, get_month_name(m));
snprintf(s, sizeof(s), "%s, %d %s", get_day_name(dse%7), d, get_month_name(m));
} else {
snprintf(s, sizeof(s), "%s %s, %d %s", DynamicOn, get_day_name(jul%7), d, get_month_name(m));
snprintf(s, sizeof(s), "%s %s, %d %s", DynamicOn, get_day_name(dse%7), d, get_month_name(m));
}
#endif
SHIP_OUT(s);
@@ -434,10 +484,10 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_J_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %s %d%s, %d", get_day_name(jul%7),
snprintf(s, sizeof(s), "%s, %s %d%s, %d", get_day_name(dse%7),
get_month_name(m), d, plu, y);
} else {
snprintf(s, sizeof(s), "%s %s, %s %d%s, %d", DynamicOn, get_day_name(jul%7),
snprintf(s, sizeof(s), "%s %s, %s %d%s, %d", DynamicOn, get_day_name(dse%7),
get_month_name(m), d, plu, y);
}
#endif
@@ -449,10 +499,10 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_K_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %s %d%s", get_day_name(jul%7),
snprintf(s, sizeof(s), "%s, %s %d%s", get_day_name(dse%7),
get_month_name(m), d, plu);
} else {
snprintf(s, sizeof(s), "%s %s, %s %d%s", DynamicOn, get_day_name(jul%7),
snprintf(s, sizeof(s), "%s %s, %s %d%s", DynamicOn, get_day_name(dse%7),
get_month_name(m), d, plu);
}
#endif
@@ -494,7 +544,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
#ifdef L_O_OVER
L_O_OVER
#else
if (RealToday == JulianToday) snprintf(s, sizeof(s), " (%s)", DynamicToday);
if (RealToday == DSEToday) snprintf(s, sizeof(s), " (%s)", DynamicToday);
else *s = 0;
#endif
SHIP_OUT(s);
@@ -550,10 +600,10 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_U_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %d%s %s, %d", get_day_name(jul%7), d,
snprintf(s, sizeof(s), "%s, %d%s %s, %d", get_day_name(dse%7), d,
plu, get_month_name(m), y);
} else {
snprintf(s, sizeof(s), "%s %s, %d%s %s, %d", DynamicOn, get_day_name(jul%7), d,
snprintf(s, sizeof(s), "%s %s, %d%s %s, %d", DynamicOn, get_day_name(dse%7), d,
plu, get_month_name(m), y);
}
#endif
@@ -565,10 +615,10 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
L_V_OVER
#else
if (altmode == '*' || !strcmp(DynamicOn, "")) {
snprintf(s, sizeof(s), "%s, %d%s %s", get_day_name(jul%7), d, plu,
snprintf(s, sizeof(s), "%s, %d%s %s", get_day_name(dse%7), d, plu,
get_month_name(m));
} else {
snprintf(s, sizeof(s), "%s %s, %d%s %s", DynamicOn, get_day_name(jul%7), d, plu,
snprintf(s, sizeof(s), "%s %s, %d%s %s", DynamicOn, get_day_name(dse%7), d, plu,
get_month_name(m));
}
#endif
@@ -579,7 +629,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
#ifdef L_W_OVER
L_W_OVER
#else
snprintf(s, sizeof(s), "%s", get_day_name(jul%7));
snprintf(s, sizeof(s), "%s", get_day_name(dse%7));
#endif
SHIP_OUT(s);
break;
@@ -836,21 +886,21 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
/* */
/***************************************************************/
int DoSubstFromString(char const *source, DynamicBuffer *dbuf,
int jul, int tim)
int dse, int tim)
{
Trigger tempTrig;
TimeTrig tempTime;
Parser tempP;
int r;
if (jul == NO_DATE) jul=JulianToday;
if (dse == NO_DATE) dse=DSEToday;
if (tim == NO_TIME) tim=SystemTime(0)/60;
CreateParser(source, &tempP);
tempP.allownested = 0;
tempTrig.typ = MSG_TYPE;
tempTime.ttime = tim;
r = DoSubst(&tempP, dbuf, &tempTrig, &tempTime, jul, NORMAL_MODE);
r = DoSubst(&tempP, dbuf, &tempTrig, &tempTime, dse, NORMAL_MODE);
DestroyParser(&tempP);
return r;
}

View File

@@ -6,7 +6,8 @@
/* buffers. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -5,7 +5,8 @@
/* Declaration of functions for manipulating dynamic buffers */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -31,6 +32,8 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp);
#define DBufValue(bufPtr) ((bufPtr)->buffer)
#define DBufLen(bufPtr) ((bufPtr)->len)
#define DBufPutc(dbuf, c) ( (dbuf)->allocatedLen < (dbuf)->len+1 ) ? (dbuf)->buffer[(dbuf)->len++] = c, (dbuf)->buffer[(dbuf)->len] = 0, OK : DBufPutcFN((dbuf), c)
#define DBufPutc(dbuf, c) ( ( (dbuf)->allocatedLen <= (dbuf)->len+1 ) ? \
DBufPutcFN( (dbuf), c) : \
( (dbuf)->buffer[(dbuf)->len++] = c, (dbuf)->buffer[(dbuf)->len] = 0, OK) )
#endif /* DYNBUF_H */

View File

@@ -5,7 +5,8 @@
/* Error definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -70,7 +71,7 @@
#define E_MON_TWICE 51
#define E_DAY_TWICE 52
#define E_UNKNOWN_TOKEN 53
#define E_SPEC_MON_DAY 54
#define E_SPEC_MON 54
#define E_2MANY_PART 55
#define E_2MANY_FULL 56
#define E_PUSH_NOPOP 57
@@ -187,7 +188,7 @@ EXTERN char *ErrMsg[]
"Month specified twice",
"Day specified twice",
"Unknown token",
"Must specify month and day in OMIT command",
"Must specify month in OMIT command",
"Too many partial OMITs",
"Too many full OMITs",
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",

View File

@@ -5,7 +5,8 @@
/* This file contains routines to parse and evaluate */
/* expressions. */
/* */
/* Copyright 1992-2022 by Dianne Skoll */
/* Copyright 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -84,10 +85,12 @@ Operator UnOp[] = {
extern BuiltinFunc Func[];
Operator OpStack[OP_STACK_SIZE];
Value ValStack[VAL_STACK_SIZE];
int OpStackPtr = 0;
int ValStackPtr = 0;
static Operator OpStack[OP_STACK_SIZE];
static int OpStackPtr = 0;
/* ValStack can't be static - needed by funcs.c */
Value ValStack[VAL_STACK_SIZE];
int ValStackPtr = 0;
/***************************************************************/
/* */
@@ -251,6 +254,10 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
DBufFree(buf);
return E_NO_MEM;
}
if (!**in) {
DBufFree(buf);
return E_MISS_QUOTE;
}
continue;
}
c = *(*in)++;
@@ -656,13 +663,13 @@ int DoCoerce(char type, Value *v)
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);
case DATE_TYPE: FromDSE(v->v.val, &y, &m, &d);
sprintf(coerce_buf, "%04d%c%02d%c%02d",
y, DateSep, m+1, DateSep, d);
break;
case DATETIME_TYPE:
i = v->v.val / MINUTES_PER_DAY;
FromJulian(i, &y, &m, &d);
FromDSE(i, &y, &m, &d);
k = v->v.val % MINUTES_PER_DAY;
h = k / 60;
i = k % 60;
@@ -1188,9 +1195,9 @@ static int LogNot(void)
/***************************************************************/
/* */
/* FindFunc */
/* FindOperator */
/* */
/* Find a function. */
/* Find an operator. */
/* */
/***************************************************************/
Operator *FindOperator(char const *name, Operator where[], int num)
@@ -1199,7 +1206,7 @@ Operator *FindOperator(char const *name, Operator where[], int num)
int mid, r;
while (top >= bot) {
mid = (top + bot) / 2;
r = StrCmpi(name, where[mid].name);
r = strcmp(name, where[mid].name);
if (!r) return &where[mid];
else if (r > 0) bot = mid+1;
else top = mid-1;
@@ -1207,6 +1214,20 @@ Operator *FindOperator(char const *name, Operator where[], int num)
return NULL;
}
/* Compare two strings case-insensitively, where we KNOW
that the second string is definitely lower-case */
static int strcmp_lcfirst(char const *s1, char const *s2)
{
int r;
while (*s1 && *s2) {
r = tolower(*s1) - *s2;
if (r) return r;
s1++;
s2++;
}
return tolower(*s1) - *s2;
}
/***************************************************************/
/* */
/* FindFunc */
@@ -1220,7 +1241,7 @@ BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
int mid, r;
while (top >= bot) {
mid = (top + bot) / 2;
r = StrCmpi(name, where[mid].name);
r = strcmp_lcfirst(name, where[mid].name);
if (!r) return &where[mid];
else if (r > 0) bot = mid+1;
else top = mid-1;
@@ -1238,12 +1259,31 @@ BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
void PrintValue (Value *v, FILE *fp)
{
int y, m, d;
char const *s;
unsigned char const *s;
if (v->type == STR_TYPE) {
s=v->v.str;
s = (unsigned char const *) v->v.str;
putc('"', fp);
for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, fp);
for (y=0; y<MAX_PRT_LEN && *s; y++) {
switch(*s) {
case '\a': fprintf(ErrFp, "\\a"); break;
case '\b': fprintf(ErrFp, "\\b"); break;
case '\f': fprintf(ErrFp, "\\f"); break;
case '\n': fprintf(ErrFp, "\\n"); break;
case '\r': fprintf(ErrFp, "\\r"); break;
case '\t': fprintf(ErrFp, "\\t"); break;
case '\v': fprintf(ErrFp, "\\v"); break;
case '"': fprintf(ErrFp, "\\\""); break;
case '\\': fprintf(ErrFp, "\\\\"); break;
default:
if (*s < 32) {
fprintf(ErrFp, "\\x%02x", (unsigned int) *s);
} else {
putc(*s, ErrFp); break;
}
}
s++;
}
putc('"',fp);
if (*s) fprintf(fp, "...");
}
@@ -1251,11 +1291,11 @@ void PrintValue (Value *v, FILE *fp)
else if (v->type == TIME_TYPE) fprintf(fp, "%02d%c%02d", v->v.val / 60,
TimeSep, v->v.val % 60);
else if (v->type == DATE_TYPE) {
FromJulian(v->v.val, &y, &m, &d);
FromDSE(v->v.val, &y, &m, &d);
fprintf(fp, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
}
else if (v->type == DATETIME_TYPE) {
FromJulian(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
FromDSE(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
fprintf(fp, "%04d%c%02d%c%02d%c%02d%c%02d", y, DateSep, m+1, DateSep, d, DateTimeSep,
(v->v.val % MINUTES_PER_DAY) / 60, TimeSep, (v->v.val % MINUTES_PER_DAY) % 60);
}
@@ -1328,11 +1368,11 @@ int ParseLiteralTime(char const **s, int *tim)
/* */
/* ParseLiteralDate */
/* */
/* Parse a literal date or datetime. Return result in jul */
/* Parse a literal date or datetime. Return result in dse */
/* and tim; update s. */
/* */
/***************************************************************/
int ParseLiteralDate(char const **s, int *jul, int *tim)
int ParseLiteralDate(char const **s, int *dse, int *tim)
{
int y, m, d;
int r;
@@ -1362,7 +1402,7 @@ int ParseLiteralDate(char const **s, int *jul, int *tim)
}
if (!DateOK(y, m, d)) return E_BAD_DATE;
*jul = Julian(y, m, d);
*dse = DSE(y, m, d);
/* Do we have a time part as well? */
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {

View File

@@ -5,7 +5,8 @@
/* Contains a few definitions used by expression evaluator. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -7,7 +7,8 @@
/* files. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -96,6 +97,7 @@ static int ReadLineFromFile (int use_pclose);
static int CacheFile (char const *fname, int use_pclose);
static void DestroyCache (CachedFile *cf);
static int CheckSafety (void);
static int CheckSafetyAux (struct stat *statbuf);
static int PopFile (void);
static int IncludeCmd(char const *);
static void OpenPurgeFile(char const *fname, char const *mode)
@@ -971,6 +973,11 @@ int IncludeFile(char const *fname)
if (stat(fname, &statbuf) == 0) {
FilenameChain *fc;
if (S_ISDIR(statbuf.st_mode)) {
/* Check safety */
if (!CheckSafetyAux(&statbuf)) {
PopFile();
return E_NO_MATCHING_REMS;
}
if (SetupGlobChain(fname, i) == OK) { /* Glob succeeded */
if (!i->chain) { /* Oops... no matching files */
if (!Hush) {
@@ -1031,7 +1038,7 @@ int GetAccessDate(char const *file)
if (t1->tm_year + 1900 < BASE)
return 0;
else
return Julian(t1->tm_year+1900, t1->tm_mon, t1->tm_mday);
return DSE(t1->tm_year+1900, t1->tm_mon, t1->tm_mday);
}
/***************************************************************/
@@ -1084,8 +1091,8 @@ int TopLevel(void)
/* CheckSafety */
/* */
/* Returns 1 if current file is safe to read; 0 otherwise. */
/* Currently only meaningful for UNIX. If we are running as */
/* root, we refuse to open files not owned by root. */
/* If we are running as root, we refuse to open files not */
/* owned by root. */
/* We also reject world-writable files, no matter */
/* who we're running as. */
/* As a side effect, if we don't own the file, or it's not */
@@ -1105,25 +1112,44 @@ static int CheckSafety(void)
return 0;
}
if (!CheckSafetyAux(&statbuf)) {
fclose(fp);
fp = NULL;
return 0;
}
return 1;
}
/***************************************************************/
/* */
/* CheckSafetyAux */
/* */
/* Returns 1 if file whos info is in statbuf is safe to read; */
/* 0 otherwise. If we are running as */
/* root, we refuse to open files not owned by root. */
/* We also reject world-writable files, no matter */
/* who we're running as. */
/* As a side effect, if we don't own the file, or it's not */
/* owned by a trusted user, we disable RUN */
/***************************************************************/
static int CheckSafetyAux(struct stat *statbuf)
{
/* Under UNIX, take extra precautions if running as root */
if (!geteuid()) {
/* Reject files not owned by root or group/world writable */
if (statbuf.st_uid != 0) {
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file when running as root!\n");
fclose(fp);
fp = NULL;
if (statbuf->st_uid != 0) {
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file or directory when running as root!\n");
return 0;
}
}
/* Sigh... /dev/null is usually world-writable, so ignore devices,
FIFOs, sockets, etc. */
if (!S_ISREG(statbuf.st_mode)) {
if (!S_ISREG(statbuf->st_mode) && !S_ISDIR(statbuf->st_mode)) {
return 1;
}
if ((statbuf.st_mode & S_IWOTH)) {
fprintf(ErrFp, "SECURITY: Won't read world-writable file!\n");
fclose(fp);
fp = NULL;
if ((statbuf->st_mode & S_IWOTH)) {
fprintf(ErrFp, "SECURITY: Won't read world-writable file or directory!\n");
return 0;
}
@@ -1131,13 +1157,13 @@ static int CheckSafety(void)
/* Assume unsafe */
RunDisabled |= RUN_NOTOWNER;
if (statbuf.st_uid == geteuid()) {
if (statbuf->st_uid == geteuid()) {
/* Owned by me... safe */
RunDisabled &= ~RUN_NOTOWNER;
} else {
int i;
for (i=0; i<NumTrustedUsers; i++) {
if (statbuf.st_uid == TrustedUsers[i]) {
if (statbuf->st_uid == TrustedUsers[i]) {
/* Owned by a trusted user... safe */
RunDisabled &= ~RUN_NOTOWNER;
break;

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,8 @@
/* globals.h and err.h */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -8,6 +8,7 @@
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2021 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -40,7 +41,7 @@ EXTERN FILE *ErrFp;
#define DestroyValue(x) (void) (((x).type == STR_TYPE && (x).v.str) ? (free((x).v.str),(x).type = ERR_TYPE) : 0)
EXTERN int JulianToday;
EXTERN int DSEToday;
EXTERN int RealToday;
EXTERN int CurDay;
EXTERN int CurMon;
@@ -58,9 +59,10 @@ EXTERN INIT( int DoSimpleCalendar, 0);
EXTERN INIT( int DoSimpleCalDelta, 0);
EXTERN INIT( int DoPrefixLineNo, 0);
EXTERN INIT( int MondayFirst, 0);
EXTERN INIT( int AddBlankLines, 1);
EXTERN INIT( int Iterations, 1);
EXTERN INIT( int PsCal, 0);
EXTERN INIT( int CalWidth, -1);
EXTERN INIT( int CalWidth, 80);
EXTERN INIT( int CalWeeks, 0);
EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0);
@@ -80,6 +82,7 @@ EXTERN INIT( long SysTime, -1L);
EXTERN char const *InitialFile;
EXTERN int FileAccessDate;
EXTERN INIT( int WeekdayOmits, 0);
EXTERN INIT( int DontSuppressQuoteMarkers, 0);
EXTERN INIT( int DontFork, 0);
EXTERN INIT( int DontQueue, 0);
@@ -111,11 +114,13 @@ EXTERN INIT( int LastTriggerTime, 0);
EXTERN INIT( int ShouldCache, 0);
EXTERN char const *CurLine;
EXTERN INIT( int NumTriggered, 0);
EXTERN INIT( int DidMsgReminder, 0);
EXTERN int ArgC;
EXTERN char const **ArgV;
EXTERN INIT( int CalLines, CAL_LINES);
EXTERN INIT( int CalPad, 1);
EXTERN INIT( int UseVTChars, 0);
EXTERN INIT( int UseBGVTColors, 0);
EXTERN INIT( int UseUTF8Chars, 0);
EXTERN INIT( int UseVTColors, 0);
EXTERN INIT( int Use256Colors, 0);
@@ -313,6 +318,12 @@ EXTERN char *DynamicWas
EXTERN char *SysDir
#ifdef MK_GLOBALS
= STRSYSDIR(SYSDIR);
= STRSYSDIR(SYSDIR)
#endif
;
EXTERN int SuppressLRM
#ifdef MK_GLOBALS
= 0
#endif
;

View File

@@ -5,7 +5,8 @@
/* Support for the Hebrew calendar */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/* Derived from code written by Amos Shapir in 1978; revised */
/* 1985. */
@@ -67,7 +68,7 @@ static char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
/* */
/* RoshHashana */
/* */
/* Return the Julian date for Rosh Hashana of specified */
/* Return DSE date for Rosh Hashana of specified */
/* Hebrew year. (ie, 5751, not 1990) */
/* */
/***************************************************************/
@@ -155,14 +156,14 @@ char const *DaysInHebMonths(int ylen)
/***************************************************************/
/* */
/* HebToJul */
/* HebToDSE */
/* */
/* Convert a Hebrew date to Julian. */
/* Convert a Hebrew date to DSE. */
/* Hebrew months range from 0-12, but Adar A has 0 length in */
/* non-leap-years. */
/* */
/***************************************************************/
int HebToJul(int hy, int hm, int hd)
int HebToDSE(int hy, int hm, int hd)
{
int ylen;
char const *monlens;
@@ -188,39 +189,39 @@ int HebToJul(int hy, int hm, int hd)
/***************************************************************/
/* */
/* JulToHeb */
/* DSEToHeb */
/* */
/* Convert a Julian date to Hebrew. */
/* Convert a DSE to Hebrew. */
/* Hebrew months range from 0-12, but Adar A has 0 length in */
/* non-leap-years. */
/* */
/***************************************************************/
void JulToHeb(int jul, int *hy, int *hm, int *hd)
void DSEToHeb(int dse, int *hy, int *hm, int *hd)
{
int y, m, d;
int rh;
int ylen;
char const *monlen;
/* Get the common year */
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
y += 3763; /* Over-estimate a bit to be on the safe side below... */
/* Find the RH just before desired date */
while ((rh=RoshHashana(y))>jul) y--;
while ((rh=RoshHashana(y))>dse) y--;
/* Got the year - now find the month */
jul -= rh;
dse -= rh;
ylen = DaysInHebYear(y);
monlen = DaysInHebMonths(ylen);
m = 0;
while((jul >= monlen[m]) || !monlen[m]) {
jul -= monlen[m];
while((dse >= monlen[m]) || !monlen[m]) {
dse -= monlen[m];
m++;
}
*hy = y;
*hm = m;
*hd = jul+1;
*hd = dse+1;
}
/***************************************************************/
@@ -389,20 +390,20 @@ int GetValidHebDate(int yin, int min, int din, int adarbehave,
/* Returns 0 for success, non-zero for failure. */
/* */
/***************************************************************/
int GetNextHebrewDate(int julstart, int hm, int hd,
int GetNextHebrewDate(int dsestart, int hm, int hd,
int jahr, int adarbehave, int *ans)
{
int r, yout, mout, dout, jul=1;
int r, yout, mout, dout, dse=1;
int adarflag = adarbehave;
/* I initialize jul above to stop gcc from complaining about
/* I initialize dse above to stop gcc from complaining about
possible use of uninitialized variable. You can take it
out if the small inefficiency really bothers you. */
/* If adarbehave == ADAR2BOTH, set adarflag to ADAR2ADARA for now */
if (adarbehave == ADAR2BOTH) adarflag = ADAR2ADARA;
JulToHeb(julstart, &yout, &mout, &dout);
DSEToHeb(dsestart, &yout, &mout, &dout);
r = 1;
while(r) {
@@ -419,9 +420,9 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
} else yout++;
continue;
}
jul = HebToJul(yout, mout, dout);
if (jul < 0) return E_DATE_OVER;
if (jul >= julstart) break;
dse = HebToDSE(yout, mout, dout);
if (dse < 0) return E_DATE_OVER;
if (dse >= dsestart) break;
else {
if (adarbehave == ADAR2BOTH && hm == ADAR) {
if (adarflag == ADAR2ADARA) {
@@ -434,7 +435,7 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
r=1; /* Force loop to continue */
}
}
*ans = jul;
*ans = dse;
return OK;
}

View File

@@ -7,7 +7,8 @@
/* in normal mode. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -21,6 +22,10 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/ioctl.h>
@@ -43,7 +48,8 @@
* 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
* -@[n,m,b]= Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
* b=0 ignore SHADE b=1 respect SHADE
* -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
@@ -94,6 +100,25 @@ static void AddTrustedUser(char const *username);
static DynamicBuffer default_filename_buf;
static void
InitCalWidthAndFormWidth(int fd)
{
struct winsize w;
if (!isatty(fd)) {
return;
}
if (ioctl(fd, TIOCGWINSZ, &w) == 0) {
CalWidth = w.ws_col;
if (CalWidth < 71) {
CalWidth = 71;
}
FormWidth = w.ws_col - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
/***************************************************************/
/* */
/* DefaultFilename */
@@ -140,20 +165,14 @@ void InitRemind(int argc, char const *argv[])
char const *s;
int weeks;
int x;
int jul;
int dse;
int ttyfd;
jul = NO_DATE;
dse = NO_DATE;
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
but clamp to [20, 500] */
if (isatty(STDOUT_FILENO)) {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
FormWidth = w.ws_col - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
InitCalWidthAndFormWidth(STDOUT_FILENO);
/* Initialize global dynamic buffers */
DBufInit(&Banner);
@@ -181,8 +200,8 @@ void InitRemind(int argc, char const *argv[])
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
exit(EXIT_FAILURE);
}
JulianToday = RealToday;
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
DSEToday = RealToday;
FromDSE(DSEToday, &CurYear, &CurMon, &CurDay);
/* Initialize Latitude and Longitude */
set_components_from_lat_and_long();
@@ -233,22 +252,36 @@ void InitRemind(int argc, char const *argv[])
} else if (x == 2) {
UseTrueColors = 1;
} else if (x != 0) {
fprintf(ErrFp, "%s: -@n,m: n must be 0, 1 or 2 (assuming 0)\n",
fprintf(ErrFp, "%s: -@n,m,b: n must be 0, 1 or 2 (assuming 0)\n",
argv[0]);
}
}
if (*arg == ',') {
arg++;
PARSENUM(x, arg);
if (x == 0) {
TerminalBackground = TERMINAL_BACKGROUND_DARK;
} else if (x == 1) {
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
} else {
fprintf(ErrFp, "%s: -@n,m: m must be 0 or 1\n",
argv[0]);
if (*arg != ',') {
PARSENUM(x, arg);
if (x == 0) {
TerminalBackground = TERMINAL_BACKGROUND_DARK;
} else if (x == 1) {
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
} else if (x == 2) {
TerminalBackground = TERMINAL_BACKGROUND_UNKNOWN;
} else {
fprintf(ErrFp, "%s: -@n,m,b: m must be 0, 1 or 2 (assuming 2)\n",
argv[0]);
}
}
}
if (*arg == ',') {
arg++;
PARSENUM(x, arg);
if (x != 0 && x != 1) {
fprintf(ErrFp, "%s: -@n,m,b: b must be 0 or 1 (assuming 0)\n",
argv[0]);
x = 0;
}
UseBGVTColors = x;
}
break;
case 'j':
@@ -495,11 +528,27 @@ void InitRemind(int argc, char const *argv[])
case 'w':
case 'W':
if (*arg != ',') {
PARSENUM(CalWidth, arg);
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
if (*arg == 't') {
arg++;
/* -wt means get width from /dev/tty */
ttyfd = open("/dev/tty", O_RDONLY);
if (!ttyfd) {
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n",
argv[0], strerror(errno));
} else {
InitCalWidthAndFormWidth(ttyfd);
close(ttyfd);
}
} else {
PARSENUM(CalWidth, arg);
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
if (CalWidth == 0) {
CalWidth = -1;
}
FormWidth = CalWidth - 8;
if (FormWidth < 20) FormWidth = 20;
if (FormWidth > 500) FormWidth = 500;
}
}
if (*arg == ',') {
arg++;
@@ -590,30 +639,30 @@ void InitRemind(int argc, char const *argv[])
case T_DateTime:
if (SysTime != -1L) Usage();
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
if (m != NO_MON || d != NO_DAY || y != NO_YR || dse != NO_DATE) Usage();
SysTime = (tok.val % MINUTES_PER_DAY) * 60;
DontQueue = 1;
Daemon = 0;
jul = tok.val / MINUTES_PER_DAY;
dse = tok.val / MINUTES_PER_DAY;
break;
case T_Date:
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
jul = tok.val;
if (m != NO_MON || d != NO_DAY || y != NO_YR || dse != NO_DATE) Usage();
dse = tok.val;
break;
case T_Month:
if (m != NO_MON || jul != NO_DATE) Usage();
if (m != NO_MON || dse != NO_DATE) Usage();
else m = tok.val;
break;
case T_Day:
if (d != NO_DAY || jul != NO_DATE) Usage();
if (d != NO_DAY || dse != NO_DATE) Usage();
else d = tok.val;
break;
case T_Year:
if (y != NO_YR || jul != NO_DATE) Usage();
if (y != NO_YR || dse != NO_DATE) Usage();
else y = tok.val;
break;
@@ -633,8 +682,8 @@ void InitRemind(int argc, char const *argv[])
Daemon = 0;
}
if (jul != NO_DATE) {
FromJulian(jul, &y, &m, &d);
if (dse != NO_DATE) {
FromDSE(dse, &y, &m, &d);
}
/* Must supply date in the form: day, mon, yr OR mon, yr */
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
@@ -652,22 +701,22 @@ void InitRemind(int argc, char const *argv[])
fprintf(ErrFp, "%s", BadDate);
Usage();
}
JulianToday = Julian(y, m, d);
if (JulianToday == -1) {
DSEToday = DSE(y, m, d);
if (DSEToday == -1) {
fprintf(ErrFp, "%s", BadDate);
Usage();
}
CurYear = y;
CurMon = m;
CurDay = d;
if (JulianToday != RealToday) IgnoreOnce = 1;
if (DSEToday != RealToday) IgnoreOnce = 1;
}
}
/* Figure out the offset from UTC */
if (CalculateUTC)
(void) CalcMinsFromUTC(JulianToday, SystemTime(0)/60,
(void) CalcMinsFromUTC(DSEToday, SystemTime(0)/60,
&MinsFromUTC, NULL);
}
@@ -681,7 +730,7 @@ void InitRemind(int argc, char const *argv[])
#ifndef L_USAGE_OVERRIDE
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
@@ -689,7 +738,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, " -@[n,m,b] Colorize COLOR/SHADE 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");

View File

@@ -5,7 +5,8 @@
/* Header file for language support for various languages. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -23,7 +24,7 @@
#define ITALIAN 9 /* translated by Valerio Aimale */
#define ROMANIAN 10 /* translated by Liviu Daia */
#define SPANISH 11 /* translated by Rafa Couto */
#define ICELANDIC 12 /* translated by Björn Davíðsson */
#define ICELANDIC 12 /* translated by Björn Davíðsson */
/* Add more languages here - but please e-mail dianne@skoll.ca
to have your favorite language assigned a number. If you add a

View File

@@ -6,8 +6,9 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -80,10 +81,10 @@
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " om natten" : " om formiddagen" : (hour > 17) ? " om aftenen" : " om eftermiddagen";
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
#define L_E_OVER sprintf(s, "den %02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
#define L_F_OVER sprintf(s, "den %02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
#define L_H_OVER sprintf(s, "den %02d%c%02d", d, DateSep, m+1);
#define L_I_OVER sprintf(s, "den %02d%c%02d", m+1, DateSep, d);
#define L_U_OVER L_A_OVER

View File

@@ -11,7 +11,8 @@
/* Further corrections by Erik-Jan Vens */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -5,7 +5,8 @@
/* Support for the English language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -11,7 +11,8 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -103,19 +104,19 @@
default: plu = ":ntenä"; break; \
} \
}
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s%s %d. %s%s %d", DayName[jul%7], L_ON, d, MonthName[m], L_PARTIT, y); }
#define L_C_OVER if (altmode == '*') { sprintf(s, "%s", DayName[jul%7]); } else { sprintf(s, "%s%s", DayName[jul%7], L_ON); }
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s%s %d. %s%s %d", DayName[dse%7], L_ON, d, MonthName[m], L_PARTIT, y); }
#define L_C_OVER if (altmode == '*') { sprintf(s, "%s", DayName[dse%7]); } else { sprintf(s, "%s%s", DayName[dse%7], L_ON); }
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s%s %d. %s%s", DayName[jul%7], L_ON, d, MonthName[m], L_PARTIT); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s%s %d. %s%s", DayName[dse%7], L_ON, d, MonthName[m], L_PARTIT); }
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s %d", DayName[jul%7], MonthName[m], d, plu, y); } else { sprintf(s, "%s%s %sn %d%s %d", DayName[jul%7], L_ON, MonthName[m], d, plu, y); }
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s", DayName[jul%7], MonthName[m], d, plu); } else { sprintf(s, "%s%s %sn %d%s", DayName[jul%7], L_ON, MonthName[m], d, plu); }
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s %d", DayName[dse%7], MonthName[m], d, plu, y); } else { sprintf(s, "%s%s %sn %d%s %d", DayName[dse%7], L_ON, MonthName[m], d, plu, y); }
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s", DayName[dse%7], MonthName[m], d, plu); } else { sprintf(s, "%s%s %sn %d%s", DayName[dse%7], L_ON, MonthName[m], d, plu); }
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
#define L_Q_OVER sprintf(s, "n");
#define L_U_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s %d", DayName[jul%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s%s %d%s %s%s %d", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT, y); }
#define L_V_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s", DayName[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s%s %d%s %s%s", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT); }
#define L_U_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s %d", DayName[dse%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s%s %d%s %s%s %d", DayName[dse%7], L_ON, d, plu, MonthName[m], L_PARTIT, y); }
#define L_V_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s", DayName[dse%7], d, plu, MonthName[m]); } else { sprintf(s, "%s%s %d%s %s%s", DayName[dse%7], L_ON, d, plu, MonthName[m], L_PARTIT); }
#define L_1_OVER \
if (tdiff == 0) \
sprintf(s, "%s", L_NOW); \
@@ -195,7 +196,7 @@ EXTERN char *ErrMsg[] =
"Kuukausi annettu kahdesti",
"Päivä annettu kahdesti",
"Tuntematon sana tai merkki",
"OMIT-komennossa on annettava kuukausi ja päivä",
"OMIT-komennossa on annettava kuukausi",
"Liian monta osittaista OMIT-komentoa",
"Liian monta täydellistä OMIT-komentoa",
"Varoitus: PUSH-OMIT-CONTEXT ilman POP-OMIT-CONTEXTia",
@@ -253,7 +254,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
#endif

View File

@@ -8,9 +8,10 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
/* This file is Copyright (C) 1993 by Laurent Duperval and */
/* Dianne Skoll. */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -106,9 +107,9 @@ else if (tdiff < 0) { \
sprintf(s, "dans %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
}
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s, %d", DayName[jul%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d, plu, MonthName[m], y); }
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s, %d", DayName[dse%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[dse%7], d, plu, MonthName[m], y); }
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s", DayName[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu, MonthName[m]); }
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s", DayName[dse%7], d, plu, MonthName[m]); } else { sprintf(s, "%s %s, %d%s %s", L_ON, DayName[dse%7], d, plu, MonthName[m]); }
/* The next ones are used only when MK_GLOBALS is set */
#ifdef MK_GLOBALS
@@ -227,7 +228,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif

View File

@@ -9,7 +9,8 @@
/* I don't speak German. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -81,7 +82,7 @@
See the file dosubst.c for more info. */
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER

View File

@@ -5,8 +5,9 @@
/* Support for the Icelandic language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -7,7 +7,8 @@
/* This file is part of REMIND. */
/* It is Copyright (C) 1996 by Valerio Aimale */
/* */
/* Remind is copyright (C) 1992-2022 by Dianne Skoll */
/* Remind is copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -84,30 +85,30 @@
#define L_HPLU_OVER hplu = (hdiff == 1 ? "a" : "e");
#define L_MPLU_OVER mplu = (mdiff == 1 ? "o" : "i");
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d,\
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d,\
MonthName[m], y);
#define L_C_OVER sprintf(s, "%s", DayName[jul%7]);
#define L_C_OVER sprintf(s, "%s", DayName[dse%7]);
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep,\
m+1, DateSep, y);
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
#define L_J_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, \
#define L_J_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, \
MonthName[m], y);
#define L_K_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, \
#define L_K_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, \
MonthName[m]);
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, \
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, \
MonthName[m], y);
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, \
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, \
MonthName[m]);

View File

@@ -6,7 +6,8 @@
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993 by Trygve Randen. */
/* Remind is Copyright (C) 1992-2022 by Dianne Skoll */
/* Remind is Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -77,7 +78,7 @@
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER

View File

@@ -9,7 +9,8 @@
/* Polish. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -95,8 +96,8 @@ ampm = (hour<12) ? \
: (hour<22) ? " wieczorem" \
: " w nocy";
#define L_ORDINAL_OVERRIDE plu = "";
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER
@@ -185,7 +186,7 @@ EXTERN char *ErrMsg[] =
"Miesiąc podany dwókrotnie",
"Dzień podany dwókrotnie",
"Nieznane słowo",
"W komendzie OMIT trzeba podać miesiąc i dzień",
"W komendzie OMIT trzeba podać miesiąc",
"Za dużo częściowych komend OMIT",
"Za dużo pełnych komend OMIT",
"Ostrzeżenie: PUSH-OMIT-CONTEXT bez POP-OMIT-CONTEXT",
@@ -243,7 +244,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif

View File

@@ -8,9 +8,10 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
/* This file is Copyright (C) 1996 by Marco Paganini and */
/* Dianne Skoll. */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -88,26 +89,26 @@
#define _ON_WEEKDAY(x) ((x % 7) < 2) ? "no" : "na"
#define L_A_OVER \
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
#define L_C_OVER \
sprintf(s, "%s %s", _ON_WEEKDAY(jul), DayName[jul%7]);
sprintf(s, "%s %s", _ON_WEEKDAY(dse), DayName[dse%7]);
#define L_G_OVER \
sprintf(s, "%s %s, %d %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
sprintf(s, "%s %s, %d %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
#define L_J_OVER \
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
#define L_K_OVER \
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
/* Portuguese does not use some suffixes, some some %u and %j are the same */
#define L_U_OVER \
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
#define L_V_OVER \
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
#define L_1_OVER \
{ \
@@ -194,7 +195,7 @@ EXTERN char *ErrMsg[] =
"Mes especificado duas vezes",
"Dia especificado duas vezes",
"Token desconhecido",
"Mes e dia devem ser especificados no comando OMIT",
"O mes deve ser especificados no comando OMIT",
"Muitos OMITs parciais",
"Muitos OMITs full",
"Aviso: PUSH-OMIT-CONTEXT sem POP-OMIT-CONTEXT correspondente",
@@ -252,7 +253,7 @@ EXTERN char *ErrMsg[] =
#define L_USAGE_OVERRIDE 1
void Usage(void)
{
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
#endif

View File

@@ -8,8 +8,9 @@
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -84,14 +85,14 @@
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<4) ? " noaptea" : " dimineaţa" : (hour > 17) ? " seara" : " după-amiaza";
#define L_ORDINAL_OVERRIDE plu = "";
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, MonthName[m], y);
#define L_C_OVER sprintf(s, "%s", DayName[jul%7]);
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
#define L_J_OVER sprintf(s, "%s, %s %d, %d", DayName[jul%7], MonthName[m], d, y);
#define L_K_OVER sprintf(s, "%s, %s %d", DayName[jul%7], MonthName[m], d);
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, MonthName[m], y);
#define L_C_OVER sprintf(s, "%s", DayName[dse%7]);
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
#define L_J_OVER sprintf(s, "%s, %s %d, %d", DayName[dse%7], MonthName[m], d, y);
#define L_K_OVER sprintf(s, "%s, %s %d", DayName[dse%7], MonthName[m], d);
#define L_S_OVER
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, MonthName[m], y);
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, MonthName[m], y);
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
#define L_1_OVER \
if (tdiff == 0) \
sprintf(s, L_NOW); \

View File

@@ -7,7 +7,8 @@
/* Author: Rafa Couto <rafacouto@biogate.com> */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/

View File

@@ -6,12 +6,15 @@
/* routines, etc. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
#define _XOPEN_SOURCE 600
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -35,6 +38,10 @@
#endif
#include <sys/types.h>
#ifdef REM_USE_WCHAR
#include <wctype.h>
#include <wchar.h>
#endif
#include "types.h"
#include "protos.h"
@@ -67,6 +74,7 @@ int main(int argc, char *argv[])
ArgV = (char const **) argv;
InitRemind(argc, (char const **) argv);
DBufInit(&(LastTrigger.tags));
ClearLastTriggers();
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
@@ -124,7 +132,7 @@ int main(int argc, char *argv[])
}
if (Iterations) {
PerIterationInit();
JulianToday++;
DSEToday++;
}
}
return 0;
@@ -169,14 +177,16 @@ static void DoReminders(void)
Parser p;
int purge_handled;
DidMsgReminder = 0;
if (!UseStdin) {
FileAccessDate = GetAccessDate(InitialFile);
} else {
FileAccessDate = JulianToday;
FileAccessDate = DSEToday;
}
if (FileAccessDate < 0) {
fprintf(ErrFp, "%s: `%s'.\n", ErrMsg[E_CANTACCESS], InitialFile);
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
exit(1);
}
@@ -253,6 +263,7 @@ static void DoReminders(void)
case T_Flush: r=DoFlush(&p); break;
case T_Set: r=DoSet(&p); break;
case T_Fset: r=DoFset(&p); break;
case T_Funset: r=DoFunset(&p); break;
case T_UnSet: r=DoUnset(&p); break;
case T_Clr: r=DoClear(&p); break;
case T_Debug: r=DoDebug(&p); break;
@@ -307,13 +318,16 @@ static void DoReminders(void)
/***************************************************************/
/* */
/* Julian */
/* DSE */
/* */
/* Given day, month, year, return Julian date in days since */
/* DSE stands for "Days Since Epoch"; the Remind epoch is */
/* midnight on 1990-01-01 */
/* */
/* Given day, month, year, return DSE date in days since */
/* 1 January 1990. */
/* */
/***************************************************************/
int Julian(int year, int month, int day)
int DSE(int year, int month, int day)
{
int y1 = BASE-1, y2 = year-1;
@@ -327,14 +341,15 @@ int Julian(int year, int month, int day)
/***************************************************************/
/* */
/* FromJulian */
/* FromDSE */
/* */
/* Convert a Julian date to year, month, day. */
/* Convert a DSE date to year, month, day. You may supply */
/* NULL for y, m or d if you're not interested in that value */
/* */
/***************************************************************/
void FromJulian(int jul, int *y, int *m, int *d)
void FromDSE(int dse, int *y, int *m, int *d)
{
int try_yr = (jul / 365) + BASE;
int try_yr = (dse / 365) + BASE;
int try_mon = 0;
int t;
@@ -344,23 +359,29 @@ void FromJulian(int jul, int *y, int *m, int *d)
int y100 = (y2 / 100) - (y1 / 100); /* Don't count multiples of 100... */
int y400 = (y2 / 400) - (y1 / 400); /* ... but do count multiples of 400 */
int try_jul= 365 * (try_yr-BASE) + y4 - y100 + y400;
int try_dse= 365 * (try_yr-BASE) + y4 - y100 + y400;
while (try_jul > jul) {
while (try_dse > dse) {
try_yr--;
try_jul -= DaysInYear(try_yr);
try_dse -= DaysInYear(try_yr);
}
jul -= try_jul;
dse -= try_dse;
t = DaysInMonth(try_mon, try_yr);
while (jul >= t) {
jul -= t;
while (dse >= t) {
dse -= t;
try_mon++;
t = DaysInMonth(try_mon, try_yr);
}
*y = try_yr;
*m = try_mon;
*d = jul + 1;
if (y) {
*y = try_yr;
}
if (m) {
*m = try_mon;
}
if (d) {
*d = dse + 1;
}
return;
}
@@ -732,7 +753,7 @@ long SystemTime(int realtime)
/* */
/* SystemDate */
/* */
/* Obtains today's date. Returns Julian date or -1 for */
/* Obtains today's date. Returns DSE date or -1 for */
/* failure. (Failure happens if sys date is before BASE */
/* year.) */
/* */
@@ -749,7 +770,7 @@ int SystemDate(int *y, int *m, int *d)
*m = t->tm_mon;
*y = t->tm_year + 1900;
return Julian(*y, *m, *d);
return DSE(*y, *m, *d);
}
@@ -842,7 +863,7 @@ int DoIfTrig(ParsePtr p)
unsigned syndrome;
Trigger trig;
TimeTrig tim;
int jul;
int dse;
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
@@ -850,26 +871,26 @@ 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, &tim, &r, 1);
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) {
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
if (!Hush || r != E_RUN_DISABLED) {
Eprint("%s", ErrMsg[r]);
}
}
syndrome = IF_TRUE | BEFORE_ELSE;
syndrome = IF_FALSE | BEFORE_ELSE;
}
else {
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
syndrome = IF_TRUE | BEFORE_ELSE;
} else {
syndrome = IF_FALSE | BEFORE_ELSE;
if (PurgeMode) {
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
}
}
}
if (syndrome == (IF_FALSE | BEFORE_ELSE) && PurgeMode) {
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
}
FreeTrig(&trig);
}
NumIfs++;
@@ -1124,7 +1145,7 @@ int DoErrMsg(ParsePtr p)
DBufInit(&buf);
t.typ = MSG_TYPE;
tt.ttime = SystemTime(0) / 60;
if ( (r=DoSubst(p, &buf, &t, &tt, JulianToday, NORMAL_MODE)) ) {
if ( (r=DoSubst(p, &buf, &t, &tt, DSEToday, NORMAL_MODE)) ) {
return r;
}
s = DBufValue(&buf);
@@ -1154,28 +1175,30 @@ static int FoldArray[2][7] = {
{2024, 2008, 2020, 2004, 2016, 2000, 2012}
};
int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
int CalcMinsFromUTC(int dse, int tim, int *mins, int *isdst)
{
/* Convert jul and tim to an Unix tm struct */
/* Convert dse and tim to an Unix tm struct */
int yr, mon, day;
int tdiff;
struct tm local, utc, *temp;
time_t loc_t, utc_t;
int isdst_tmp;
FromJulian(jul, &yr, &mon, &day);
FromDSE(dse, &yr, &mon, &day);
/* If the year is greater than 2037, some Unix machines have problems.
Fold it back to a "similar" year and trust that the UTC calculations
are still valid... */
if (FoldYear && yr>2037) {
jul = Julian(yr, 0, 1);
yr = FoldArray[IsLeapYear(yr)][jul%7];
dse = DSE(yr, 0, 1);
yr = FoldArray[IsLeapYear(yr)][dse%7];
}
local.tm_sec = 0;
local.tm_min = tim % 60;
local.tm_hour = tim / 60;
local.tm_mday = day;
local.tm_mon = mon;
local.tm_year = yr-1900;
@@ -1204,6 +1227,144 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
return 0;
}
static char const *OutputEscapeSequences(char const *s, int print)
{
while (*s == 0x1B && *(s+1) == '[') {
if (print) putchar(*s);
s++;
if (print) putchar(*s);
s++;
while (*s && (*s < 0x40 || *s > 0x7E)) {
if (print) putchar(*s);
s++;
}
if (*s) {
if (print) putchar(*s);
s++;
}
}
return s;
}
#ifdef REM_USE_WCHAR
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print)
{
while (*s == 0x1B && *(s+1) == '[') {
if (print) PutWideChar(*s);
s++;
if (print) PutWideChar(*s);
s++;
while (*s && (*s < 0x40 || *s > 0x7E)) {
if (print) PutWideChar(*s);
s++;
}
if (*s) {
if (print) PutWideChar(*s);
s++;
}
}
return s;
}
static void
FillParagraphWCAux(wchar_t const *s)
{
int line = 0;
int i, j;
int doublespace = 1;
int pendspace;
int len;
wchar_t const *t;
int roomleft;
/* Start formatting */
while(1) {
/* If it's a carriage return, output it and start new paragraph */
if (*s == '\n') {
putchar('\n');
s++;
line = 0;
while(ISWBLANK(*s)) s++;
continue;
}
if (!*s) {
return;
}
/* Over here, we're at the beginning of a line. Emit the correct
number of spaces */
j = line ? SubsIndent : FirstIndent;
for (i=0; i<j; i++) {
putchar(' ');
}
/* Calculate the amount of room left on this line */
roomleft = FormWidth - j;
pendspace = 0;
/* Emit words until the next one won't fit */
while(1) {
while(ISWBLANK(*s)) s++;
if (*s == '\n') break;
while(1) {
t = s;
s = OutputEscapeSequencesWS(s, 1);
if (s == t) break;
while(ISWBLANK(*s)) s++;
}
t = s;
len = 0;
while(*s && !iswspace(*s)) {
if (*s == 0x1B && *(s+1) == '[') {
s = OutputEscapeSequencesWS(s, 0);
continue;
}
len += wcwidth(*s);
s++;
}
if (s == t) {
return;
}
if (!pendspace || len+pendspace <= roomleft) {
for (i=0; i<pendspace; i++) {
putchar(' ');
}
while(t < s) {
PutWideChar(*t);
if (strchr(EndSent, *t)) doublespace = 2;
else if (!strchr(EndSentIg, *t)) doublespace = 1;
t++;
}
} else {
s = t;
putchar('\n');
line++;
break;
}
roomleft -= len+doublespace;
pendspace = doublespace;
}
}
}
static int
FillParagraphWC(char const *s)
{
size_t len;
wchar_t *buf;
len = mbstowcs(NULL, s, 0);
if (len == (size_t) -1) return E_NO_MEM;
buf = calloc(len+1, sizeof(wchar_t));
if (!buf) return E_NO_MEM;
(void) mbstowcs(buf, s, len+1);
FillParagraphWCAux(buf);
free(buf);
return OK;
}
#endif
/***************************************************************/
/* */
/* FillParagraph */
@@ -1230,11 +1391,17 @@ void FillParagraph(char const *s)
char const *t;
int roomleft;
if (!s || !*s) return;
/* Skip leading spaces */
while(ISBLANK(*s)) s++;
if (!*s) return;
#ifdef REM_USE_WCHAR
if (FillParagraphWC(s) == OK) {
return;
}
#endif
/* Start formatting */
while(1) {
@@ -1265,10 +1432,23 @@ void FillParagraph(char const *s)
while(1) {
while(ISBLANK(*s)) s++;
if (*s == '\n') break;
while(1) {
t = s;
s = OutputEscapeSequences(s, 1);
if (s == t) break;
while(ISBLANK(*s)) s++;
}
t = s;
while(*s && !isspace(*s)) s++;
len = s - t;
if (!len) {
len = 0;
while(*s && !isspace(*s)) {
if (*s == 0x1B && *(s+1) == '[') {
s = OutputEscapeSequences(s, 0);
continue;
}
s++;
len++;
}
if (s == t) {
return;
}
if (!pendspace || len+pendspace <= roomleft) {
@@ -1357,13 +1537,23 @@ void UTCToLocal(int utcdate, int utctime, int *locdate, int *loctime)
/* command-line flag is supplied. */
/* */
/***************************************************************/
static sig_atomic_t got_sigint = 0;
void SigIntHandler(int d)
void
SigIntHandler(int d)
{
UNUSED(d);
signal(SIGINT, SigIntHandler);
GotSigInt();
exit(0);
got_sigint = 1;
}
int
GotSigInt(void)
{
if (got_sigint) {
got_sigint = 0;
return 1;
}
return 0;
}
void
@@ -1404,6 +1594,7 @@ ClearLastTriggers(void)
LastTrigger.warn[0] = 0;
LastTrigger.omitfunc[0] = 0;
LastTrigger.passthru[0] = 0;
DBufFree(&(LastTrigger.tags));
LastTimeTrig.ttime = NO_TIME;
LastTimeTrig.delta = NO_DELTA;
@@ -1424,8 +1615,10 @@ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigt
void
SaveLastTrigger(Trigger const *t)
{
DBufFree(&(LastTrigger.tags));
memcpy(&LastTrigger, t, sizeof(LastTrigger));
DBufInit(&(LastTrigger.tags));
DBufPuts(&(LastTrigger.tags), DBufValue(&(t->tags)));
}
void

View File

@@ -5,7 +5,8 @@
/* Calculations for figuring out moon phases. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -143,7 +144,7 @@ static double phase (double, double *, double *, double *, double *, double *, d
/* */
/* jdate */
/* */
/* Convert a date and time to Julian day and fraction. */
/* Convert a date and time to DSE day and fraction. */
/* */
/***************************************************************/
static long jdate(int y, int mon, int day)
@@ -400,8 +401,8 @@ static double phase(double pdate,
double *suangdia)
{
double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon,
double Day, N, M, Ec, Lambdasun, ml, MM, Ev, Ae, A3, MmP,
mEc, A4, lP, V, lPP,
MoonAge, MoonPhase,
MoonDist, MoonDFrac, MoonAng,
F, SunDist, SunAng;
@@ -431,9 +432,6 @@ static double phase(double pdate,
/* Moon's mean anomaly */
MM = fixangle(ml - 0.1114041 * Day - mmlongp);
/* Moon's ascending node mean longitude */
MN = fixangle(mlnode - 0.0529539 * Day);
/* Evection */
Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
@@ -461,19 +459,6 @@ static double phase(double pdate,
/* 1 longitude */
lPP = lP + V;
/* Corrected longitude of the node */
NP = MN - 0.16 * sin(torad(M));
/* Y inclination coordinate */
y = sin(torad(lPP - NP)) * cos(torad(minc));
/* X inclination coordinate */
x = cos(torad(lPP - NP));
/* Ecliptic longitude */
Lambdamoon = todeg(atan2(y, x));
Lambdamoon += NP;
/* Calculation of the phase of the Moon */
/* Age of the Moon in degrees */
@@ -520,10 +505,10 @@ int MoonPhase(int date, int time)
LocalToUTC(date, time, &utcd, &utct);
/* Convert from Remind representation to year/mon/day */
FromJulian(utcd, &y, &m, &d);
FromDSE(utcd, &y, &m, &d);
/* Convert to a true Julian date -- sorry for the name clashes! */
jd = jtime(y, m, d, (utct / 60), (utct % 60), 0);
/* Convert to a Julian date */
jd = jtime(y, m, d, (utct / 60), (utct % 60), 0);
/* Calculate moon phase */
mp = 360.0 * phase(jd, NULL, NULL, NULL, NULL, NULL, NULL);
@@ -553,8 +538,8 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
LocalToUTC(startdate, starttim, &utcd, &utct);
/* Convert from Remind representation to year/mon/day */
FromJulian(utcd, &y, &m, &d);
/* Convert to a true Julian date -- sorry for the name clashes! */
FromDSE(utcd, &y, &m, &d);
/* Convert to a true Julian date */
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
jd = jdorig - 45.0;
nt1 = meanphase(jd, 0.0, &k1);
@@ -572,7 +557,7 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
jyear(jd, &y, &m, &d);
jhms(jd, &h, &min, &s);
d1 = Julian(y, m, d);
d1 = DSE(y, m, d);
t1 = h*60 + min;
UTCToLocal(d1, t1, date, time);
}

View File

@@ -6,7 +6,8 @@
/* the data structures for OMITted dates. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -28,6 +29,8 @@ static void InsertIntoSortedArray (int *array, int num, int key);
static int FullOmitArray[MAX_FULL_OMITS];
static int PartialOmitArray[MAX_PARTIAL_OMITS];
/* WeekdayOmits is declared in global.h */
/* How many of each omit types do we have? */
static int NumFullOmits, NumPartialOmits;
@@ -37,6 +40,7 @@ typedef struct omitcontext {
int numfull, numpart;
int *fullsave;
int *partsave;
int weekdaysave;
} OmitContext;
/* The stack of saved omit contexts */
@@ -52,6 +56,7 @@ static OmitContext *SavedOmitContexts = NULL;
int ClearGlobalOmits(void)
{
NumFullOmits = NumPartialOmits = 0;
WeekdayOmits = 0;
return OK;
}
@@ -113,6 +118,7 @@ int PushOmitContext(ParsePtr p)
context->numfull = NumFullOmits;
context->numpart = NumPartialOmits;
context->weekdaysave = WeekdayOmits;
context->fullsave = malloc(NumFullOmits * sizeof(int));
if (NumFullOmits && !context->fullsave) {
free(context);
@@ -154,6 +160,7 @@ int PopOmitContext(ParsePtr p)
if (!c) return E_POP_NO_PUSH;
NumFullOmits = c->numfull;
NumPartialOmits = c->numpart;
WeekdayOmits = c->weekdaysave;
/* Copy the context over */
for (i=0; i<NumFullOmits; i++)
@@ -181,7 +188,7 @@ int PopOmitContext(ParsePtr p)
/* OK or an error code. */
/* */
/***************************************************************/
int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
{
int y, m, d;
@@ -193,7 +200,7 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
int r;
Value v;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
sprintf(expr, "%s('%04d-%02d-%02d')",
omitfunc, y, m+1, d);
s = expr;
@@ -208,18 +215,24 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
}
/* Is it omitted because of local omits? */
if (localomit & (1 << (jul % 7))) {
if (localomit & (1 << (dse % 7))) {
*omit = 1;
return OK;
}
/* Is it omitted because of global weekday omits? */
if (WeekdayOmits & (1 << (dse % 7))) {
*omit = 1;
return OK;
}
/* Is it omitted because of fully-specified omits? */
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
if (BexistsIntArray(FullOmitArray, NumFullOmits, dse)) {
*omit = 1;
return OK;
}
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
*omit = 1;
return OK;
@@ -271,7 +284,6 @@ static void InsertIntoSortedArray(int *array, int num, int key)
*cur = key;
}
static int DoThroughOmit(ParsePtr p, int y, int m, int d);
static void DumpOmits(void);
/***************************************************************/
@@ -283,11 +295,16 @@ static void DumpOmits(void);
/***************************************************************/
int DoOmit(ParsePtr p)
{
int y = NO_YR, m = NO_MON, d = NO_DAY, r;
int y[2] = {NO_YR, NO_YR}, m[2] = {NO_MON, NO_MON}, d[2] = {NO_DAY, NO_DAY}, r;
Token tok;
int parsing=1;
int parsing = 1;
int seen_through = 0;
int syndrome;
int not_first_token = -1;
int start, end, tmp;
int wd = 0;
int mc, dc;
DynamicBuffer buf;
DBufInit(&buf);
@@ -298,9 +315,15 @@ int DoOmit(ParsePtr p)
if ( (r=ParseToken(p, &buf)) ) return r;
FindToken(DBufValue(&buf), &tok);
switch (tok.type) {
case T_Dumpvars:
if (not_first_token) return E_PARSE_ERR;
case T_WkDay:
DBufFree(&buf);
if (wd & (1 << tok.val)) return E_WD_TWICE;
wd |= (1 << tok.val);
break;
case T_Dumpvars:
DBufFree(&buf);
if (not_first_token) return E_PARSE_ERR;
r = VerifyEoln(p);
if (r != OK) return r;
DumpOmits();
@@ -308,28 +331,28 @@ int DoOmit(ParsePtr p)
case T_Date:
DBufFree(&buf);
if (y != NO_YR) return E_YR_TWICE;
if (m != NO_MON) return E_MON_TWICE;
if (d != NO_DAY) return E_DAY_TWICE;
FromJulian(tok.val, &y, &m, &d);
if (y[seen_through] != NO_YR) return E_YR_TWICE;
if (m[seen_through] != NO_MON) return E_MON_TWICE;
if (d[seen_through] != NO_DAY) return E_DAY_TWICE;
FromDSE(tok.val, &y[seen_through], &m[seen_through], &d[seen_through]);
break;
case T_Year:
DBufFree(&buf);
if (y != NO_YR) return E_YR_TWICE;
y = tok.val;
if (y[seen_through] != NO_YR) return E_YR_TWICE;
y[seen_through] = tok.val;
break;
case T_Month:
DBufFree(&buf);
if (m != NO_MON) return E_MON_TWICE;
m = tok.val;
if (m[seen_through] != NO_MON) return E_MON_TWICE;
m[seen_through] = tok.val;
break;
case T_Day:
DBufFree(&buf);
if (d != NO_DAY) return E_DAY_TWICE;
d = tok.val;
if (d[seen_through] != NO_DAY) return E_DAY_TWICE;
d[seen_through] = tok.val;
break;
case T_Delta:
@@ -338,8 +361,10 @@ int DoOmit(ParsePtr p)
case T_Through:
DBufFree(&buf);
if (y == NO_YR || m == NO_MON || d == NO_DAY) return E_INCOMPLETE;
return DoThroughOmit(p, y, m, d);
if (wd) return E_PARSE_ERR;
if (seen_through) return E_UNTIL_TWICE;
seen_through = 1;
break;
case T_Empty:
case T_Comment:
@@ -358,131 +383,113 @@ int DoOmit(ParsePtr p)
return E_UNKNOWN_TOKEN;
}
}
if (m == NO_MON || d == NO_DAY) return E_SPEC_MON_DAY;
if (y == NO_YR) {
if (NumPartialOmits == MAX_PARTIAL_OMITS) return E_2MANY_PART;
if (wd) {
if (y[0] != NO_YR || m[0] != NO_MON || d[0] != NO_DAY) {
return E_PARSE_ERR;
}
if ((WeekdayOmits | wd) == 0x7F) {
return E_2MANY_LOCALOMIT;
}
WeekdayOmits |= wd;
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
return OK;
}
if (d > MonthDays[m]) return E_BAD_DATE;
syndrome = (m<<5) + d;
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
NumPartialOmits++;
}
if (!seen_through) {
/* We must have at least a month */
if (m[0] == NO_MON) return E_SPEC_MON;
m[1] = m[0];
y[1] = y[0];
if (d[0] == NO_DAY) {
d[0] = 1;
if (y[0] == NO_YR) {
d[1] = MonthDays[m[0]];
} else {
d[1] = DaysInMonth(m[0], y[0]);
}
} else {
d[1] = d[0];
m[1] = m[0];
y[1] = y[0];
}
} else {
if (d > DaysInMonth(m, y)) return E_BAD_DATE;
syndrome = Julian(y, m, d);
r = AddGlobalOmit(syndrome);
if (r) {
return r;
if (m[0] == NO_MON) return E_SPEC_MON;
if (m[1] == NO_MON) return E_SPEC_MON;
if ((y[0] != NO_YR && y[1] == NO_YR) ||
(y[0] == NO_YR && y[1] != NO_YR)) {
return E_BAD_DATE;
}
if (d[0] == NO_DAY) d[0] = 1;
if (d[1] == NO_DAY) {
if (y[1] == NO_YR) {
d[1] = MonthDays[m[1]];
} else {
d[1] = DaysInMonth(m[1], y[1]);
}
}
}
if (y[0] == NO_YR) {
/* Partial OMITs */
if (d[0] > MonthDays[m[0]]) return E_BAD_DATE;
if (d[1] > MonthDays[m[1]]) return E_BAD_DATE;
dc = d[0];
mc = m[0];
while(1) {
syndrome = (mc<<5) + dc;
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
NumPartialOmits++;
}
if (mc == m[1] && dc == d[1]) {
break;
}
dc++;
if (dc > MonthDays[mc]) {
dc = 1;
mc++;
if (mc > 11) {
mc = 0;
}
}
}
} else {
/* Full OMITs */
if (d[0] > DaysInMonth(m[0], y[0])) return E_BAD_DATE;
if (d[1] > DaysInMonth(m[1], y[1])) return E_BAD_DATE;
start = DSE(y[0], m[0], d[0]);
end = DSE(y[1], m[1], d[1]);
if (end < start) {
Eprint("Error: THROUGH date earlier than start date");
return E_BAD_DATE;
}
for (tmp = start; tmp <= end; tmp++) {
if (!BexistsIntArray(FullOmitArray, NumFullOmits, tmp)) {
if (NumFullOmits >= MAX_FULL_OMITS) return E_2MANY_FULL;
InsertIntoSortedArray(FullOmitArray, NumFullOmits, tmp);
NumFullOmits++;
}
}
}
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
return OK;
}
int
AddGlobalOmit(int jul)
AddGlobalOmit(int dse)
{
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
if (!BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
InsertIntoSortedArray(FullOmitArray, NumFullOmits, jul);
if (!BexistsIntArray(FullOmitArray, NumFullOmits, dse)) {
InsertIntoSortedArray(FullOmitArray, NumFullOmits, dse);
NumFullOmits++;
}
return OK;
}
static int
DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
{
int yend = NO_YR, mend = NO_MON, dend = NO_DAY, r;
int start, end, tmp;
int parsing = 1;
Token tok;
DynamicBuffer buf;
DBufInit(&buf);
while(parsing) {
if ( (r=ParseToken(p, &buf)) ) return r;
FindToken(DBufValue(&buf), &tok);
switch(tok.type) {
case T_Date:
DBufFree(&buf);
if (yend != NO_YR) return E_YR_TWICE;
if (mend != NO_MON) return E_MON_TWICE;
if (dend != NO_DAY) return E_DAY_TWICE;
FromJulian(tok.val, &yend, &mend, &dend);
break;
case T_Year:
DBufFree(&buf);
if (yend != NO_YR) return E_YR_TWICE;
yend = tok.val;
break;
case T_Month:
DBufFree(&buf);
if (mend != NO_MON) return E_MON_TWICE;
mend = tok.val;
break;
case T_Day:
DBufFree(&buf);
if (dend != NO_DAY) return E_DAY_TWICE;
dend = tok.val;
break;
case T_Empty:
case T_Comment:
case T_RemType:
case T_Priority:
case T_Tag:
case T_Duration:
DBufFree(&buf);
parsing = 0;
break;
default:
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
DBufValue(&buf));
DBufFree(&buf);
return E_UNKNOWN_TOKEN;
}
}
if (yend == NO_YR || mend == NO_MON || dend == NO_DAY) return E_INCOMPLETE;
if (dend > DaysInMonth(mend, yend)) return E_BAD_DATE;
if (dstart > DaysInMonth(mstart, ystart)) return E_BAD_DATE;
start = Julian(ystart, mstart, dstart);
end = Julian(yend, mend, dend);
if (end < start) {
Wprint("Warning: Swapping dates on OMIT ... THROUGH ... line");
tmp = start;
start = end;
end = tmp;
}
tmp = end - start + 1;
/* Don't create any OMITs if there would be too many. */
if (NumFullOmits + tmp >= MAX_FULL_OMITS) return E_2MANY_FULL;
for (tmp = start; tmp <= end; tmp++) {
if (!BexistsIntArray(FullOmitArray, NumFullOmits, tmp)) {
InsertIntoSortedArray(FullOmitArray, NumFullOmits, tmp);
NumFullOmits++;
}
}
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
return OK;
}
void
DumpOmits(void)
{
@@ -493,7 +500,7 @@ DumpOmits(void)
printf("\tNone.\n");
} else {
for (i=0; i<NumFullOmits; i++) {
FromJulian(FullOmitArray[i], &y, &m, &d);
FromDSE(FullOmitArray[i], &y, &m, &d);
printf("\t%04d%c%02d%c%02d\n",
y, DateSep, m+1, DateSep, d);
}
@@ -508,5 +515,15 @@ DumpOmits(void)
printf("\t%02d%c%02d\n", m+1, DateSep, d);
}
}
printf("Global Weekday OMITs:\n");
if (WeekdayOmits == 0) {
printf("\tNone.\n");
} else {
for (i=0; i<7; i++) {
if (WeekdayOmits & (1<<i)) {
printf("\t%s\n", EnglishDayName[i]);
}
}
}
}

View File

@@ -5,7 +5,8 @@
/* Function Prototypes. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -22,9 +23,11 @@
#define isempty(c) (isspace(c) || ((c) == '\\'))
#include "dynbuf.h"
#include <ctype.h>
int CallUserFunc (char const *name, int nargs, ParsePtr p);
int DoFset (ParsePtr p);
int DoFunset (ParsePtr p);
void ProduceCalendar (void);
char const *SimpleTime (int tim);
char const *CalendarTime (int tim, int duration);
@@ -32,11 +35,11 @@ int DoRem (ParsePtr p);
int DoFlush (ParsePtr p);
void DoExit (ParsePtr p);
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul);
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
int ParseLiteralDate (char const **s, int *jul, int *tim);
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse);
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
int ParseLiteralDate (char const **s, int *dse, int *tim);
int ParseLiteralTime (char const **s, int *tim);
int EvalExpr (char const **e, Value *v, ParsePtr p);
int DoCoerce (char type, Value *v);
@@ -48,13 +51,13 @@ int DoInclude (ParsePtr p, enum TokTypes tok);
int DoIncludeCmd (ParsePtr p);
int IncludeFile (char const *fname);
int GetAccessDate (char const *file);
int SetAccessDate (char const *fname, int jul);
int SetAccessDate (char const *fname, int dse);
int TopLevel (void);
int CallFunc (BuiltinFunc *f, int nargs);
void InitRemind (int argc, char const *argv[]);
void Usage (void);
int Julian (int year, int month, int day);
void FromJulian (int jul, int *y, int *m, int *d);
int DSE (int year, int month, int day);
void FromDSE (int dse, int *y, int *m, int *d);
int ParseChar (ParsePtr p, int *err, int peek);
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
@@ -84,7 +87,7 @@ int DoClear (ParsePtr p);
int DestroyOmitContexts (void);
int PushOmitContext (ParsePtr p);
int PopOmitContext (ParsePtr p);
int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
int IsOmitted (int dse, int localomit, char const *omitfunc, int *omit);
int DoOmit (ParsePtr p);
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
void HandleQueuedReminders (void);
@@ -118,24 +121,24 @@ unsigned int HashVal (char const *str);
int DateOK (int y, int m, int d);
Operator *FindOperator (char const *name, Operator where[], int num);
BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
int InsertIntoSortBuffer (int jul, int tim, char const *body, int typ, int prio);
int InsertIntoSortBuffer (int dse, int tim, char const *body, int typ, int prio);
void IssueSortedReminders (void);
int UserFuncExists (char const *fn);
void JulToHeb (int jul, int *hy, int *hm, int *hd);
void DSEToHeb (int dse, int *hy, int *hm, int *hd);
int HebNameToNum (char const *mname);
char const *HebMonthName (int m, int y);
int RoshHashana (int i);
long DaysToHebYear (int y);
int DaysInHebYear (int y);
char const *DaysInHebMonths (int ylen);
int HebToJul (int hy, int hm, int hd);
int HebToDSE (int hy, int hm, int hd);
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
int GetNextHebrewDate (int julstart, int hm, int hd, int yahr, int adarbehave, int *ans);
int GetNextHebrewDate (int dsestart, int hm, int hd, int yahr, int adarbehave, int *ans);
int ComputeJahr (int y, int m, int d, int *ans);
int GetSysVar (char const *name, Value *val);
int SetSysVar (char const *name, Value *val);
void DumpSysVarByName (char const *name);
int CalcMinsFromUTC (int jul, int tim, int *mins, int *isdst);
int CalcMinsFromUTC (int dse, int tim, int *mins, int *isdst);
void FillParagraph (char const *s);
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
@@ -143,7 +146,7 @@ int MoonPhase (int date, int time);
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
void SigIntHandler (int d);
void GotSigInt (void);
int GotSigInt (void);
void PurgeEchoLine(char const *fmt, ...);
void FreeTrig(Trigger *t);
void AppendTag(DynamicBuffer *buf, char const *s);
@@ -154,17 +157,17 @@ void SaveLastTimeTrig(TimeTrig const *t);
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
void PerIterationInit(void);
char const *Decolorize(int r, int g, int b);
char const *Colorize(int r, int g, int b);
char const *Decolorize(void);
char const *Colorize(int r, int g, int b, int bg, int clamp);
void PrintJSONString(char const *s);
void PrintJSONKeyPairInt(char const *name, int val);
void PrintJSONKeyPairString(char const *name, char const *val);
void PrintJSONKeyPairDate(char const *name, int jul);
void PrintJSONKeyPairDate(char const *name, int dse);
void PrintJSONKeyPairDateTime(char const *name, int dt);
void PrintJSONKeyPairTime(char const *name, int t);
void System(char const *cmd);
int ShellEscape(char const *in, DynamicBuffer *out);
int AddGlobalOmit(int jul);
int AddGlobalOmit(int dse);
void set_lat_and_long_from_components(void);
void set_components_from_lat_and_long(void);
@@ -176,3 +179,9 @@ void clear_callstack(void);
int have_callstack(void);
int print_callstack(FILE *fp);
void pop_call(void);
#ifdef REM_USE_WCHAR
#define _XOPEN_SOURCE 600
#include <wctype.h>
#include <wchar.h>
void PutWideChar(wchar_t const wc);
#endif

View File

@@ -5,7 +5,8 @@
/* Queue up reminders for subsequent execution. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -59,6 +60,7 @@ static QueuedRem *FindNextReminder (void);
static int CalculateNextTimeUsingSched (QueuedRem *q);
static void DaemonWait (struct timeval *sleep_tv);
static void reread (void);
static void PrintQueue(void);
/***************************************************************/
/* */
@@ -74,6 +76,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
QueuedRem *qelem;
if (DontQueue ||
trig->noqueue ||
tim->ttime == NO_TIME ||
trig->typ == CAL_TYPE ||
tim->ttime < SystemTime(0) / 60 ||
@@ -123,9 +126,10 @@ void HandleQueuedReminders(void)
Trigger trig;
struct timeval tv;
struct timeval sleep_tv;
struct sigaction sa;
/* Suppress the BANNER from being issued */
NumTriggered = 1;
DidMsgReminder = 1;
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
SortByDate = 0;
@@ -161,7 +165,11 @@ void HandleQueuedReminders(void)
q = q->next;
}
if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
if (!DontFork || Daemon) {
sa.sa_handler = SigIntHandler;
sa.sa_flags = 0;
(void) sigaction(SIGINT, &sa, NULL);
}
/* Sit in a loop, issuing reminders when necessary */
while(1) {
@@ -184,7 +192,9 @@ void HandleQueuedReminders(void)
while (TimeToSleep > 0L) {
SleepTime = TimeToSleep;
if (Daemon > 0 && SleepTime > (unsigned int) 60*Daemon) SleepTime = 60*Daemon;
if (Daemon > 0 && SleepTime > (unsigned int) 60*Daemon) {
SleepTime = 60*Daemon;
}
/* Wake up once a minute to recalibrate sleep time in
case of laptop hibernation */
@@ -203,6 +213,10 @@ void HandleQueuedReminders(void)
sleep(SleepTime);
}
if (GotSigInt()) {
PrintQueue();
}
/* If not in daemon mode and day has rolled around,
exit -- not much we can do. */
if (!Daemon) {
@@ -252,8 +266,8 @@ void HandleQueuedReminders(void)
/* Set up global variables so some functions like trigdate()
and trigtime() work correctly */
SaveAllTriggerInfo(&(q->t), &(q->tt), JulianToday, q->tt.ttime, 1);
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
SaveAllTriggerInfo(&(q->t), &(q->tt), DSEToday, q->tt.ttime, 1);
(void) TriggerReminder(&p, &trig, &q->tt, DSEToday);
if (Daemon < 0) {
printf("NOTE endreminder\n");
}
@@ -335,13 +349,13 @@ static QueuedRem *FindNextReminder(void)
/***************************************************************/
/* */
/* GotSigInt */
/* PrintQueue */
/* */
/* Split out what's done on a SIGINT from the SIGINT Handler. */
/* This will be necessary for OS/2 multithreaded. */
/* For debugging: Print queue contents to STDOUT */
/* */
/***************************************************************/
void GotSigInt(void)
static
void PrintQueue(void)
{
QueuedRem *q = QueueHead;
@@ -366,6 +380,7 @@ void GotSigInt(void)
q = q->next;
}
printf(NL);
printf("To terminate program, send SIGQUIT (probably Ctrl-\\ on the keyboard.)%s", NL);
}
/***************************************************************/

View File

@@ -5,7 +5,8 @@
/* Print a PostScript calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -349,7 +350,7 @@ int main(int argc, char *argv[])
!strcmp(DBufValue(&buf), PSBEGIN2)) {
if (!validfile) {
if (Verbose) {
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2022 by Dianne Skoll\n\n", VERSION);
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2023 by Dianne Skoll\n\n", VERSION);
fprintf(stderr, "Generating PostScript calendar\n");
}
}

View File

@@ -5,7 +5,8 @@
/* Define the PostScript prologue */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -13,7 +14,7 @@ char *PSProlog1[] =
{
"% This file was produced by Remind and Rem2PS, written by",
"% Dianne Skoll.",
"% Remind and Rem2PS are Copyright 1992-2022 Dianne Skoll.",
"% Remind and Rem2PS are Copyright 1992-2023 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,8 @@
/* Routines for sorting reminders by trigger date */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -34,8 +35,8 @@ typedef struct sortrem {
/* The sorted reminder queue */
static Sortrem *SortedQueue = (Sortrem *) NULL;
static Sortrem *MakeSortRem (int jul, int tim, char const *body, int typ, int prio);
static void IssueSortBanner (int jul);
static Sortrem *MakeSortRem (int dse, int tim, char const *body, int typ, int prio);
static void IssueSortBanner (int dse);
/***************************************************************/
/* */
@@ -44,7 +45,7 @@ static void IssueSortBanner (int jul);
/* Create a new Sortrem entry - return NULL on failure. */
/* */
/***************************************************************/
static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int prio)
static Sortrem *MakeSortRem(int dse, int tim, char const *body, int typ, int prio)
{
Sortrem *new = NEW(Sortrem);
if (!new) return NULL;
@@ -55,7 +56,7 @@ static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int pri
return NULL;
}
new->trigdate = jul;
new->trigdate = dse;
new->trigtime = tim;
new->typ = typ;
new->priority = prio;
@@ -70,9 +71,9 @@ static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int pri
/* Insert a reminder into the sort buffer */
/* */
/***************************************************************/
int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
int InsertIntoSortBuffer(int dse, int tim, char const *body, int typ, int prio)
{
Sortrem *new = MakeSortRem(jul, tim, body, typ, prio);
Sortrem *new = MakeSortRem(dse, tim, body, typ, prio);
Sortrem *cur = SortedQueue, *prev = NULL;
int ShouldGoAfter;
@@ -168,7 +169,7 @@ void IssueSortedReminders(void)
/* defined to take one argument. */
/* */
/***************************************************************/
static void IssueSortBanner(int jul)
static void IssueSortBanner(int dse)
{
char BanExpr[64];
int y, m, d;
@@ -178,13 +179,13 @@ static void IssueSortBanner(int jul)
if (UserFuncExists("sortbanner") != 1) return;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
y = EvalExpr(&s, &v, NULL);
if (y) return;
if (DoCoerce(STR_TYPE, &v)) return;
DBufInit(&buf);
if (!DoSubstFromString(v.v.str, &buf, jul, NO_TIME)) {
if (!DoSubstFromString(v.v.str, &buf, dse, NO_TIME)) {
if (*DBufValue(&buf)) printf("%s\n", DBufValue(&buf));
DBufFree(&buf);
}

View File

@@ -6,7 +6,8 @@
/* classifying the tokens parsed. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -62,6 +63,7 @@ Token TokArray[] = {
{ "friday", 3, T_WkDay, 4 },
{ "from", 4, T_Scanfrom, FROM_TYPE },
{ "fset", 4, T_Fset, 0 },
{ "funset", 6, T_Funset, 0 },
{ "if", 2, T_If, 0 },
{ "iftrig", 6, T_IfTrig, 0 },
{ "in", 2, T_In, 0 },
@@ -79,6 +81,7 @@ Token TokArray[] = {
{ "monday", 3, T_WkDay, 0 },
{ "msf", 3, T_RemType, MSF_TYPE },
{ "msg", 3, T_RemType, MSG_TYPE },
{ "noqueue", 7, T_NoQueue, 0 },
{ "november", 3, T_Month, 10 },
{ "october", 3, T_Month, 9 },
{ "omit", 3, T_Omit, 0 },
@@ -238,16 +241,16 @@ void FindNumericToken(char const *s, Token *t)
/* If we hit a '-' or a '/', we may have a date or a datetime */
if (*s == '-' || *s == '/') {
char const *p = s_orig;
int jul, tim;
if (ParseLiteralDate(&p, &jul, &tim) == OK) {
int dse, tim;
if (ParseLiteralDate(&p, &dse, &tim) == OK) {
if (*p) return;
if (tim == NO_TIME) {
t->type = T_Date;
t->val = jul;
t->val = dse;
return;
}
t->type = T_DateTime;
t->val = MINUTES_PER_DAY * jul + tim;
t->val = MINUTES_PER_DAY * dse + tim;
}
return;
}
@@ -354,7 +357,8 @@ static int TokStrCmp(Token const *t, char const *s)
register int r;
char const *tk = t->name;
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
r = tolower(*tk) - tolower(*s);
/* t->name is already lower-case */
r = *tk - tolower(*s);
tk++;
s++;
if (r) return r;
@@ -362,5 +366,5 @@ static int TokStrCmp(Token const *t, char const *s)
/* Ignore trailing commas on s */
if (!*s || (*s == ',' && !*(s+1))) return 0;
return (tolower(*tk) - tolower(*s));
return (*tk - tolower(*s));
}

View File

@@ -5,7 +5,8 @@
/* Routines for figuring out the trigger date of a reminder */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -26,8 +27,8 @@
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
static int JYear(int jul);
static int JMonth(int jul);
static int DSEYear(int dse);
static int DSEMonth(int dse);
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart);
@@ -39,7 +40,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* ONLY the day of week, day, month and year components. */
/* Normally, returns -1 if the trigger has expired. As a */
/* special case, if D, M, Y [WD] are specified, returns the */
/* Julian date, regardless of whether it's expired. This is */
/* DSE date, regardless of whether it's expired. This is */
/* so that dates with a REP can be handled properly. */
/* */
/***************************************************************/
@@ -49,7 +50,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
int d, m, y, j, d2, m2, y2;
*err = 0;
FromJulian(startdate, &y, &m, &d);
FromDSE(startdate, &y, &m, &d);
d2 = d;
m2 = m;
y2 = y;
@@ -72,17 +73,17 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
if (m == 12) { m = 0; y++; }
}
while (trig->d > DaysInMonth(m, trig->y)) m++;
j = Julian(y, m, trig->d);
j = DSE(y, m, trig->d);
return j;
case GOT_MON:
if (m == trig->m) return startdate;
else if (m > trig->m) return Julian(y+1, trig->m, 1);
else return Julian(y, trig->m, 1);
else if (m > trig->m) return DSE(y+1, trig->m, 1);
else return DSE(y, trig->m, 1);
case GOT_YR:
if (y == trig->y) return startdate;
else if (y < trig->y) return Julian(trig->y, 0, 1);
else if (y < trig->y) return DSE(trig->y, 0, 1);
else return -1;
case GOT_DAY+GOT_MON:
@@ -94,10 +95,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
/* Take care of Feb. 29 */
while (trig->d > DaysInMonth(trig->m, y)) y++;
return Julian(y, trig->m, trig->d);
return DSE(y, trig->m, trig->d);
case GOT_DAY+GOT_YR:
if (y < trig->y) return Julian(trig->y, 0, trig->d);
if (y < trig->y) return DSE(trig->y, 0, trig->d);
else if (y > trig->y) return -1;
if (d > trig->d) {
@@ -105,37 +106,37 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
if (m == 12) return -1;
}
while (trig->d > DaysInMonth(m, trig->y)) m++;
return Julian(trig->y, m, trig->d);
return DSE(trig->y, m, trig->d);
case GOT_MON+GOT_YR:
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
if (y < trig->y) return Julian(trig->y, trig->m, 1);
if (y < trig->y) return DSE(trig->y, trig->m, 1);
if (m == trig->m) return startdate;
return Julian(trig->y, trig->m, 1);
return DSE(trig->y, trig->m, 1);
case GOT_DAY+GOT_MON+GOT_YR:
if (trig->d > DaysInMonth(trig->m, trig->y)) {
*err = E_BAD_DATE;
return -1;
}
return Julian(trig->y, trig->m, trig->d);
return DSE(trig->y, trig->m, trig->d);
case GOT_YR+GOT_WD:
if (y > trig->y) return -1;
if (y < trig->y) j = Julian(trig->y, 0, 1);
if (y < trig->y) j = DSE(trig->y, 0, 1);
else j = startdate;
ADVANCE_TO_WD(j, trig->wd);
if (JYear(j) > trig->y) return -1;
if (DSEYear(j) > trig->y) return -1;
return j;
case GOT_MON+GOT_WD:
if (m == trig->m) {
j = startdate;
ADVANCE_TO_WD(j, trig->wd);
if (JMonth(j) == trig->m) return j;
if (DSEMonth(j) == trig->m) return j;
}
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
else j = Julian(y, trig->m, 1);
if (m >= trig->m) j = DSE(y+1, trig->m, 1);
else j = DSE(y, trig->m, 1);
ADVANCE_TO_WD(j, trig->wd);
return j; /* Guaranteed to be within the month */
@@ -146,7 +147,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
/* If there are fewer days in previous month, no match */
if (trig->d <= DaysInMonth(m2, y2)) {
j = Julian(y2, m2, trig->d);
j = DSE(y2, m2, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (j >= startdate) return j;
@@ -155,7 +156,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
/* Try this month */
if (trig->d <= DaysInMonth(m, y)) {
j = Julian(y, m, trig->d);
j = DSE(y, m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (j >= startdate) return j;
}
@@ -164,18 +165,18 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
m2 = m+1;
if (m2 > 11) { m2 = 0; y++; }
while (trig->d > DaysInMonth(m2, y)) m2++;
j = Julian(y, m2, trig->d);
j = DSE(y, m2, trig->d);
ADVANCE_TO_WD(j, trig->wd);
return j;
case GOT_WD+GOT_YR+GOT_DAY:
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
if (y > trig->y) {
j = Julian(trig->y, 11, trig->d);
j = DSE(trig->y, 11, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (j >= startdate) return j;
} else if (y < trig->y) {
j = Julian(trig->y, 0, trig->d);
j = DSE(trig->y, 0, trig->d);
ADVANCE_TO_WD(j, trig->wd);
return j;
} else {
@@ -183,17 +184,17 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
if (m > 0) {
m2 = m-1;
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
j = Julian(trig->y, m2, trig->d);
j = DSE(trig->y, m2, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (JYear(j) > trig->y) return -1;
if (DSEYear(j) > trig->y) return -1;
if (j >= startdate) return j;
}
}
/* Try this month */
if (trig->d <= DaysInMonth(m, trig->y)) {
j = Julian(trig->y, m, trig->d);
j = DSE(trig->y, m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (JYear(j) > trig->y) return -1;
if (DSEYear(j) > trig->y) return -1;
if (j >= startdate) return j;
}
@@ -201,9 +202,9 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
if (m == 11) return -1;
m++;
while (trig->d > DaysInMonth(m, trig->d)) m++;
j = Julian(trig->y, m, trig->d);
j = DSE(trig->y, m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (JYear(j) > trig->y) return -1;
if (DSEYear(j) > trig->y) return -1;
return j;
case GOT_DAY+GOT_MON+GOT_WD:
@@ -220,34 +221,34 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
while (trig->d > DaysInMonth(trig->m, y)) y++;
/* Try last year */
j = Julian(y, trig->m, trig->d);
j = DSE(y, trig->m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (j >= startdate) return j;
/* Try this year */
y++;
while (trig->d > DaysInMonth(trig->m, y)) y++;
j = Julian(y, trig->m, trig->d);
j = DSE(y, trig->m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
if (j >= startdate) return j;
/* Must be next year */
y++;
while (trig->d > DaysInMonth(trig->m, y)) y++;
j = Julian(y, trig->m, trig->d);
j = DSE(y, trig->m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
return j;
case GOT_WD+GOT_MON+GOT_YR:
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
if (trig->y > y || (trig->y == y && trig->m > m)) {
j = Julian(trig->y, trig->m, 1);
j = DSE(trig->y, trig->m, 1);
ADVANCE_TO_WD(j, trig->wd);
return j;
} else {
j = startdate;
ADVANCE_TO_WD(j, trig->wd);
FromJulian(j, &y2, &m2, &d2);
FromDSE(j, &y2, &m2, &d2);
if (m2 == trig->m) return j; else return -1;
}
@@ -256,7 +257,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
*err = E_BAD_DATE;
return -1;
}
j = Julian(trig->y, trig->m, trig->d);
j = DSE(trig->y, trig->m, trig->d);
ADVANCE_TO_WD(j, trig->wd);
return j;
@@ -269,25 +270,25 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
/***************************************************************/
/* */
/* JMonth - Given a Julian date, what's the month? */
/* DSEMonth - Given a DSE date, what's the month? */
/* */
/***************************************************************/
static int JMonth(int jul)
static int DSEMonth(int dse)
{
int y, m, d;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
return m;
}
/***************************************************************/
/* */
/* JYear - Given a Julian date, what's the year? */
/* DSEYear - Given a DSE date, what's the year? */
/* */
/***************************************************************/
static int JYear(int jul)
static int DSEYear(int dse)
{
int y, m, d;
FromJulian(jul, &y, &m, &d);
FromDSE(dse, &y, &m, &d);
return y;
}
@@ -297,7 +298,7 @@ static int JYear(int jul)
/* */
/* Given a trigger, compute the next trigger date. */
/* */
/* Returns the Julian date of next trigger, -1 if */
/* Returns the DSE date of next trigger, -1 if */
/* expired, -2 if can't compute trigger date. */
/* */
/***************************************************************/
@@ -439,7 +440,7 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
/* Change trigger date to today */
r = today;
if (DebugFlag & DB_PRTTRIG) {
FromJulian(r, &y, &m, &d);
FromDSE(r, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
FileName, LineNo,
get_day_name(r % 7),
@@ -530,7 +531,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
*err = OK;
/* But check for obvious problems... */
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
if ((WeekdayOmits | trig->localomit) == 0x7F) {
*err = E_2MANY_LOCALOMIT;
return -1;
}
@@ -590,7 +591,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
LastTrigValid = 1;
}
if (DebugFlag & DB_PRTTRIG) {
FromJulian(result, &y, &m, &d);
FromDSE(result, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
FileName, LineNo,
get_day_name(result % 7),

View File

@@ -5,7 +5,8 @@
/* Type definitions all dumped here. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -77,6 +78,7 @@ typedef struct {
int eventduration; /* Original event duration (minutes) */
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
int addomit; /* Add trigger date to global OMITs */
int noqueue; /* Don't queue even if timed */
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
@@ -155,8 +157,8 @@ enum TokTypes
/* Commands first */
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeR, T_IncludeCmd, T_If, T_Else, T_EndIf,
T_IfTrig, T_ErrMsg,
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
T_AddOmit,
T_Set, T_UnSet, T_Fset, T_Funset, T_Omit, T_Banner, T_Exit,
T_AddOmit, T_NoQueue,
T_WkDay,
T_Month, T_Time, T_Date, T_DateTime,
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta,
@@ -238,6 +240,6 @@ typedef struct {
/* Pure JSON */
#define PSCAL_LEVEL3 3
#define TERMINAL_BACKGROUND_UNKNOWN 0
#define TERMINAL_BACKGROUND_DARK 1
#define TERMINAL_BACKGROUND_LIGHT 2
#define TERMINAL_BACKGROUND_UNKNOWN -1
#define TERMINAL_BACKGROUND_DARK 0
#define TERMINAL_BACKGROUND_LIGHT 1

View File

@@ -6,7 +6,8 @@
/* functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -53,6 +54,34 @@ static void FSet (UserFunc *f);
static int SetUpLocalVars (UserFunc *f);
static void DestroyLocalVals (UserFunc *f);
/***************************************************************/
/* */
/* DoFunset */
/* */
/* Undefine a user-defined function - the FUNSET command. */
/* */
/***************************************************************/
int DoFunset(ParsePtr p)
{
int r;
int seen_one = 0;
DynamicBuffer buf;
DBufInit(&buf);
while(1) {
r = ParseIdentifier(p, &buf);
if (r == E_EOLN) {
DBufFree(&buf);
break;
}
seen_one = 1;
FUnset(DBufValue(&buf));
DBufFree(&buf);
}
if (seen_one) return OK;
return E_PARSE_ERR;
}
/***************************************************************/
/* */
/* DoFset */

View File

@@ -5,7 +5,8 @@
/* Useful utility functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -24,8 +25,6 @@ static char const DontEscapeMe[] =
#include "globals.h"
#include "protos.h"
#define UPPER(c) toupper(c)
/***************************************************************/
/* */
/* StrnCpy */
@@ -68,12 +67,12 @@ int StrinCmp(char const *s1, char const *s2, int n)
register int r;
while (n && *s1 && *s2) {
n--;
r = UPPER(*s1) - UPPER(*s2);
r = toupper(*s1) - toupper(*s2);
if (r) return r;
s1++;
s2++;
}
if (n) return (UPPER(*s1) - UPPER(*s2)); else return 0;
if (n) return (toupper(*s1) - toupper(*s2)); else return 0;
}
/***************************************************************/
@@ -102,12 +101,12 @@ int StrCmpi(char const *s1, char const *s2)
{
int r;
while (*s1 && *s2) {
r = UPPER(*s1) - UPPER(*s2);
r = toupper(*s1) - toupper(*s2);
if (r) return r;
s1++;
s2++;
}
return UPPER(*s1) - UPPER(*s2);
return toupper(*s1) - toupper(*s2);
}
/***************************************************************/

260
src/var.c
View File

@@ -6,7 +6,8 @@
/* user- and system-defined variables. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-2022 by Dianne Skoll */
/* Copyright (C) 1992-2023 by Dianne Skoll */
/* SPDX-License-Identifier: GPL-2.0-only */
/* */
/***************************************************************/
@@ -170,10 +171,11 @@ static int latitude_func(int do_set, Value *val)
static int trig_date_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = DATE_TYPE;
if (!LastTrigValid) {
val->type = INT_TYPE;
val->v.val = 0;
} else {
val->type = DATE_TYPE;
val->v.val = LastTriggerDate;
}
return OK;
@@ -188,7 +190,7 @@ static int trig_day_func(int do_set, Value *val)
return OK;
}
FromJulian(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, &y, &m, &d);
val->v.val = d;
return OK;
}
@@ -203,7 +205,7 @@ static int trig_mon_func(int do_set, Value *val)
return OK;
}
FromJulian(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, &y, &m, &d);
val->v.val = m+1;
return OK;
}
@@ -218,7 +220,7 @@ static int trig_year_func(int do_set, Value *val)
return OK;
}
FromJulian(LastTriggerDate, &y, &m, &d);
FromDSE(LastTriggerDate, &y, &m, &d);
val->v.val = y;
return OK;
}
@@ -240,7 +242,7 @@ static int today_date_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = DATE_TYPE;
val->v.val = JulianToday;
val->v.val = DSEToday;
return OK;
}
static int today_day_func(int do_set, Value *val)
@@ -248,7 +250,7 @@ static int today_day_func(int do_set, Value *val)
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
FromDSE(DSEToday, &y, &m, &d);
val->v.val = d;
return OK;
}
@@ -258,7 +260,7 @@ static int today_mon_func(int do_set, Value *val)
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
FromDSE(DSEToday, &y, &m, &d);
val->v.val = m+1;
return OK;
}
@@ -268,7 +270,7 @@ static int today_year_func(int do_set, Value *val)
int y, m, d;
UNUSED(do_set);
val->type = INT_TYPE;
FromJulian(JulianToday, &y, &m, &d);
FromDSE(DSEToday, &y, &m, &d);
val->v.val = y;
return OK;
}
@@ -277,7 +279,7 @@ static int today_wday_func(int do_set, Value *val)
{
UNUSED(do_set);
val->type = INT_TYPE;
val->v.val = (JulianToday + 1) % 7;
val->v.val = (DSEToday + 1) % 7;
return OK;
}
@@ -762,7 +764,6 @@ typedef struct {
void *value;
int min;
int max;
int (*validate)(void const *newvalue);
} SysVar;
/* If the type of a sys variable is STR_TYPE, then min is redefined
@@ -774,100 +775,107 @@ typedef struct {
/* All of the system variables sorted alphabetically */
static SysVar SysVarArr[] = {
/* name mod type value min/mal max validate*/
{"Ago", 1, STR_TYPE, &DynamicAgo, 0, 0, NULL },
{"Am", 1, STR_TYPE, &DynamicAm, 0, 0, NULL },
{"And", 1, STR_TYPE, &DynamicAnd, 0, 0, NULL },
{"April", 1, STR_TYPE, &DynamicMonthName[3], 0, 0, NULL },
{"At", 1, STR_TYPE, &DynamicAt, 0, 0, NULL },
{"August", 1, STR_TYPE, &DynamicMonthName[7], 0, 0, NULL },
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1, NULL },
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0, NULL },
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0, NULL },
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0, NULL },
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0, NULL },
{"December", 1, STR_TYPE, &DynamicMonthName[11],0, 0, NULL },
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0, NULL },
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999, NULL },
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, 1440, NULL },
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0, NULL },
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0, NULL },
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0, NULL },
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0, NULL },
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0, NULL },
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0, NULL },
{"February", 1, STR_TYPE, &DynamicMonthName[1], 0, 0, NULL },
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132, NULL },
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1, NULL },
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500, NULL },
{"Friday", 1, STR_TYPE, &DynamicDayName[4], 0, 0, NULL },
{"Fromnow", 1, STR_TYPE, &DynamicFromnow, 0, 0, NULL },
{"Hour", 1, STR_TYPE, &DynamicHour, 0, 0, NULL },
{"Hplu", 1, STR_TYPE, &DynamicHplu, 0, 0, NULL },
{"HushMode", 0, INT_TYPE, &Hush, 0, 0, NULL },
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0, NULL },
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0, NULL },
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0, NULL },
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0, NULL },
{"Is", 1, STR_TYPE, &DynamicIs, 0, 0, NULL },
{"January", 1, STR_TYPE, &DynamicMonthName[0], 0, 0, NULL },
{"July", 1, STR_TYPE, &DynamicMonthName[6], 0, 0, NULL },
{"June", 1, STR_TYPE, &DynamicMonthName[5], 0, 0, NULL },
{"LatDeg", 1, SPECIAL_TYPE, latdeg_func, 0, 0, NULL },
{"Latitude", 1, SPECIAL_TYPE, latitude_func, 0, 0, NULL },
{"LatMin", 1, SPECIAL_TYPE, latmin_func, 0, 0, NULL },
{"LatSec", 1, SPECIAL_TYPE, latsec_func, 0, 0, NULL },
{"Location", 1, STR_TYPE, &Location, 0, 0, NULL },
{"LongDeg", 1, SPECIAL_TYPE, longdeg_func, 0, 0, NULL },
{"Longitude", 1, SPECIAL_TYPE, longitude_func, 0, 0, NULL },
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0, NULL },
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0, NULL },
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0, NULL },
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY, NULL },
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY, NULL },
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0, NULL },
{"MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -780, 780, NULL },
{"Minute", 1, STR_TYPE, &DynamicMinute, 0, 0, NULL },
{"Monday", 1, STR_TYPE, &DynamicDayName[0], 0, 0, NULL },
{"Mplu", 1, STR_TYPE, &DynamicMplu, 0, 0, NULL },
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0, NULL },
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0, NULL },
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0, NULL },
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0, NULL },
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0, NULL },
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0, NULL },
{"On", 1, STR_TYPE, &DynamicOn, 0, 0, NULL },
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0, NULL },
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0, NULL },
{"PSCal", 0, INT_TYPE, &PsCal, 0, 0, NULL },
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0, NULL },
{"Saturday", 1, STR_TYPE, &DynamicDayName[5], 0, 0, NULL },
{"September", 1, STR_TYPE, &DynamicMonthName[8], 0, 0, NULL },
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0, NULL },
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0, NULL },
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0, NULL },
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0, NULL },
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132, NULL },
{"Sunday", 1, STR_TYPE, &DynamicDayName[6], 0, 0, NULL },
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0, NULL },
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0, NULL },
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0, NULL },
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0, NULL },
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0, NULL },
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0, NULL },
{"Today", 1, STR_TYPE, &DynamicToday, 0, 0, NULL },
{"Tomorrow", 1, STR_TYPE, &DynamicTomorrow, 0, 0, NULL },
{"Tuesday", 1, STR_TYPE, &DynamicDayName[1], 0, 0, NULL },
{"Tw", 0, SPECIAL_TYPE, trig_wday_func, 0, 0, NULL },
{"Ty", 0, SPECIAL_TYPE, trig_year_func, 0, 0, NULL },
{"U", 0, SPECIAL_TYPE, today_date_func, 0, 0, NULL },
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0, NULL },
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0, NULL },
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0, NULL },
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0, NULL },
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0, NULL },
{"Was", 1, STR_TYPE, &DynamicWas, 0, 0, NULL },
{"Wednesday", 1, STR_TYPE, &DynamicDayName[2], 0, 0, NULL }
/* name mod type value min/mal max */
{"AddBlankLines", 1, INT_TYPE, &AddBlankLines, 0, 1 },
{"Ago", 1, STR_TYPE, &DynamicAgo, 0, 0 },
{"Am", 1, STR_TYPE, &DynamicAm, 0, 0 },
{"And", 1, STR_TYPE, &DynamicAnd, 0, 0 },
{"April", 1, STR_TYPE, &DynamicMonthName[3], 0, 0 },
{"At", 1, STR_TYPE, &DynamicAt, 0, 0 },
{"August", 1, STR_TYPE, &DynamicMonthName[7], 0, 0 },
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
{"December", 1, STR_TYPE, &DynamicMonthName[11],0, 0 },
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, 1440 },
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
{"February", 1, STR_TYPE, &DynamicMonthName[1], 0, 0 },
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500 },
{"Friday", 1, STR_TYPE, &DynamicDayName[4], 0, 0 },
{"Fromnow", 1, STR_TYPE, &DynamicFromnow, 0, 0 },
{"Hour", 1, STR_TYPE, &DynamicHour, 0, 0 },
{"Hplu", 1, STR_TYPE, &DynamicHplu, 0, 0 },
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0 },
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0 },
{"Is", 1, STR_TYPE, &DynamicIs, 0, 0 },
{"January", 1, STR_TYPE, &DynamicMonthName[0], 0, 0 },
{"July", 1, STR_TYPE, &DynamicMonthName[6], 0, 0 },
{"June", 1, STR_TYPE, &DynamicMonthName[5], 0, 0 },
{"LatDeg", 1, SPECIAL_TYPE, latdeg_func, 0, 0 },
{"Latitude", 1, SPECIAL_TYPE, latitude_func, 0, 0 },
{"LatMin", 1, SPECIAL_TYPE, latmin_func, 0, 0 },
{"LatSec", 1, SPECIAL_TYPE, latsec_func, 0, 0 },
{"Location", 1, STR_TYPE, &Location, 0, 0 },
{"LongDeg", 1, SPECIAL_TYPE, longdeg_func, 0, 0 },
{"Longitude", 1, SPECIAL_TYPE, longitude_func, 0, 0 },
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0 },
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0 },
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0 },
{"MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -780, 780 },
{"Minute", 1, STR_TYPE, &DynamicMinute, 0, 0 },
{"Monday", 1, STR_TYPE, &DynamicDayName[0], 0, 0 },
{"Mplu", 1, STR_TYPE, &DynamicMplu, 0, 0 },
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0 },
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0 },
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
{"On", 1, STR_TYPE, &DynamicOn, 0, 0 },
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0 },
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0 },
{"PSCal", 0, INT_TYPE, &PsCal, 0, 0 },
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
{"Saturday", 1, STR_TYPE, &DynamicDayName[5], 0, 0 },
{"September", 1, STR_TYPE, &DynamicMonthName[8], 0, 0 },
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 },
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 },
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0 },
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132 },
{"Sunday", 1, STR_TYPE, &DynamicDayName[6], 0, 0 },
{"SuppressLRM", 1, INT_TYPE, &SuppressLRM, 0, 1 },
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0 },
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
{"TerminalBackground", 0, INT_TYPE, &TerminalBackground, 0, 0 },
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0 },
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
{"Today", 1, STR_TYPE, &DynamicToday, 0, 0 },
{"Tomorrow", 1, STR_TYPE, &DynamicTomorrow, 0, 0 },
{"Tuesday", 1, STR_TYPE, &DynamicDayName[1], 0, 0 },
{"Tw", 0, SPECIAL_TYPE, trig_wday_func, 0, 0 },
{"Ty", 0, SPECIAL_TYPE, trig_year_func, 0, 0 },
{"U", 0, SPECIAL_TYPE, today_date_func, 0, 0 },
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0 },
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0 },
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 },
{"Use256Colors", 0, INT_TYPE, &Use256Colors, 0, 0 },
{"UseBGVTColors", 0, INT_TYPE, &UseBGVTColors, 0, 0 },
{"UseTrueColors", 0, INT_TYPE, &UseTrueColors, 0, 0 },
{"UseVTColors", 0, INT_TYPE, &UseVTColors, 0, 0 },
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0 },
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0 },
{"Was", 1, STR_TYPE, &DynamicWas, 0, 0 },
{"Wednesday", 1, STR_TYPE, &DynamicDayName[2], 0, 0 }
};
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
@@ -898,16 +906,7 @@ int SetSysVar(char const *name, Value *value)
DestroyValue(*value);
return r;
}
if (v->validate) {
if (v->type == STR_TYPE) {
r = (v->validate)((void *) value->v.str);
} else {
r = (v->validate)((void *) &(value->v.val));
}
if (r != OK) {
return r;
}
}
if (v->type == STR_TYPE) {
/* If it's already the same, don't bother doing anything */
if (!strcmp(value->v.str, (char const *) v->value)) {
@@ -1021,6 +1020,7 @@ void DumpSysVarByName(char const *name)
static void DumpSysVar(char const *name, const SysVar *v)
{
char buffer[VAR_NAME_LEN+10];
Value vtmp;
if (name && !*name) name=NULL;
if (!v && !name) return; /* Shouldn't happen... */
@@ -1034,32 +1034,20 @@ static void DumpSysVar(char const *name, const SysVar *v)
fprintf(ErrFp, "%16s ", buffer);
if (v) {
if (v->type == SPECIAL_TYPE) {
Value val;
SysVarFunc f = (SysVarFunc) v->value;
f(0, &val);
PrintValue(&val, ErrFp);
f(0, &vtmp);
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
DestroyValue(val);
DestroyValue(vtmp);
} else if (v->type == STR_TYPE) {
char const *s = *((char **)v->value);
int y;
putc('"', ErrFp);
for (y=0; y<MAX_PRT_LEN && *s; y++) {
if (*s == '"') {
fprintf(ErrFp, "\" + char(34) + \"");
s++;
} else {
putc(*s++, ErrFp);
}
}
putc('"', ErrFp);
if (*s) fprintf(ErrFp, "...");
vtmp.type = STR_TYPE;
vtmp.v.str = * ((char **)v->value);
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
} else if (v->type == DATE_TYPE) {
Value val;
val.type = DATE_TYPE;
val.v.val = * (int *) v->value;
PrintValue(&val, ErrFp);
vtmp.type = DATE_TYPE;
vtmp.v.val = * (int *) v->value;
PrintValue(&vtmp, ErrFp);
putc('\n', ErrFp);
} else {
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));

49
tests/ansicolors.rem Normal file
View File

@@ -0,0 +1,49 @@
BANNER %
MSG TerminalBackground is: [$TerminalBackground]%
MSG UseVTColors is: [$UseVTColors]%
MSG Use256Colors is: [$Use256Colors]%
MSG UseTrueColors is: [$UseTrueColors]%
MSG UseBGVTColors is: [$UseBGVTColors]%
set n ansicolor("")]
MSG This is [ansicolor(0,255,0)]green[n], [ansicolor("255 0 0")]red[n] and [ansicolor("0 0 255")]blue[n] text.%
MSG This is [ansicolor(0,0,0)][ansicolor(0,255,0,1)]black text on a green background[n]%
MSG This is [ansicolor(0,0,0,0,1)]clamped black text[n]%
MSG This is [ansicolor(255,255,255,0,1)]clamped white text[n]
FLUSH
# Test that MSF ignores ansi color sequences
set r ansicolor(255, 0, 0)
set g ansicolor(0, 255, 0)
set b ansicolor(0, 0, 255)
set n ansicolor("")
REM MSF Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.%_Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.
# Should have exactly the same word breaks
REM MSF [r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]%_[r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]
REM MSF Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
REM MSF [r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_[r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
FLUSH
# Some invalid combos
set a ansicolor(1)
set a ansicolor(-1, 0, 0)
set a ansicolor(42, 42, 256)
set a ansicolor("foo")
set a ansicolor("1 1")
set a ansicolor("-1 -1 0");
set a ansicolor("256 1 1");
set a ansicolor(128, 128, 128, 2)
set a ansicolor(128, 128, 128, -1)
set a ansicolor(128, 128, 128, 0, 2)
set a ansicolor(128, 128, 128, 0, -1)
set a ansicolor(128,0,0)
set str a + "foo: 🌅"
set w columns(str)
MSG Width of [str] is: [w]

5
tests/blanks.rem Normal file
View File

@@ -0,0 +1,5 @@
MSG $AddBlankLines=[$AddBlankLines]%_
MSG Hello
MSG Hi
MSF How are you?
MSG OK

View File

@@ -15,3 +15,6 @@ REM 28 SPECIAL COLOUR 129 0 129 Bright Magenta
REM 28 SPECIAL COLOUR 129 129 0 Bright Yellow
REM 28 SPECIAL COLOUR 129 129 129 Bright White
SET $DefaultColor "255 255 0"
REM 23 SATISFY [1] MSG DefaultColor_Yellow

43
tests/soleq.rem Normal file
View File

@@ -0,0 +1,43 @@
BANNER Solstice/Equinox Tests
SET $AddBlankLines 0
# Test solstice and equinox functions
MSG March Solstice 2022 is [localtoutc(soleq(0,2022))] UTC
MSG June Equinox 2022 is [localtoutc(soleq(1,2022))] UTC
MSG September Solstice 2022 is [localtoutc(soleq(2,2022))] UTC
MSG December Equinox 2022 is [localtoutc(soleq(3,2022))] UTC
MSG March Solstice 2023 is [localtoutc(soleq(0,2023))] UTC
MSG June Equinox 2023 is [localtoutc(soleq(1,2023))] UTC
MSG September Solstice 2023 is [localtoutc(soleq(2,2023))] UTC
MSG December Equinox 2023 is [localtoutc(soleq(3,2023))] UTC
MSG March Solstice 2024 is [localtoutc(soleq(0,2024))] UTC
MSG June Equinox 2024 is [localtoutc(soleq(1,2024))] UTC
MSG September Solstice 2024 is [localtoutc(soleq(2,2024))] UTC
MSG December Equinox 2024 is [localtoutc(soleq(3,2024))] UTC
MSG March Solstice 2025 is [localtoutc(soleq(0,2025))] UTC
MSG June Equinox 2025 is [localtoutc(soleq(1,2025))] UTC
MSG September Solstice 2025 is [localtoutc(soleq(2,2025))] UTC
MSG December Equinox 2025 is [localtoutc(soleq(3,2025))] UTC
MSG March Solstice 2026 is [localtoutc(soleq(0,2026))] UTC
MSG June Equinox 2026 is [localtoutc(soleq(1,2026))] UTC
MSG September Solstice 2026 is [localtoutc(soleq(2,2026))] UTC
MSG December Equinox 2026 is [localtoutc(soleq(3,2026))] UTC
MSG March Solstice 2030 is [localtoutc(soleq(0,2030))] UTC
MSG June Equinox 2030 is [localtoutc(soleq(1,2030))] UTC
MSG September Solstice 2030 is [localtoutc(soleq(2,2030))] UTC
MSG December Equinox 2030 is [localtoutc(soleq(3,2030))] UTC
MSG March Solstice 2050 is [localtoutc(soleq(0,2050))] UTC
MSG June Equinox 2050 is [localtoutc(soleq(1,2050))] UTC
MSG September Solstice 2050 is [localtoutc(soleq(2,2050))] UTC
MSG December Equinox 2050 is [localtoutc(soleq(3,2050))] UTC
MSG Next March Solstice is [localtoutc(soleq(0))] UTC
MSG Next June Equinox is [localtoutc(soleq(1))] UTC
MSG Next September Solstice is [localtoutc(soleq(2))] UTC
MSG Next December Equinox is [localtoutc(soleq(3))] UTC

View File

@@ -7,7 +7,8 @@
# in the build directory.
#
# This file is part of REMIND.
# Copyright (C) 1992-2022 Dianne Skoll
# Copyright (C) 1992-2023 Dianne Skoll
# SPDX-License-Identifier: GPL-2.0-only
# ---------------------------------------------------------------------------
DIR=`dirname $0`
@@ -26,11 +27,30 @@ if test `id -u` = 0 ; then
exit 1
fi
# If we're already in a utf-8 locale, do
# nothing; otherwise, set LC_ALL
OK=0
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
OK=1
fi
if test -z "$LC_ALL" ; then
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
export LC_ALL="$LANG"
OK=1
fi
fi
if test "$OK" = 0 ; then
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
fi
chmod 000 include_dir/04cantread.rem
TEST_GETENV="foo bar baz" ; export TEST_GETENV
echo "Test 1" > ../tests/test.out
echo "" >> ../tests/test.out
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out 2>&1
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 12:13 >> ../tests/test.out 2>&1
echo "" >> ../tests/test.out
echo "Test 2" >> ../tests/test.out
echo "" >> ../tests/test.out
@@ -76,6 +96,32 @@ echo 'REM Mon 31 2021 MSG [$T]' | ../src/remind -dt - 31 dec 2021 >> ../tests/te
echo "Color Test" >> ../tests/test.out
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
echo "ANSI Color Test" >> ../tests/test.out
../src/remind ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,0 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,0,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@0,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@1,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind -@2,1,1 ../tests/ansicolors.rem 1 Jan 2022 >> ../tests/test.out 2>&1
echo '$AddBlankLines test' >> ../tests/test.out
../src/remind ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind '-i$AddBlankLines=1' ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
../src/remind '-i$AddBlankLines=0' ../tests/blanks.rem 1 Jan 2022 >> ../tests/test.out 2>&1
echo "MON WKDAY DAY across year test" >> ../tests/test.out
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
@@ -123,23 +169,37 @@ REM Mon OMITFUNC foo MSG bar
EOF
# Test default color
../src/remind -ppp - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
../src/remind -pppq - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
REM 2 MSG Normal
SET $DefaultColor "255 0 0"
REM 3 MSG Red
REM 3 MSG %"Red%" on the calendar!
SET $DefaultColor "-1 -1 -1"
REM 4 MSG Normal
# Should give an error
SET $DefaultColor "256 0 0"
EOF
# Test stdout
../src/remind - 1 jan 2012 <<'EOF' >> ../tests/test.out 2>&1
BANNER %
MSG STDOUT is a: [stdout()]%
EOF
../src/remind - 1 jan 2012 <<'EOF' 2>&1 | cat >> ../tests/test.out
BANNER %
MSG STDOUT is a: [stdout()]%
EOF
# Test -@ option
../src/remind -w,0,0 -@0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
../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
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -153,12 +213,15 @@ 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
../src/remind -w,0,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,0
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -172,12 +235,15 @@ 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
../src/remind -w,0,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 -@0,1
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -191,12 +257,15 @@ 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
../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
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -210,12 +279,15 @@ 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
../src/remind -w,0,0 -@1,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,0
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -229,12 +301,15 @@ 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
../src/remind -w,0,0 -@1,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 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -248,12 +323,15 @@ 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
../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
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -267,12 +345,15 @@ 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
../src/remind -w,0,0 -@2,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 -@2,0
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -286,12 +367,15 @@ 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
../src/remind -w,0,0 -@2,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 -@2,1
rem 6 SPECIAL SHADE 255 255 0
rem 7 SPECIAL SHADE 255 0 255
rem 8 SPECIAL SHADE 0 255 255
rem 15 SPECIAL COLOR 65 0 0 RED
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
rem 17 SPECIAL COLOR 65 65 0 YELLOW
@@ -306,30 +390,36 @@ rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF
# If we're already in a utf-8 locale, do
# nothing; otherwise, set LC_ALL
OK=0
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
OK=1
fi
if test -z "$LC_ALL" ; then
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
export LC_ALL="$LANG"
OK=1
fi
fi
if test "$OK" = 0 ; then
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
fi
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
../src/remind -c ../tests/test-addomit.rem 1 Sep 2021 >> ../tests/test.out
../src/remind -cu ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
../src/remind -cu '-i$SuppressLRM=1' ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
TZ=America/Toronto ../src/remind -dxe ../tests/tz.rem >> ../tests/test.out 2>&1
TZ=Europe/Berlin ../src/remind -dxe ../tests/tz.rem >> ../tests/test.out 2>&1
../src/remind ../tests/soleq.rem 1 April 2044 >> ../tests/test.out 2>&1
# Test that banner is printed on every iteration
echo "MSG Should be three banners." | ../src/remind - 2022-10-20 '*3' >> ../tests/test.out 2>&1
# World-writable file
rm -rf include_dir/ww
touch include_dir/ww
chmod 0666 include_dir/ww
../src/remind include_dir/ww >> ../tests/test.out 2>&1
rm -rf include_dir/ww
# World-writable directory
mkdir -p include_dir/ww
touch include_dir/ww/0.rem
chmod 0777 include_dir/ww
../src/remind include_dir/ww >> ../tests/test.out 2>&1
rm -rf include_dir/ww
# Remove references to SysInclude, which is build-specific
fgrep -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED"
@@ -341,3 +431,4 @@ else
echo "reference file test.cmp."
exit 1
fi

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More