mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 06:18:47 +02:00
Compare commits
547 Commits
04.02.05
...
5e738020a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e738020a7 | ||
|
|
7949341037 | ||
|
|
f4d8331456 | ||
|
|
17beef5ce6 | ||
|
|
aaae80d02b | ||
|
|
e97de16203 | ||
|
|
d5e38ee3b4 | ||
|
|
11594aee2d | ||
|
|
711f0b6c69 | ||
|
|
87a8b9811d | ||
|
|
689b1d0e13 | ||
|
|
a8650e888f | ||
|
|
dea2aed628 | ||
|
|
5618b928e0 | ||
|
|
91187c4c60 | ||
|
|
636ae8f21a | ||
|
|
405398b226 | ||
|
|
0df3a903b1 | ||
|
|
eac07d212c | ||
|
|
96da3a6596 | ||
|
|
94ef20d702 | ||
|
|
c9c309e436 | ||
|
|
52c973509b | ||
|
|
c192c580da | ||
|
|
235e5ec1c7 | ||
|
|
3d30173f9a | ||
|
|
8b0bbc9fb7 | ||
|
|
c57d2fd52a | ||
|
|
2970591187 | ||
|
|
23ec559ddf | ||
|
|
302bc5a5de | ||
|
|
950c0b3747 | ||
|
|
ad382fea25 | ||
|
|
a66e855ca7 | ||
|
|
a1b814d6b1 | ||
|
|
62030719bb | ||
|
|
985816dc32 | ||
|
|
a131a53132 | ||
|
|
c5e723b6ac | ||
|
|
3fe2b88e65 | ||
|
|
54603090ee | ||
|
|
2514b3681f | ||
|
|
0b7b101814 | ||
|
|
3ac1c622fd | ||
|
|
7878f6623c | ||
|
|
00ad38e5fe | ||
|
|
10ae0b0077 | ||
|
|
e032f3315d | ||
|
|
a38fd95a90 | ||
|
|
9f7609b2c6 | ||
|
|
a6c166ae0c | ||
|
|
e9c89b770f | ||
|
|
df6298bd63 | ||
|
|
739d285e36 | ||
|
|
ee1c931932 | ||
|
|
0806b6738f | ||
|
|
020e82d575 | ||
|
|
a20f2b588e | ||
|
|
631e721a96 | ||
|
|
8453e17c6c | ||
|
|
76c1e2abb3 | ||
|
|
3389f1c91b | ||
|
|
b2d47ae979 | ||
|
|
e2c615f310 | ||
|
|
e8492a4303 | ||
|
|
4695efaabd | ||
|
|
c433f42587 | ||
|
|
4708e59a43 | ||
|
|
d56ac6332a | ||
|
|
b054baf590 | ||
|
|
42f5e3467d | ||
|
|
97013ae89b | ||
|
|
2acead9118 | ||
|
|
a53a80acb4 | ||
|
|
56e62b1b4d | ||
|
|
c645db5ede | ||
|
|
ef6b9c3783 | ||
|
|
019bee26cb | ||
|
|
152cd4090b | ||
|
|
b7fc2b5776 | ||
|
|
723aba9b7c | ||
|
|
8a5b88338b | ||
|
|
7236441e02 | ||
|
|
e4bab0dda4 | ||
|
|
5b7d4a07ec | ||
|
|
8c3d2c4003 | ||
|
|
f485d607ff | ||
|
|
a0effa5f0b | ||
|
|
7d501cda6f | ||
|
|
5d7f55c8d5 | ||
|
|
097bf92bea | ||
|
|
b9dea59206 | ||
|
|
46aa144b65 | ||
|
|
914971308d | ||
|
|
a22e81040f | ||
|
|
72f74f03cf | ||
|
|
d0e45e727e | ||
|
|
ce2b2e80da | ||
|
|
11771b7d3d | ||
|
|
01cb028532 | ||
|
|
58b6f43b9c | ||
|
|
1dedb667e8 | ||
|
|
8a96236788 | ||
|
|
2a13163659 | ||
|
|
336a9684d4 | ||
|
|
86945c6e18 | ||
|
|
684280db5e | ||
|
|
d801408933 | ||
|
|
79b3da3820 | ||
|
|
ed021d3f46 | ||
|
|
27d0fda280 | ||
|
|
ef12da4ec6 | ||
|
|
7b098e95ad | ||
|
|
7d13f4b09e | ||
|
|
cecdfe6ade | ||
|
|
216bbd6378 | ||
|
|
30e2e9c633 | ||
|
|
bf2aabd610 | ||
|
|
c019221d15 | ||
|
|
b7bd6faf07 | ||
|
|
80d58220fe | ||
|
|
cd8624e176 | ||
|
|
8515fb7ddd | ||
|
|
84f9f4ae0a | ||
|
|
e201ebcfa4 | ||
|
|
4e15c3ec35 | ||
|
|
1adccf9b1f | ||
|
|
a1aa5c2ad9 | ||
|
|
1e0d650737 | ||
|
|
553d092ca8 | ||
|
|
dc62841517 | ||
|
|
326e7bfc53 | ||
|
|
b9dc7c16ad | ||
|
|
abd54b016b | ||
|
|
db02b54067 | ||
|
|
40a78dfbbb | ||
|
|
c860b46baa | ||
|
|
1458ba8856 | ||
|
|
7b9b6ebc96 | ||
|
|
7ee4073c7a | ||
|
|
8c072cd9b6 | ||
|
|
b794a45c3f | ||
|
|
98e491ed1d | ||
|
|
c397cc06da | ||
|
|
8616236b3c | ||
|
|
702704af1a | ||
|
|
a0d1b19050 | ||
|
|
a5c8ae491c | ||
|
|
b3cf741d15 | ||
|
|
0b28dde9c7 | ||
|
|
5a3980b5b8 | ||
|
|
a8e33118d6 | ||
|
|
2223277f64 | ||
|
|
c72413e3c1 | ||
|
|
fa1033db6f | ||
|
|
61e3edd2ac | ||
|
|
093c97ff91 | ||
|
|
6e64b175aa | ||
|
|
09dba4bc94 | ||
|
|
2e443ac5b7 | ||
|
|
59a8c88178 | ||
|
|
40eab03d84 | ||
|
|
e993bf59cf | ||
|
|
c6de5a2c8f | ||
|
|
51cc939d0c | ||
|
|
c857192e6d | ||
|
|
4591c2b181 | ||
|
|
7843a1b2ba | ||
|
|
649481cf01 | ||
|
|
c253bdfcbe | ||
|
|
1910808fd7 | ||
|
|
1d8cb9749e | ||
|
|
e3f9380fcd | ||
|
|
326c3f59b0 | ||
|
|
03f1c5a047 | ||
|
|
02122491c3 | ||
|
|
735f6f5686 | ||
|
|
ac033d75c0 | ||
|
|
e2185e773a | ||
|
|
d9ae417e01 | ||
|
|
e1d0948538 | ||
|
|
357ddf285a | ||
|
|
41859fc484 | ||
|
|
07275e71b0 | ||
|
|
f68521cb95 | ||
|
|
526610bdd2 | ||
|
|
973e3448ae | ||
|
|
9a3f28f6fc | ||
|
|
a3e32d2dc4 | ||
|
|
a8b78eff00 | ||
|
|
460db83298 | ||
|
|
4560712778 | ||
|
|
ce8803dde9 | ||
|
|
60ca5d45e3 | ||
|
|
4454613d00 | ||
|
|
0704808500 | ||
|
|
166b1ac499 | ||
|
|
e33bf4e80a | ||
|
|
b3af44d212 | ||
|
|
1e753d5209 | ||
|
|
4bf31005ea | ||
|
|
7c86bc910a | ||
|
|
4f146a99a9 | ||
|
|
a6a638e0e6 | ||
|
|
325814f5e1 | ||
|
|
5c4ea7d09e | ||
|
|
2bf73987ac | ||
|
|
3e9eeea8dc | ||
|
|
d164d72c1c | ||
|
|
632cee62d9 | ||
|
|
7a40260f0d | ||
|
|
09f043b3de | ||
|
|
c0341c8ba3 | ||
|
|
850c717803 | ||
|
|
f13f9e18bd | ||
|
|
8bdca0d684 | ||
|
|
129bf5612e | ||
|
|
829962fae1 | ||
|
|
c5f9ed8541 | ||
|
|
4a7cef4644 | ||
|
|
0e010b56ec | ||
|
|
ee179ee2f5 | ||
|
|
e28712cef3 | ||
|
|
8f0a2a7e79 | ||
|
|
ef23bba77f | ||
|
|
602086ae2d | ||
|
|
f5a170acbd | ||
|
|
8125b96f0b | ||
|
|
0bb7d89bb9 | ||
|
|
eb109bbbc0 | ||
|
|
1a0809fd31 | ||
|
|
09625b9d68 | ||
|
|
4e164c4268 | ||
|
|
691185f22c | ||
|
|
a8bfb41a9e | ||
|
|
fafb30db05 | ||
|
|
243e816523 | ||
|
|
b49c0f52bd | ||
|
|
07fca94a7f | ||
|
|
73917ee537 | ||
|
|
76f9edecf6 | ||
|
|
d77d9854d2 | ||
|
|
c2b53f95a4 | ||
|
|
caef8b80d6 | ||
|
|
5e016768af | ||
|
|
ee08ce98d7 | ||
|
|
581bd95838 | ||
|
|
bb92dab1ab | ||
|
|
83b5c52c76 | ||
|
|
93eca25141 | ||
|
|
34421cb10e | ||
|
|
29b87898aa | ||
|
|
e9e4db94bd | ||
|
|
c95ad0261a | ||
|
|
7fef456483 | ||
|
|
386131e74d | ||
|
|
824d3c88f1 | ||
|
|
18a206abd2 | ||
|
|
8dbae776c9 | ||
|
|
b78702cc53 | ||
|
|
d2b43605ad | ||
|
|
7728e09337 | ||
|
|
2666353ce6 | ||
|
|
0b8a306483 | ||
|
|
b51a0b2d08 | ||
|
|
959355b19c | ||
|
|
9c3f0f1994 | ||
|
|
dac337a65b | ||
|
|
98739dfdbc | ||
|
|
17b7a1ea84 | ||
|
|
4d45925758 | ||
|
|
8cadb23f48 | ||
|
|
63211b65c2 | ||
|
|
1be84525b1 | ||
|
|
67ae95a464 | ||
|
|
c03a95ad94 | ||
|
|
51aa7aecb9 | ||
|
|
592cfe5a20 | ||
|
|
b4cf15e73e | ||
|
|
862e143372 | ||
|
|
1f10ca49ad | ||
|
|
4a0c4ffdca | ||
|
|
27c8737f3a | ||
|
|
ecf45fc453 | ||
|
|
0a1178cfd7 | ||
|
|
20a35dc627 | ||
|
|
79887c06f0 | ||
|
|
f7ff424904 | ||
|
|
6678721fe3 | ||
|
|
496302097b | ||
|
|
fe3e2b9a20 | ||
|
|
400a6b066f | ||
|
|
76d181e7fc | ||
|
|
77373eed2d | ||
|
|
6b52be388f | ||
|
|
0518a12a91 | ||
|
|
362a02c4b8 | ||
|
|
3e3a0cde47 | ||
|
|
c16f93effd | ||
|
|
61b27c02b5 | ||
|
|
ba28eaad53 | ||
|
|
92c2d0cc9f | ||
|
|
21d5e8a095 | ||
|
|
60417d68a7 | ||
|
|
7d25387403 | ||
|
|
b454cf5b20 | ||
|
|
9ea6385b72 | ||
|
|
55b7908444 | ||
|
|
e9ff66478b | ||
|
|
d3240d711d | ||
|
|
a8d63a4199 | ||
|
|
a4807a21c3 | ||
|
|
a394ef53a0 | ||
|
|
eb8243743a | ||
|
|
8444bb15c5 | ||
|
|
b86245c4c6 | ||
|
|
499fcfad41 | ||
|
|
bddbbf061b | ||
|
|
05136f4cf0 | ||
|
|
e62e3d5d03 | ||
|
|
595fdaa4a4 | ||
|
|
133febc2c1 | ||
|
|
f8c6d7ff6c | ||
|
|
db3341db91 | ||
|
|
8cbcd3ec01 | ||
|
|
4c6512e9b6 | ||
|
|
4769789a8f | ||
|
|
b4a8cb085c | ||
|
|
4f816d52fd | ||
|
|
94b3a0248d | ||
|
|
5fbf1d82e4 | ||
|
|
55eb3ebe95 | ||
|
|
2afa3c5558 | ||
|
|
30d9a42db2 | ||
|
|
74d357b84d | ||
|
|
09c98a93ec | ||
|
|
ed89ab7c04 | ||
|
|
27c74be02b | ||
|
|
8f22ab39dc | ||
|
|
795c53f4ce | ||
|
|
3fd18a9cc0 | ||
|
|
a5afb4a87e | ||
|
|
379fc4542d | ||
|
|
538ef6c8ce | ||
|
|
95c7e8856c | ||
|
|
95523c8f10 | ||
|
|
97b53d5e40 | ||
|
|
fb688850b1 | ||
|
|
5b1bad2650 | ||
|
|
e5ff132c5e | ||
|
|
a0830ad23c | ||
|
|
9290f53466 | ||
|
|
e5711032bd | ||
|
|
08e3c1d5a2 | ||
|
|
29c579a301 | ||
|
|
61f55bceee | ||
|
|
6586fae3eb | ||
|
|
d5a86f3e4f | ||
|
|
96551ccaa4 | ||
|
|
c83ee86d10 | ||
|
|
c913306cbd | ||
|
|
03d385df97 | ||
|
|
61fcc1b275 | ||
|
|
26977a4ac0 | ||
|
|
28acd05215 | ||
|
|
be4eed8b20 | ||
|
|
cdb0850373 | ||
|
|
0d55e04284 | ||
|
|
f4cce54b70 | ||
|
|
2dc6ca44f1 | ||
|
|
d1d833f0f3 | ||
|
|
1d44577ce9 | ||
|
|
1be7c2d6d7 | ||
|
|
b1f418ee42 | ||
|
|
72b0bf96fe | ||
|
|
3388849fa5 | ||
|
|
dc9650d5fa | ||
|
|
8eb40ae748 | ||
|
|
89184f1d0f | ||
|
|
e899c790b9 | ||
|
|
bd6d695020 | ||
|
|
20d4626a71 | ||
|
|
8ff94c5031 | ||
|
|
ee185a0eeb | ||
|
|
06f8932efd | ||
|
|
1dc627148c | ||
|
|
3cdde5351f | ||
|
|
6e93b8a73d | ||
|
|
267e8533cf | ||
|
|
d3bfb0a28f | ||
|
|
5a31bc7058 | ||
|
|
746bde71bd | ||
|
|
b274ac635c | ||
|
|
9e0a74e583 | ||
|
|
0f782f7697 | ||
|
|
8efde3e9af | ||
|
|
3bf3137dc4 | ||
|
|
63ec32d28d | ||
|
|
d2f4177cdb | ||
|
|
1d958fb7a8 | ||
|
|
fcd580d42e | ||
|
|
34dab68805 | ||
|
|
216dd03922 | ||
|
|
5eef9ac621 | ||
|
|
6b798d5f7c | ||
|
|
22ccce0934 | ||
|
|
fe2af14952 | ||
|
|
8e99ed27e7 | ||
|
|
bb12362cc8 | ||
|
|
1bfc630a64 | ||
|
|
987983f8ae | ||
|
|
657a6118aa | ||
|
|
43e7e6ec7f | ||
|
|
b8b3c19fbf | ||
|
|
69298c96a5 | ||
|
|
7356138872 | ||
|
|
616966f5df | ||
|
|
a59e277c21 | ||
|
|
740ae2c3e9 | ||
|
|
25b7a40f2b | ||
|
|
2beaab1a2f | ||
|
|
60793d53c6 | ||
|
|
4f869c8c81 | ||
|
|
8955180a35 | ||
|
|
a30cbf5797 | ||
|
|
b2bd6109dc | ||
|
|
9455ec48d7 | ||
|
|
f751f5defa | ||
|
|
994edbebbe | ||
|
|
70959b791c | ||
|
|
524ece5119 | ||
|
|
6334bd61b6 | ||
|
|
2e56edd557 | ||
|
|
8cae1d21cd | ||
|
|
1de6ed16eb | ||
|
|
860cb94f41 | ||
|
|
6b505704e9 | ||
|
|
167631451d | ||
|
|
fa5180b94d | ||
|
|
ae01d7be43 | ||
|
|
d5ce39ade1 | ||
|
|
a043dfe8b9 | ||
|
|
7cfb75e3b3 | ||
|
|
a18f0d982f | ||
|
|
0e2dc805c2 | ||
|
|
4c1e11df2c | ||
|
|
76776d054a | ||
|
|
45ebd05cb6 | ||
|
|
0203ce3979 | ||
|
|
72d10178bf | ||
|
|
96f4e26d53 | ||
|
|
4fd86f1b6a | ||
|
|
2f3ee0aec3 | ||
|
|
a5dde31160 | ||
|
|
b45428df05 | ||
|
|
d938763643 | ||
|
|
e4e2157622 | ||
|
|
04b349c6c7 | ||
|
|
7fe3eb7391 | ||
|
|
c1992b577a | ||
|
|
632283d47f | ||
|
|
1d9e46997c | ||
|
|
861ce34022 | ||
|
|
32e8db322d | ||
|
|
3df2b72175 | ||
|
|
e7ac4f95be | ||
|
|
e7ed69287b | ||
|
|
2e80417f53 | ||
|
|
ee435d2bb9 | ||
|
|
bb516946be | ||
|
|
81157e1cb5 | ||
|
|
51dfd707a2 | ||
|
|
7c3bf8601b | ||
|
|
714195efe5 | ||
|
|
eaeca2d09b | ||
|
|
ffa3b13437 | ||
|
|
2551e98d11 | ||
|
|
1bfd7761bc | ||
|
|
de9cb1d0a3 | ||
|
|
b2d32b514a | ||
|
|
6e53fd6924 | ||
|
|
8296d2b962 | ||
|
|
d6e66ee1e6 | ||
|
|
a49532b9c5 | ||
|
|
57d87f4caf | ||
|
|
ec9b30c616 | ||
|
|
27d8a62ab6 | ||
|
|
5077814c4a | ||
|
|
ca795a352a | ||
|
|
e59fc36458 | ||
|
|
39e3657539 | ||
|
|
6031f70701 | ||
|
|
3567c9e55f | ||
|
|
26de4e3fd3 | ||
|
|
cd65c6144d | ||
|
|
d32edbbb1f | ||
|
|
eae48a5538 | ||
|
|
63eba104d9 | ||
|
|
ae64961735 | ||
|
|
f7bb91320c | ||
|
|
c11071a859 | ||
|
|
53cbcc22db | ||
|
|
af9dcec3e9 | ||
|
|
d5a4b0d235 | ||
|
|
3b870403d9 | ||
|
|
284d822884 | ||
|
|
d881a26ad0 | ||
|
|
8519edde29 | ||
|
|
a30c467c48 | ||
|
|
887cd83ebe | ||
|
|
242d787ca2 | ||
|
|
5dd2cf7356 | ||
|
|
5efb70909d | ||
|
|
a60d466774 | ||
|
|
1c01f36271 | ||
|
|
3718632551 | ||
|
|
e8f3d5ff9f | ||
|
|
d77e27942d | ||
|
|
734cc61489 | ||
|
|
44d489d3d2 | ||
|
|
3e36ffa9ff | ||
|
|
12104a96b1 | ||
|
|
8ab8d65a15 | ||
|
|
f7a8122cef | ||
|
|
77d9bbb7d6 | ||
|
|
623def52fd | ||
|
|
d088e35142 | ||
|
|
5821e55eb8 | ||
|
|
1ee989c65d | ||
|
|
62388fb21f | ||
|
|
13571f84af | ||
|
|
03fdc06b65 | ||
|
|
4bce675ae6 | ||
|
|
7b64623115 | ||
|
|
e268bbf31d | ||
|
|
5863404de6 | ||
|
|
2de5996f4e | ||
|
|
695e79602a | ||
|
|
cf0d958da5 | ||
|
|
85b0348fa7 | ||
|
|
15a5d9a876 | ||
|
|
1baa6dab0c | ||
|
|
34bb250ba3 | ||
|
|
598b1b7464 | ||
|
|
e63d4be4e8 | ||
|
|
65561e7f34 | ||
|
|
da31dadb71 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,11 +16,13 @@ man/remind.1
|
||||
man/tkremind.1
|
||||
pm_to_blib
|
||||
rem2html/Makefile
|
||||
rem2html/rem2html
|
||||
rem2html/rem2html.1
|
||||
rem2pdf/Makefile.PL
|
||||
rem2pdf/Makefile.old
|
||||
rem2pdf/Makefile.top
|
||||
rem2pdf/bin/rem2pdf
|
||||
scripts/tkremind
|
||||
set-irc-topic
|
||||
src/*.tar.gz*
|
||||
src/Makefile
|
||||
@@ -32,3 +34,4 @@ src/version.h
|
||||
tests/test.out
|
||||
www/Makefile
|
||||
gmon.out
|
||||
tests/once.timestamp
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH =~ /wip/
|
||||
when: never
|
||||
|
||||
tests:
|
||||
image: 'debian:stable-slim'
|
||||
before_script:
|
||||
|
||||
@@ -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-2023 Dianne Skoll, except where noted in
|
||||
2. REMIND is Copyright 1992-2024 Dianne Skoll, except where noted in
|
||||
individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
@@ -16,7 +16,7 @@ individual files.
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
MICROSOFT WINDOWS
|
||||
=================
|
||||
|
||||
I used to prohibit porting Remind to Microsoft Windows. However, this
|
||||
may cause problems with the GPL, so I have removed that restriction.
|
||||
|
||||
Although I cannot prevent you from porting Remind to Windows, I appeal
|
||||
to you not to do it. I am trying to encourage the growth of free
|
||||
software, not proprietary software.
|
||||
|
||||
If you port Remind to Windows, I will not provide support or answers to
|
||||
questions -- you're on your own. On the other hand, I will feel no guilt
|
||||
in taking enhancements and merging them into the UNIX stream.
|
||||
|
||||
APPLE
|
||||
=====
|
||||
|
||||
I can't prevent you from using Remind on Apple's products, but I hope
|
||||
you don't. Apple's corporate culture is the very antithesis of Free
|
||||
Software. Rather than using Mac OS X, I encourage you to switch to
|
||||
Linux or FreeBSD, two Free Software operating systems that are every
|
||||
bit as capable as Mac OS X and which are unencumbered by Apple's
|
||||
arbitrary restrictions.
|
||||
|
||||
And if you're looking to port Remind to other Apple products like the
|
||||
iPhone or iPad, please don't. Those products enforce Apple's rigorous
|
||||
controls much more stringently than Mac OS X on an Apple PC.
|
||||
|
||||
--
|
||||
Dianne Skoll
|
||||
4
Makefile
4
Makefile
@@ -24,7 +24,7 @@ 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
|
||||
-rm man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1 scripts/tkremind
|
||||
-$(MAKE) -C src clean
|
||||
-$(MAKE) -C rem2pdf clean
|
||||
|
||||
@@ -44,7 +44,7 @@ test:
|
||||
@$(MAKE) -C src -s test
|
||||
|
||||
distclean: clean
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile rem2pdf/Makefile.top rem2pdf/Makefile.old rem2pdf/Makefile rem2pdf/Makefile.PL rem2pdf/bin/rem2pdf
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile rem2pdf/Makefile.top rem2pdf/Makefile.old rem2pdf/Makefile rem2pdf/Makefile.PL rem2pdf/bin/rem2pdf rem2html/rem2html
|
||||
|
||||
src/Makefile: src/Makefile.in
|
||||
./configure
|
||||
|
||||
54
build.tk
Normal file → Executable file
54
build.tk
Normal file → Executable file
@@ -15,6 +15,8 @@
|
||||
# the next line restarts using wish \
|
||||
exec wish "$0" "$@"
|
||||
|
||||
global RemindExecutable
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: SetConfigDefaults
|
||||
# %ARGUMENTS:
|
||||
@@ -27,10 +29,10 @@ exec wish "$0" "$@"
|
||||
proc SetConfigDefaults {} {
|
||||
global Config
|
||||
set Config(LAT_DEG) 45
|
||||
set Config(LAT_MIN) 24
|
||||
set Config(LAT_MIN) 25
|
||||
set Config(LAT_SEC) 14
|
||||
set Config(LON_DEG) 75
|
||||
set Config(LON_MIN) 39
|
||||
set Config(LON_MIN) 41
|
||||
set Config(LON_SEC) 23
|
||||
set Config(LOCATION) "Ottawa"
|
||||
set Config(DEFAULT_PAGE) "Letter"
|
||||
@@ -40,7 +42,7 @@ proc SetConfigDefaults {} {
|
||||
set Config(WESTERN_HEMISPHERE) 1
|
||||
set Config(LANGUAGE) "English"
|
||||
set Config(INST_DIR) "/usr/local/bin"
|
||||
set Config(MAN_DIR) "/usr/local/man"
|
||||
set Config(MAN_DIR) "/usr/local/share/man"
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -53,7 +55,7 @@ proc SetConfigDefaults {} {
|
||||
# Pops up an error dialog; then calls exit.
|
||||
#***********************************************************************
|
||||
proc Bail { msg } {
|
||||
tk_dialog .err "Remind Configuration Error" $msg error 0 "Bummer"
|
||||
tk_messageBox -message "Remind Build Error" -detail $msg -icon error -type ok
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ proc CreateMainDialog {} {
|
||||
# Creates the "installation directories" dialog.
|
||||
#***********************************************************************
|
||||
proc CreateInstallDirDialog { w } {
|
||||
global Config
|
||||
global Config RemindExecutable
|
||||
label $w.binlabel -text "Location for programs: "
|
||||
entry $w.bin -width 30
|
||||
$w.bin insert end $Config(INST_DIR)
|
||||
@@ -133,16 +135,19 @@ proc CreateInstallDirDialog { w } {
|
||||
entry $w.man -width 30
|
||||
$w.man insert end $Config(MAN_DIR)
|
||||
|
||||
text $w.blurb -width 1 -height 5 -wrap word -relief flat -takefocus 0
|
||||
$w.blurb insert end "\n(Tabbed-notebook Tcl code taken from \"Effective Tcl/Tk Programming\" by Mark Harrison and Michael McLennan, Addison-Wesley Professional Computing Series.)"
|
||||
$w.blurb configure -state disabled
|
||||
# Disable all text-window behaviour
|
||||
bindtags $w.blurb {NoSuchTag}
|
||||
text $w.blurb -width 1 -height 20 -wrap word -relief flat -takefocus 0
|
||||
if { "$RemindExecutable" != "" } {
|
||||
$w.blurb insert end "Note: Default settings were obtained by querying the existing installed version of Remind found at: $RemindExecutable\n"
|
||||
}
|
||||
$w.blurb insert end "\n(Tabbed-notebook Tcl code taken from \"Effective Tcl/Tk Programming\" by Mark Harrison and Michael McLennan, Addison-Wesley Professional Computing Series.)\n"
|
||||
grid $w.binlabel -row 0 -column 0 -sticky e
|
||||
grid $w.bin -row 0 -column 1 -sticky nsew
|
||||
grid $w.manlabel -row 1 -column 0 -sticky e
|
||||
grid $w.man -row 1 -column 1 -sticky nsew
|
||||
grid $w.blurb - -sticky nsew
|
||||
# Disable all text-window behaviour
|
||||
bindtags $w.blurb {NoSuchTag}
|
||||
$w.blurb configure -state disabled
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -190,8 +195,8 @@ proc CreateLocationDialog { w } {
|
||||
|
||||
grid $w.north $w.west
|
||||
grid $w.south $w.east
|
||||
grid $w.loclab -sticky e
|
||||
grid $w.location -sticky nsew -row 6 -column 1
|
||||
grid $w.loclab -sticky e
|
||||
grid $w.location -sticky nsew -row 8 -column 1
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -293,9 +298,9 @@ proc BuildRemind {} {
|
||||
|
||||
.msgs insert end "\n>>> Creating src/custom.h...\n\n" green
|
||||
CreateCustomH
|
||||
.msgs insert end ">>> Calling `./configure'...\n\n" green
|
||||
.msgs insert end "\n>>> Calling `./configure'...\n\n" green
|
||||
CallConfigure
|
||||
.msgs insert end ">>> Calling `make'...\n\n" green
|
||||
.msgs insert end "\n>>> Calling `make'...\n\n" green
|
||||
CallMake
|
||||
.msgs insert end "\n----------------------------------------------\n\n"
|
||||
.msgs insert end "Remind" red
|
||||
@@ -447,12 +452,12 @@ proc CreateCustomH {} {
|
||||
"#define DEFAULT_LATITUDE *" {
|
||||
set lat [expr $LAT_DEG + ($LAT_MIN/60.0) + ($LAT_SEC/3600.0)];
|
||||
puts $out "#define DEFAULT_LATITUDE $lat"
|
||||
.msgs insert end "#define DEFAULT_LATITUDE $lat"
|
||||
.msgs insert end "#define DEFAULT_LATITUDE $lat\n"
|
||||
}
|
||||
"#define DEFAULT_LONGITUDE *" {
|
||||
set lon [expr -1.0 * ($LON_DEG + ($LON_MIN/60.0) + ($LON_SEC/3600.0))]
|
||||
puts $out "#define DEFAULT_LONGITUDE $lon"
|
||||
.msgs insert end "#define DEFAULT_LONGITUDE $lon"
|
||||
.msgs insert end "#define DEFAULT_LONGITUDE $lon\n"
|
||||
}
|
||||
"#define LOCATION *" {
|
||||
puts $out "#define LOCATION \"$Config(LOCATION)\""
|
||||
@@ -506,7 +511,13 @@ proc CallMake {} {
|
||||
"Icelandic" { set lang ICELANDIC }
|
||||
default { set lang ENGLISH }
|
||||
}
|
||||
RunCommand "make \"LANGDEF=-DLANG=$lang\""
|
||||
set nproc 0
|
||||
catch { set nproc [exec nproc] }
|
||||
if { $nproc != 0 } {
|
||||
RunCommand "make -j $nproc \"LANGDEF=-DLANG=$lang\""
|
||||
} else {
|
||||
RunCommand "make \"LANGDEF=-DLANG=$lang\""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -721,7 +732,7 @@ proc notebook_fix_size {win} {
|
||||
#***********************************************************************
|
||||
proc FindRemind {} {
|
||||
global env
|
||||
set path [concat [split $env(PATH) ":"] "/bin" "/usr/bin" "/usr/local/bin"]
|
||||
set path [concat [split $env(PATH) ":"] "/usr/local/bin" "/bin" "/usr/bin" ]
|
||||
foreach thing $path {
|
||||
if [file executable [file join $thing "remind"]] {
|
||||
return [file join $thing "remind"]
|
||||
@@ -739,16 +750,17 @@ proc FindRemind {} {
|
||||
# sensible defaults.
|
||||
#***********************************************************************
|
||||
proc SetConfigFromRemind {} {
|
||||
global Config
|
||||
global Config RemindExecutable
|
||||
SetConfigDefaults
|
||||
set rem [FindRemind]
|
||||
set RemindExecutable $rem
|
||||
if {"$rem" == ""} {
|
||||
return
|
||||
}
|
||||
set dir [file dirname $rem]
|
||||
set Config(INST_DIR) $dir
|
||||
if {"$dir" == "/usr/local/bin"} {
|
||||
set Config(MAN_DIR) "/usr/local/man"
|
||||
set Config(MAN_DIR) "/usr/local/share/man"
|
||||
} elseif {$dir == "/usr/bin"} {
|
||||
set Config(MAN_DIR) "/usr/share/man"
|
||||
}
|
||||
@@ -758,6 +770,8 @@ proc SetConfigFromRemind {} {
|
||||
set Config(MAN_DIR) "/usr/share/man"
|
||||
} elseif {[file readable "/usr/man/man1/remind.1"]} {
|
||||
set Config(MAN_DIR) "/usr/man"
|
||||
} elseif {[file readable "/usr/local/share/man/man1/remind.1"]} {
|
||||
set Config(MAN_DIR) "/usr/local/share/man"
|
||||
} elseif {[file readable "/usr/local/man/man1/remind.1"]} {
|
||||
set Config(MAN_DIR) "/usr/local/man"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(src/queue.c)
|
||||
AC_INIT(remind, 05.00.07, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_CONFIG_SRCDIR([src/queue.c])
|
||||
|
||||
cat <<'EOF'
|
||||
|
||||
@@ -12,7 +13,7 @@ cat <<'EOF'
|
||||
|
||||
EOF
|
||||
|
||||
AC_CONFIG_HEADER(src/config.h)
|
||||
AC_CONFIG_HEADERS([src/config.h])
|
||||
|
||||
AC_ARG_ENABLE(perl-build-artifacts,
|
||||
[ --disable-perl-build-artifacts
|
||||
@@ -29,32 +30,30 @@ AC_PATH_PROG([PERL], [perl])
|
||||
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB(m, sqrt)
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h stdint.h])
|
||||
|
||||
dnl Integer sizes
|
||||
AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(time_t)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/types.h glob.h wctype.h locale.h langinfo.h)
|
||||
AC_CHECK_HEADERS(strings.h sys/types.h glob.h wctype.h locale.h langinfo.h sys/inotify.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_HEADER_TIME
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
# Check for link-time optimization support
|
||||
f=-flto=auto
|
||||
AC_MSG_CHECKING([whether $CC supports $f])
|
||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
||||
if $CC -Werror -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
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS $f"
|
||||
else
|
||||
@@ -65,6 +64,12 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl If sizeof(time_t) is 4, try to get 64-bit time_t
|
||||
if test "$ac_cv_sizeof_time_t" = "4" ; then
|
||||
AC_MSG_NOTICE([time_t is 32-bits on this system; attempting to use 64-bit time_t])
|
||||
CFLAGS="$CFLAGS -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64"
|
||||
fi
|
||||
|
||||
if test "$ac_cv_perlartifacts" = "yes" ; then
|
||||
PERLARTIFACTS=
|
||||
else
|
||||
@@ -79,11 +84,18 @@ 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.02.05
|
||||
AC_CHECK_FUNCS(strdup strcasecmp strncasecmp setenv unsetenv glob mbstowcs setlocale initgroups inotify_init1)
|
||||
|
||||
VERSION=$PACKAGE_VERSION
|
||||
CONFIG_CMD="$0$ac_configure_args_raw"
|
||||
CONFIG_CMD=`echo "$CONFIG_CMD" | sed -e 's/"/\\\\"/g'`
|
||||
AC_DEFINE_UNQUOTED([CONFIG_CMD], ["$CONFIG_CMD"], [Configuration command used to build Remind])
|
||||
AC_SUBST(CONFIG_CMD)
|
||||
AC_SUBST(VERSION)
|
||||
AC_SUBST(PERL)
|
||||
AC_SUBST(PERLARTIFACTS)
|
||||
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)
|
||||
AC_CONFIG_FILES([src/Makefile www/Makefile src/version.h rem2html/Makefile rem2html/rem2html rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1 scripts/tkremind])
|
||||
AC_OUTPUT
|
||||
chmod a+x rem2pdf/bin/rem2pdf
|
||||
chmod a+x scripts/tkremind
|
||||
3
contrib/ical2rem-0.8/GITHUB
Normal file
3
contrib/ical2rem-0.8/GITHUB
Normal file
@@ -0,0 +1,3 @@
|
||||
The upstream GitHub project for ical2rem is:
|
||||
|
||||
https://github.com/jbalcorn/ical2rem
|
||||
21
contrib/ical2rem-0.8/LICENSE
Normal file
21
contrib/ical2rem-0.8/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
103
contrib/ical2rem-0.8/README.md
Normal file
103
contrib/ical2rem-0.8/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# ical2rem
|
||||
The original iCal to Remind script, first released in 2005.
|
||||
|
||||
Reads iCal files and outputs remind-compatible files. Tested ONLY with
|
||||
calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
|
||||
|
||||
## License
|
||||
In 2005, this was released with the Gnu Public License V2. However, I am changing it to the MIT License, since that provides greater freedom to do with this code what you want.
|
||||
|
||||
Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
|
||||
## How I use Remind and Google Calendar together
|
||||
|
||||
- My family has a Google Email domain, and our email addresses all end in the same domain. We all use Google Calendars and I want to mail reminders to each of the family members containing both Google Calendar and .reminder information.
|
||||
- Under my ~/.rem/ directory each family member has a directory. Each directory contains a standard remind file called 'reminders' that at the very least has the line "INCLUDE /home/jalcorn/.rem/<username>/ical2rem" and flag files indicating whether they want Daily or Weekly reminders. My reminders files references my standard .reminders file, and I also have a flag so if I run a Test run I'll get it. There's actually a lot more files (I have a big family).
|
||||
````
|
||||
./rem
|
||||
./son1:
|
||||
drwxrwxr-x 2 jalcorn jalcorn 4096 Dec 12 14:02 .
|
||||
drwxr-xr-x 12 jalcorn jalcorn 4096 Dec 12 14:13 ..
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 51 Mar 3 06:10 ical2rem
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 33 Oct 27 2016 son1.ics -> /home/jalcorn/calendars/son1.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 976 Dec 12 14:02 reminders
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Oct 27 2016 Weekly
|
||||
|
||||
./justin:
|
||||
drwxrwxr-x 2 jalcorn jalcorn 4096 Feb 27 08:29 .
|
||||
drwxr-xr-x 12 jalcorn jalcorn 4096 Dec 12 14:13 ..
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 32 Oct 27 2016 son1.ics -> /home/jalcorn/calendars/son1.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Nov 7 2016 Daily
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 family.ics -> /home/jalcorn/calendars/family.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 37320 Mar 3 06:10 ical2rem
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 justin.ics -> /home/jalcorn/calendars/justin.ics
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 24 Nov 7 2016 reminders -> /home/jalcorn/.reminders
|
||||
lrwxrwxrwx 1 jalcorn jalcorn 34 Oct 27 2016 vmd.ics -> /home/jalcorn/calendars/vmd.ics
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Oct 27 2016 Test
|
||||
-rw-rw-r-- 1 jalcorn jalcorn 0 Nov 7 2016 Weekly
|
||||
````
|
||||
- bin/getgooglecals.sh runs out of crontab and downloads whatever calendars I want. Note that we can also download organization calendars, I've included a public one here (Cleveland Heights Vocal Music Department calendar).
|
||||
- dailyreminders.sh is linked to weeklyreminders.sh and testreminders.sh so I can run it in different modes. The concatenate the various calendar outputs as a single remind file then send the reminders via email.
|
||||
### Example: .rem/son1/reminders file:
|
||||
````
|
||||
INCLUDE /home/jalcorn/.rem/defs.rem
|
||||
INCLUDE /home/jalcorn/.rem/float
|
||||
INCLUDE /home/jalcorn/.rem/son1/ical2rem
|
||||
fset _weeks() coerce("STRING", (trigdate()-today())/7) + plural((trigdate()-today())/7, " week")
|
||||
FSET _sfun(x) choose(x, -60, 30, 5, 0)
|
||||
FSET oldfloat(y,m,d) trigger(MAX(realtoday(), date(y,m,d)))
|
||||
FSET due(y,m,d) "(" + (date(y,m,d)-trigdate()) + ")"
|
||||
SET fullmoon moondate(2)
|
||||
REM [trigger(realtoday())] SPECIAL SHADE 145 70 100 %
|
||||
REM [float(2019,4,15,105)] MSG File tax return [due(2017,4,15)]%
|
||||
REM PRIORITY 9999 MSG %"%"%
|
||||
INCLUDE /home/jalcorn/.rem/bdays
|
||||
SET $LongDeg 81
|
||||
SET $LongMin 11
|
||||
SET $LongSec 11
|
||||
SET $LatDeg 41
|
||||
SET $LatMin 11
|
||||
SET $LatSec 11
|
||||
REM [trigger(moondate(2))] +1 MSG %"Full Moon%" %b%
|
||||
fset _srtd() coerce("STRING", _no_lz(_am_pm(sunrise(today()))))
|
||||
fset _sstd() coerce("STRING", _no_lz(_am_pm(sunset(today()))))
|
||||
MSG Sun is up today from [_srtd()] to [_sstd()].%"%"%
|
||||
````
|
||||
## Revision History
|
||||
### Version 0.7 2024-09-04
|
||||
- ISSUE 8: New version of remind complains if _sfun isn't defined. Output a header
|
||||
to define a function that does nothing if the function doesn't exist.
|
||||
### Version 0.6 2019-03-01
|
||||
- Publish on GitHub and change license to MIT License
|
||||
- Add supporting files and explanation of how I use it
|
||||
### version 0.5.2 2007-03-23
|
||||
- BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
- remove project-lead-time, since Category was a non-standard attribute
|
||||
- NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
|
||||
fail if a calendar with recurring events is followed by a calendar with no
|
||||
recurring events. This has been reported to the iCal::Parser author.
|
||||
### version 0.5.1 2007-03-21
|
||||
- BUG: Handle multiple calendars on STDIN
|
||||
- add --heading option for priority on section headers
|
||||
### version 0.5 2007-03-21
|
||||
- Add more help options
|
||||
- --project-lead-time option
|
||||
- Supress printing of heading if there are no todos to print
|
||||
### version 0.4
|
||||
- Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
- Change to GetOptions
|
||||
- Change to pipe
|
||||
- Add --label, --help options
|
||||
- Add Help Text
|
||||
- Change to subroutines
|
||||
- Efficiency and Cleanup
|
||||
### version 0.3
|
||||
- Convert to GPL (Thanks to Mark Stosberg)
|
||||
- Add usage
|
||||
### version 0.2
|
||||
- add command line switches
|
||||
- add debug code
|
||||
- add SCHED _sfun keyword
|
||||
- fix typos
|
||||
### version 0.1 - ALPHA CODE.
|
||||
|
||||
82
contrib/ical2rem-0.8/cal_futureonly.pl
Normal file
82
contrib/ical2rem-0.8/cal_futureonly.pl
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# cal_futureonly.pl -
|
||||
# Reads iCal files and outputs events between 1 month ago and 1 year from now.
|
||||
# Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cal_futureonly.pl --file=filname.ics > output.ics
|
||||
|
||||
--help Usage
|
||||
--man Complete man page
|
||||
--infile (REQUIRED) name of input calendar file
|
||||
--file (REQUIRED) name of output calendar file
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
|
||||
=head2 --infile
|
||||
|
||||
Input file
|
||||
|
||||
=head2 --file
|
||||
|
||||
Output File
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Data::ICal;
|
||||
use Data::ICal::Entry;
|
||||
use DateTime::Span;
|
||||
use Data::ICal::DateTime;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
use Data::Dumper;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.1";
|
||||
|
||||
my $help;
|
||||
my $man;
|
||||
my $infile;
|
||||
my $file;
|
||||
my $debug = 0;
|
||||
|
||||
GetOptions (
|
||||
"help|?" => \$help,
|
||||
"man" => \$man,
|
||||
"debug" => \$debug,
|
||||
"infile=s" => \$infile,
|
||||
"file=s" => \$file
|
||||
);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(1) if (! $file);
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
my $limit = DateTime->now();
|
||||
$limit->subtract( months => 1);
|
||||
my $endlimit = DateTime->now()->add(years =>1);
|
||||
print STDERR "including events from: ",$limit->ymd," to: ".$endlimit->ymd,"\n" if $debug;
|
||||
my $span = DateTime::Span->from_datetimes( start => $limit, end => $endlimit );
|
||||
print STDERR "Parsing $infile\n" if $debug;
|
||||
my $cal = Data::ICal->new(filename => $infile);
|
||||
if (! $cal) {
|
||||
die "Died Trying to read $infile :".$cal->error_message;
|
||||
}
|
||||
#my $archive = Data::ICal->new(filename => 'archive.ics');
|
||||
print "Output = $file\n" if $debug;
|
||||
my $new = Data::ICal->new();
|
||||
if (! $new) {
|
||||
die $new->error_message;
|
||||
}
|
||||
|
||||
my @events = $cal->events($span);
|
||||
$new->add_entries(@events);
|
||||
|
||||
open(NEW, ">$file");
|
||||
print NEW $new->as_string;
|
||||
close NEW;
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 expandtab :
|
||||
45
contrib/ical2rem-0.8/dailyreminders.sh
Normal file
45
contrib/ical2rem-0.8/dailyreminders.sh
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
|
||||
r=`basename $0`
|
||||
|
||||
if [ $r == 'weeklyreminders.sh' ];
|
||||
then
|
||||
t=14;
|
||||
w=Weekly;
|
||||
elif [ $r == 'dailyreminders.sh' ];
|
||||
then
|
||||
t=3;
|
||||
w=Daily;
|
||||
else
|
||||
t=5
|
||||
w=Test;
|
||||
fi
|
||||
|
||||
cd .rem
|
||||
for d in * ;
|
||||
do
|
||||
if [ "$( ls -A $d/$w 2>/dev/null )" ];
|
||||
then
|
||||
echo "Sending a $w reminder to $d"
|
||||
ft=/tmp/$d-t-$$.txt
|
||||
f=/tmp/$d-$$.txt
|
||||
echo "Reminders for next $t days:" >> $f
|
||||
cat /dev/null > $d/ical2rem
|
||||
for c in $d/*.ics
|
||||
do
|
||||
calname=`basename $c .ics | tr a-z A-Z`
|
||||
cat $c 2>/dev/null | sed -e "s/^SUMMARY:/SUMMARY: {${calname}} /" \
|
||||
| sed -e 's/DT\([A-Z]*\);TZID=UTC:\([0-9T]*\)/DT\1:\2Z/' >> $ft
|
||||
done
|
||||
cat $ft | ~/bin/ical2rem.pl --label "Online Calendar" --heading "PRIORITY 9999" --lead-time $t >> $d/ical2rem
|
||||
if [ -e $d/reminders ];then r="${d}/reminders"; else r="${d}/ical2rem";fi
|
||||
/usr/bin/remind -q -iplain=1 $r >> $f
|
||||
echo "
|
||||
All calendars can be accessed by logging into https://calendar.google.com/ as $d@jalcorn.net
|
||||
" >> $f
|
||||
cat $f | mail -s "$w Reminders for $d" $d@jalcorn.net;
|
||||
cat $f
|
||||
rm $f
|
||||
rm $ft
|
||||
fi;
|
||||
done
|
||||
21
contrib/ical2rem-0.8/getgooglecals.sh
Normal file
21
contrib/ical2rem-0.8/getgooglecals.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Get google calendars, fix issues caused by changes in Google calendars, and remove all past events.
|
||||
#
|
||||
# Obviously, I've removed the private hashes from private calendars.
|
||||
#
|
||||
cd ~/calendars
|
||||
wget -q -O full/justin.ics --no-check-certificate https://www.google.com/calendar/ical/jbalcorn\%40gmail.com/private-aaaaaaaaaaaaaaaaaaaaaaaaaa/basic.ics
|
||||
wget -q -O full/family.ics --no-check-certificate https://www.google.com/calendar/ical/jalcorn.net_aaaaaaaaaaaaaaaaaaaaaaaaaa\%40group.calendar.google.com/private-6c42a79dec0b3b3bb7b9b0ebf9776bc1/basic.ics
|
||||
wget -q -O full/son1.ics --no-check-certificate https://www.google.com/calendar/ical/son1\%40jalcorn.net/private-aaaaaaaaaaaaaaaaaaaaaaaaaa/basic.ics
|
||||
wget -q -O full/vmd.ics --no-check-certificate https://calendar.google.com/calendar/ical/chuh.org_0pmkefjkiqc4snoel7occlslh8%40group.calendar.google.com/public/basic.ics
|
||||
|
||||
for i in full/*.ics;do
|
||||
cat $i 2>/dev/null | sed -e 's/DT\([A-Z]*\);TZID=UTC:\([0-9T]*\)/DT\1:\2Z/' > /tmp/temp.ics
|
||||
cp /tmp/temp.ics $i
|
||||
done
|
||||
|
||||
~/bin/cal_futureonly.pl --infile=full/justin.ics --file=justin.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/family.ics --file=family.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/son1.ics --file=son1.ics
|
||||
~/bin/cal_futureonly.pl --infile=full/vmd.ics --file=vmd.ics
|
||||
396
contrib/ical2rem-0.8/ical2rem.pl
Executable file
396
contrib/ical2rem-0.8/ical2rem.pl
Executable file
@@ -0,0 +1,396 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# ical2rem.pl -
|
||||
# Reads iCal files and outputs remind-compatible files. Tested ONLY with
|
||||
# calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2005, 2007, 2019 Justin B. Alcorn
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# version 0.8 2024-10-16
|
||||
# - Issue 9. Remove extra day notation on all day events.
|
||||
# version 0.7.1 2024-09-19
|
||||
# - Made sure license statements were consistent
|
||||
# version 0.7 2024-09-04
|
||||
# - Added dummy _sfun to resolve Issue #8
|
||||
# version 0.6 2019-03-01
|
||||
# - Updates to put on GitHub
|
||||
# version 0.5.2 2007-03-23
|
||||
# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
# - remove project-lead-time, since Category was a non-standard attribute
|
||||
# - NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
|
||||
# fail if a calendar with recurring events is followed by a calendar with no
|
||||
# recurring events. This has been reported to the iCal::Parser author.
|
||||
# version 0.5.1 2007-03-21
|
||||
# - BUG: Handle multiple calendars on STDIN
|
||||
# - add --heading option for priority on section headers
|
||||
# version 0.5 2007-03-21
|
||||
# - Add more help options
|
||||
# - --project-lead-time option
|
||||
# - Supress printing of heading if there are no todos to print
|
||||
# version 0.4
|
||||
# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
# - Change to GetOptions
|
||||
# - Change to pipe
|
||||
# - Add --label, --help options
|
||||
# - Add Help Text
|
||||
# - Change to subroutines
|
||||
# - Efficiency and Cleanup
|
||||
# version 0.3
|
||||
# - Convert to GPL (Thanks to Mark Stosberg)
|
||||
# - Add usage
|
||||
# version 0.2
|
||||
# - add command line switches
|
||||
# - add debug code
|
||||
# - add SCHED _sfun keyword
|
||||
# - fix typos
|
||||
# version 0.1 - ALPHA CODE.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
|
||||
|
||||
All options have reasonable defaults:
|
||||
--label Calendar name (Default: Calendar)
|
||||
--start Start of time period to parse (parsed by str2time)
|
||||
--end End of time period to parse
|
||||
--lead-time Advance days to start reminders (Default: 3)
|
||||
--todos, --no-todos Process Todos? (Default: Yes)
|
||||
--iso8601 Use YYYY-MM-DD date format
|
||||
--locations, --no-locations Include location? (Default: Yes)
|
||||
--end-times, --no-end-times Include event end times in reminder text
|
||||
(Default: No)
|
||||
--heading Define a priority for static entries
|
||||
--help Usage
|
||||
--debug Enable debug output
|
||||
--man Complete man page
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
|
||||
=head2 --label
|
||||
|
||||
ical2rem.pl --label "Bob's Calendar"
|
||||
|
||||
The syntax generated includes a label for the calendar parsed.
|
||||
By default this is "Calendar". You can customize this with
|
||||
the "--label" option.
|
||||
|
||||
=head2 --iso8601
|
||||
|
||||
Use YYYY-MM-DD date format in output instead of Mmm DD YYYY
|
||||
|
||||
=head2 --locations, --no-locations
|
||||
|
||||
Whether or not to include locations in events
|
||||
|
||||
=head2 --lead-time
|
||||
|
||||
ical2rem.pl --lead-time 3
|
||||
|
||||
How may days in advance to start getting reminders about the events. Defaults to 3.
|
||||
|
||||
=head2 --no-todos
|
||||
|
||||
ical2rem.pl --no-todos
|
||||
|
||||
If you don't care about the ToDos the calendar, this will surpress
|
||||
printing of the ToDo heading, as well as skipping ToDo processing.
|
||||
|
||||
=head2 --heading
|
||||
|
||||
ical2rem.pl --heading "PRIORITY 9999"
|
||||
|
||||
Set an option on static messages output. Using priorities can made the static messages look different from
|
||||
the calendar entries. See the file defs.rem from the remind distribution for more information.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use iCal::Parser;
|
||||
use Date::Parse;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
use Data::Dumper;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.5.2";
|
||||
|
||||
# Declare how many days in advance to remind
|
||||
my $DEFAULT_LEAD_TIME = 3;
|
||||
my $PROCESS_TODOS = 1;
|
||||
my $HEADING = "";
|
||||
my $help;
|
||||
my $debug;
|
||||
my $man;
|
||||
my $iso8601;
|
||||
my $do_location = 1;
|
||||
my $do_end_times;
|
||||
my $start;
|
||||
my $end;
|
||||
|
||||
my $label = 'Calendar';
|
||||
GetOptions (
|
||||
"label=s" => \$label,
|
||||
"start=s" => \$start,
|
||||
"end=s" => \$end,
|
||||
"lead-time=i" => \$DEFAULT_LEAD_TIME,
|
||||
"todos!" => \$PROCESS_TODOS,
|
||||
"iso8601!" => \$iso8601,
|
||||
"locations!" => \$do_location,
|
||||
"end-times!" => \$do_end_times,
|
||||
"heading=s" => \$HEADING,
|
||||
"help|?" => \$help,
|
||||
"debug" => \$debug,
|
||||
"man" => \$man
|
||||
) or pod2usage(1);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
my $month = ['None','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
|
||||
my @calendars;
|
||||
my $in;
|
||||
|
||||
while (<>) {
|
||||
$in .= $_;
|
||||
if (/END:VCALENDAR/) {
|
||||
push(@calendars,$in);
|
||||
$in = "";
|
||||
}
|
||||
}
|
||||
print STDERR "Read all calendars\n" if $debug;
|
||||
my(%parser_opts) = ("debug" => $debug);
|
||||
if ($start) {
|
||||
my $t = str2time($start);
|
||||
die "Invalid time $start\n" if (! $t);
|
||||
$parser_opts{'start'} = DateTime->from_epoch(epoch => $t);
|
||||
}
|
||||
if ($end) {
|
||||
my $t = str2time($end);
|
||||
die "Invalid time $end\n" if (! $t);
|
||||
$parser_opts{'end'} = DateTime->from_epoch(epoch => $t);
|
||||
}
|
||||
print STDERR "About to parse calendars\n" if $debug;
|
||||
my $parser = iCal::Parser->new(%parser_opts);
|
||||
my $hash = $parser->parse_strings(@calendars);
|
||||
print STDERR "Calendars parsed\n" if $debug;
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# Subroutines
|
||||
#
|
||||
#############################################################
|
||||
#
|
||||
# _process_todos()
|
||||
# expects 'todos' hashref from iCal::Parser is input
|
||||
# returns String to output
|
||||
sub _process_todos {
|
||||
my $todos = shift;
|
||||
|
||||
my ($todo, @newtodos, $leadtime);
|
||||
my $output = "";
|
||||
|
||||
$output .= 'REM '.$HEADING.' MSG '.$label.' ToDos:%"%"%'."\n";
|
||||
|
||||
# For sorting, make sure everything's got something
|
||||
# To sort on.
|
||||
my $now = DateTime->now;
|
||||
for $todo (@{$todos}) {
|
||||
# remove completed items
|
||||
if ($todo->{'STATUS'} && $todo->{'STATUS'} eq 'COMPLETED') {
|
||||
next;
|
||||
} elsif ($todo->{'DUE'}) {
|
||||
# All we need is a due date, everything else is sugar
|
||||
$todo->{'SORT'} = $todo->{'DUE'}->clone;
|
||||
} elsif ($todo->{'DTSTART'}) {
|
||||
# for sorting, sort on start date if there's no due date
|
||||
$todo->{'SORT'} = $todo->{'DTSTART'}->clone;
|
||||
} else {
|
||||
# if there's no due or start date, just make it now.
|
||||
$todo->{'SORT'} = $now;
|
||||
}
|
||||
push(@newtodos,$todo);
|
||||
}
|
||||
if (! (scalar @newtodos)) {
|
||||
return "";
|
||||
}
|
||||
# Now sort on the new Due dates and print them out.
|
||||
for $todo (sort { DateTime->compare($a->{'SORT'}, $b->{'SORT'}) } @newtodos) {
|
||||
my $due = $todo->{'SORT'}->clone();
|
||||
my $priority = "";
|
||||
if (defined($todo->{'PRIORITY'})) {
|
||||
if ($todo->{'PRIORITY'} == 1) {
|
||||
$priority = "PRIORITY 1000";
|
||||
} elsif ($todo->{'PRIORITY'} == 3) {
|
||||
$priority = "PRIORITY 7500";
|
||||
}
|
||||
}
|
||||
if (defined($todo->{'DTSTART'}) && defined($todo->{'DUE'})) {
|
||||
# Lead time is duration of task + lead time
|
||||
my $diff = ($todo->{'DUE'}->delta_days($todo->{'DTSTART'})->days())+$DEFAULT_LEAD_TIME;
|
||||
$leadtime = "+".$diff;
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
$output .= "REM ".$due->month_abbr." ".$due->day." ".$due->year." $leadtime $priority MSG \%a $todo->{'SUMMARY'}\%\"\%\"\%\n";
|
||||
}
|
||||
$output .= 'REM '.$HEADING.' MSG %"%"%'."\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Main Program
|
||||
#
|
||||
######################################################################
|
||||
|
||||
# Issue 8 https://github.com/jbalcorn/ical2rem/issues/8
|
||||
# Make sure there is a _sfun function declared in the reminder file. We'll just make it do nothing here.
|
||||
print 'IF args("_sfun") < 1
|
||||
FSET _sfun(x) choose(x,0)
|
||||
ENDIF
|
||||
';
|
||||
|
||||
print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
|
||||
|
||||
my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
|
||||
print 'REM '.$HEADING.' MSG '.$label.' Events:%"%"%'."\n";
|
||||
my $events = $hash->{'events'};
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if ($eventsbyuid{$uid}) {
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
for (my $i = 0;$i < $DEFAULT_LEAD_TIME && !defined($event->{'LEADTIME'});$i++) {
|
||||
if ($eventsbyuid{$uid}{$curreventday->subtract( days => $i+1 )->epoch() }) {
|
||||
$event->{'LEADTIME'} = $i;
|
||||
}
|
||||
}
|
||||
# Issue 9. Multi-day events have extra day with zero time. Mark this as the date not needed in reminders file so we can skip later
|
||||
# Repeating multi-day events have the same uid so we need to mark each one.
|
||||
if ($event->{'DTSTART'} eq $event->{'DTEND'} and $event->{'DTEND'}->hour eq 0 and $event->{'DTEND'}->minute eq 0 and $event->{'DTEND'}->second eq 0) {
|
||||
$eventsbyuid{$uid}{$event->{'DTSTART'}->ymd} = 'rm';
|
||||
}
|
||||
} else {
|
||||
$eventsbyuid{$uid} = $event;
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if (exists($event->{'LEADTIME'})) {
|
||||
$leadtime = "+".$event->{'LEADTIME'};
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
my $start = $event->{'DTSTART'};
|
||||
my $end = $event->{'DTEND'};
|
||||
my $duration = "";
|
||||
# Issue 9. All Day events create an event that has zero length and DTSTART and DTEND at 00:00 on last day. Marked while handling multi-day events. Ignore these
|
||||
if ($start eq $end and $eventsbyuid{$uid}{$start->ymd} and $eventsbyuid{$uid}{$start->ymd} eq 'rm') {
|
||||
next;
|
||||
}
|
||||
if ($end and ($start->hour or $start->minute or $end->hour or $end->minute)) {
|
||||
# We need both an HH:MM version of the delta, to put in the
|
||||
# DURATION specifier, and a human-readable version of the
|
||||
# delta, to put in the message if the user requested it.
|
||||
my $seconds = $end->epoch - $start->epoch;
|
||||
my $minutes = int($seconds / 60);
|
||||
my $hours = int($minutes / 60);
|
||||
$minutes -= $hours * 60;
|
||||
$duration = sprintf("DURATION %d:%02d ", $hours, $minutes);
|
||||
}
|
||||
print "REM ";
|
||||
if ($iso8601) {
|
||||
print $start->strftime("%F ");
|
||||
} else {
|
||||
print $start->month_abbr." ".$start->day." ".$start->year." ";
|
||||
}
|
||||
print "$leadtime ";
|
||||
if ($duration or $start->hour > 0 or $start->minute > 0) {
|
||||
print "AT ";
|
||||
print $start->strftime("%H:%M");
|
||||
print " SCHED _sfun ${duration}MSG %a %2 ";
|
||||
} else {
|
||||
print "MSG %a ";
|
||||
}
|
||||
print "%\"", "e($event->{'SUMMARY'});
|
||||
print(" at ", "e($event->{'LOCATION'}))
|
||||
if ($do_location and $event->{'LOCATION'});
|
||||
print "\%\"";
|
||||
if ($do_end_times and ($start->hour or $start->minute or
|
||||
$end->hour or $end->minute)) {
|
||||
my $start_date = $start->strftime("%F");
|
||||
my $start_time = $start->strftime("%k:%M");
|
||||
my $end_date = $end->strftime("%F");
|
||||
my $end_time = $end->strftime("%k:%M");
|
||||
# We don't want leading whitespace; some strftime's support
|
||||
# disabling the pdding in the format string, but not all,
|
||||
# so for maximum portability we do it ourselves.
|
||||
$start_time =~ s/^\s+//;
|
||||
$end_time =~ s/^\s+//;
|
||||
my(@pieces);
|
||||
if ($start_date ne $end_date) {
|
||||
push(@pieces, $end_date);
|
||||
}
|
||||
if ($start_time ne $end_time) {
|
||||
push(@pieces, $end_time);
|
||||
}
|
||||
print " (-", join(" ", @pieces), ")";
|
||||
}
|
||||
print "%\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub quote {
|
||||
local($_) = @_;
|
||||
s/\[/["["]/g;
|
||||
return $_;
|
||||
}
|
||||
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 tabstop=4 expandtab :
|
||||
@@ -1,279 +0,0 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# ical2rem.pl -
|
||||
# Reads iCal files and outputs remind-compatible files. Tested ONLY with
|
||||
# calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
|
||||
# Copyright (c) 2005, 2007, Justin B. Alcorn
|
||||
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
# version 0.5.2 2007-03-23
|
||||
# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
# - remove project-lead-time, since Category was a non-standard attribute
|
||||
# - NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
|
||||
# fail if a calendar with recurring events is followed by a calendar with no
|
||||
# recurring events. This has been reported to the iCal::Parser author.
|
||||
# version 0.5.1 2007-03-21
|
||||
# - BUG: Handle multiple calendars on STDIN
|
||||
# - add --heading option for priority on section headers
|
||||
# version 0.5 2007-03-21
|
||||
# - Add more help options
|
||||
# - --project-lead-time option
|
||||
# - Suppress printing of heading if there are no todos to print
|
||||
# version 0.4
|
||||
# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
# - Change to GetOptions
|
||||
# - Change to pipe
|
||||
# - Add --label, --help options
|
||||
# - Add Help Text
|
||||
# - Change to subroutines
|
||||
# - Efficiency and Cleanup
|
||||
# version 0.3
|
||||
# - Convert to GPL (Thanks to Mark Stosberg)
|
||||
# - Add usage
|
||||
# version 0.2
|
||||
# - add command line switches
|
||||
# - add debug code
|
||||
# - add SCHED _sfun keyword
|
||||
# - fix typos
|
||||
# version 0.1 - ALPHA CODE.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
|
||||
|
||||
All options have reasonable defaults:
|
||||
--label Calendar name (Default: Calendar)
|
||||
--lead-time Advance days to start reminders (Default: 3)
|
||||
--todos, --no-todos Process Todos? (Default: Yes)
|
||||
--heading Define a priority for static entries
|
||||
--help Usage
|
||||
--man Complete man page
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
|
||||
=head2 --label
|
||||
|
||||
ical2rem.pl --label "Bob's Calendar"
|
||||
|
||||
The syntax generated includes a label for the calendar parsed.
|
||||
By default this is "Calendar". You can customize this with
|
||||
the "--label" option.
|
||||
|
||||
=head2 --lead-time
|
||||
|
||||
ical2rem.pl --lead-time 3
|
||||
|
||||
How may days in advance to start getting reminders about the events. Defaults to 3.
|
||||
|
||||
=head2 --no-todos
|
||||
|
||||
ical2rem.pl --no-todos
|
||||
|
||||
If you don't care about the ToDos the calendar, this will suppress
|
||||
printing of the ToDo heading, as well as skipping ToDo processing.
|
||||
|
||||
=head2 --heading
|
||||
|
||||
ical2rem.pl --heading "PRIORITY 9999"
|
||||
|
||||
Set an option on static messages output. Using priorities can made the static messages look different from
|
||||
the calendar entries. See the file defs.rem from the remind distribution for more information.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use iCal::Parser;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
use Data::Dumper;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.5.2";
|
||||
|
||||
# Declare how many days in advance to remind
|
||||
my $DEFAULT_LEAD_TIME = 3;
|
||||
my $PROCESS_TODOS = 1;
|
||||
my $HEADING = "";
|
||||
my $help;
|
||||
my $man;
|
||||
|
||||
my $label = 'Calendar';
|
||||
GetOptions (
|
||||
"label=s" => \$label,
|
||||
"lead-time=i" => \$DEFAULT_LEAD_TIME,
|
||||
"todos!" => \$PROCESS_TODOS,
|
||||
"heading=s" => \$HEADING,
|
||||
"help|?" => \$help,
|
||||
"man" => \$man
|
||||
);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
my $month = ['None','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
|
||||
my @calendars;
|
||||
my $in;
|
||||
|
||||
while (<>) {
|
||||
$in .= $_;
|
||||
if (/END:VCALENDAR/) {
|
||||
push(@calendars,$in);
|
||||
$in = "";
|
||||
}
|
||||
}
|
||||
my $parser = iCal::Parser->new();
|
||||
my $hash = $parser->parse_strings(@calendars);
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# Subroutines
|
||||
#
|
||||
#############################################################
|
||||
#
|
||||
# _process_todos()
|
||||
# expects 'todos' hashref from iCal::Parser is input
|
||||
# returns String to output
|
||||
sub _process_todos {
|
||||
my $todos = shift;
|
||||
|
||||
my ($todo, @newtodos, $leadtime);
|
||||
my $output = "";
|
||||
|
||||
$output .= 'REM '.$HEADING.' MSG '.$label.' ToDos:%"%"%'."\n";
|
||||
|
||||
# For sorting, make sure everything's got something
|
||||
# To sort on.
|
||||
my $now = DateTime->now;
|
||||
for $todo (@{$todos}) {
|
||||
# remove completed items
|
||||
if ($todo->{'STATUS'} && $todo->{'STATUS'} eq 'COMPLETED') {
|
||||
next;
|
||||
} elsif ($todo->{'DUE'}) {
|
||||
# All we need is a due date, everything else is sugar
|
||||
$todo->{'SORT'} = $todo->{'DUE'}->clone;
|
||||
} elsif ($todo->{'DTSTART'}) {
|
||||
# for sorting, sort on start date if there's no due date
|
||||
$todo->{'SORT'} = $todo->{'DTSTART'}->clone;
|
||||
} else {
|
||||
# if there's no due or start date, just make it now.
|
||||
$todo->{'SORT'} = $now;
|
||||
}
|
||||
push(@newtodos,$todo);
|
||||
}
|
||||
if (! (scalar @newtodos)) {
|
||||
return "";
|
||||
}
|
||||
# Now sort on the new Due dates and print them out.
|
||||
for $todo (sort { DateTime->compare($a->{'SORT'}, $b->{'SORT'}) } @newtodos) {
|
||||
my $due = $todo->{'SORT'}->clone();
|
||||
my $priority = "";
|
||||
if (defined($todo->{'PRIORITY'})) {
|
||||
if ($todo->{'PRIORITY'} == 1) {
|
||||
$priority = "PRIORITY 1000";
|
||||
} elsif ($todo->{'PRIORITY'} == 3) {
|
||||
$priority = "PRIORITY 7500";
|
||||
}
|
||||
}
|
||||
if (defined($todo->{'DTSTART'}) && defined($todo->{'DUE'})) {
|
||||
# Lead time is duration of task + lead time
|
||||
my $diff = ($todo->{'DUE'}->delta_days($todo->{'DTSTART'})->days())+$DEFAULT_LEAD_TIME;
|
||||
$leadtime = "+".$diff;
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
$output .= "REM ".$due->month_abbr." ".$due->day." ".$due->year." $leadtime $priority MSG \%a $todo->{'SUMMARY'}\%\"\%\"\%\n";
|
||||
}
|
||||
$output .= 'REM '.$HEADING.' MSG %"%"%'."\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Main Program
|
||||
#
|
||||
######################################################################
|
||||
|
||||
print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
|
||||
|
||||
my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
|
||||
print 'REM '.$HEADING.' MSG '.$label.' Events:%"%"%'."\n";
|
||||
my $events = $hash->{'events'};
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if ($eventsbyuid{$uid}) {
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
for (my $i = 0;$i < $DEFAULT_LEAD_TIME && !defined($event->{'LEADTIME'});$i++) {
|
||||
if ($eventsbyuid{$uid}{$curreventday->subtract( days => $i+1 )->epoch() }) {
|
||||
$event->{'LEADTIME'} = $i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$eventsbyuid{$uid} = $event;
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if (exists($event->{'LEADTIME'})) {
|
||||
$leadtime = "+".$event->{'LEADTIME'};
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
my $start = $event->{'DTSTART'};
|
||||
print "REM ".$start->month_abbr." ".$start->day." ".$start->year." $leadtime ";
|
||||
if ($start->hour > 0) {
|
||||
print " AT ";
|
||||
print $start->strftime("%H:%M");
|
||||
print " SCHED _sfun MSG %a %2 ";
|
||||
} else {
|
||||
print " MSG %a ";
|
||||
}
|
||||
print "%\"$event->{'SUMMARY'}";
|
||||
print " at $event->{'LOCATION'}" if $event->{'LOCATION'};
|
||||
print "\%\"%\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 expandtab :
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software
|
||||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
;; 02111-1307, USA.
|
||||
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
@@ -110,18 +109,15 @@
|
||||
|
||||
(defconst remind-keywords
|
||||
(sort
|
||||
(list "ADDOMIT" "AFTER" "AT" "BANNER" "BEFORE"
|
||||
"CAL" "CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMPVARS"
|
||||
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "FIRST"
|
||||
"FLUSH" "FOURTH" "FROM" "FSET" "IF" "IFTRIG" "IN"
|
||||
"INCLUDE" "INCLUDECMD" "LAST" "LASTDAY"
|
||||
"LASTWORKDAY" "MAYBE-UNCOMPUTABLE" "MSF"
|
||||
"MSG" "OMIT" "OMITFUNC" "ONCE"
|
||||
"POP-OMIT-CONTEXT" "PRESERVE" "PRIORITY" "PS" "PSFILE"
|
||||
"PUSH-OMIT-CONTEXT" "REM" "RUN" "SATISFY" "SCANFROM"
|
||||
"SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
|
||||
"TAG" "THIRD" "THROUGH" "UNSET" "UNTIL"
|
||||
"WARN")
|
||||
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
|
||||
"CLEAR-OMIT-CONTEXT" "DEBUG" "DO" "DUMP" "DUMPVARS" "DURATION" "ELSE"
|
||||
"ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST" "FLUSH" "FOURTH" "FROM" "FSET"
|
||||
"FUNSET" "IF" "IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "LAST"
|
||||
"LASTDAY" "LASTWORKDAY" "MAYBE" "MAYBE-UNCOMPUTABLE" "MSF" "MSG"
|
||||
"NOQUEUE" "OMIT" "OMITFUNC" "ONCE" "POP" "POP-OMIT-CONTEXT" "PRESERVE"
|
||||
"PRIORITY" "PS" "PSFILE" "PUSH" "PUSH-OMIT-CONTEXT" "REM" "RUN"
|
||||
"SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET" "SKIP" "SPECIAL"
|
||||
"TAG" "THIRD" "THROUGH" "UNSET" "UNTIL" "WARN")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
@@ -132,50 +128,57 @@
|
||||
|
||||
(defconst remind-builtin-variables
|
||||
(sort
|
||||
(list "$Ago" "$Am" "$And" "$April" "$At" "$August" "$CalcUTC" "$CalMode" "$Daemon" "$DateSep"
|
||||
"$DateTimeSep" "$December" "$DefaultColor" "$DefaultPrio"
|
||||
"$DefaultTDelta" "$DeltaOffset" "$DontFork" "$DontQueue"
|
||||
"$DontTrigAts" "$EndSent" "$EndSentIg" "$February" "$FirstIndent"
|
||||
"$FoldYear" "$FormWidth" "$Friday" "$Fromnow" "$Hour" "$Hplu" "$HushMode" "$IgnoreOnce"
|
||||
"$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$July" "$June" "$LatDeg"
|
||||
"$Latitude" "$LatMin" "$LatSec" "$Location" "$LongDeg" "$Longitude"
|
||||
"$LongMin" "$LongSec" "$March" "$MaxSatIter" "$MaxStringLen" "$May"
|
||||
"$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode" "$November" "$Now" "$NumQueued"
|
||||
"$NumTrig" "$October" "$On" "$Pm" "$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday"
|
||||
"$September" "$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime"
|
||||
"$SubsIndent" "$Sunday" "$SysInclude" "$T" "$Td" "$Thursday" "$TimeSep" "$Tm"
|
||||
"$Today" "$Tomorrow" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um" "$UntimedFirst" "$Uw" "$Uy"
|
||||
"$Was" "$Wednesday")
|
||||
(list "$AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
||||
"$CalcUTC" "$CalMode" "$Daemon" "$DateSep" "$DateTimeSep" "$December"
|
||||
"$DefaultColor" "$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
||||
"$DontFork" "$DontQueue" "$DontTrigAts" "$EndSent" "$EndSentIg"
|
||||
"$ExpressionTimeLimit" "$February" "$FirstIndent" "$FoldYear"
|
||||
"$FormWidth" "$Friday" "$Fromnow" "$Hour" "$Hplu" "$HushMode"
|
||||
"$IgnoreOnce" "$InfDelta" "$IntMax" "$IntMin" "$Is" "$January" "$July"
|
||||
"$June" "$LatDeg" "$Latitude" "$LatMin" "$LatSec" "$Location"
|
||||
"$LongDeg" "$Longitude" "$LongMin" "$LongSec" "$March" "$MaxFullOmits"
|
||||
"$MaxLateMinutes" "$MaxPartialOmits" "$MaxSatIter" "$MaxStringLen"
|
||||
"$May" "$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode"
|
||||
"$November" "$Now" "$NumFullOmits" "$NumPartialOmits" "$NumQueued"
|
||||
"$NumTrig" "$October" "$On" "$OnceFile" "$ParseUntriggered" "$Pm"
|
||||
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September"
|
||||
"$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent"
|
||||
"$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Td"
|
||||
"$TerminalBackground" "$Thursday" "$TimeSep" "$Tm" "$Today"
|
||||
"$Tomorrow" "$Tt" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um"
|
||||
"$UntimedFirst" "$Use256Colors" "$UseBGVTColors" "$UseTrueColors"
|
||||
"$UseVTColors" "$Uw" "$Uy" "$Was" "$Wednesday")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
(defconst remind-time-words
|
||||
(sort
|
||||
(list "Jan" "January" "Feb" "Mar" "Apr" "Jun" "Jul" "Aug" "Sept" "Sep" "Oct" "Nov" "Dec"
|
||||
"February" "March" "April" "May" "June" "July" "August" "September" "October"
|
||||
"November" "December" "Mon" "Monday" "Tue" "Tues" "Tuesday" "Wed" "Wednesday"
|
||||
"Thu" "Thursday" "Thurs" "Fri" "Friday" "Saturday" "Sat" "Sun" "Sunday")
|
||||
(list "Apr" "April" "Aug" "August" "Dec" "December" "Feb" "February"
|
||||
"Jan" "January" "Jul" "July" "Jun" "June" "Mar" "March" "May"
|
||||
"Nov" "November" "Oct" "October" "Sep" "September" "Fri"
|
||||
"Friday" "Mon" "Monday" "Sat" "Saturday" "Sun" "Sunday" "Thu"
|
||||
"Thursday" "Tue" "Tuesday" "Wed" "Wednesday")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "abs" "access" "adawn" "adusk" "ampm" "args" "asc" "baseyr" "char"
|
||||
"choose" "coerce" "current" "date" "datepart" "datetime" "dawn" "day"
|
||||
"daysinmon" "defined" "dosubst" "dusk" "easterdate" "evaltrig"
|
||||
"filedate" "filedatetime" "filedir" "filename" "getenv" "hebdate"
|
||||
"hebday" "hebmon" "hebyear" "hour" "iif" "index" "isany" "isdst"
|
||||
"isleap" "isomitted" "language" "lower" "max" "min" "minsfromutc"
|
||||
(list "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc"
|
||||
"baseyr" "char" "choose" "coerce" "columns" "current" "date"
|
||||
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst"
|
||||
"dusk" "easterdate" "evaltrig" "filedate" "filedatetime" "filedir"
|
||||
"filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear" "hour"
|
||||
"htmlescape" "htmlstriptags" "iif" "index" "isany" "isdst" "isleap"
|
||||
"isomitted" "language" "localtoutc" "lower" "max" "min" "minsfromutc"
|
||||
"minute" "mon" "monnum" "moondate" "moondatetime" "moonphase"
|
||||
"moontime" "ndawn" "ndusk" "nonomitted" "now" "ord" "ostype" "pad" "plural"
|
||||
"psmoon" "psshade" "realcurrent" "realnow" "realtoday" "sgn" "shell"
|
||||
"shellescape" "slide" "strlen" "substr" "sunrise" "sunset" "time"
|
||||
"timepart" "today" "trig" "trigback" "trigdate" "trigdatetime"
|
||||
"trigdelta" "trigduration" "trigeventduration" "trigeventstart"
|
||||
"trigfrom" "trigger" "trigpriority" "trigrep" "trigscanfrom"
|
||||
"trigtime" "trigtimedelta" "trigtimerep" "triguntil" "trigvalid"
|
||||
"typeof" "tzconvert" "upper" "value" "version" "weekno" "wkday"
|
||||
"wkdaynum" "year")
|
||||
"moontime" "multitrig" "ndawn" "ndusk" "nonomitted" "now" "ord"
|
||||
"orthodoxeaster" "ostype" "pad" "plural" "psmoon" "psshade"
|
||||
"realcurrent" "realnow" "realtoday" "rows" "sgn" "shell" "shellescape"
|
||||
"slide" "soleq" "stdout" "strlen" "substr" "sunrise" "sunset" "time"
|
||||
"timepart" "timezone" "today" "trig" "trigback" "trigdate"
|
||||
"trigdatetime" "trigdelta" "trigduration" "trigeventduration"
|
||||
"trigeventstart" "trigfrom" "trigger" "trigpriority" "trigrep"
|
||||
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep"
|
||||
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal"
|
||||
"value" "version" "weekno" "wkday" "wkdaynum" "year")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
;;; faces
|
||||
@@ -291,7 +294,7 @@
|
||||
|
||||
(defconst remind-conf-font-lock-keywords-1
|
||||
(list
|
||||
'("^[\;\#]\\s-+.*$" . remind-comment-face)
|
||||
'("^\s*[\;\#].*$" . remind-comment-face)
|
||||
'(remind-keywords-matcher . remind-conf-keyword-face)
|
||||
'("%[\"_]" . font-lock-warning-face)
|
||||
'("\\(%[a-mops-w]\\)" . remind-conf-substitutes-face)
|
||||
@@ -514,6 +517,7 @@ Acts on the region or places point where it needs to be."
|
||||
(set (make-local-variable 'comment-start) ";")
|
||||
(set (make-local-variable 'comment-start) "#")
|
||||
(set (make-local-variable 'comment-end) "\n")
|
||||
(set (make-local-variable 'comment-end-skip) "[ \t]*\\(\\s>\\||#\\)")
|
||||
(set (make-local-variable 'skeleton-end-hook) nil) ; so the skeletons will not automatically go to a new line.
|
||||
(set (make-local-variable 'fill-column) '100);cause I was having problems with autofill.
|
||||
(set (make-local-variable 'indent-line-function) 'remind-indent-line)
|
||||
|
||||
@@ -95,7 +95,7 @@ Norman Walsh.
|
||||
#!/usr/local/bin/wish
|
||||
wm withdraw .
|
||||
after 15000 { destroy . ; exit }
|
||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
||||
tk_messageBox -message Message -detail $argv -icon info -type ok
|
||||
destroy .
|
||||
exit
|
||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
||||
|
||||
661
docs/WHATSNEW
661
docs/WHATSNEW
@@ -1,5 +1,552 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* VERSION 5.0 Patch 7 - 2024-10-16
|
||||
|
||||
- NEW FEATURE: tkremind: Add option to create a desktop notification when
|
||||
a queued reminder is triggered. For Tcl/Tk 9.0 or later, uses the native
|
||||
"tk sysnotify" facility. For earlier versions of Tcl/Tk, executes the
|
||||
"notify-send" program if possible.
|
||||
|
||||
- NEW FEATURE: remind: Add --print-config-cmd option which prints the
|
||||
exact ./configure command used to build Remind. This will let you
|
||||
configure future Remind releases exactly the same way an installed
|
||||
version was configured.
|
||||
|
||||
- UPDATE: include/holidays/ca.rem: Add National Day for Truth and
|
||||
Reconciliation to Canadian holiday list.
|
||||
|
||||
- MINOR IMPROVEMENTS: Update examples/ansitext and examples/astro
|
||||
|
||||
- MINOR IMPROVEMENT: remind: Use HashPJW to hash variable and function
|
||||
names; make the hash table size a prime rather than a power of two.
|
||||
This seems to improve hash performance ever so slightly in most cases.
|
||||
|
||||
- UPDATE: Update contrib/ical2rem to upstream version 0.7.1
|
||||
|
||||
- FIX: tkremind: Make tkremind work with Tcl/Tk 8.5 or higher, including
|
||||
Tcl/Tk 9.0
|
||||
|
||||
- MINOR CHANGE: remind: Add hash table statistics to "-ds" debugging
|
||||
output. This is probably of no use to anyone except the author of
|
||||
Remind.
|
||||
|
||||
* VERSION 5.0 Patch 6 - 2024-09-16
|
||||
|
||||
- NEW FEATURE: remind: Include a file containing the dates of Chinese
|
||||
New Year through 2050.
|
||||
|
||||
- NEW FEATURE: remind: Add $SuppressImplicitWarnings system variable.
|
||||
Setting this to 1 suppresses the warnings "Unrecognized command;
|
||||
interpreting as REM" and "Missing REM type; assuming MSG"
|
||||
|
||||
- NEW FEATURE: remind: Add --print-tokens command-line argument. This
|
||||
simply prints all of Remind's built-in tokens, functions, and system
|
||||
variables. It's designed to help people who are writing editor
|
||||
add-ons for syntax highlighting.
|
||||
|
||||
- CHANGE: remind: allow '12:34' to be parsed as a TIME constant. This
|
||||
matches DATEs and DATETIMEs which are enclosed in single-quotes.
|
||||
(The quotes are optional for TIME constants, however.)
|
||||
|
||||
- IMPROVEMENT: Improve many error messages and warnings.
|
||||
|
||||
- UPDATE: contrib/ical2rem: Update to upstream version 0.7
|
||||
|
||||
- IMPROVEMENT: contrib/remind-conf-mode: Improve the Emacs
|
||||
remind-conf-mode package. Add new keywords and make comment
|
||||
highlighting correct.
|
||||
|
||||
- FIX: remind man page: Remove note saying REM can be omitted.
|
||||
|
||||
* VERSION 5.0 Patch 5 - 2024-09-02
|
||||
|
||||
- CHANGE: remind: When using the "-c" option and with the SHADE special
|
||||
enabled, shade the entire calendar box including the line containing the
|
||||
day number.
|
||||
|
||||
- IMPROVEMENT: remind: Better error messages when diagnosing certain
|
||||
errors in expressions.
|
||||
|
||||
- IMPROVEMENT: include/holidays/jewish.rem: Remove unnecessary _h()
|
||||
function definition.
|
||||
|
||||
- BUG FIX: remind: In a couple of spots when we parsed a character, we did
|
||||
not check for an error return. This has been fixed.
|
||||
|
||||
- BUG FIX: remind: Fix edge-case bugs in "remind -c" output formatting.
|
||||
|
||||
- BUG FIX: make test: Fix a test that was broken for all of September 2024.
|
||||
|
||||
- BUG FIX: remind: Fix a couple of potential file-descriptor leaks.
|
||||
|
||||
- BUG FIX: contrib/ical2rem.pl: Replace "SCHED _sfun" with "+15" to
|
||||
hard-code 15-minutes advance warning rather than using an undefined
|
||||
scheduling function. If this is not what you want, you should edit
|
||||
ical2rem.pl to suit your taste; it's not officially part of Remind and
|
||||
is meant more as a starting point for you to customize than a finished
|
||||
product.
|
||||
|
||||
- DOCUMENTATION FIX: Remove obsolete info from Remind man page.
|
||||
|
||||
* VERSION 5.0 Patch 4 - 2024-08-29
|
||||
|
||||
- IMPROVEMENT: remind: When checking if a SATISFY expression refers to the
|
||||
trigger date, look recursively at any user-defined functions it calls.
|
||||
This reduces spurious warnings.
|
||||
|
||||
- CHANGE: remind: Allow any type to be used as the test argument for IIF.
|
||||
|
||||
- IMPROVEMENT: remind man page: Clarify how various types are treated
|
||||
in boolean context.
|
||||
|
||||
* VERSION 5.0 Patch 3 - 2024-08-28
|
||||
|
||||
- IMPROVEMENT: remind: Preserve newlines ("%_" sequences) in calendar
|
||||
mode in most cases. See the remind man page for details.
|
||||
|
||||
- IMPROVEMENT: rem2pdf: rem2pdf can now produce PostScript and
|
||||
Encapsulated PostScript output in addition to PDF and SVG.
|
||||
|
||||
- IMPROVEMENT: remind: Emit warnings if a subst_XXX function takes the
|
||||
wrong number of arguments, or for custom sequences, if the function
|
||||
is not defined.
|
||||
|
||||
- IMPROVEMENT: remind: Emit warnings if WARN/SCHED/OMITFUNC functions
|
||||
do not reference their argument.
|
||||
|
||||
- IMPROVEMENT: remind: Allow strings to be used with logical
|
||||
operators. The empty string "" is considered false and all other
|
||||
strings are considered true.
|
||||
|
||||
- IMPROVEMENT: remind: Emit warnings for lines that are implicitly
|
||||
treated as REM commands; add warnings for REM commands that are
|
||||
implicitly treated as MSG-type reminders.
|
||||
|
||||
- IMPROVEMENT: remind: Add an optional fourth argument to the built-in
|
||||
ampm() function that specifies not to suppress a leading zero in the
|
||||
hour component.
|
||||
|
||||
- IMPROVEMENT: remind: If a SATISFY expression is not constant and
|
||||
doesn't reference the trigger date somehow, issue a warning.
|
||||
|
||||
- IMPROVEMENT: remind: Add a warning if a user-defined function is
|
||||
redefined. If you do have a use-case that requires you to redefine
|
||||
a function, simply FUNSET it first before FSETting it for the second
|
||||
time.
|
||||
|
||||
- DOCUMENTATION FIX: Clarify man pages and remove some information that
|
||||
has become incorrect as Remind has evolved.
|
||||
|
||||
- BUG FIX: Fix typos in man pages
|
||||
|
||||
* VERSION 5.0 Patch 2 - 2024-07-26
|
||||
|
||||
- IMPROVEMENT: Remind: Revamp how ONCE works. You can now set a
|
||||
special variable $OnceFile to be the path to a timestamp file. The
|
||||
ONCE directive uses this timestamp file to track when it was last
|
||||
run rather than the access date of the main reminder script. This
|
||||
is more reliable because it doesn't rely on the atime of a file
|
||||
(which might not be maintained accurately) and is not affected if
|
||||
you edit your reminder script.
|
||||
|
||||
- CHANGE: Taking input from stdin no longer implies the "-o" option; ONCE can
|
||||
work if you set $OnceFile
|
||||
|
||||
- CHANGE: Any of the -c, -n, -p and -s options implicitly enable the
|
||||
-o option. As before, specifying a repeat factor *N or a date that
|
||||
is not today on the command-line also implies -o.
|
||||
|
||||
- MINOR NEW FEATURE: Rem2PDF: Add the "--svg" command-line option to produce
|
||||
SVG output rather than PDF.
|
||||
|
||||
- MINOR IMPROVEMENT: Remind: Improve the storage efficiency of short
|
||||
string constants in compiled expression trees.
|
||||
|
||||
- MINOR IMPROVEMENT: Remind: Remove some obsolete macro definitions
|
||||
|
||||
* VERSION 5.0 Patch 1 - 2024-06-08
|
||||
|
||||
- MINOR IMPROVEMENT: Add short-circuit evaluation to the isany() function,
|
||||
which now only evaluates those arguments absolutely necessary to determine
|
||||
the result.
|
||||
|
||||
- BUG FIX: Mark weekno() as a non-constant function (the zero-argument form
|
||||
depends on external conditions.)
|
||||
|
||||
- BUG FIX: Fix a couple of memory leaks.
|
||||
|
||||
- BUG FIX: Don't rely on support for unnamed function parameters; this caused
|
||||
compilation failures with older versions of gcc.
|
||||
|
||||
* VERSION 5.0 Patch 0 - 2024-06-06
|
||||
|
||||
- MAJOR CHANGE: The expression evaluation engine has been completely replaced
|
||||
with a new one that splits parsing and evaluating into two separate steps.
|
||||
It also features short-circuit evaluation of &&, ||, iif() and choose().
|
||||
This should speed up expression-heavy reminder files.
|
||||
|
||||
NOTE INCOMPATIBILITY: In expressions with side-effects, the short-circuit
|
||||
evaluation might change the result you get. For example, consider
|
||||
running the following file through: remind file.rem 2024-06-04
|
||||
|
||||
SET a trig("Mon +7") || trig("Thu +7")
|
||||
MSG trig = [trig()]
|
||||
|
||||
Older Remind versions will output:
|
||||
|
||||
trig = 2024-06-06
|
||||
|
||||
whereas this version outputs:
|
||||
|
||||
trig = 2024-06-10
|
||||
|
||||
because the second part of the "||" expression is not evaluated. The vast
|
||||
majority of Remind expressions do not have side-effects and should yield
|
||||
the same results as before.
|
||||
|
||||
The newer expression engine also permits recursive functions, but
|
||||
these are not recommended. Still, if you want to, you can do:
|
||||
|
||||
fset factorial(n) iif(n <= 1, 1, n*factorial(n-1))
|
||||
|
||||
and it will work for values of n that don't cause integer overflow.
|
||||
|
||||
- IMPROVEMENT: If there's an unmatched PUSH-OMIT-CONTEXT, print the
|
||||
filename and line number containing it.
|
||||
|
||||
- IMPROVEMENT: If there's an IF with a missing ENDIF, print the filename
|
||||
and line number of the IF statement.
|
||||
|
||||
- NEW FEATURE: Add EXPR OFF command to completely disable expression
|
||||
evaluation. Useful if you INCLUDE files that you don't expect to
|
||||
contain expressions and may come from slightly untrustworthy sources.
|
||||
|
||||
- NEW FEATURE: Add $ExpressionTimeLimit system variable to enforce a
|
||||
maximum limit on how long evaluating an expression is allowed to take.
|
||||
|
||||
- NEW FEATURE: Add --max-execution-time=n command-line option to terminate
|
||||
Remind if it runs for more than n seconds.
|
||||
|
||||
- CHANGE: Make the command-line option "-ifoo" equivalent to "-ifoo=0"
|
||||
|
||||
- CHANGE: Permit a literal [ in a reminder by using the sequence [[
|
||||
The old ["["] still works.
|
||||
|
||||
- BUG FIX: In "purge" mode, Remind would sometimes purge reminders with
|
||||
a relative "SCANFROM" which haven't actually expired. This has been fixed.
|
||||
|
||||
- BUG FIX: Disallow something like: FSET func(x, x) expr
|
||||
which shouldn't have been allowed in the first place.
|
||||
|
||||
- BUG FIX: Replace leading spaces with tabs in Makefiles (per Emanuele Torre
|
||||
and Tim Chase)
|
||||
|
||||
* VERSION 4.3 Patch 7 - 2024-04-29
|
||||
|
||||
- IMPROVEMENT: build.tk: Add a note if build.tk obtains default settings
|
||||
from an existing Remind installation.
|
||||
|
||||
- IMPROVEMENT: configure: Pass all args to AC_INIT including the Remind
|
||||
home page. Remove some unused autoconf cruft.
|
||||
|
||||
- IMPROVEMENT: Use standard C library versions of strdup, strcasecmp and
|
||||
strncasecmp where available, rather than using our own versions.
|
||||
|
||||
- MINOR FEATURE: remind: Make $Tt a synonym for trigtime().
|
||||
|
||||
- BUG FIX: remind: Make sure shellescape() doesn't mangle UTF-8 characters
|
||||
with high-bits set.
|
||||
|
||||
- BUG FIX: remind: Don't rely on undefined behavior of "%" operator in
|
||||
the ord() built-in function.
|
||||
|
||||
- BUG FIX: remind: Do not clear out trigtime() unnecessarily. Before,
|
||||
you could not write things like the following; now you can:
|
||||
|
||||
REM Tue AT 11:30 DURATION 0:30 MSG Thing 1
|
||||
REM Tue AT [trigtime()+trigduration()] DURATION 1:00 MSG Thing 2
|
||||
REM Tue AT [trigtime()+trigduration()] DURATION 0:45 MSG Thing 3
|
||||
|
||||
for successive reminders that should be moved as a block if the time of
|
||||
the first one changes.
|
||||
|
||||
- BUG FIX: Don't update trigdate() or trigtime() while parsing a REM
|
||||
statement... only when actually computing the trigger.
|
||||
|
||||
* VERSION 4.3 Patch 6 - 2024-04-02
|
||||
|
||||
- NEW FILE: Add [$SysInclude]/holidays/pt.rem - Portuguese holidays, courtesy
|
||||
of Joop Kiefte.
|
||||
|
||||
- BUG FIX: remind: Fix compile error on systems that don't support inotify(7).
|
||||
|
||||
- BUG FIX: remind: Fix test failures on FreeBSD. On FreeBSD, you have to copy
|
||||
the result of getenv() or else a subsequent setenv() can change the stored
|
||||
value.
|
||||
|
||||
* VERSION 4.3 Patch 5 - 2024-04-01
|
||||
|
||||
- IMPROVEMENT: remind: Use inotify to detect reminder file changes
|
||||
even in regular daemon mode (-zn where n>0).
|
||||
|
||||
- INTERNAL IMPROVEMENTS: Rearrange and refactor some code.
|
||||
|
||||
- FIXES: Various fixes and improvements to man pages.
|
||||
|
||||
- BUG FIX: remind: Handle queued "SPECIAL COLOR" reminders correctly.
|
||||
|
||||
- BUG FIX: remind: Preserve the value of $DefaultColor that was in effect
|
||||
when a reminder was queued; restore it before issuing the queued reminder.
|
||||
|
||||
* VERSION 4.3 Patch 4 - 2024-03-25
|
||||
|
||||
- NEW FEATURE: remind: Add the new "multitrig" function, which is how "trig"
|
||||
should have worked in the first place. See man page for details.
|
||||
|
||||
- IMPROVEMENT: tkremind: Make errors in your reminders file stand out more
|
||||
prominently.
|
||||
|
||||
- IMPROVEMENT: tkremind: If you click on an error in the "Errors..." popup,
|
||||
tkremind will open a text editor on the offending file and line.
|
||||
|
||||
- IMPROVEMENT: tkremind: Format the "Queue..." output better and make queue
|
||||
items clickable; clicking on a queue item opens a text editor on the
|
||||
corresponding file and line.
|
||||
|
||||
- IMPROVEMENT: Add a standard [$SysInclude]/moonphases.rem file to display
|
||||
moon phases on your calendar.
|
||||
|
||||
- IMPROVEMENT: Clean up the demo code in www/ and add PDF output.
|
||||
|
||||
- BUG FIX: tkremind: Correctly handle filenames containing spaces and other
|
||||
characters that tend to confuse the shell.
|
||||
|
||||
- BUG FIX: tkremind: Raise dialog boxes after errors so that they
|
||||
remain visible.
|
||||
|
||||
- CLEANUP: tkremind: Remove some dead code.
|
||||
|
||||
* VERSION 4.3 Patch 3 - 2024-03-18
|
||||
|
||||
- IMPROVEMENT: tkremind: Update icon to include a white border so it shows
|
||||
up better on dark backgrounds.
|
||||
|
||||
- IMPROVEMENT: C code: Fix a number of cppcheck static-analysis warnings.
|
||||
|
||||
- IMPROVEMENT: remind: Update the "-zj" protocol to include a queue-id for
|
||||
each queued reminder and add the DEL client command to delete a specific
|
||||
item from the queue. Used by tkremind to implement "don't remind me about
|
||||
this again today."
|
||||
|
||||
- MINOR NEW FEATURE: Add a "-ds" debugging flag to print out expression-parsing
|
||||
stack high-water marks on exit. This esoteric feature is of no use to
|
||||
anyone but the Remind author.
|
||||
|
||||
- IMPROVEMENT: tkremind: Stop using the deprecated tk_dialog command in favor
|
||||
of the newer tk_messageBox command.
|
||||
|
||||
- IMPROVEMENT: remind: In server mode, try to minimize redraws by
|
||||
consuming inotify events until at least 0.2s elapses without an
|
||||
event appearing.
|
||||
|
||||
- BUG FIX: tkremind: The "Don't remind me about this again today" feature
|
||||
was unreliable and only worked for reminders created with TkRemind itself.
|
||||
It has been made more reliable and works with any reminder.
|
||||
|
||||
- BUG FIX: remind: Make it a syntax error if a local OMIT in a REM statement
|
||||
is not followed by at least one weekday name.
|
||||
|
||||
* VERSION 4.3 Patch 2 - 2024-03-01
|
||||
|
||||
- BUG FIX: remind: Fix a logic error when implementing the RUN command in
|
||||
server mode. As it turns out, the error is harmless, but it's best to do
|
||||
things correctly.
|
||||
|
||||
- BUG FIX: The Makefile would install the tkremind.png and tkremind.desktop
|
||||
files in the wrong location. This has been fixed.
|
||||
|
||||
* VERSION 4.3 Patch 1 - 2024-02-29
|
||||
|
||||
- BUG FIX: tests: "make test" could fail because of a bad test. This
|
||||
has been fixed. There are no actual code changes to any of the programs
|
||||
in Remind compared to 04.03.00.
|
||||
|
||||
* VERSION 4.3 Patch 0 - 2024-02-29
|
||||
|
||||
- IMPROVEMENT: remind: If Remind is compiled on a system that supports
|
||||
inotify, then in server mode (-z0 or -zj) it monitors the reminders file
|
||||
and restarts itself if it detects a change, and also notifies the client.
|
||||
Moving inotify support directly into Remind means that tkremind no longer
|
||||
has to invoke a separate inotifywait process.
|
||||
|
||||
- IMPROVEMENT: remind: Set the CLOEXEC flag on files we open so we
|
||||
don't leak file descriptors to programs that we run. While I don't
|
||||
think there's a security issue here (any program you run can do
|
||||
anything as your userid anyway) it's best to be clean and tidy.
|
||||
|
||||
- IMPROVEMENT: remind: Add localization for the Catalan language, courtesy
|
||||
of Eloi Torrents.
|
||||
|
||||
- IMPROVEMENT: tkremind: Add a .desktop file and icon so TkRemind can be
|
||||
integrated into the desktop menu system, courtesy of Eloi Torrents.
|
||||
|
||||
- CHANGE: Add a new server mode with the "-zj" flag. This is just
|
||||
like "-z0" except it uses JSON messages to communicate with the
|
||||
client rather than an ad-hoc protocol. The "-z0" mode is still
|
||||
supported, but is deprecated.
|
||||
|
||||
- CHANGE: In server mode (-z0 or -zj) any RUN-type reminders, or message
|
||||
commands of the "-kcommand" type are run with standard input and standard
|
||||
output connected to /dev/null. NOTE INCOMPATIBILITY: If you previously
|
||||
relied on RUN-type reminders to pop up reminders in TkRemind, they no
|
||||
longer do. If you want this, you'll have to get the command that you
|
||||
run to pop up its own window with "xmessage" or something similar.
|
||||
|
||||
- IMPROVEMENT: tkremind: Make the "Go to date..." dialog non-modal.
|
||||
|
||||
- CHANGE: remind: Allow the argument to easterdate() and
|
||||
orthodoxeaster() to be omitted, in which case it defaults to
|
||||
today().
|
||||
|
||||
- BUG FIX: Miscellaneous man page fixes.
|
||||
|
||||
- BUG FIX: Fix a leap-year edge-case. The reminder: REM 29 MSG whatever
|
||||
was not triggered on Feb 29 of leap years.
|
||||
|
||||
- BUG FIX: rem2html: Make the version of rem2html track the version of
|
||||
Remind. Noted by Ian! D. Allen.
|
||||
|
||||
* VERSION 4.2 Patch 9 - 2024-02-04
|
||||
|
||||
- CHANGE: remind: Do not attempt to guess terminal background color on
|
||||
startup. Only obtain it as needed. This can prevent mojibake from
|
||||
appearing on terminals that don't support the color query escape
|
||||
sequence.
|
||||
|
||||
- IMPROVEMENT: remind: Add new system variables $NumFullOmits,
|
||||
$MaxFullOmits, $NumPartialOmits and $MaxPartialOmits.
|
||||
|
||||
- IMPROVEMENT: remind: Issue a warning if someone OMITs every possible date.
|
||||
|
||||
- IMPROVEMENT: remind: In several error messages complaining about limits
|
||||
being exceeded, include the actual limit in the error message. Clarify
|
||||
the man page regarding limits on the number of OMITs.
|
||||
|
||||
- MINOR NEW FEATURE: remind: The expression STRING * INT or INT * STRING
|
||||
is now accepted and yields a string that is INT concatenations of the
|
||||
original STRING. In this case, INT must be non-negative and the total
|
||||
string length can't exceed $MaxStringLen.
|
||||
|
||||
- DOCUMENTATION: Add "Astronomical Algorithms" by Jean Meeus to bibliography.
|
||||
|
||||
- DOCUMENTATION FIX: Update address of the Free Software Foundation in the
|
||||
license file.
|
||||
|
||||
- DOCUMENTATION: Note that rem2ps is deprecated and will not received any
|
||||
new features. Further development will happen on rem2pdf.
|
||||
|
||||
- BUG FIX: Preserve the filename() and priority context for queued reminders.
|
||||
Previously, the filename information was lost and the priority was
|
||||
coming from uninitialized memory (yikes!). bug found by Alexander
|
||||
Möller.
|
||||
|
||||
- BUG FIX: build.tk: Various minor improvements.
|
||||
|
||||
- BUG FIX: remind: In server mode, if we de-queue a reminder without
|
||||
triggering it, issue a "NOTE queued %d" message to update the
|
||||
client's notion of the queue size.
|
||||
|
||||
- BUG FIX: tkremind: Fix typo found by Lorenzo Bazzanini.
|
||||
|
||||
* VERSION 4.2 Patch 8 - 2023-12-14
|
||||
|
||||
- NEW FEATURE: Add the $MaxLateMinutes system variable. This suppresses
|
||||
a queued time reminder if the current time is more than $MaxLateMinutes
|
||||
past the trigger time. (This typically only occurs if the computer
|
||||
has been suspended/hibernated and then resumed.)
|
||||
|
||||
- IMPROVEMENT: tkremind: If an error occurs during printing, catch it
|
||||
and change the Queue... button to Errors... (the same way errors in
|
||||
reminder files are handled.)
|
||||
|
||||
- IMPROVEMENT: rem2html: add the --utf8 flag to set the HTML charset to
|
||||
UTF-8.
|
||||
|
||||
- MINOR IMPROVEMENTS: Refactor some of the C code; use symbolic exit
|
||||
statuses and file descriptors for stdin/stdout/stderr where possible.
|
||||
|
||||
- BUG FIX: configure.in: Use better option detection so we don't use the
|
||||
unsupported option -ffat-lto-objects if compiling with clang instead of gcc.
|
||||
|
||||
- BUG FIXES: Many fixes to man pages, some by Jochen Sprickerhof
|
||||
|
||||
- MINOR BUG FIX: If Remind puts itself in the background, only close
|
||||
stdout/stderr if they are not associated with a terminal. If
|
||||
we close a descriptor, dup /dev/null onto it.
|
||||
|
||||
- MINOR BUG FIX: Catch SIGCONT when running in daemon/background mode.
|
||||
This forces the select() call to be interrupted so we can update the
|
||||
sleep time. This really only matters if the computer or the background
|
||||
Remind process is suspended and then resumed.
|
||||
|
||||
* VERSION 4.2 Patch 7 - 2023-10-09
|
||||
|
||||
- IMPROVEMENT: remind: On 32-bit systems, attempt to use a 64-bit time_t
|
||||
if the C library supports that. This lets Remind work properly with
|
||||
dates after 2038 in the few cases it has to call mktime() internally.
|
||||
|
||||
- MINOR NEW FEATURE: remind: Attempt to obtain the terminal background
|
||||
color using an OSC sequence. This normally only happens if standard
|
||||
output is a terminal, but can be forced with the '-@..,t' option.
|
||||
|
||||
- MINOR NEW FEATURE: remind: Add "--version" long option to print out
|
||||
Remind's version and exit.
|
||||
|
||||
- MINOR IMPROVEMENT: tkremind: Use a higher-resolution PNG image for
|
||||
the icon.
|
||||
|
||||
- MINOR IMPROVEMENT: remind-conf-mode.el: Update highlighting rules
|
||||
courtesy of Bill Benedetto
|
||||
|
||||
- MINOR CHANGE: Make AT optional. If we encounter a TIME in a REM
|
||||
command, implicitly begin an AT clause.
|
||||
|
||||
- DOCUMENTATION: Many minor fixes and improvements courtesy of Dan Jacobson.
|
||||
|
||||
- BUG FIX: Make "-w0" set the calendar width based on standard output
|
||||
rather than setting it to zero and causing an infinite loop.
|
||||
|
||||
* VERSION 4.2 Patch 6 - 2023-09-12
|
||||
|
||||
- NEW FEATURE: remind: The "nonomitted()" function takes an optional
|
||||
extra INT argument called "step". See man page for details. Also
|
||||
allows the "start" argument to be greater than the "end" argument,
|
||||
in which case they are effectively swapped.
|
||||
|
||||
- NEW FEATURE: remind: The "slide()" function takes an optional extra
|
||||
INT argument called "step", similar to "nonomitted()". See man page
|
||||
for details.
|
||||
|
||||
- NEW FEATURE: remind: Added the $ParseUntriggered system variable;
|
||||
see the man page for details. You almost certainly will never need
|
||||
to use this.
|
||||
|
||||
- NEW FILE: holidays/ie.rem: Added Irish holidays, courtesy of
|
||||
Amy de Buitléir.
|
||||
|
||||
- CHANGE: remind: The "-tn" option sets all REM statement deltas to
|
||||
++n rather than adding n to any existing REM statement's delta.
|
||||
Additionally, the corresponding system variable $DeltaOffset has
|
||||
been renamed to $DeltaOverride.
|
||||
|
||||
- NEW OPTION: remind: Add the "-tz" option to explicitly set all
|
||||
REM statement deltas to zero.
|
||||
|
||||
- DOCUMENTATION FIX: remind: various documentation improvements.
|
||||
|
||||
- BUG FIX: Correct some errors in Italian localization, courtesy of
|
||||
Emanuele Torre
|
||||
|
||||
* VERSION 4.2 Patch 5 - 2023-04-11
|
||||
|
||||
- MINOR IMPROVEMENT: remind: If someone uses OMIT yyyy-mm-dd UNTIL yyyy-mm-dd
|
||||
@@ -779,7 +1326,7 @@ CHANGES TO REMIND
|
||||
|
||||
- MINOR IMPROVEMENT: Add the "ampm()" built-in function.
|
||||
|
||||
* Version 3.3 Patch 0 - 2020-01-31
|
||||
* VERSION 3.3 Patch 0 - 2020-01-31
|
||||
|
||||
- FIX: rem2ps: Add a %%PageBoundingBox: document structuring convention
|
||||
comment.
|
||||
@@ -814,7 +1361,7 @@ CHANGES TO REMIND
|
||||
- CHANGE: SPECIALs are now case-insensitive. Before, only SPECIAL COLOR
|
||||
would work. Now you can use Special Color, special color, etc.
|
||||
|
||||
* Version 3.2 Patch 0 - 2020-01-03
|
||||
* VERSION 3.2 Patch 0 - 2020-01-03
|
||||
|
||||
- IMPROVEMENT: Add support for events spanning multiple days (with AT
|
||||
and DURATION). Add trigeventstart() and trigeventduration()
|
||||
@@ -856,7 +1403,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: TkRemind: Fix startup failure of TkRemind if options are at
|
||||
default. :(
|
||||
|
||||
* Version 3.1 Patch 17 - 2019-11-15
|
||||
* VERSION 3.1 Patch 17 - 2019-11-15
|
||||
|
||||
- IMPROVEMENT: Add "Extra Remind Options" setting to TkRemind.
|
||||
|
||||
@@ -873,7 +1420,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Fix various documentation errors and update man page.
|
||||
|
||||
* Version 3.1 Patch 16 - 2018-11-09
|
||||
* VERSION 3.1 Patch 16 - 2018-11-09
|
||||
|
||||
- IMPROVEMENT: Add patch from Stephen Morgan to calculate astronomical and
|
||||
nautical twilight in addition to civil twilight.
|
||||
@@ -903,7 +1450,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: In "remind -z0" mode, remind wakes up exactly on the minute instead
|
||||
of sleeping for 60 seconds each time, which could cause it to fall behind.
|
||||
|
||||
* Version 3.1 Patch 15 - 2015-07-27
|
||||
* VERSION 3.1 Patch 15 - 2015-07-27
|
||||
|
||||
- BUG FIX: Fix a buffer overflow found by Alexander Keller
|
||||
|
||||
@@ -913,7 +1460,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Make parser reject repeated delta or *repeat values.
|
||||
|
||||
* Version 3.1 Patch 14 - 2015-04-24
|
||||
* VERSION 3.1 Patch 14 - 2015-04-24
|
||||
|
||||
- NEW FEATURE: Putting the line __EOF__ in a .rem file causes Remind
|
||||
to treat it as end-of-file.
|
||||
@@ -930,7 +1477,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Typo in Spanish translation was fixed.
|
||||
|
||||
* Version 3.1 Patch 13 - 2013-03-22
|
||||
* VERSION 3.1 Patch 13 - 2013-03-22
|
||||
|
||||
- BUG FIX: Sunrise/Sunset calculations greatly improved thanks to John
|
||||
McGowan. Accuracy should now be within a couple of minutes in most
|
||||
@@ -947,7 +1494,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Spurious test harness failure was fixed.
|
||||
|
||||
* Version 3.1 Patch 12 - 2012-01-23
|
||||
* VERSION 3.1 Patch 12 - 2012-01-23
|
||||
|
||||
- NEW FEATURE: Many substitution sequences "%x" have an alternate mode
|
||||
denoted by "%*x". This alternate mode leaves out prepositions. For
|
||||
@@ -959,7 +1506,7 @@ CHANGES TO REMIND
|
||||
so the results may be off by a minute or two compared to previous versions
|
||||
of Remind.
|
||||
|
||||
* Version 3.1 Patch 11 - 2011-12-16
|
||||
* VERSION 3.1 Patch 11 - 2011-12-16
|
||||
|
||||
- BUG FIX: For some inexplicable reason, dawn was considered to happen when
|
||||
the sun was 14 degrees below the horizon instead of the standard 6
|
||||
@@ -973,7 +1520,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Apply minor Debian cleanups reported by Kurt B. Kaiser.
|
||||
|
||||
* Version 3.1 Patch 10 - 2010-11-01
|
||||
* VERSION 3.1 Patch 10 - 2010-11-01
|
||||
|
||||
- NOTE: This is the 20th anniversary of Remind's first public release.
|
||||
|
||||
@@ -997,7 +1544,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: Don't declare variables in the middle of statements (old C
|
||||
compilers choke.)
|
||||
|
||||
* Version 3.1 Patch 9 - 2010-06-20
|
||||
* VERSION 3.1 Patch 9 - 2010-06-20
|
||||
|
||||
- MAJOR ENHANCEMENT: New "purge mode" to delete expired reminders. See
|
||||
the PURGE MODE section of the remind man page.
|
||||
@@ -1013,7 +1560,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: Yom HaShoah is moved to Thursday if it would normally fall on
|
||||
a Friday. Thanks to Jonathan Kamens for pointing this out.
|
||||
|
||||
* Version 3.1 Patch 8 - 2010-03-09
|
||||
* VERSION 3.1 Patch 8 - 2010-03-09
|
||||
|
||||
- ENHANCEMENT: Include some useful scripts in contrib/
|
||||
|
||||
@@ -1033,7 +1580,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: Fix bug in SCHED calculations if Remind is started in the middle
|
||||
of a SCHED interval.
|
||||
|
||||
* Version 3.1 Patch 7 - 2009-05-31
|
||||
* VERSION 3.1 Patch 7 - 2009-05-31
|
||||
|
||||
- ENHANCEMENT: Wherever you could write "day Mon year", the parser now
|
||||
accepts "YYYY-MM-DD". This applies on the command-line and to the
|
||||
@@ -1042,7 +1589,7 @@ CHANGES TO REMIND
|
||||
|
||||
- ENHANCEMENT: New slide() built-in function eases some complicated reminders.
|
||||
|
||||
* Version 3.1 Patch 6 - 2008-11-16
|
||||
* VERSION 3.1 Patch 6 - 2008-11-16
|
||||
|
||||
- MAJOR ENHANCEMENT: A new OMITFUNC clause gives you additional
|
||||
control and flexibility over "omitted days" calculations. This is
|
||||
@@ -1070,7 +1617,7 @@ CHANGES TO REMIND
|
||||
weekday would fail if it needed to cross a year boundary. This has
|
||||
been fixed.
|
||||
|
||||
* Version 3.1 Patch 5 - 2008-04-15
|
||||
* VERSION 3.1 Patch 5 - 2008-04-15
|
||||
|
||||
- MAJOR ENHANCEMENT: If you supply a directory name on the command line
|
||||
or for an INCLUDE command, then Remind reads all *.rem file in that
|
||||
@@ -1100,7 +1647,7 @@ CHANGES TO REMIND
|
||||
|
||||
- BUG FIX: Parse error in calendar mode was fixed.
|
||||
|
||||
* Version 3.1 Patch 4 - 2008-02-03
|
||||
* VERSION 3.1 Patch 4 - 2008-02-03
|
||||
|
||||
- ENHANCEMENT: tkremind respects the "-b1" option and operates in 24-hour
|
||||
clock mode if the option is supplied.
|
||||
@@ -1122,7 +1669,7 @@ CHANGES TO REMIND
|
||||
- BUG FIX: The "-ivar=value" command-line option failed if Remind re-execed
|
||||
itself because we overwrote argv[]. This has been fixed.
|
||||
|
||||
* Version 3.1 Patch 3 - 2007-10-15
|
||||
* VERSION 3.1 Patch 3 - 2007-10-15
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1141,7 +1688,7 @@ CHANGES TO REMIND
|
||||
is not evaluated. This helps avoid spurious error messages in some
|
||||
reminders.
|
||||
|
||||
* Version 3.1 Patch 2 - 2007-09-12
|
||||
* VERSION 3.1 Patch 2 - 2007-09-12
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1195,7 +1742,7 @@ CHANGES TO REMIND
|
||||
- Using the psshade() or psmoon() functions emits a warning on stderr. You
|
||||
should use SPECIAL SHADE or SPECIAL MOON instead.
|
||||
|
||||
* Version 3.1 Patch 1 - 2007-08-23
|
||||
* VERSION 3.1 Patch 1 - 2007-08-23
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1225,7 +1772,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Various man-page fixes.
|
||||
|
||||
* Version 3.1 Patch 0 - 2007-07-14
|
||||
* VERSION 3.1 Patch 0 - 2007-07-14
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1288,7 +1835,7 @@ CHANGES TO REMIND
|
||||
- rem2ps would produce invalid PostScript in some rare cases
|
||||
(eg, for February 2007). This has been fixed.
|
||||
|
||||
* Version 3.0 Patch 24 - 2005-11-19
|
||||
* VERSION 3.0 Patch 24 - 2005-11-19
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1311,7 +1858,7 @@ CHANGES TO REMIND
|
||||
- Fixed a bug in the tokenizer that could make Remind segfault. Fix courtesy
|
||||
of Stan Tobias.
|
||||
|
||||
* Version 3.0 Patch 23 - 2005-04-14
|
||||
* VERSION 3.0 Patch 23 - 2005-04-14
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1335,7 +1882,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed parser error for unterminated date constant: '2005/01/01
|
||||
|
||||
* Version 3.0 Patch 22 - 2000-06-16
|
||||
* VERSION 3.0 Patch 22 - 2000-06-16
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1357,7 +1904,7 @@ CHANGES TO REMIND
|
||||
- Fixed serious bug in which background queued reminders were ignored and
|
||||
Remind simply exited. Doh! Sorry about that.
|
||||
|
||||
* Version 3.0 Patch 21 - 2000-03-15
|
||||
* VERSION 3.0 Patch 21 - 2000-03-15
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1388,7 +1935,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed compilation problem on FreeBSD, IRIX, Tru64 and other UNIXes.
|
||||
|
||||
* Version 3.0 Patch 20 - 1999-04-12
|
||||
* VERSION 3.0 Patch 20 - 1999-04-12
|
||||
|
||||
+ LICENSE CHANGE
|
||||
|
||||
@@ -1410,7 +1957,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed a typo in danish.h, courtesy of Niels Kristian Bech Jensen.
|
||||
|
||||
* Version 3.0 Patch 19 - 1998-05-09
|
||||
* VERSION 3.0 Patch 19 - 1998-05-09
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1452,7 +1999,7 @@ CHANGES TO REMIND
|
||||
- Lots more silly little bugs squashed -- too many to go into in
|
||||
detail.
|
||||
|
||||
* Version 3.0 Patch 18 - 1998-02-15
|
||||
* VERSION 3.0 Patch 18 - 1998-02-15
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1516,7 +2063,7 @@ CHANGES TO REMIND
|
||||
- Getting rid of fixed-sized buffers meant lots of changes to code.
|
||||
No doubt, I missed a few regression tests.
|
||||
|
||||
* Version 3.0 Patch 17 - 1997-09-07
|
||||
* VERSION 3.0 Patch 17 - 1997-09-07
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1557,7 +2104,7 @@ CHANGES TO REMIND
|
||||
library. All three of these fixes are courtesy of Christopher
|
||||
J. Madsen <madsen@iglobal.net>. Thanks, Christopher.
|
||||
|
||||
* Version 3.0 Patch 16 - 1997-02-11
|
||||
* VERSION 3.0 Patch 16 - 1997-02-11
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1585,7 +2132,7 @@ CHANGES TO REMIND
|
||||
- Fixed a problem under Solaris 2.5 whereby rem2ps was skipping some
|
||||
latin1 characters which it interpreted as white space.
|
||||
|
||||
* Version 3.0 Patch 15 - 1996-10-27
|
||||
* VERSION 3.0 Patch 15 - 1996-10-27
|
||||
|
||||
+ IMPORTANT NOTES
|
||||
|
||||
@@ -1615,7 +2162,7 @@ CHANGES TO REMIND
|
||||
- Fixed bug in TkRemind which caused a crash if the "-m" option was used
|
||||
for a month beginning on Sunday. Doh!!!
|
||||
|
||||
* Version 3.0 Patch 14 - 1996-05-25
|
||||
* VERSION 3.0 Patch 14 - 1996-05-25
|
||||
|
||||
+ CHANGE IN COPYING POLICY
|
||||
|
||||
@@ -1674,7 +2221,7 @@ CHANGES TO REMIND
|
||||
_not_ support MS Windows, and in fact do not allow Remind to run
|
||||
under Windows (see COPYRIGHT).
|
||||
|
||||
* Version 3.0 Patch 13 - 1994-05-06
|
||||
* VERSION 3.0 Patch 13 - 1994-05-06
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1709,7 +2256,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Updated the copyright notices everywhere.
|
||||
|
||||
* Version 3.0 Patch 12 - 1994-02-01
|
||||
* VERSION 3.0 Patch 12 - 1994-02-01
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1728,7 +2275,7 @@ CHANGES TO REMIND
|
||||
- Fixed a problem with the '-k' option which resulted in a newline being
|
||||
placed after the message text. This was giving sh(1) heartburn...
|
||||
|
||||
* Version 3.0 Patch 11 - 1993-11-26
|
||||
* VERSION 3.0 Patch 11 - 1993-11-26
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1760,7 +2307,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed typos in french.h
|
||||
|
||||
* Version 3.0 Patch 10
|
||||
* VERSION 3.0 Patch 10
|
||||
|
||||
+ MAJOR ENHANCEMENT
|
||||
|
||||
@@ -1808,7 +2355,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed the Finnish language support which was missing a few newlines.
|
||||
|
||||
* Version 3.0 Patch 9 - 1993-10-04
|
||||
* VERSION 3.0 Patch 9 - 1993-10-04
|
||||
|
||||
+ NOTES
|
||||
|
||||
@@ -1865,7 +2412,7 @@ CHANGES TO REMIND
|
||||
so that newlines in the body start new paragraphs, rather than being
|
||||
swallowed as white-space.
|
||||
|
||||
* Version 3.0 Patch 8 - 1993-09-08
|
||||
* VERSION 3.0 Patch 8 - 1993-09-08
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1917,7 +2464,7 @@ CHANGES TO REMIND
|
||||
range [-128, 255] (but not 0) so that char(asc(s)) works even
|
||||
on machines with signed char types.
|
||||
|
||||
* Version 3.0 Patch 7 - 1993-07-22
|
||||
* VERSION 3.0 Patch 7 - 1993-07-22
|
||||
|
||||
+ MAJOR ENHANCEMENTS
|
||||
|
||||
@@ -1960,7 +2507,7 @@ CHANGES TO REMIND
|
||||
- Changed kall so that "kall sh" doesn't commit suicide - patch courtesy
|
||||
of Michael Salmon.
|
||||
|
||||
* Version 3.0 Patch 6 - 1993-05-05
|
||||
* VERSION 3.0 Patch 6 - 1993-05-05
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
@@ -1983,7 +2530,7 @@ CHANGES TO REMIND
|
||||
- Fixed a bug in the -u option which sometimes caused a core dump
|
||||
(embarrassed grin!) The fix is due to Tina Hoeltig. Thanks, Tina!
|
||||
|
||||
* Version 3.0 Patch 5 - 1993-04-27
|
||||
* VERSION 3.0 Patch 5 - 1993-04-27
|
||||
|
||||
+ MAJOR ENHANCEMENTS:
|
||||
|
||||
@@ -2018,7 +2565,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Fixed a bug in the man page - thanks to Ed Oskiewicz.
|
||||
|
||||
* Version 3.0 Patch 4 - 1993-03-08
|
||||
* VERSION 3.0 Patch 4 - 1993-03-08
|
||||
|
||||
- Added the -g option - this sorts reminders by date/time before
|
||||
issuing them. (You can see I'm running out of letters to
|
||||
@@ -2077,13 +2624,13 @@ CHANGES TO REMIND
|
||||
|
||||
- Put my new mailing address in the README files.
|
||||
|
||||
* Version 3.0 Patch 3 - 1993-02-21
|
||||
* VERSION 3.0 Patch 3 - 1993-02-21
|
||||
|
||||
- Corrected bugs in Remind and Rem2PS. No new features added. You
|
||||
should NOT use patch level 2 - either stick to 3.0.1 or upgrade to
|
||||
3.0.3.
|
||||
|
||||
* Version 3.0 Patch 2 - 1993-02-04
|
||||
* VERSION 3.0 Patch 2 - 1993-02-04
|
||||
|
||||
- Added the -u option to Remind so that root can run it as any user.
|
||||
This simplifies the remind-all scripts, and makes them more efficient.
|
||||
@@ -2123,7 +2670,7 @@ CHANGES TO REMIND
|
||||
- Changed Remind so that supplying the -a option causes timed reminders
|
||||
not to be placed into the calendar in calendar mode.
|
||||
|
||||
* Version 3.0 Patch 1 - 1992-12-18
|
||||
* VERSION 3.0 Patch 1 - 1992-12-18
|
||||
|
||||
- Wrote the Rem2ps program to produce PostScript calendars
|
||||
|
||||
@@ -2163,7 +2710,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Re-formatted the WHATSNEW.30 file.
|
||||
|
||||
* Version 3.0 - 1992-11-09
|
||||
* VERSION 3.0 - 1992-11-09
|
||||
|
||||
- Total rewrite from previous versions
|
||||
|
||||
@@ -2184,23 +2731,23 @@ CHANGES TO REMIND
|
||||
- Fixed a lurking bug in trigger date calculation which, amazingly, had not
|
||||
been caught in the couple of years that Remind has been out!
|
||||
|
||||
* Version 2.3 Patch 5 - 1992-04-11
|
||||
* VERSION 2.3 Patch 5 - 1992-04-11
|
||||
|
||||
- Added the "c+n" option for printing a calendar by
|
||||
weeks instead of months, courtesy Dennis Cottel (dennis@peanuts.nosc.mil).
|
||||
|
||||
* Version 2.3 Patch 4 - 1991-11-06
|
||||
* VERSION 2.3 Patch 4 - 1991-11-06
|
||||
|
||||
- Made the init.c file nicer. Made the Makefile
|
||||
prettier. Added "make test", "make tar" and "make shar" Makefile targets.
|
||||
|
||||
* Version 2.3 Patch 3 - 1991-09-11
|
||||
* VERSION 2.3 Patch 3 - 1991-09-11
|
||||
|
||||
- Added a command-line option for Remind to process
|
||||
queued reminders in the foreground. This makes automatic termination
|
||||
of Remind processes from within X-Windows and Sunview easier.
|
||||
|
||||
* Version 2.3 Patch 2 - 1991-07-19
|
||||
* VERSION 2.3 Patch 2 - 1991-07-19
|
||||
|
||||
- Fixed up a problem with timed reminders which resulted
|
||||
in cursor not starting from left side of screen on some systems.
|
||||
@@ -2217,7 +2764,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Made the Makefile more portable
|
||||
|
||||
* Version 2.3 Patch 1 - 1991-03-08
|
||||
* VERSION 2.3 Patch 1 - 1991-03-08
|
||||
|
||||
- Added the "-t" command-line option to get Remind
|
||||
to trigger all non-expired reminders.
|
||||
@@ -2231,7 +2778,7 @@ CHANGES TO REMIND
|
||||
|
||||
- Added manual pages for "kall" and "rem".
|
||||
|
||||
* Version 2.3 - 1991-02-20
|
||||
* VERSION 2.3 - 1991-02-20
|
||||
|
||||
- Added the UNTIL keyword for forcing reminders to expire.
|
||||
|
||||
@@ -2253,32 +2800,32 @@ CHANGES TO REMIND
|
||||
- Modified the calendar and SimpleCalendar formats so that the % escape
|
||||
substitutions ARE performed.
|
||||
|
||||
* Version 2.2 - Patch 5 - 1990-12-03
|
||||
* VERSION 2.2 - Patch 5 - 1990-12-03
|
||||
|
||||
- Added the BEFORE, AFTER and SKIP tokens to make the
|
||||
handling of holidays more sensible. Also corrected a few more bugs.
|
||||
|
||||
* Version 2.2 - Patch 3 - 1990-11-28
|
||||
* VERSION 2.2 - Patch 3 - 1990-11-28
|
||||
|
||||
- Added the MSG or RUN tokens in an OMIT command; also
|
||||
allowed RUN-type reminders to be explicitly included in the calendar by
|
||||
using the %" escape sequence.
|
||||
|
||||
* Version 2.2 - 1990-11-16
|
||||
* VERSION 2.2 - 1990-11-16
|
||||
|
||||
- Added the AT keyword, the timed reminders daemon, and the
|
||||
calendar facility.
|
||||
|
||||
* Version 2.1 - 1990-11-06
|
||||
* VERSION 2.1 - 1990-11-06
|
||||
|
||||
- Added the "repeat" token for repeating reminders with a period
|
||||
other than 7 days. Also fixed some bugs from version 2.0
|
||||
|
||||
* Version 2.0 - 1990-11-01
|
||||
* VERSION 2.0 - 1990-11-01
|
||||
|
||||
- first public release. Included advanced date specifications,
|
||||
character substitution, and the RUN keyword.
|
||||
|
||||
* Version 1.0
|
||||
* VERSION 1.0
|
||||
|
||||
- never publicly released.
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 [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("")]
|
||||
|
||||
@@ -26,7 +26,10 @@ 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("")]%_
|
||||
MSG This is [ansicolor(0,255,255)]cyan.[ansicolor("")]
|
||||
MSG This is [ansi_bold][ansicolor(255,255,255)][ansicolor(0,0,0,1)]white on black[ansicolor("")][ansi_normal]
|
||||
MSG This is [ansi_bold][ansicolor(0,0,0)][ansicolor(255,255,255,1)]black on white[ansicolor("")][ansi_normal]
|
||||
MSG %_
|
||||
|
||||
# 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("")]
|
||||
|
||||
@@ -5,43 +5,40 @@
|
||||
# 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'
|
||||
remind -g "-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)].%_
|
||||
MSG Today is [ansi_bold][$T][ansi_normal], being the [ord($T-date(year($T),1,1)+1)] day of [year($T)].
|
||||
MSG Not including today, the year [year($T)] has [date(year($T)+1, 1, 1)-$T-1] more [plural(date(year($T)+1, 1, 1)-$T-1, "day")] left.%_
|
||||
|
||||
IF bg_dark
|
||||
IF $TerminalBackground == 0
|
||||
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%_
|
||||
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%_
|
||||
|
||||
ENDIF
|
||||
EOF
|
||||
|
||||
remind -g -ibg_dark="$bg_dark" "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
SET $AddBlankLines 0
|
||||
BANNER %
|
||||
IF bg_dark
|
||||
IF $TerminalBackground == 0
|
||||
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)
|
||||
@@ -51,7 +48,7 @@ EOF
|
||||
|
||||
echo ""
|
||||
|
||||
remind -g -ibg_dark="$bg_dark" "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||
SET $AddBlankLines 0
|
||||
BANNER %
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
# Cut and paste as desired! Also, near the end, there are a bunch of #
|
||||
# holiday definitions for the U.S. #
|
||||
# #
|
||||
# *** NOTE *** #
|
||||
# #
|
||||
# This file is simply a grab-bag of examples. It is NOT meant to be #
|
||||
# included as-is in a live reminder file. #
|
||||
# #
|
||||
# Some examples provided by George M. Sipe <gsipe@pyratl.ga.pyramid.com> #
|
||||
# #
|
||||
# U.S. holidays provided by Dave Rickel <drickel@sjc.mentorg.com> #
|
||||
@@ -16,7 +21,7 @@
|
||||
# "#PSSTUFF" for nifty PostScript examples #
|
||||
# #
|
||||
# This file is part of REMIND. #
|
||||
# Copyright (C) 1992-2023 Dianne Skoll #
|
||||
# Copyright (C) 1992-2024 Dianne Skoll #
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# #
|
||||
#############################################################################
|
||||
@@ -27,7 +32,7 @@ RUN OFF
|
||||
# Ensure required version of remind is used... #
|
||||
################################################
|
||||
IF version() < "03.04.02"
|
||||
ERRMSG This file requires at least version 03.01.10 of Remind.%
|
||||
ERRMSG This file requires at least version 03.04.02 of Remind.%
|
||||
ERRMSG This version is version [version()].
|
||||
EXIT
|
||||
ENDIF
|
||||
@@ -305,51 +310,51 @@ FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
SET Reform VALUE("Reform", 0)
|
||||
|
||||
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
||||
REM [_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.
|
||||
REM [_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
||||
REM [_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.
|
||||
REM [_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
||||
REM [_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
||||
|
||||
IF !InIsrael
|
||||
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||
REM [_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.
|
||||
REM [_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||
REM [_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||
|
||||
IF InIsrael
|
||||
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
REM [_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
ELSE
|
||||
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
REM [_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%"
|
||||
REM [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||
REM [_chan(2)] MSG %"Chanukah 2%"
|
||||
REM [_chan(3)] MSG %"Chanukah 3%"
|
||||
REM [_chan(4)] MSG %"Chanukah 4%"
|
||||
REM [_chan(5)] MSG %"Chanukah 5%"
|
||||
REM [_chan(6)] MSG %"Chanukah 6%"
|
||||
REM [_chan(7)] MSG %"Chanukah 7%"
|
||||
REM [_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.
|
||||
REM [_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.
|
||||
[_h(15, "Adar A")] ++4 MSG %"Shushan Purim Katan%" is %b.
|
||||
REM [_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
||||
REM [_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
||||
REM [_h(15, "Adar A")] ++4 MSG %"Shushan Purim Katan%" is %b.
|
||||
|
||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||
@@ -357,18 +362,18 @@ IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||
ELSE
|
||||
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||
ENDIF
|
||||
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||
[_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
||||
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||
REM [_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||
REM [_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
||||
REM [_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||
|
||||
IF !InIsrael
|
||||
[_h(16, "Nisan")] MSG %"Pesach 2%"
|
||||
REM [_h(16, "Nisan")] MSG %"Pesach 2%"
|
||||
ENDIF
|
||||
|
||||
[_h(21, "Nisan")] MSG %"Pesach 7%"
|
||||
REM [_h(21, "Nisan")] MSG %"Pesach 7%"
|
||||
|
||||
IF !InIsrael && !Reform
|
||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||
REM [_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||
ENDIF
|
||||
|
||||
REM [_PastSun(27, "Nisan")] SATISFY 1
|
||||
@@ -384,36 +389,36 @@ ENDIF
|
||||
# Thursday. If 4 Iyar is a Sunday, then Yom Hazikaron
|
||||
# moves to 5 Iyar and Yom Ha'atzmaut to 6 Iyar.
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 4 || WKDAYNUM(_h2(4, "Iyar")) == 5
|
||||
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
REM [_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
REM [_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 0
|
||||
[_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
REM [_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
REM [_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
[_h(4, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
REM [_h(4, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
REM [_h(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
# Not sure about Reform's position on Lag B'Omer
|
||||
IF !Reform
|
||||
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
||||
REM [_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.
|
||||
REM [_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
||||
REM [_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
||||
|
||||
IF !InIsrael && !Reform
|
||||
[_h(7, "Sivan")] MSG %"Shavuot 2%"
|
||||
REM [_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.
|
||||
REM [_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
||||
REM [_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
||||
ENDIF
|
||||
|
||||
# Counting the omer - do the whole spiel, i.e:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Not all sequences are supported by all terminals.
|
||||
|
||||
# This file is part of REMIND
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
if !defined("ansi_bold")
|
||||
|
||||
@@ -1,30 +1,14 @@
|
||||
# Canadian holidays
|
||||
# Canadian Federal Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# You should probably NOT include this file directly! Instead, for
|
||||
# all of the statutory holidays of the province you live in, use:
|
||||
# INCLUDE [$SysInclude]/ca/XY.rem where XY is the two-letter
|
||||
# abbreviation for yoru province. For example, if you live in
|
||||
# Ontario, use: INCLUDE [$SysInclude]/ca/on.rem
|
||||
|
||||
OMIT 1 Jan MSG New Year's Day
|
||||
|
||||
# This varies by province
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
|
||||
# This varies by province
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
|
||||
# This varies by province
|
||||
OMIT [easterdate($Uy) + 1] MSG Easter Monday
|
||||
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
OMIT 1 July MSG Canada Day
|
||||
|
||||
# This varies by province
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
|
||||
REM First Monday in Sep SCANFROM -7 ADDOMIT MSG Labour Day
|
||||
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
|
||||
REM 11 November MSG Remembrance Day
|
||||
|
||||
REM 30 Sep MSG National Day for Truth and Reconciliation
|
||||
OMIT 25 Dec MSG Christmas
|
||||
|
||||
OMIT 26 Dec MSG Boxing Day
|
||||
|
||||
|
||||
10
include/holidays/ca/ab.rem
Normal file
10
include/holidays/ca/ab.rem
Normal file
@@ -0,0 +1,10 @@
|
||||
# Alberta Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
10
include/holidays/ca/bc.rem
Normal file
10
include/holidays/ca/bc.rem
Normal file
@@ -0,0 +1,10 @@
|
||||
# British Columbia Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
9
include/holidays/ca/mb.rem
Normal file
9
include/holidays/ca/mb.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Manitoba Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Louis Riel Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
8
include/holidays/ca/nb.rem
Normal file
8
include/holidays/ca/nb.rem
Normal file
@@ -0,0 +1,8 @@
|
||||
# New Brunswick Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
9
include/holidays/ca/nl.rem
Normal file
9
include/holidays/ca/nl.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Newfoundland and Labrador Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT 17 March MSG St. Patrick's Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
OMIT 23 April MSG St. George's Day
|
||||
OMIT 24 June MSG Discovery Day
|
||||
REM 11 November MSG Remembrance Day
|
||||
8
include/holidays/ca/ns.rem
Normal file
8
include/holidays/ca/ns.rem
Normal file
@@ -0,0 +1,8 @@
|
||||
# Nova Scotia Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Heritage Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM 11 November MSG Remembrance Day
|
||||
|
||||
9
include/holidays/ca/nt.rem
Normal file
9
include/holidays/ca/nt.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Northwest Territories Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
OMIT 21 June MSG National Aboriginal Day
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
9
include/holidays/ca/nu.rem
Normal file
9
include/holidays/ca/nu.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Nunavut Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
OMIT 9 July MSG Nunavut Day
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
10
include/holidays/ca/on.rem
Normal file
10
include/holidays/ca/on.rem
Normal file
@@ -0,0 +1,10 @@
|
||||
# Ontario Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
REM 11 November MSG Remembrance Day
|
||||
OMIT 26 Dec MSG Boxing Day
|
||||
8
include/holidays/ca/pe.rem
Normal file
8
include/holidays/ca/pe.rem
Normal file
@@ -0,0 +1,8 @@
|
||||
# Prince Edward Island Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Islander Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
|
||||
9
include/holidays/ca/qc.rem
Normal file
9
include/holidays/ca/qc.rem
Normal file
@@ -0,0 +1,9 @@
|
||||
# Quebec Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) + 1] MSG Easter Monday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
OMIT 24 June MSG Fête Nationale
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
REM 11 November MSG Remembrance Day
|
||||
10
include/holidays/ca/sk.rem
Normal file
10
include/holidays/ca/sk.rem
Normal file
@@ -0,0 +1,10 @@
|
||||
# Saskatchewan Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Family Day
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
REM First Monday in Aug SCANFROM -7 ADDOMIT MSG Civic Holiday
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
10
include/holidays/ca/yt.rem
Normal file
10
include/holidays/ca/yt.rem
Normal file
@@ -0,0 +1,10 @@
|
||||
# Yukon Territory Holidays
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
DO ../ca.rem
|
||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG Discovery Day
|
||||
OMIT [easterdate($Uy) - 2] MSG Good Friday
|
||||
REM Mon 18 May SCANFROM -7 ADDOMIT MSG Victoria Day
|
||||
OMIT June 21 MSG National Indigenous Peoples Day
|
||||
REM Second Monday in Oct SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||
OMIT 11 November MSG Remembrance Day
|
||||
29
include/holidays/chinese-new-year.rem
Normal file
29
include/holidays/chinese-new-year.rem
Normal file
@@ -0,0 +1,29 @@
|
||||
REM 1 Feb 2022 MSG Chinese New Year (Tiger)
|
||||
REM 22 Jan 2023 MSG Chinese New Year (Rabbit)
|
||||
REM 10 Feb 2024 MSG Chinese New Year (Dragon)
|
||||
REM 29 Jan 2025 MSG Chinese New Year (Snake)
|
||||
REM 17 Feb 2026 MSG Chinese New Year (Horse)
|
||||
REM 6 Feb 2027 MSG Chinese New Year (Goat)
|
||||
REM 26 Jan 2028 MSG Chinese New Year (Monkey)
|
||||
REM 13 Feb 2029 MSG Chinese New Year (Rooster)
|
||||
REM 3 Feb 2030 MSG Chinese New Year (Dog)
|
||||
REM 23 Jan 2031 MSG Chinese New Year (Pig)
|
||||
REM 11 Feb 2032 MSG Chinese New Year (Rat)
|
||||
REM 31 Jan 2033 MSG Chinese New Year (Ox)
|
||||
REM 19 Feb 2034 MSG Chinese New Year (Tiger)
|
||||
REM 8 Feb 2035 MSG Chinese New Year (Rabbit)
|
||||
REM 28 Jan 2036 MSG Chinese New Year (Dragon)
|
||||
REM 15 Feb 2037 MSG Chinese New Year (Snake)
|
||||
REM 4 Feb 2038 MSG Chinese New Year (Horse)
|
||||
REM 24 Jan 2039 MSG Chinese New Year (Goat)
|
||||
REM 12 Feb 2040 MSG Chinese New Year (Monkey)
|
||||
REM 1 Feb 2041 MSG Chinese New Year (Rooster)
|
||||
REM 22 Jan 2042 MSG Chinese New Year (Dog)
|
||||
REM 10 Feb 2043 MSG Chinese New Year (Pig)
|
||||
REM 30 Jan 2044 MSG Chinese New Year (Rat)
|
||||
REM 17 Feb 2045 MSG Chinese New Year (Ox)
|
||||
REM 6 Feb 2046 MSG Chinese New Year (Tiger)
|
||||
REM 26 Jan 2047 MSG Chinese New Year (Rabbit)
|
||||
REM 14 Feb 2048 MSG Chinese New Year (Dragon)
|
||||
REM 2 Feb 2049 MSG Chinese New Year (Snake)
|
||||
REM 23 Jan 2050 MSG Chinese New Year (Horse)
|
||||
@@ -10,7 +10,7 @@ REM 28 Oct MSG ΟΧΙ
|
||||
REM 25 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ
|
||||
REM 26 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ2
|
||||
|
||||
REM [orthodoxeaster($Uy)+1] ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
||||
REM [orthodoxeaster($Uy)+1] MSG ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
||||
|
||||
|
||||
# May first is a national holiday except if Sunday, day of great week (week before easter) or Monday after easter, then
|
||||
|
||||
42
include/holidays/ie.rem
Normal file
42
include/holidays/ie.rem
Normal file
@@ -0,0 +1,42 @@
|
||||
;
|
||||
; Irish Holidays
|
||||
;
|
||||
; The dates for the Public ("bank") holidays are taken from the following site:
|
||||
; https://www.citizensinformation.ie/en/employment/employment-rights-and-conditions/leave-and-holidays/public-holidays/
|
||||
;
|
||||
; This file was derived from:
|
||||
; https://github.com/mhwombat/dotWombat/blob/master/.config/remind/IrishHolidays.rem
|
||||
; by Amy de Buitléir.
|
||||
|
||||
; fixed dates
|
||||
OMIT 31 December MSG New Year's Eve (Oíche Chinn Bliana) Public Holiday
|
||||
OMIT 1 January MSG New Year's Day (Lá Caille, Lá Bliana Nua) Public Holiday
|
||||
OMIT 17 March MSG Saint Patrick's Day (Lá Fhéile Pádraig) Public Holiday
|
||||
OMIT 24 December MSG Christmas Eve (Oíche Nollag) Public Holiday
|
||||
OMIT 25 December MSG Christmas Day (Lá Nollag) Public Holiday
|
||||
OMIT 26 December MSG Saint Stephen's Day, Wren Day (Lá Fhéile Stiofáin, Lá an Dreoilín) Public Holiday
|
||||
|
||||
; moving dates
|
||||
|
||||
; First Monday in May
|
||||
REM Monday 1 May SCANFROM -7 ADDOMIT MSG May Day (Lá Bealtaine) Public Holiday
|
||||
|
||||
; First Monday in June
|
||||
REM Monday 1 June SCANFROM -7 ADDOMIT MSG June Public Holiday
|
||||
|
||||
; First Monday in August
|
||||
REM Monday 1 August SCANFROM -7 ADDOMIT MSG August Public Holiday
|
||||
|
||||
; Last Monday in October
|
||||
REM Monday 1 -7 November SCANFROM -7 ADDOMIT MSG October Public Holiday
|
||||
|
||||
; Easter
|
||||
SET easter easterdate(today())
|
||||
REM [TRIGGER(easter-2)] MSG Good Friday (Aoine an Chéasta)
|
||||
REM [TRIGGER(easter)] MSG Easter Sunday (Domhnach Cásca)
|
||||
OMIT [TRIGGER(easter+1)] MSG Easter Monday (Luan Cásca) Public Holiday
|
||||
|
||||
; St. Brigid's Day
|
||||
REM 1 February MSG Saint Brigid's Day (Lá Fhéile Bríde or Imbolc)
|
||||
; The public holiday is the first Monday in February, or 1 February if the date falls on a Friday
|
||||
REM February SCANFROM -7 ADDOMIT SATISFY [($Td==1 && $Tw==5) || ($Td<8 && $Tw==1 && $Td!=4)] MSG Public Holiday
|
||||
@@ -10,7 +10,6 @@ SET InIsrael value("InIsrael", 0)
|
||||
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)
|
||||
@@ -19,50 +18,50 @@ FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
SET Reform VALUE("Reform", 0)
|
||||
|
||||
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
||||
REM [hebdate(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.
|
||||
REM [hebdate(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
||||
REM [_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.
|
||||
REM [hebdate(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
||||
REM [hebdate(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
||||
|
||||
IF !InIsrael
|
||||
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||
REM [hebdate(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||
ENDIF
|
||||
|
||||
[_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||
REM [hebdate(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||
REM [hebdate(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||
|
||||
IF InIsrael
|
||||
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
REM [hebdate(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
ELSE
|
||||
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||
REM [hebdate(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%"
|
||||
REM [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||
REM [_chan(2)] MSG %"Chanukah 2%"
|
||||
REM [_chan(3)] MSG %"Chanukah 3%"
|
||||
REM [_chan(4)] MSG %"Chanukah 4%"
|
||||
REM [_chan(5)] MSG %"Chanukah 5%"
|
||||
REM [_chan(6)] MSG %"Chanukah 6%"
|
||||
REM [_chan(7)] MSG %"Chanukah 7%"
|
||||
REM [_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.
|
||||
REM [hebdate(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.
|
||||
REM [hebdate(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
||||
REM [hebdate(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
|
||||
@@ -70,43 +69,39 @@ IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||
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.
|
||||
REM [hebdate(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||
REM [hebdate(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||
|
||||
IF !InIsrael
|
||||
[_h(16, "Nisan")] MSG %"Pesach 2%"
|
||||
REM [hebdate(16, "Nisan")] MSG %"Pesach 2%"
|
||||
ENDIF
|
||||
|
||||
[_h(21, "Nisan")] MSG %"Pesach 7%"
|
||||
REM [hebdate(21, "Nisan")] MSG %"Pesach 7%"
|
||||
|
||||
IF !InIsrael && !Reform
|
||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||
REM [hebdate(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.
|
||||
REM [hebdate(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
REM [_BackTwoFri(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
|
||||
REM [_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.
|
||||
REM [hebdate(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.
|
||||
REM [hebdate(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
||||
REM [hebdate(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
||||
|
||||
IF !InIsrael && !Reform
|
||||
[_h(7, "Sivan")] MSG %"Shavuot 2%"
|
||||
REM [hebdate(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.
|
||||
REM [_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
||||
REM [_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
||||
ENDIF
|
||||
|
||||
# Clean up
|
||||
FUNSET _h _h2 _PastSat _BackTwoFri _BackTwoSat _chan
|
||||
|
||||
|
||||
17
include/holidays/pt.rem
Normal file
17
include/holidays/pt.rem
Normal file
@@ -0,0 +1,17 @@
|
||||
# Portuguese holidays
|
||||
# Courtesy of Joop Kiefte
|
||||
|
||||
OMIT 1 Jan MSG Ano Novo
|
||||
OMIT [easterdate()-47] MSG Carnaval
|
||||
OMIT [easterdate()-2] MSG Sexta-feira Santa
|
||||
OMIT [easterdate()] MSG Domingo de Páscoa
|
||||
OMIT 25 Apr MSG Dia da Liberdade
|
||||
OMIT 1 May MSG Dia do Trabalhador
|
||||
OMIT [easterdate()+60] MSG Corpo de Deus
|
||||
OMIT 10 Jun MSG Dia de Portugal, de Camões e das Comunidades Portuguesas
|
||||
OMIT 15 Aug MSG Assunção de Nossa Senhora
|
||||
OMIT 5 Oct MSG Implantação da República
|
||||
OMIT 1 Nov MSG Dia de Todos os Santos
|
||||
OMIT 1 Dec MSG Restauração da Independência
|
||||
OMIT 8 Dec MSG Imaculada Conceição
|
||||
OMIT 25 Dec MSG Natal
|
||||
@@ -1,6 +1,6 @@
|
||||
# US holidays
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2023 Dianne Skoll
|
||||
# Copyright (C) 1992-2024 Dianne Skoll
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
REM [easterdate($Uy)-46] MSG Ash Wednesday
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
SET autolang getenv("REMIND_LANG")
|
||||
if !defined("__autolang__")
|
||||
SET __autolang__ 1
|
||||
PRESERVE __autolang__
|
||||
SET autolang getenv("REMIND_LANG")
|
||||
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LC_ALL")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANGUAGE")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANG")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LC_ALL")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANGUAGE")
|
||||
ENDIF
|
||||
IF autolang == ""
|
||||
SET autolang getenv("LANG")
|
||||
ENDIF
|
||||
|
||||
IF autolang != ""
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
|
||||
INCLUDE [$SysInclude]/lang/[lower(substr(autolang, 1, 5))].rem
|
||||
ELSE
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
|
||||
INCLUDE [$SysInclude]/lang/[lower(substr(autolang, 1, 2))].rem
|
||||
IF autolang != ""
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 5)) + ".rem", "r") == 0
|
||||
INCLUDE [$SysInclude]/lang/[lower(substr(autolang, 1, 5))].rem
|
||||
ELSE
|
||||
IF access($SysInclude + "/lang/" + lower(substr(autolang, 1, 2)) + ".rem", "r") == 0
|
||||
INCLUDE [$SysInclude]/lang/[lower(substr(autolang, 1, 2))].rem
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
UNSET autolang
|
||||
ENDIF
|
||||
|
||||
UNSET autolang
|
||||
|
||||
53
include/lang/ca.rem
Normal file
53
include/lang/ca.rem
Normal file
@@ -0,0 +1,53 @@
|
||||
# Support for the Catalan language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file was created by Eloi Torrents <eloitor@disroot.org>
|
||||
|
||||
SET $Monday "dilluns"
|
||||
SET $Tuesday "dimarts"
|
||||
SET $Wednesday "dimecres"
|
||||
SET $Thursday "dijous"
|
||||
SET $Friday "divendres"
|
||||
SET $Saturday "dissabte"
|
||||
SET $Sunday "diumenge"
|
||||
|
||||
SET $January "gener"
|
||||
SET $February "febrer"
|
||||
SET $March "març"
|
||||
SET $April "abril"
|
||||
SET $May "maig"
|
||||
SET $June "juny"
|
||||
SET $July "juliol"
|
||||
SET $August "agost"
|
||||
SET $September "setembre"
|
||||
SET $October "octubre"
|
||||
SET $November "novembre"
|
||||
SET $December "desembre"
|
||||
|
||||
SET $Today "avui"
|
||||
SET $Tomorrow "demà"
|
||||
FSET subst_bx(a,d,t) iif(d==today()+2, "demà passat", "d'aquí " + (d-today()) + " dies")
|
||||
|
||||
# 1 d'abril vs 1 de maig.
|
||||
FSET subst_sx(a,d,t) iif(isany(substr(mon(d), 1, 1), "a", "o") , "d'", "de")
|
||||
FSET subst_ordinal(d) ""
|
||||
|
||||
BANNER Agenda pel %w, %d %s %m de %y%o:
|
||||
|
||||
SET $Am "am"
|
||||
SET $Pm "pm"
|
||||
|
||||
SET $Ago "fa"
|
||||
SET $Fromnow "des d'avui"
|
||||
SET $On "el dia"
|
||||
SET $Now "ara"
|
||||
SET $At "a les"
|
||||
|
||||
SET $Minute "minut"
|
||||
SET $Mplu "s"
|
||||
SET $Hour "hora"
|
||||
FSET subst_hours(h) iif(h==1, "1 hora", h + " hores")
|
||||
|
||||
SET $Is "és"
|
||||
SET $Was "va ser"
|
||||
SET $And "i"
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Danish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Mogens Lynnerup.
|
||||
|
||||
SET $Sunday "Søndag"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the German language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Wolfgang Thronicke
|
||||
|
||||
# Day names
|
||||
@@ -87,3 +87,5 @@ SET daylightST_starts_str "Beginn Sommerzeit"
|
||||
|
||||
# Daylight saving time ends
|
||||
SET daylightST_ends_str "Ende Sommerzeit"
|
||||
|
||||
PRESERVE earthseasons_Perihelion_str earthseasons_EquinoxMar_str earthseasons_SolsticeJun_str earthseasons_Aphelion_str earthseasons_EquinoxSep_str earthseasons_SolsticeDec_str daylightST_starts_str daylightST_ends_str
|
||||
@@ -1,4 +1,4 @@
|
||||
# Support for the English language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# Nothing to do for English since it is the default.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Spanish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
||||
|
||||
SET $Sunday "Domingo"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Finnish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Mikko Silvonen
|
||||
|
||||
SET $Sunday "sunnuntai"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the French language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Laurent Duperval
|
||||
|
||||
SET $Sunday "dimanche"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Hellenic (Greek) language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
||||
|
||||
SET $Sunday "Κυριακή"
|
||||
@@ -81,3 +81,5 @@ SET daylightST_starts_str "Έναρξη θέρους"
|
||||
|
||||
# Daylight saving time ends
|
||||
SET daylightST_ends_str "Τέλος θέρους"
|
||||
|
||||
PRESERVE earthseasons_Perihelion_str earthseasons_EquinoxMar_str earthseasons_SolsticeJun_str earthseasons_Aphelion_str earthseasons_EquinoxSep_str earthseasons_SolsticeDec_str daylightST_starts_str daylightST_ends_str
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Icelanding language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
||||
|
||||
SET $Sunday "sunnudagur"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Support for the Italian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Valerio Aimale
|
||||
|
||||
SET $Sunday "Domenica"
|
||||
SET $Monday "Lunedí"
|
||||
SET $Tuesday "Martedí"
|
||||
SET $Wednesday "Mercoledí"
|
||||
SET $Thursday "Giovedí"
|
||||
SET $Friday "Venerdí"
|
||||
SET $Monday "Lunedì"
|
||||
SET $Tuesday "Martedì"
|
||||
SET $Wednesday "Mercoledì"
|
||||
SET $Thursday "Giovedì"
|
||||
SET $Friday "Venerdì"
|
||||
SET $Saturday "Sabato"
|
||||
|
||||
SET $January "Gennaio"
|
||||
@@ -40,7 +40,7 @@ SET $Now "ora"
|
||||
SET $At "alle"
|
||||
SET $Minute "minuto"
|
||||
SET $Hour "ora"
|
||||
SET $Is "é"
|
||||
SET $Is "è"
|
||||
SET $Was "era"
|
||||
SET $And "e"
|
||||
SET $Hplu "a"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Dutch language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
||||
|
||||
SET $Sunday "zondag"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Norwegian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Trygve Randen
|
||||
|
||||
SET $Sunday "Søndag"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Polish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Jerzy Sobczyk
|
||||
|
||||
SET $Sunday "Niedziela"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the (Brazilian) Portuguese language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Marco Paganini
|
||||
|
||||
SET $Sunday "domingo"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Romanian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||
# This file is derived from a translation by Liviu Daia
|
||||
|
||||
SET $Sunday "Duminică"
|
||||
|
||||
14
include/moonphases.rem
Normal file
14
include/moonphases.rem
Normal file
@@ -0,0 +1,14 @@
|
||||
# Moon phases
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
IF $CalMode || $PsCal
|
||||
REM [moondate(0)] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||
REM [moondate(1)] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||
REM [moondate(2)] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||
REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
ELSE
|
||||
REM NOQUEUE [moondatetime(0)] MSG New Moon (%2)
|
||||
REM NOQUEUE [moondatetime(1)] MSG First Quarter (%2)
|
||||
REM NOQUEUE [moondatetime(2)] MSG Full Moon (%2)
|
||||
REM NOQUEUE [moondatetime(3)] MSG Last Quarter (%2)
|
||||
ENDIF
|
||||
@@ -19,4 +19,4 @@ Remind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
.SH HOME PAGE
|
||||
https://dianne.skoll.ca/projects/remind/
|
||||
.SH SEE ALSO
|
||||
\fBremind\fR
|
||||
\fBremind\fR(1)
|
||||
|
||||
@@ -5,22 +5,25 @@ rem2ps \- draw a PostScript calendar from Remind output
|
||||
.SH SYNOPSIS
|
||||
.B rem2ps [\fIoptions\fR]
|
||||
.SH DESCRIPTION
|
||||
\fBRem2ps\fR reads the standard input, which should be the results of
|
||||
\fBrem2ps\fR reads the standard input, which should be the results of
|
||||
running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
|
||||
emits PostScript code (which draws a calendar) to the standard output.
|
||||
.PP
|
||||
See the section "Rem2PS Input Format" for details about the \fB\-p\fR
|
||||
Although \fBrem2ps\fR will be maintained, no new features will be added
|
||||
to it. Instead, all new development will continue on \fBrem2pdf\fR.
|
||||
.PP
|
||||
See the section "REM2PS INPUT FORMAT" for details about the \fB\-p\fR
|
||||
data. This may be useful if you wish to create other \fBRemind\fR
|
||||
back-ends.
|
||||
.PP
|
||||
Note that \fBRem2PS\fR does not handle UTF-8 input. If you need to
|
||||
Note that \fBrem2ps\fR does not handle UTF-8 input. If you need to
|
||||
render characters outside the ASCII character set, see
|
||||
\fBrem2pdf\fR instead.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-v
|
||||
Be more verbose. This causes \fBRem2ps\fR to print progress messages
|
||||
Be more verbose. This causes \fBrem2ps\fR to print progress messages
|
||||
to the standard error stream. Normally, it is silent.
|
||||
.TP
|
||||
.B \-p file
|
||||
@@ -133,7 +136,7 @@ numbers.
|
||||
|
||||
.PP
|
||||
Type "rem2ps \-m help" for a list of available media. Note that the media
|
||||
type (and all \fBRem2ps\fR options) are case-sensitive. If you don't use
|
||||
type (and all \fBrem2ps\fR options) are case-sensitive. If you don't use
|
||||
the \fB\-m\fR option, the media defaults to a compiled-in default - this
|
||||
is usually Letter for North America and A4 for Europe. The "\-m help"
|
||||
option will display the compiled-in default.
|
||||
@@ -193,8 +196,8 @@ for good output:
|
||||
rem2ps \-ol 72 \-sh 12
|
||||
.fi
|
||||
.SH USAGE
|
||||
To use \fBRem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
|
||||
option to \fBRem2ps\fR, and then send the result to a printer. This is most easily
|
||||
To use \fBrem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
|
||||
option to \fBrem2ps\fR, and then send the result to a printer. This is most easily
|
||||
illustrated with examples:
|
||||
.PP
|
||||
.nf
|
||||
@@ -228,10 +231,10 @@ calendar entries. This border is normally blank space.
|
||||
.TP
|
||||
BoxWidth and BoxHeight
|
||||
The width and height of the calendar box, from center-to-center of the
|
||||
black gridlines.
|
||||
black grid lines.
|
||||
.TP
|
||||
InBoxHeight
|
||||
The height from the center of the bottom black gridline to the top
|
||||
The height from the center of the bottom black grid line to the top
|
||||
of the regular calendar entry area. The space from here to the top
|
||||
of the box is used only to draw the day number.
|
||||
.TP
|
||||
@@ -260,7 +263,7 @@ PostScript files. Always test your PostScript thoroughly with a PostScript
|
||||
viewer before sending it to the printer. You should not use any document
|
||||
structuring comments in your PostScript code.
|
||||
.PP
|
||||
In addition, prior to drawing a calendar page, \fBRem2ps\fR emits
|
||||
In addition, prior to drawing a calendar page, \fBrem2ps\fR emits
|
||||
the following PostScript code:
|
||||
.PP
|
||||
.nf
|
||||
@@ -320,14 +323,14 @@ For an example, create a file called "myprolog" whose contents are:
|
||||
} bind def
|
||||
.fi
|
||||
.PP
|
||||
Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
|
||||
with the year and month in large grey letters in the background of the
|
||||
Use that file with the \fBrem2ps\fR \fB\-p\fR option to create calendars
|
||||
with the year and month in large gray letters in the background of the
|
||||
calendar.
|
||||
.PP
|
||||
.SH REM2PS INPUT FORMAT (-P OPTION)
|
||||
The \fB\-p\fR option is an older, simpler interchange format used by
|
||||
\fBRemind\fR to communicate with back-ends. New back-ends are
|
||||
encoraged to support the new \fB\-pp\fR format preferably, though they
|
||||
encouraged to support the new \fB\-pp\fR format preferably, though they
|
||||
are encouraged to support the older \fB\-p\fR format as well if the
|
||||
older format contains enough information for them to work properly.
|
||||
.PP
|
||||
@@ -380,7 +383,7 @@ been set to "-". The consistent use of "/" is designed to ease parsing.
|
||||
.PP
|
||||
\fIspecial\fR is a string used
|
||||
for "out-of-band" communication with back-ends. If the reminder
|
||||
is a normal reminder, \fIspecial\fR is "*". The \fBRem2PS\fR
|
||||
is a normal reminder, \fIspecial\fR is "*". The \fBrem2ps\fR
|
||||
back-end understands the specials \fBPostScript\fR and \fBPSFile\fR.
|
||||
Other back-ends may understand other specials. A back end should
|
||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
||||
@@ -458,7 +461,7 @@ JSON object. The keys that may be present in the JSON object are as
|
||||
follows:
|
||||
.TP
|
||||
.B date \fIYYYY-MM-DD\fR
|
||||
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||
The \fBdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
||||
.TP
|
||||
.B filename \fIf\fR
|
||||
@@ -522,9 +525,9 @@ contains the back value. If the "back" value was \-n, the value will
|
||||
be positive; if it was \-\-n, the value will be negative.
|
||||
.TP
|
||||
.B delta \fIn\fR
|
||||
If the reminder contained a "delta" clause (\+n or \+\+n), this key
|
||||
contains the delta value. If the "delta" value was \+n, the value will
|
||||
be positive; if it was \+\+n, the value will be negative.
|
||||
If the reminder contained a "delta" clause (+n or ++n), this key
|
||||
contains the delta value. If the "delta" value was +n, the value will
|
||||
be positive; if it was ++n, the value will be negative.
|
||||
.TP
|
||||
.B rep \fIn\fR
|
||||
If the reminder contained a "repeat" clause (*n), this key contains
|
||||
@@ -674,17 +677,17 @@ is desired.
|
||||
|
||||
|
||||
.SH AUTHOR
|
||||
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
|
||||
rem2ps was written by Dianne Skoll <dianne@skoll.ca>
|
||||
.SH BUGS
|
||||
All \fBRem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
|
||||
All \fBrem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
|
||||
Any time you supply
|
||||
a font name or size, line thickness, or border width, it is treated as a
|
||||
string and sent straight to the PostScript interpreter. Thus, if you
|
||||
supply invalid fonts or sizes, \fBRem2ps\fR will not complain, but the
|
||||
supply invalid fonts or sizes, \fBrem2ps\fR will not complain, but the
|
||||
resulting PostScript output will probably not work.
|
||||
.PP
|
||||
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,
|
||||
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/
|
||||
|
||||
790
man/remind.1.in
790
man/remind.1.in
File diff suppressed because it is too large
Load Diff
@@ -184,7 +184,9 @@ on the reminder.
|
||||
If there are any errors in your reminder file, the "Queue..." button
|
||||
changes to "Errors...". Click on "Errors..." to see the Remind error
|
||||
output. Click "OK" to close the error window; this makes the button
|
||||
in the main TkRemind window to revert to "Queue..."
|
||||
in the main TkRemind window to revert to "Queue..." You can click on
|
||||
any error message to open an editor on the file and line number that
|
||||
caused the error.
|
||||
|
||||
.SH BACKGROUND REMINDERS
|
||||
|
||||
@@ -192,7 +194,7 @@ If you create "timed" reminders, \fBTkRemind\fR will queue them in
|
||||
the background and pop up boxes as they are triggered. Additionally,
|
||||
if you created the reminder using \fBTkRemind\fR, you will be given the
|
||||
option of "turning off" the reminder for the rest of the day.
|
||||
\fBTkRemind\fR achieves queueing of background reminders by running
|
||||
\fBTkRemind\fR achieves queuing of background reminders by running
|
||||
\fBRemind\fR in \fIserver mode\fR, described later.
|
||||
|
||||
.SH OPTIONS
|
||||
@@ -222,6 +224,14 @@ If this is selected, pop-up reminder boxes will be closed after one minute
|
||||
has elapsed. Otherwise, they remain on your screen forever until you
|
||||
explicitly dismiss them.
|
||||
|
||||
.TP
|
||||
.B Use system notifications when issuing a reminder
|
||||
This option is available only for Tcl/Tk version 9.0 or later, or if
|
||||
you have the \fBnotify-send\fR program installed; it will be greyed
|
||||
out if neither condition is true. If selected, then when a reminder
|
||||
is popped up, it will also be sent to the desktop notification system,
|
||||
causing a notification to appear.
|
||||
|
||||
.TP
|
||||
.B Beep terminal when popping up a reminder
|
||||
If selected, \fBTkRemind\fR beeps the terminal bell when a queued reminder
|
||||
@@ -264,7 +274,7 @@ Useful strings might be "emacs +%d %s" or "gvim +%d %s"
|
||||
.TP
|
||||
.B Extra Argument for Remind
|
||||
This specifies any extra arguments that should be passed to Remind
|
||||
when \BTkRemind\fR invokes \fBremind\fR. Unless you know what
|
||||
when \fBTkRemind\fR invokes \fBremind\fR. Unless you know what
|
||||
you are doing, leave this blank.
|
||||
|
||||
.TP
|
||||
@@ -301,11 +311,11 @@ 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.)
|
||||
If you are running \fBTkRemind\fR on Linux and \fBRemind\fR has been
|
||||
compiled with \fBinotify\fR(7) support, 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,
|
||||
@@ -366,60 +376,110 @@ your hand-edited files in a separate \fB*.rem\fR file than \fBTkRemind\fR's
|
||||
|
||||
\fBRemind\fR has a special mode for interacting with programs like
|
||||
\fBTkRemind\fR. This mode is called \fIserver mode\fR and is
|
||||
selected by supplying the \fB\-z0\fR option to \fBRemind\fR.
|
||||
selected by supplying the \fB\-zj\fR option to \fBRemind\fR.
|
||||
|
||||
In server mode, \fBRemind\fR operates similar to daemon mode, except
|
||||
it reads commands (one per line)
|
||||
from standard input and writes status lines to standard output.
|
||||
it reads commands (one per line) from standard input and writes status
|
||||
lines to standard output. Each status line is a JSON object.
|
||||
|
||||
The commands accepted in server mode are:
|
||||
|
||||
.TP
|
||||
EXIT
|
||||
Terminate the \fBRemind\fR process. EOF on standard input does the
|
||||
same thing.
|
||||
same thing. \fBRemind\fR exits immediately without printing
|
||||
a JSON status line.
|
||||
|
||||
.TP
|
||||
STATUS
|
||||
Return the number of queued reminders.
|
||||
Return the number of queued reminders. The JSON object looks
|
||||
something like this:
|
||||
.nf
|
||||
|
||||
{"response":"queued","nqueued":n,"command":"STATUS"}
|
||||
|
||||
.fi
|
||||
where \fIn\fR is the number of reminders queued.
|
||||
|
||||
.TP
|
||||
QUEUE or JSONQUEUE
|
||||
Returns the contents of the queue. The JSON object looks something
|
||||
like this:
|
||||
.nf
|
||||
|
||||
{"response":"queue","queue":[ ... ],"command":"QUEUE"}
|
||||
|
||||
.fi
|
||||
The value of the \fBqueue\fR key is an array of JSON objects, each
|
||||
representing a queued reminder.
|
||||
|
||||
.TP
|
||||
DEL \fIqid\fR
|
||||
Delete the reminder with queue-id \fIqid\fR from the queue.
|
||||
|
||||
.TP
|
||||
REREAD
|
||||
Re-read the reminder file
|
||||
Re-read the reminder file. Returns the following status line:
|
||||
|
||||
.nf
|
||||
|
||||
{"response":"reread","command":"REREAD"}
|
||||
|
||||
.fi
|
||||
|
||||
.PP
|
||||
The status lines written are as follows:
|
||||
Additional status lines written are as follows:
|
||||
|
||||
.TP
|
||||
NOTE reminder \fItime\fR \fItag\fR
|
||||
Signifies the beginning of a timed reminder whose trigger time is
|
||||
\fItime\fR with tag \fItag\fR. If the reminder has no tag, an
|
||||
asterisk is supplied for \fItag\fR. All lines following this line
|
||||
are the body of the reminder, until the line \fBNOTE endreminder\fR
|
||||
is transmitted.
|
||||
.nf
|
||||
|
||||
{"response":"reminder","ttime":tt,"now":now,"tags":tags,"qid":qid,"body":body}
|
||||
|
||||
.fi
|
||||
In this line, \fItt\fR is the trigger time of the reminder (expressed
|
||||
as a string), \fInow\fR is the current time, \fItags\fR (if present)
|
||||
is the tag or tags associated with the reminder, and \fIbody\fR is the
|
||||
body of the reminder. This response causes \fBTkRemind\fR to pop up a
|
||||
reminder notification. \fIqid\fR is a unique identifier for this
|
||||
reminder. You may delete it from the queue by sending a \fBDEL\fR
|
||||
\fIqid\fR command to the server. Note that \fIqid\fRs are not stable
|
||||
across re-reads; if \fBRemind\fR restarts itself to re-read the reminder
|
||||
file, then the \fIqid\fR values are likely to change, and any reminder
|
||||
deleted with a \fBDEL\fR \fIqid\fR command is likely to be re-queued.
|
||||
.TP
|
||||
NOTE newdate
|
||||
.nf
|
||||
|
||||
{"response":"newdate"}
|
||||
|
||||
.fi
|
||||
|
||||
This line is emitted whenever \fBRemind\fR has detected a rollover of
|
||||
the system date. The front-end program should redraw its calendar
|
||||
or take whatever other action is needed.
|
||||
|
||||
.TP
|
||||
NOTE reread
|
||||
This line is emitted whenever the number of reminders in \fBRemind\fR's
|
||||
queue changes because of a date rollover or a \fBREREAD\fR command.
|
||||
The front-end should issue a \fBSTATUS\fR command in response to this
|
||||
message.
|
||||
.nf
|
||||
|
||||
.TP
|
||||
NOTE queued \fIn\fR
|
||||
This line is emitted in response to a \fBSTATUS\fR command. The number
|
||||
\fIn\fR is the number of reminders in the queue.
|
||||
{"response":"reread","command":"inotify"}
|
||||
|
||||
.fi
|
||||
|
||||
If \fBRemind\fR was compiled with support for \fBinotify\fR(7), then
|
||||
if it detects a change to the top-level reminder file or directory,
|
||||
it issues the above response. The front-end should redraw its
|
||||
calendar since this response indicates that a change has been made
|
||||
to the reminder file or directory.
|
||||
|
||||
.PP
|
||||
Please note that \fBRemind\fR can write a status message \fIat any time\fR
|
||||
and not just in response to a command sent to its standard input. Therefore,
|
||||
a program that runs \fBRemind\fR in server mode must be prepared to handle
|
||||
asynchronous status messages.
|
||||
|
||||
.SH AUTHOR
|
||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
\fBTkRemind\fR is Copyright 1996-2023 by Dianne Skoll.
|
||||
\fBTkRemind\fR is Copyright 1996-2024 by Dianne Skoll.
|
||||
|
||||
.SH FILES
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ install:
|
||||
@if test "$(PERL)" = "" ; then \
|
||||
echo "Not installing rem2html; Perl is required"; exit 0; fi; \
|
||||
for m in $(PERLMODS_NEEDED) ; \
|
||||
do \
|
||||
do \
|
||||
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
|
||||
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
||||
done; \
|
||||
|
||||
@@ -6,10 +6,11 @@ use warnings;
|
||||
|
||||
use Getopt::Long;
|
||||
use JSON::MaybeXS;
|
||||
use Encode;
|
||||
|
||||
my %Options;
|
||||
|
||||
my $rem2html_version = '2.1';
|
||||
my $rem2html_version = '@VERSION@';
|
||||
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||
@@ -25,12 +26,12 @@ rem2html - Convert the output of "remind -pp" to HTML
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
remind -pp ... | rem2html [options]
|
||||
remind -pp [remind_options] file | rem2html [options]
|
||||
|
||||
You can also use the old interchange format as below, but the -pp
|
||||
version is preferred.
|
||||
|
||||
remind -p ... | rem2html [options]
|
||||
remind -p [remind_options] file | rem2html [options]
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
@@ -44,6 +45,11 @@ Print usage information
|
||||
|
||||
Print version
|
||||
|
||||
=item --utf8
|
||||
|
||||
Assume standard input is encoded in UTF-8; write UTF-8 data to standard
|
||||
output.
|
||||
|
||||
=item --backurl I<url>
|
||||
|
||||
When producing the small calendar for the previous month, make the
|
||||
@@ -149,11 +155,12 @@ sub usage
|
||||
print STDERR <<"EOM";
|
||||
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
|
||||
|
||||
Usage: remind -pp ... | rem2html [options]
|
||||
Usage: remind -pp [remind_options] file | rem2html [options]
|
||||
|
||||
Options:
|
||||
|
||||
--help, -h Print usage information
|
||||
--utf8 Assume UTF-8 input and write UTF-8 output
|
||||
--man Show man page (requires "perldoc")
|
||||
--version Print version
|
||||
--backurl url Make the title on the previous month's small calendar
|
||||
@@ -197,6 +204,7 @@ sub parse_options
|
||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||
if (!GetOptions(\%Options, "help|h",
|
||||
"man",
|
||||
"utf8",
|
||||
"pngs",
|
||||
"version",
|
||||
"stylesheet=s",
|
||||
@@ -216,13 +224,22 @@ sub parse_options
|
||||
if ($stylesheet) {
|
||||
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||
}
|
||||
if ($Options{utf8}) {
|
||||
binmode(STDIN, ':encoding(UTF-8)');
|
||||
binmode(STDOUT, ':encoding(UTF-8)');
|
||||
}
|
||||
}
|
||||
|
||||
sub start_output
|
||||
{
|
||||
return if ($Options{tableonly});
|
||||
|
||||
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
||||
print("<html>\n<head>\n");
|
||||
if ($Options{utf8}) {
|
||||
print '<meta charset="UTF-8">' . "\n";
|
||||
}
|
||||
|
||||
print("<title>" . $Options{title} . "</title>\n");
|
||||
if (!$Options{nostyle}) {
|
||||
if ($Options{stylesheet}) {
|
||||
print('<link rel="stylesheet" type="text/css" href="' .
|
||||
@@ -310,7 +327,12 @@ sub parse_input
|
||||
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
} elsif (/\{/) {
|
||||
my $obj = decode_json($_);
|
||||
my $obj;
|
||||
if ($Options{utf8}) {
|
||||
$obj = decode_json(encode('UTF-8', $_, Encode::FB_DEFAULT));
|
||||
} else {
|
||||
$obj = decode_json($_);
|
||||
}
|
||||
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||
$y = $1;
|
||||
$m = $2;
|
||||
@@ -352,19 +374,37 @@ sub parse_input
|
||||
($1 % 256), ($1 % 256), ($1 % 256));
|
||||
}
|
||||
} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
|
||||
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {
|
||||
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/s) {
|
||||
my($r, $g, $b, $text) = ($1, $2, $3, $4);
|
||||
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
|
||||
$r % 256, $g % 256, $b % 256);
|
||||
push(@{$days->[$d]}, "<p$class $color>" . escape_html($text) . '</p>');
|
||||
push(@{$days->[$d]}, "<p$class $color>" . fix_whitespace(escape_html($text)) . '</p>');
|
||||
}
|
||||
} elsif ($special eq '*') {
|
||||
push(@{$days->[$d]}, "<p$class>" . escape_html($body) . '</p>');
|
||||
push(@{$days->[$d]}, "<p$class>" . fix_whitespace(escape_html($body)) . '</p>');
|
||||
}
|
||||
}
|
||||
return $found_data;
|
||||
}
|
||||
|
||||
sub fix_whitespace
|
||||
{
|
||||
my ($text) = @_;
|
||||
|
||||
# Collapse multiple spaces/tabs to a single space
|
||||
$text =~ s/[ \t]+/ /gs;
|
||||
|
||||
# Remove whitespace before/after newlines
|
||||
$text =~ s/\s+\n/\n/gs;
|
||||
$text =~ s/\n\s+/\n/gs;
|
||||
# Collapse multiple newlines to a single newline
|
||||
$text =~ s/\n+/\n/gs;
|
||||
|
||||
# Convert newlines to <br />
|
||||
$text =~ s|\n|<br />|g;
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub small_calendar
|
||||
{
|
||||
my($month, $monlen, $url, $first_col) = @_;
|
||||
@@ -60,7 +60,9 @@ my $settings = {
|
||||
margin_bottom => 36,
|
||||
margin_left => 36,
|
||||
margin_right => 36,
|
||||
|
||||
svg => 0,
|
||||
ps => 0,
|
||||
eps => 0,
|
||||
verbose => 0,
|
||||
};
|
||||
|
||||
@@ -80,6 +82,9 @@ Options:
|
||||
|
||||
--landscape, -l Print in landscape orientation
|
||||
--small-calendars=N Choose location for small calendars
|
||||
--svg Output SVG instead of PDF
|
||||
--ps Output PostScript instead of PDF
|
||||
--eps Output encapsulated PostScript instead of PDF
|
||||
-cN Synonym for --small-calendars=N
|
||||
--left-numbers, -x Print day numbers on the left
|
||||
--fill-page, -e Fill the entire page
|
||||
@@ -112,6 +117,9 @@ Getopt::Long::Configure('bundling_values');
|
||||
my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
||||
'small-calendars|c=i' => \$settings->{small_calendars},
|
||||
'left-numbers|x' => \$settings->{numbers_on_left},
|
||||
'svg' => \$settings->{svg},
|
||||
'ps' => \$settings->{ps},
|
||||
'eps' => \$settings->{eps},
|
||||
'fill-page|e' => \$settings->{fill_entire_page},
|
||||
'media|m=s' => \$settings->{media},
|
||||
'width|w=i' => \$settings->{width},
|
||||
@@ -176,6 +184,17 @@ if ($settings->{landscape}) {
|
||||
$settings->{height} = $tmp;
|
||||
}
|
||||
|
||||
if ($settings->{svg} && $settings->{ps} ||
|
||||
$settings->{svg} && $settings->{eps} ||
|
||||
$settings->{eps} && $settings->{ps}) {
|
||||
print STDERR "Only one of --eps, --ps or --svg may be used.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($settings->{eps}) {
|
||||
$settings->{ps} = 1;
|
||||
}
|
||||
|
||||
# Don't read from a terminal
|
||||
if (-t STDIN) { ## no critic
|
||||
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
||||
@@ -187,8 +206,25 @@ my $done_one = 0;
|
||||
|
||||
my $errored_out = 0;
|
||||
|
||||
my $surface = Cairo::PdfSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||
$settings->{width}, $settings->{height});
|
||||
my $surface;
|
||||
if ($settings->{svg}) {
|
||||
$surface = Cairo::SvgSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||
$settings->{width}, $settings->{height});
|
||||
} elsif ($settings->{ps}) {
|
||||
if ($settings->{landscape}) {
|
||||
$surface = Cairo::PsSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||
$settings->{height}, $settings->{width});
|
||||
} else {
|
||||
$surface = Cairo::PsSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||
$settings->{width}, $settings->{height});
|
||||
}
|
||||
if ($settings->{eps}) {
|
||||
$surface->set_eps(1);
|
||||
}
|
||||
} else {
|
||||
$surface = Cairo::PdfSurface->create_for_stream(sub { print $_[1] unless $errored_out; }, undef,
|
||||
$settings->{width}, $settings->{height});
|
||||
}
|
||||
|
||||
# set_metadata not available in older versions of Cairo
|
||||
eval { $surface->set_metadata('title', 'Calendar'); };
|
||||
@@ -196,10 +232,26 @@ eval { $surface->set_metadata('author', 'Remind (https://dianne.skoll.ca/project
|
||||
eval { $surface->set_metadata('creator', 'rem2pdf (https://dianne.skoll.ca/projects/remind/)'); };
|
||||
eval { $surface->set_metadata('subject', 'Calendar'); };
|
||||
|
||||
if ($settings->{ps}) {
|
||||
$surface->dsc_comment('%%Title: Calendar');
|
||||
$surface->dsc_comment('%%Producer: rem2pdf (https://dianne.skoll.ca/projects/remind/)');
|
||||
$surface->dsc_comment('%%PageOrientation: ' . (($settings->{landscape}) ? 'Landscape' : 'Portrait'));
|
||||
$surface->dsc_begin_setup();
|
||||
}
|
||||
|
||||
my $cr = Cairo::Context->create($surface);
|
||||
$cr->set_line_width($settings->{line_thickness});
|
||||
if ($settings->{ps} && $settings->{landscape}) {
|
||||
$cr->translate(0, $settings->{width});
|
||||
$cr->rotate(-1.5707963267949); # Rotate -90 degrees
|
||||
}
|
||||
|
||||
my $warned = 0;
|
||||
while(1) {
|
||||
if ($settings->{ps}) {
|
||||
$surface->dsc_begin_page_setup();
|
||||
$surface->dsc_comment('%%PageOrientation: ' . (($settings->{landscape}) ? 'Landscape' : 'Portrait'));
|
||||
}
|
||||
my ($obj, $err) = Remind::PDF->create_from_stream(*STDIN,
|
||||
{color => 1,
|
||||
shade => 1,
|
||||
@@ -215,8 +267,15 @@ while(1) {
|
||||
}
|
||||
last;
|
||||
}
|
||||
$done_one = 1;
|
||||
if (($settings->{eps} || $settings->{svg}) && $done_one) {
|
||||
if (!$warned) {
|
||||
print STDERR "WARNING: --eps and --svg can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
||||
$warned = 1;
|
||||
}
|
||||
next;
|
||||
}
|
||||
$obj->render($cr, $settings);
|
||||
$done_one = 1;
|
||||
}
|
||||
|
||||
$surface->finish();
|
||||
@@ -273,17 +332,22 @@ __END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rem2pdf - draw a PDF calendar from Remind output
|
||||
rem2pdf - draw a PDF, SVG or PostScript calendar from Remind output
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
remind -pp [options] file | rem2pdf [options] > output.pdf
|
||||
remind -pp [remind_options] file | rem2pdf [options] > output.pdf
|
||||
remind -pp [remind_options] file | rem2pdf --svg [options] > output.svg
|
||||
remind -pp [remind_options] file | rem2pdf --ps [options] > output.ps
|
||||
remind -pp [remind_options] file | rem2pdf --eps [options] > output.eps
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<rem2pdf> reads the standard input, which should be the results of
|
||||
running B<remind> with the B<-p>, B<-pp> or B<-ppp> options. It emits
|
||||
PDF code that draws a calendar to standard output.
|
||||
PDF, SVG or PostScript code that draws a calendar to standard output. (The
|
||||
addition of support for SVG and PostScript means that rem2pdf is increasingly
|
||||
misnamed...)
|
||||
|
||||
B<rem2pdf> uses the Pango text formatting library (L<https://pango.gnome.org/>)
|
||||
and the Cairo graphics library (L<https://www.cairographics.org/>) to produce
|
||||
@@ -298,6 +362,22 @@ output at all.
|
||||
|
||||
=over
|
||||
|
||||
=item --ps
|
||||
|
||||
Output PostScript instead of PDF.
|
||||
|
||||
=item --eps
|
||||
|
||||
Output Encapsulated PostScript instead of PDF. In this case, you
|
||||
should feed C<rem2pdf> only one month's worth of calendar data,
|
||||
because it cannot create a multi-page encapsulated PostScript file.
|
||||
|
||||
=item --svg
|
||||
|
||||
Output SVG instead of PDF. In this case, you should feed C<rem2pdf>
|
||||
only one month's worth of calendar data, because it cannot create
|
||||
a multi-page SVG file.
|
||||
|
||||
=item --landscape, -l
|
||||
|
||||
Print the calendar in landscape orientation. Essentially, this swaps
|
||||
@@ -486,7 +566,7 @@ output for the invalid reminder.
|
||||
=head1 ABSOLUTELY-POSITIONED TEXT
|
||||
|
||||
If your B<PANGO> special reminder starts with C<@I<x>,I<y>> where I<x>
|
||||
and I<y> are floating-point numbers, then the Pango marked-up test is
|
||||
and I<y> are floating-point numbers, then the Pango marked-up text is
|
||||
positioned absolutely with respect to the day's box (and is not
|
||||
counted when calculating the box's height.)
|
||||
|
||||
|
||||
@@ -1008,7 +1008,17 @@ as were read from the C<remind -ppp> stream
|
||||
sub render
|
||||
{
|
||||
my ($self, $cr, $settings) = @_;
|
||||
my $done = 0;
|
||||
my $warned = 0;
|
||||
foreach my $e (@{$self->{entries}}) {
|
||||
if ($settings->{svg} && $done) {
|
||||
if (!$warned) {
|
||||
print STDERR "WARNING: --svg can only output one page; ignoring subsequent\nmonths in a multi-month calendar.\n";
|
||||
$warned = 1;
|
||||
}
|
||||
next;
|
||||
}
|
||||
$done = 1;
|
||||
$e->render($cr, $settings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,18 @@ sub render
|
||||
} else {
|
||||
$body = $self->{body};
|
||||
}
|
||||
|
||||
# Clean up the body:
|
||||
|
||||
# Collapse multiple spaces/tabs to a single space
|
||||
$body =~ s/[ \t]+/ /gs;
|
||||
|
||||
# Remove whitespace before/after newlines
|
||||
$body =~ s/\s+\n/\n/gs;
|
||||
$body =~ s/\n\s+/\n/gs;
|
||||
# Collapse multiple newlines to a single newline
|
||||
$body =~ s/\n+/\n/gs;
|
||||
|
||||
$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);
|
||||
|
||||
15
resources/tkremind.desktop
Executable file
15
resources/tkremind.desktop
Executable file
@@ -0,0 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Exec=tkremind
|
||||
StartupNotify=true
|
||||
Icon=tkremind
|
||||
Terminal=false
|
||||
Name=tkremind
|
||||
Comment=TkRemind Calendar Program
|
||||
Categories=Office;Calendar;
|
||||
Keywords=Calendar;remind;
|
||||
Keywords[ca]=Calendari;remind;
|
||||
Keywords[de]=Kalender;remind;
|
||||
Keywords[en_GB]=Calendar;remind;
|
||||
Keywords[es]=Calendario;remind;
|
||||
|
||||
BIN
resources/tkremind.png
Normal file
BIN
resources/tkremind.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
739
scripts/tkremind → scripts/tkremind.in
Executable file → Normal file
739
scripts/tkremind → scripts/tkremind.in
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@ REMINDSRCS= calendar.c dynbuf.c dorem.c dosubst.c expr.c files.c funcs.c \
|
||||
globals.c hbcal.c init.c main.c md5.c moon.c omit.c queue.c \
|
||||
sort.c token.c trigger.c userfns.c utils.c var.c
|
||||
|
||||
REMINDHDRS=config.h custom.h dynbuf.h err.h expr.h globals.h lang.h \
|
||||
REMINDHDRS=config.h custom.h dynbuf.h err.h globals.h lang.h \
|
||||
md5.h protos.h rem2ps.h types.h version.h
|
||||
REMINDOBJS= $(REMINDSRCS:.c=.o)
|
||||
|
||||
@@ -63,6 +63,16 @@ install: all
|
||||
done
|
||||
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
|
||||
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
|
||||
chmod -R a+rX $(DESTDIR)$(datarootdir)/remind
|
||||
-mkdir -p $(DESTDIR)$(prefix)/share/pixmaps
|
||||
-mkdir -p $(DESTDIR)$(prefix)/share/applications
|
||||
$(INSTALL_DATA) $(srcdir)/../resources/tkremind.png $(DESTDIR)$(prefix)/share/pixmaps
|
||||
$(INSTALL_PROGRAM) $(srcdir)/../resources/tkremind.desktop $(DESTDIR)$(prefix)/share/applications
|
||||
-if test "$(DESTDIR)" = ""; then \
|
||||
update-desktop-database < /dev/null > /dev/null 2>&1 ; \
|
||||
xdg-icon-resource install --novendor --size 64 $(DESTDIR)$(prefix)/share/pixmaps/tkremind.png < /dev/null > /dev/null 2>&1 || true; \
|
||||
xdg-desktop-menu install --novendor $(DESTDIR)$(prefix)/share/applications/tkremind.desktop < /dev/null > /dev/null 2>&1 || true; \
|
||||
fi
|
||||
|
||||
install-stripped: install
|
||||
strip $(DESTDIR)$(bindir)/remind || true
|
||||
@@ -71,9 +81,6 @@ install-stripped: install
|
||||
clean:
|
||||
rm -f *.o *~ core *.bak $(PROGS)
|
||||
|
||||
cppcheck:
|
||||
cppcheck --force --enable=all --suppress=variableScope --suppress=ConfigurationNotChecked *.c
|
||||
|
||||
clobber:
|
||||
rm -f *.o *~ remind rem2ps test.out core *.bak
|
||||
|
||||
@@ -83,6 +90,9 @@ depend:
|
||||
# The next targets are not very useful to you. I use them to build
|
||||
# distributions, etc.
|
||||
|
||||
cppcheck:
|
||||
cppcheck -j`nproc` --force --enable=all --suppress=ConfigurationNotChecked --suppress=unmatchedSuppression --suppress=variableScope --inline-suppr .
|
||||
|
||||
# Build a tar file based on all files checked into git.
|
||||
distro:
|
||||
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION).tar
|
||||
|
||||
340
src/calendar.c
340
src/calendar.c
@@ -5,7 +5,7 @@
|
||||
/* The code for generating a calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "lang.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "md5.h"
|
||||
@@ -282,6 +281,7 @@ static void ColorizeEntry(CalEntry const *e, int clamp);
|
||||
static void SortCol (CalEntry **col);
|
||||
static void DoCalendarOneWeek (int nleft);
|
||||
static void DoCalendarOneMonth (void);
|
||||
static void DoSimpleCalendarOneMonth (void);
|
||||
static int WriteCalendarRow (void);
|
||||
static void WriteWeekHeaderLine (void);
|
||||
static void WritePostHeaderLine (void);
|
||||
@@ -339,6 +339,7 @@ UnBackgroundize(int d)
|
||||
printf("%s", Decolorize());
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static void
|
||||
send_lrm(void)
|
||||
{
|
||||
@@ -353,6 +354,7 @@ send_lrm(void)
|
||||
printf("\xE2\x80\x8E");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static char const *
|
||||
despace(char const *s)
|
||||
@@ -475,7 +477,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
void PutWideChar(wchar_t const wc)
|
||||
void PutWideChar(wchar_t const wc, DynamicBuffer *output)
|
||||
{
|
||||
char buf[MB_CUR_MAX+1];
|
||||
int len;
|
||||
@@ -483,7 +485,11 @@ void PutWideChar(wchar_t const wc)
|
||||
len = wctomb(buf, wc);
|
||||
if (len > 0) {
|
||||
buf[len] = 0;
|
||||
fputs(buf, stdout);
|
||||
if (output) {
|
||||
DBufPuts(output, buf);
|
||||
} else {
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -523,9 +529,9 @@ get_month_abbrev(char const *mon)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static int make_wchar_versions(CalEntry *e)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
size_t len;
|
||||
wchar_t *buf;
|
||||
len = mbstowcs(NULL, e->text, 0);
|
||||
@@ -539,10 +545,8 @@ static int make_wchar_versions(CalEntry *e)
|
||||
e->wc_text = buf;
|
||||
e->wc_pos = buf;
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gon(void)
|
||||
{
|
||||
@@ -556,11 +560,11 @@ static void goff(void)
|
||||
static void
|
||||
ClampColor(int *r, int *g, int *b)
|
||||
{
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_UNKNOWN) {
|
||||
if (GetTerminalBackground() == TERMINAL_BACKGROUND_UNKNOWN) {
|
||||
/* No special clamping if terminal background is unknown */
|
||||
return;
|
||||
}
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
|
||||
if (GetTerminalBackground() == TERMINAL_BACKGROUND_DARK) {
|
||||
if (*r <= 64 && *g <= 64 && *b <= 64) {
|
||||
int max = *r;
|
||||
double factor;
|
||||
@@ -579,7 +583,7 @@ ClampColor(int *r, int *g, int *b)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
|
||||
if (GetTerminalBackground() == TERMINAL_BACKGROUND_LIGHT) {
|
||||
if (*r > 191 && *g > 191 && *b > 191) {
|
||||
int min = *r;
|
||||
if (*g < min) min = *g;
|
||||
@@ -667,11 +671,11 @@ Colorize(int r, int g, int b, int bg, int clamp)
|
||||
if (b > 64) b = 1;
|
||||
else b = 0;
|
||||
|
||||
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_DARK && !bg) {
|
||||
if (clamp && GetTerminalBackground() == TERMINAL_BACKGROUND_DARK && !bg) {
|
||||
/* Convert black-on-black to grey */
|
||||
if (!r && !g && !b) return VT100Colors[1][0][0][0];
|
||||
}
|
||||
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_LIGHT && !bg) {
|
||||
if (clamp && GetTerminalBackground() == TERMINAL_BACKGROUND_LIGHT && !bg) {
|
||||
/* Convert white-on-white to grey */
|
||||
if (r && g && b) return VT100Colors[1][0][0][0];
|
||||
}
|
||||
@@ -755,13 +759,11 @@ SetMoonEntry(int dse, char const *moon)
|
||||
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);
|
||||
@@ -899,13 +901,17 @@ static void DoCalendarOneWeek(int nleft)
|
||||
if (UseVTColors) {
|
||||
printf("\x1B[1m"); /* Bold */
|
||||
}
|
||||
Backgroundize(d);
|
||||
PrintLeft(buf, ColSpaces-1, '*');
|
||||
putchar(' ');
|
||||
UnBackgroundize(d);
|
||||
if (UseVTColors) {
|
||||
printf("\x1B[0m"); /* Normal */
|
||||
}
|
||||
putchar(' ');
|
||||
} else {
|
||||
Backgroundize(d);
|
||||
PrintLeft(buf, ColSpaces, ' ');
|
||||
UnBackgroundize(d);
|
||||
}
|
||||
gon();
|
||||
DRAW(tb);
|
||||
@@ -962,21 +968,20 @@ static void DoCalendarOneWeek(int nleft)
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoCalendarOneMonth */
|
||||
/* DoSimpleCalendarOneMonth */
|
||||
/* */
|
||||
/* Produce a calendar for the current month. */
|
||||
/* Produce a "simple" calendar for the current month. */
|
||||
/* */
|
||||
/* A simple calendar is produced if the -s or -p option */
|
||||
/* was used. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DoCalendarOneMonth(void)
|
||||
static void DoSimpleCalendarOneMonth(void)
|
||||
{
|
||||
int y, m, d, mm, yy, i, j;
|
||||
|
||||
InitMoonsAndShades();
|
||||
|
||||
if (!DoSimpleCalendar) WriteCalHeader();
|
||||
|
||||
DidADay = 0;
|
||||
|
||||
if (PsCal) {
|
||||
FromDSE(DSEToday, &y, &m, &d);
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
@@ -1037,7 +1042,7 @@ static void DoCalendarOneMonth(void)
|
||||
printf("\"entries\":[\n");
|
||||
}
|
||||
}
|
||||
while (WriteCalendarRow()) continue;
|
||||
while (WriteCalendarRow()) /* continue */;
|
||||
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
printf("%s\n", PSEND);
|
||||
@@ -1049,7 +1054,29 @@ static void DoCalendarOneMonth(void)
|
||||
}
|
||||
printf("]\n}");
|
||||
}
|
||||
if (!DoSimpleCalendar) WriteCalTrailer();
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoCalendarOneMonth */
|
||||
/* */
|
||||
/* Produce a calendar for the current month. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DoCalendarOneMonth(void)
|
||||
{
|
||||
InitMoonsAndShades();
|
||||
|
||||
if (DoSimpleCalendar) {
|
||||
DoSimpleCalendarOneMonth();
|
||||
return;
|
||||
}
|
||||
|
||||
WriteCalHeader();
|
||||
|
||||
while (WriteCalendarRow()) /* continue */;
|
||||
|
||||
WriteCalTrailer();
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1121,13 +1148,17 @@ static int WriteCalendarRow(void)
|
||||
if (UseVTColors) {
|
||||
printf("\x1B[1m"); /* Bold */
|
||||
}
|
||||
Backgroundize(d+i-wd);
|
||||
PrintLeft(buf, ColSpaces-1, '*');
|
||||
putchar(' ');
|
||||
if (UseVTColors) {
|
||||
printf("\x1B[0m"); /* Normal */
|
||||
}
|
||||
putchar(' ');
|
||||
UnBackgroundize(d+i-wd);
|
||||
} else {
|
||||
Backgroundize(d+i-wd);
|
||||
PrintLeft(buf, ColSpaces, ' ');
|
||||
UnBackgroundize(d+i-wd);
|
||||
}
|
||||
}
|
||||
gon();
|
||||
@@ -1195,15 +1226,17 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
printf("%s", s);
|
||||
while (len++ < width) putchar(pad);
|
||||
int i;
|
||||
for (i=0; i<len && i<width; i++) {
|
||||
fputc(*(s+i), stdout);
|
||||
}
|
||||
while (i++ < width) putchar(pad);
|
||||
#else
|
||||
size_t len = mbstowcs(NULL, s, 0);
|
||||
int i;
|
||||
wchar_t static_buf[128];
|
||||
wchar_t *buf;
|
||||
wchar_t *ws;
|
||||
int display_len;
|
||||
|
||||
if (!len) {
|
||||
for (i=0; i<width; i++) {
|
||||
@@ -1218,30 +1251,36 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
display_len = wcswidth(buf, len+1);
|
||||
|
||||
ws = buf;
|
||||
for (i=0; i<width;) {
|
||||
i=0;
|
||||
while (i<width) {
|
||||
if (*ws) {
|
||||
PutWideChar(*ws++);
|
||||
i+= wcwidth(*ws);
|
||||
if (i + wcwidth(*ws) > width) {
|
||||
break;
|
||||
}
|
||||
i += wcwidth(*ws);
|
||||
PutWideChar(*ws++, NULL);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Mop up any potential combining characters */
|
||||
while (*ws && wcwidth(*ws) == 0) {
|
||||
PutWideChar(*ws++);
|
||||
PutWideChar(*ws++, NULL);
|
||||
}
|
||||
|
||||
/* Possibly send lrm control sequence */
|
||||
send_lrm();
|
||||
|
||||
for (i=display_len; i<width; i++) fputc(pad, stdout);
|
||||
while (i<width) {
|
||||
fputc(pad, stdout);
|
||||
i++;
|
||||
}
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
|
||||
@@ -1262,7 +1301,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
||||
int i;
|
||||
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
for (i=0; i<width-d; i++) {
|
||||
if (*s) {
|
||||
if (isspace(*s)) {
|
||||
putchar(' ');
|
||||
@@ -1297,7 +1336,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
@@ -1306,25 +1345,29 @@ static void PrintCentered(char const *s, int width, char *pad)
|
||||
if (d < 0) d = 0;
|
||||
ws = buf;
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
i=0;
|
||||
while (i+d < width) {
|
||||
if (*ws) {
|
||||
PutWideChar(*ws++);
|
||||
if (wcwidth(*ws) == 0) {
|
||||
/* Don't count this character... it's zero-width */
|
||||
i--;
|
||||
if (i+d + wcwidth(*ws) > width) {
|
||||
break;
|
||||
}
|
||||
i += wcwidth(*ws);
|
||||
PutWideChar(*ws++, NULL);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Mop up any potential combining characters */
|
||||
while (*ws && wcwidth(*ws) == 0) {
|
||||
PutWideChar(*ws++);
|
||||
PutWideChar(*ws++, NULL);
|
||||
}
|
||||
/* Possibly send lrm control sequence */
|
||||
send_lrm();
|
||||
|
||||
for (i=d+display_len; i<width; i++) fputs(pad, stdout);
|
||||
while (i+d<width) {
|
||||
fputs(pad, stdout);
|
||||
i++;
|
||||
}
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
}
|
||||
@@ -1411,7 +1454,7 @@ static int WriteOneColLine(int col)
|
||||
/* Find the last space char within the column. */
|
||||
width = 0;
|
||||
while (width <= ColSpaces) {
|
||||
if (!*ws) {
|
||||
if (!*ws || *ws == '\n') {
|
||||
wspace = ws;
|
||||
break;
|
||||
}
|
||||
@@ -1448,7 +1491,7 @@ static int WriteOneColLine(int col)
|
||||
}
|
||||
numwritten += wcwidth(*ws);
|
||||
}
|
||||
PutWideChar(*ws);
|
||||
PutWideChar(*ws, NULL);
|
||||
}
|
||||
}
|
||||
e->wc_pos = ws;
|
||||
@@ -1463,7 +1506,7 @@ static int WriteOneColLine(int col)
|
||||
if (wcwidth(*ws) > 0) {
|
||||
numwritten += wcwidth(*ws);
|
||||
}
|
||||
PutWideChar(*ws);
|
||||
PutWideChar(*ws, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1517,7 +1560,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (!*s || *s == '\n') {space = s; break;}
|
||||
if (isspace(*s)) space = s;
|
||||
s++;
|
||||
}
|
||||
@@ -1603,7 +1646,7 @@ static void GenerateCalEntries(int col)
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
@@ -1611,7 +1654,7 @@ static void GenerateCalEntries(int col)
|
||||
if (r == E_EOF) return;
|
||||
if (r) {
|
||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
s = FindInitialToken(&tok, CurLine);
|
||||
|
||||
@@ -1666,6 +1709,7 @@ static void GenerateCalEntries(int col)
|
||||
case T_Pop: r=PopOmitContext(&p); break;
|
||||
case T_Push: r=PushOmitContext(&p); break;
|
||||
case T_Preserve: r=DoPreserve(&p); break;
|
||||
case T_Expr: r = DoExpr(&p); break;
|
||||
case T_RemType: if (tok.val == RUN_TYPE) {
|
||||
r=DoRun(&p);
|
||||
break;
|
||||
@@ -1679,7 +1723,12 @@ static void GenerateCalEntries(int col)
|
||||
/* Note: Since the parser hasn't been used yet, we don't */
|
||||
/* need to destroy it here. */
|
||||
|
||||
default: CreateParser(CurLine, &p);
|
||||
default:
|
||||
if (!SuppressImplicitRemWarnings) {
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoCalRem(&p, col);
|
||||
break;
|
||||
}
|
||||
@@ -1766,7 +1815,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&raw_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
@@ -2138,7 +2187,9 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
#ifdef REM_USE_WCHAR
|
||||
make_wchar_versions(e);
|
||||
#endif
|
||||
DBufInit(&(e->tags));
|
||||
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
||||
if (SynthesizeTags) {
|
||||
@@ -2211,10 +2262,114 @@ static void WriteSimpleEntryProtocol1(CalEntry *e)
|
||||
printf("%s\n", e->text);
|
||||
}
|
||||
|
||||
void WriteJSONTimeTrigger(TimeTrig const *tt)
|
||||
{
|
||||
PrintJSONKeyPairTime("time", tt->ttime);
|
||||
PrintJSONKeyPairTime("nexttime", tt->nexttime);
|
||||
PrintJSONKeyPairInt("tdelta", tt->delta);
|
||||
PrintJSONKeyPairInt("trep", tt->rep);
|
||||
if (tt->duration != NO_TIME) {
|
||||
PrintJSONKeyPairInt("duration", tt->duration);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||
{
|
||||
/* wd is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (t->wd != NO_WD) {
|
||||
printf("\"wd\":[");
|
||||
int done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (t->wd & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("],");
|
||||
}
|
||||
if (t->d != NO_DAY) {
|
||||
PrintJSONKeyPairInt("d", t->d);
|
||||
}
|
||||
if (t->m != NO_MON) {
|
||||
PrintJSONKeyPairInt("m", t->m+1);
|
||||
}
|
||||
if (t->y != NO_YR) {
|
||||
PrintJSONKeyPairInt("y", t->y);
|
||||
}
|
||||
if (t->back) {
|
||||
PrintJSONKeyPairInt("back", t->back);
|
||||
}
|
||||
if (t->delta) {
|
||||
PrintJSONKeyPairInt("delta", t->delta);
|
||||
}
|
||||
if (t->rep) {
|
||||
PrintJSONKeyPairInt("rep", t->rep);
|
||||
}
|
||||
/* Local omit is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (t->localomit != NO_WD) {
|
||||
printf("\"localomit\":[");
|
||||
int done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (t->localomit & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("],");
|
||||
}
|
||||
switch(t->skip) {
|
||||
case SKIP_SKIP:
|
||||
PrintJSONKeyPairString("skip", "SKIP");
|
||||
break;
|
||||
case BEFORE_SKIP:
|
||||
PrintJSONKeyPairString("skip", "BEFORE");
|
||||
break;
|
||||
case AFTER_SKIP:
|
||||
PrintJSONKeyPairString("skip", "AFTER");
|
||||
break;
|
||||
}
|
||||
PrintJSONKeyPairDate("until", t->until);
|
||||
if (t->once != NO_ONCE) {
|
||||
PrintJSONKeyPairInt("once", t->once);
|
||||
}
|
||||
if (t->scanfrom != today) {
|
||||
PrintJSONKeyPairDate("scanfrom", t->scanfrom);
|
||||
}
|
||||
PrintJSONKeyPairDate("from", t->from);
|
||||
PrintJSONKeyPairInt("priority", t->priority);
|
||||
PrintJSONKeyPairDateTime("eventstart", t->eventstart);
|
||||
if (t->eventduration != NO_TIME) {
|
||||
PrintJSONKeyPairInt("eventduration", t->eventduration);
|
||||
}
|
||||
if (t->maybe_uncomputable) {
|
||||
PrintJSONKeyPairInt("maybe_uncomputable", 1);
|
||||
}
|
||||
if (t->noqueue) {
|
||||
PrintJSONKeyPairInt("noqueue", 1);
|
||||
}
|
||||
PrintJSONKeyPairString("sched", t->sched);
|
||||
PrintJSONKeyPairString("warn", t->warn);
|
||||
PrintJSONKeyPairString("omitfunc", t->omitfunc);
|
||||
if (t->addomit) {
|
||||
PrintJSONKeyPairInt("addomit", 1);
|
||||
}
|
||||
if (include_tags) {
|
||||
PrintJSONKeyPairString("tags", DBufValue(&(t->tags)));
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
{
|
||||
int done = 0;
|
||||
char const *s;
|
||||
if (DoPrefixLineNo) {
|
||||
PrintJSONKeyPairString("filename", e->filename);
|
||||
@@ -2234,88 +2389,13 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
PrintJSONKeyPairInt("trep", e->tt.rep);
|
||||
}
|
||||
}
|
||||
if (e->trig.eventduration != NO_TIME) {
|
||||
PrintJSONKeyPairInt("eventduration", e->trig.eventduration);
|
||||
}
|
||||
/* wd is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (e->trig.wd != NO_WD) {
|
||||
printf("\"wd\":[");
|
||||
done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (e->trig.wd & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("],");
|
||||
}
|
||||
if (e->trig.d != NO_DAY) {
|
||||
PrintJSONKeyPairInt("d", e->trig.d);
|
||||
}
|
||||
if (e->trig.m != NO_MON) {
|
||||
PrintJSONKeyPairInt("m", e->trig.m+1);
|
||||
}
|
||||
if (e->trig.y != NO_YR) {
|
||||
PrintJSONKeyPairInt("y", e->trig.y);
|
||||
}
|
||||
PrintJSONKeyPairDateTime("eventstart", e->trig.eventstart);
|
||||
if (e->trig.back) {
|
||||
PrintJSONKeyPairInt("back", e->trig.back);
|
||||
}
|
||||
if (e->trig.delta) {
|
||||
PrintJSONKeyPairInt("delta", e->trig.delta);
|
||||
}
|
||||
if (e->trig.rep) {
|
||||
PrintJSONKeyPairInt("rep", e->trig.rep);
|
||||
}
|
||||
WriteJSONTrigger(&e->trig, 0, today);
|
||||
if (e->nonconst_expr) {
|
||||
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
|
||||
}
|
||||
if (e->if_depth) {
|
||||
PrintJSONKeyPairInt("if_depth", e->if_depth);
|
||||
}
|
||||
switch(e->trig.skip) {
|
||||
case SKIP_SKIP:
|
||||
PrintJSONKeyPairString("skip", "SKIP");
|
||||
break;
|
||||
case BEFORE_SKIP:
|
||||
PrintJSONKeyPairString("skip", "BEFORE");
|
||||
break;
|
||||
case AFTER_SKIP:
|
||||
PrintJSONKeyPairString("skip", "AFTER");
|
||||
break;
|
||||
}
|
||||
/* Local omit is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (e->trig.localomit != NO_WD) {
|
||||
printf("\"localomit\":[");
|
||||
done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (e->trig.localomit & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("],");
|
||||
}
|
||||
PrintJSONKeyPairDate("until", e->trig.until);
|
||||
if (e->trig.once != NO_ONCE) {
|
||||
PrintJSONKeyPairInt("once", e->trig.once);
|
||||
}
|
||||
if (e->trig.scanfrom != today) {
|
||||
PrintJSONKeyPairDate("scanfrom", e->trig.scanfrom);
|
||||
}
|
||||
PrintJSONKeyPairDate("from", e->trig.from);
|
||||
PrintJSONKeyPairInt("priority", e->trig.priority);
|
||||
|
||||
if (e->is_color) {
|
||||
PrintJSONKeyPairInt("r", e->r);
|
||||
|
||||
@@ -24,27 +24,46 @@ if (!$ARGV[0]) {
|
||||
}
|
||||
|
||||
my $lang = $ARGV[0];
|
||||
if (!exists($language_map->{$lang})) {
|
||||
print STDERR "$lang is not a valid language.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my $flag = $language_map->{$lang};
|
||||
print STDERR "Testing for: $lang - $flag.\n";
|
||||
my_sys("make clean > /dev/null 2>&1") && die("make clean failed");
|
||||
my_sys("make -j6 all LANGDEF=-DLANG=$flag > /dev/null 2>&1") && die("make all failed");
|
||||
my_sys("./remind -q -r ../tests/tstlang.rem 2022-03-23 11:44 > test-$lang-compiled.out 2>&1");
|
||||
|
||||
my_sys("make clean > /dev/null 2>&1") && die("make clean failed");
|
||||
my_sys("make -j6 all > /dev/null 2>&1") && die("make all failed");
|
||||
my_sys("./remind -q -r -ii=\\\"../include/lang/$lang.rem\\\" ../tests/tstlang.rem 2022-03-23 11:44 > test-$lang-runtime.out 2>&1");
|
||||
|
||||
my $rc = my_sys("cmp test-$lang-compiled.out test-$lang-runtime.out > /dev/null 2>&1");
|
||||
if ($rc == 0) {
|
||||
print STDERR "Congrats! Compiled and runtime language output matches for $lang.\n";
|
||||
my $rc = 0;
|
||||
if ($lang eq 'all') {
|
||||
foreach my $l (sort(keys(%$language_map))) {
|
||||
if (check($l)) {
|
||||
$rc = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print STDERR "Whoops. Compiled and runtime language output differs for $lang.\n"
|
||||
$rc = check($lang);
|
||||
}
|
||||
|
||||
exit($rc);
|
||||
|
||||
sub check
|
||||
{
|
||||
my ($lang) = @_;
|
||||
if (!exists($language_map->{$lang})) {
|
||||
print STDERR "$lang is not a valid language.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $flag = $language_map->{$lang};
|
||||
print STDERR "Testing for: $lang - $flag.\n";
|
||||
my_sys("make clean > /dev/null 2>&1") && die("make clean failed");
|
||||
my_sys("make -j18 all LANGDEF=-DLANG=$flag > /dev/null 2>&1") && die("make all failed");
|
||||
my_sys("./remind -q -r ../tests/tstlang.rem 2022-03-23 11:44 > test-$lang-compiled.out 2>&1");
|
||||
|
||||
my_sys("make clean > /dev/null 2>&1") && die("make clean failed");
|
||||
my_sys("make -j18 all > /dev/null 2>&1") && die("make all failed");
|
||||
my_sys("./remind -q -r -ii=\\\"../include/lang/$lang.rem\\\" ../tests/tstlang.rem 2022-03-23 11:44 > test-$lang-runtime.out 2>&1");
|
||||
|
||||
my $rc = my_sys("cmp test-$lang-compiled.out test-$lang-runtime.out > /dev/null 2>&1");
|
||||
if ($rc == 0) {
|
||||
print STDERR "Congrats! Compiled and runtime language output matches for $lang.\n";
|
||||
} else {
|
||||
print STDERR "Whoops. Compiled and runtime language output differs for $lang.\n"
|
||||
}
|
||||
return $rc;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
sub my_sys
|
||||
|
||||
127
src/config.h.in
127
src/config.h.in
@@ -1,40 +1,119 @@
|
||||
/* Define if utime(file, NULL) sets file's timestamp to the present. */
|
||||
#undef HAVE_UTIME_NULL
|
||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Define if your <sys/time.h> declares struct tm. */
|
||||
#undef TM_IN_SYS_TIME
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
#undef HAVE_LANGINFO_H
|
||||
/* Configuration command used to build Remind */
|
||||
#undef CONFIG_CMD
|
||||
|
||||
/* Define to 1 if you have the `glob' function. */
|
||||
#undef HAVE_GLOB
|
||||
|
||||
#undef HAVE_SETENV
|
||||
/* Define to 1 if you have the <glob.h> header file. */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
/* Define to 1 if you have the `initgroups' function. */
|
||||
#undef HAVE_INITGROUPS
|
||||
|
||||
#undef HAVE_UNSETENV
|
||||
/* Define to 1 if you have the `inotify_init1' function. */
|
||||
#undef HAVE_INOTIFY_INIT1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <langinfo.h> header file. */
|
||||
#undef HAVE_LANGINFO_H
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `mbstowcs' function. */
|
||||
#undef HAVE_MBSTOWCS
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* The number of bytes in a unsigned int. */
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#undef HAVE_STRDUP
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#undef HAVE_STRNCASECMP
|
||||
|
||||
/* Define to 1 if you have the <sys/inotify.h> header file. */
|
||||
#undef HAVE_SYS_INOTIFY_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `unsetenv' function. */
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* The size of `time_t', as computed by sizeof. */
|
||||
#undef SIZEOF_TIME_T
|
||||
|
||||
/* The size of `unsigned int', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_INT
|
||||
|
||||
/* The number of bytes in a unsigned long. */
|
||||
/* The size of `unsigned long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG
|
||||
|
||||
#include "custom.h"
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
#undef TM_IN_SYS_TIME
|
||||
|
||||
#include <custom.h>
|
||||
|
||||
24
src/custom.h
24
src/custom.h
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -20,7 +20,7 @@
|
||||
/* western hemisphere. */
|
||||
/* */
|
||||
/* The default values are initially set to the city hall in Ottawa, */
|
||||
/* Ontario, Canada. */
|
||||
/* Ontario, Canada. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DEFAULT_LATITUDE 45.420556
|
||||
#define DEFAULT_LONGITUDE -75.689722
|
||||
@@ -68,12 +68,6 @@
|
||||
/**********************************************************************/
|
||||
/**********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* WANT_SHELL_ESCAPING: Define this if you want special shell */
|
||||
/* characters to be escaped with a backslash for the -k option. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define WANT_SHELL_ESCAPING 1
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
||||
/* base year MUST be a Monday, else Remind will not work! */
|
||||
@@ -109,16 +103,6 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define OP_STACK_SIZE 100
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define VAL_STACK_SIZE 1000
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -166,6 +150,10 @@
|
||||
|
||||
#define PASSTHRU_LEN 32
|
||||
|
||||
#define MAX_RECURSION_LEVEL 1000
|
||||
|
||||
#define MAX_FUNC_ARGS 64
|
||||
|
||||
#define PSBEGIN "# rem2ps begin"
|
||||
#define PSEND "# rem2ps end"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -20,7 +20,7 @@
|
||||
/* western hemisphere. */
|
||||
/* */
|
||||
/* The default values are initially set to the city hall in Ottawa, */
|
||||
/* Ontario, Canada. */
|
||||
/* Ontario, Canada. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DEFAULT_LATITUDE 45.420556
|
||||
#define DEFAULT_LONGITUDE -75.689722
|
||||
@@ -68,12 +68,6 @@
|
||||
/**********************************************************************/
|
||||
/**********************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* WANT_SHELL_ESCAPING: Define this if you want special shell */
|
||||
/* characters to be escaped with a backslash for the -k option. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define WANT_SHELL_ESCAPING 1
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* BASE: The base year for date calculation. NOTE! January 1 of the */
|
||||
/* base year MUST be a Monday, else Remind will not work! */
|
||||
@@ -109,16 +103,6 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define OP_STACK_SIZE 100
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define VAL_STACK_SIZE 1000
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -166,6 +150,10 @@
|
||||
|
||||
#define PASSTHRU_LEN 32
|
||||
|
||||
#define MAX_RECURSION_LEVEL 1000
|
||||
|
||||
#define MAX_FUNC_ARGS 64
|
||||
|
||||
#define PSBEGIN "# rem2ps begin"
|
||||
#define PSEND "# rem2ps end"
|
||||
|
||||
|
||||
367
src/dorem.c
367
src/dorem.c
@@ -7,7 +7,7 @@
|
||||
/* commands. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -23,9 +23,8 @@
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim);
|
||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||
@@ -33,6 +32,152 @@ static int ParseUntil (ParsePtr s, Trigger *t, int type);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
|
||||
static int ComputeTrigDuration(TimeTrig *t);
|
||||
|
||||
static int
|
||||
ensure_expr_references_first_local_arg(expr_node *node)
|
||||
{
|
||||
expr_node *other;
|
||||
|
||||
if (!node) {
|
||||
return 0;
|
||||
}
|
||||
if (node->type == N_LOCAL_VAR && node->u.arg == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (ensure_expr_references_first_local_arg(node->child)) {
|
||||
return 1;
|
||||
}
|
||||
other = node->sibling;
|
||||
while (other) {
|
||||
if (ensure_expr_references_first_local_arg(other)) {
|
||||
return 1;
|
||||
}
|
||||
other = other->sibling;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
check_trigger_function(char const *fname, char const *type)
|
||||
{
|
||||
UserFunc *f;
|
||||
if (!*fname) {
|
||||
return;
|
||||
}
|
||||
f = FindUserFunc(fname);
|
||||
if (!f) {
|
||||
if (strcmp(type, "WARN")) {
|
||||
/* Undefined WARN functions are diagnosed elsewhere... */
|
||||
Wprint("Undefined %s function: `%s'", type, fname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (f->nargs != 1) {
|
||||
Wprint("%s function `%s' defined at %s:%d should take 1 argument but actually takes %d", type, fname, f->filename, f->lineno, f->nargs);
|
||||
return;
|
||||
}
|
||||
if (ensure_expr_references_first_local_arg(f->node)) {
|
||||
return;
|
||||
}
|
||||
Wprint("%s function `%s' defined at %s:%d does not use its argument", type, fname, f->filename, f->lineno);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_satnode_mentions_trigdate_aux(expr_node *node, int *mentioned)
|
||||
{
|
||||
char const *name;
|
||||
expr_node *other;
|
||||
UserFunc *f;
|
||||
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
if (*mentioned) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->type == N_BUILTIN_FUNC) {
|
||||
name = node->u.builtin_func->name;
|
||||
if (!strcmp(name, "trigdate") ||
|
||||
!strcmp(name, "trigdatetime")) {
|
||||
*mentioned = 1;
|
||||
return;
|
||||
}
|
||||
} else if (node->type == N_SHORT_SYSVAR || node->type == N_SYSVAR) {
|
||||
if (node->type == N_SHORT_SYSVAR) {
|
||||
name = node->u.name;
|
||||
} else {
|
||||
name = node->u.value.v.str;
|
||||
}
|
||||
if (!StrCmpi(name, "T") ||
|
||||
!StrCmpi(name, "Td") ||
|
||||
!StrCmpi(name, "Tm") ||
|
||||
!StrCmpi(name, "Tw") ||
|
||||
!StrCmpi(name, "Ty")) {
|
||||
*mentioned = 1;
|
||||
return;
|
||||
}
|
||||
} else if (node->type == N_SHORT_USER_FUNC || node->type == N_USER_FUNC) {
|
||||
if (node->type == N_SHORT_USER_FUNC) {
|
||||
name = node->u.name;
|
||||
} else {
|
||||
name = node->u.value.v.str;
|
||||
}
|
||||
f = FindUserFunc(name);
|
||||
if (f && !f->recurse_flag) {
|
||||
f->recurse_flag = 1;
|
||||
ensure_satnode_mentions_trigdate_aux(f->node, mentioned);
|
||||
f->recurse_flag = 0;
|
||||
if (*mentioned) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ensure_satnode_mentions_trigdate_aux(node->child, mentioned);
|
||||
if (*mentioned) {
|
||||
return;
|
||||
}
|
||||
other = node->sibling;
|
||||
while (other) {
|
||||
ensure_satnode_mentions_trigdate_aux(other, mentioned);
|
||||
if (*mentioned) {
|
||||
return;
|
||||
}
|
||||
other = other->sibling;
|
||||
}
|
||||
}
|
||||
|
||||
static void ensure_satnode_mentions_trigdate(expr_node *node)
|
||||
{
|
||||
int mentioned = 0;
|
||||
char const *str;
|
||||
if (node->type == N_CONSTANT || node->type == N_SHORT_STR) {
|
||||
if (node->type == N_CONSTANT) {
|
||||
if (node->u.value.type == INT_TYPE) {
|
||||
if (node->u.value.v.val == 0) {
|
||||
Wprint("SATISFY: constant 0 will never be true");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (node->u.value.type != STR_TYPE) {
|
||||
return;
|
||||
}
|
||||
str = node->u.value.v.str;
|
||||
} else {
|
||||
str = node->u.name;
|
||||
}
|
||||
if (!*str) {
|
||||
Wprint("SATISFY: constant \"\" will never be true");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ensure_satnode_mentions_trigdate_aux(node, &mentioned);
|
||||
if (!mentioned) {
|
||||
Wprint("SATISFY: expression has no reference to trigdate() or $T...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ComputeTrigDuration(TimeTrig *t)
|
||||
{
|
||||
@@ -63,7 +208,7 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) != OK ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
@@ -163,6 +308,7 @@ int DoRem(ParsePtr p)
|
||||
if (p->expr_happened) {
|
||||
if (p->nonconst_expr) {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
||||
PurgeEchoLine("%s\n", "#!P: or a relative SCANFROM clause");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line has expired, but contains expression... please verify");
|
||||
@@ -182,7 +328,7 @@ int DoRem(ParsePtr p)
|
||||
if (dse == DSEToday &&
|
||||
!(!IgnoreOnce &&
|
||||
trig.once != NO_ONCE &&
|
||||
FileAccessDate == DSEToday))
|
||||
GetOnceDate() == DSEToday))
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) {
|
||||
@@ -192,16 +338,18 @@ int DoRem(ParsePtr p)
|
||||
|
||||
r = OK;
|
||||
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0)) ) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0, NULL)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
/* Parse the rest of the line to catch any potential
|
||||
expression-pasting errors */
|
||||
while (ParseChar(p, &r, 0)) {
|
||||
if (r != 0) {
|
||||
break;
|
||||
if (ParseUntriggered) {
|
||||
while (ParseChar(p, &r, 0)) {
|
||||
if (r != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,7 +366,7 @@ int DoRem(ParsePtr p)
|
||||
/* trigger structure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
{
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
@@ -260,10 +408,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->need_wkday = 0;
|
||||
trig->adj_for_last = 0;
|
||||
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = NO_TIME;
|
||||
}
|
||||
|
||||
int parsing = 1;
|
||||
while(parsing) {
|
||||
/* Read space-delimited string */
|
||||
@@ -293,10 +437,17 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
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;
|
||||
DBufFree(&buf);
|
||||
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;
|
||||
}
|
||||
|
||||
FromDSE(tok.val, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
@@ -313,10 +464,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->m = m;
|
||||
trig->d = d;
|
||||
tim->ttime = (tok.val % MINUTES_PER_DAY);
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_WkDay:
|
||||
@@ -348,9 +495,19 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
/* A time implicitly introduces an AT if AT is not explicit */
|
||||
case T_Time:
|
||||
DBufFree(&buf);
|
||||
if (tim->ttime != NO_TIME) return E_TIME_TWICE;
|
||||
tim->ttime = tok.val;
|
||||
r = ParseTimeTrig(s, tim);
|
||||
if (r) return r;
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
|
||||
case T_At:
|
||||
DBufFree(&buf);
|
||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||
r=ParseTimeTrig(s, tim);
|
||||
if (r) return r;
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
@@ -392,6 +549,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_Number:
|
||||
DBufFree(&buf);
|
||||
Eprint("`%d' is not recognized as a year (%d-%d) or a day number (1-31)",
|
||||
tok.val, BASE, BASE+YR_RANGE);
|
||||
return E_PARSE_ERR;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
@@ -469,10 +632,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
r=ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
|
||||
|
||||
strtolower(trig->omitfunc);
|
||||
/* An OMITFUNC counts as a nonconst_expr! */
|
||||
s->expr_happened = 1;
|
||||
s->nonconst_expr = 1;
|
||||
s->expr_happened = 1;
|
||||
s->nonconst_expr = 1;
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
@@ -480,6 +643,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
r=ParseToken(s, &buf);
|
||||
if(r) return r;
|
||||
StrnCpy(trig->warn, DBufValue(&buf), VAR_NAME_LEN);
|
||||
strtolower(trig->warn);
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
@@ -510,9 +674,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
} else {
|
||||
tim->duration = NO_TIME;
|
||||
}
|
||||
if (save_in_globals) {
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
default:
|
||||
@@ -524,6 +685,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
r=ParseToken(s, &buf);
|
||||
if(r) return r;
|
||||
StrnCpy(trig->sched, DBufValue(&buf), VAR_NAME_LEN);
|
||||
strtolower(trig->sched);
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
@@ -533,10 +695,19 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
trig->typ = MSG_TYPE;
|
||||
if (s->isnested) return E_CANT_NEST_RTYPE;
|
||||
if (!WarnedAboutImplicit && !SuppressImplicitRemWarnings) {
|
||||
Wprint("Missing REM type; assuming MSG");
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
parsing = 0;
|
||||
break;
|
||||
}
|
||||
@@ -588,6 +759,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->scanfrom = DSEToday;
|
||||
}
|
||||
|
||||
/* Check that any SCHED / WARN / OMITFUNC functions refer to
|
||||
their arguments */
|
||||
check_trigger_function(trig->sched, "SCHED");
|
||||
check_trigger_function(trig->warn, "WARN");
|
||||
check_trigger_function(trig->omitfunc, "OMITFUNC");
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -596,7 +772,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
/* ParseTimeTrig - parse the AT part of a timed reminder */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
{
|
||||
Token tok;
|
||||
int r;
|
||||
@@ -629,13 +805,13 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
|
||||
|
||||
/* Save trigger time in global variable */
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -667,6 +843,9 @@ static int ParseLocalOmit(ParsePtr s, Trigger *t)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (t->localomit == NO_WD) {
|
||||
return E_EXPECTING_WEEKDAY;
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -748,6 +927,11 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", which, ErrMsg[E_INCOMPLETE]);
|
||||
DBufFree(&buf);
|
||||
@@ -861,9 +1045,17 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
tok.val = -tok.val;
|
||||
}
|
||||
FromDSE(DSEToday - tok.val, &y, &m, &d);
|
||||
/* Don't purge reminders with a relative scanfrom */
|
||||
s->expr_happened = 1;
|
||||
s->nonconst_expr = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
Eprint("%s: `%s'", ErrMsg[-tok.val], DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return -tok.val;
|
||||
}
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
|
||||
DBufFree(&buf);
|
||||
@@ -898,7 +1090,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 dse, int is_queued)
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output)
|
||||
{
|
||||
int r, y, m, d;
|
||||
char PrioExpr[VAR_NAME_LEN+25];
|
||||
@@ -965,7 +1157,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
}
|
||||
/* 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)
|
||||
&& !DidMsgReminder && !NextMode && !msg_command) {
|
||||
&& !DidMsgReminder && !NextMode && !msg_command && !is_queued) {
|
||||
DidMsgReminder = 1;
|
||||
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
||||
DSEToday, NO_TIME) &&
|
||||
@@ -1032,11 +1224,18 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
printf("%s%s%s\n", DBufValue(&calRow), DBufValue(&pre_buf), DBufValue(&buf));
|
||||
r = OK;
|
||||
if (output) {
|
||||
if (DBufPuts(output, DBufValue(&calRow)) != OK) r = E_NO_MEM;
|
||||
if (DBufPuts(output, DBufValue(&pre_buf)) != OK) r = E_NO_MEM;
|
||||
if (DBufPuts(output, DBufValue(&buf)) != OK) r = E_NO_MEM;
|
||||
} else {
|
||||
printf("%s%s%s\n", DBufValue(&calRow), DBufValue(&pre_buf), DBufValue(&buf));
|
||||
}
|
||||
DBufFree(&buf);
|
||||
DBufFree(&pre_buf);
|
||||
DBufFree(&calRow);
|
||||
return OK;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Correct colors */
|
||||
@@ -1132,18 +1331,27 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
||||
case MSG_TYPE:
|
||||
case PASSTHRU_TYPE:
|
||||
if (msg_command) {
|
||||
DoMsgCommand(msg_command, DBufValue(&buf));
|
||||
DoMsgCommand(msg_command, DBufValue(&buf), is_queued);
|
||||
} else {
|
||||
printf("%s", DBufValue(&buf));
|
||||
if (output) {
|
||||
DBufPuts(output, DBufValue(&buf));
|
||||
} else {
|
||||
/* Add a space before "NOTE endreminder" */
|
||||
if (IsServerMode() && !strncmp(DBufValue(&buf), "NOTE endreminder", 16)) {
|
||||
printf(" %s", DBufValue(&buf));
|
||||
} else {
|
||||
printf("%s", DBufValue(&buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSF_TYPE:
|
||||
FillParagraph(DBufValue(&buf));
|
||||
FillParagraph(DBufValue(&buf), output);
|
||||
break;
|
||||
|
||||
case RUN_TYPE:
|
||||
System(DBufValue(&buf));
|
||||
System(DBufValue(&buf), is_queued);
|
||||
break;
|
||||
|
||||
default: /* Unknown/illegal type? */
|
||||
@@ -1171,7 +1379,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
*err = 0;
|
||||
|
||||
/* Handle the ONCE modifier in the reminder. */
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == DSEToday)
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && GetOnceDate() == DSEToday)
|
||||
return 0;
|
||||
|
||||
if (dse < DSEToday) return 0;
|
||||
@@ -1182,7 +1390,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
if (DontIssueAts > 1) {
|
||||
/* If two or more -a options, then *DO* issue ats that are in the
|
||||
future */
|
||||
if (tim->ttime < SystemTime(0) / 60) {
|
||||
if (tim->ttime < MinutesPastMidnight(0)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -1190,29 +1398,31 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't trigger "old" timed reminders */
|
||||
/*** REMOVED...
|
||||
if (dse == DSEToday &&
|
||||
tim->ttime != NO_TIME &&
|
||||
tim->ttime < SystemTime(0) / 60) return 0;
|
||||
*** ...UNTIL HERE */
|
||||
|
||||
/* If "infinite delta" option is chosen, always trigger future reminders */
|
||||
if (InfiniteDelta || NextMode) return 1;
|
||||
|
||||
/* If there's a "warn" function, it overrides any deltas */
|
||||
/* If there's a "warn" function, it overrides any deltas except
|
||||
* DeltaOverride*/
|
||||
if (t->warn[0] != 0) {
|
||||
if (DeltaOffset) {
|
||||
if (dse <= DSEToday + DeltaOffset) {
|
||||
if (DeltaOverride > 0) {
|
||||
if (dse <= DSEToday + DeltaOverride) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return ShouldTriggerBasedOnWarn(t, dse, err);
|
||||
}
|
||||
|
||||
/* Zero delta */
|
||||
if (DeltaOverride < 0) {
|
||||
return dse == DSEToday;
|
||||
}
|
||||
|
||||
/* Move back by delta days, if any */
|
||||
if (t->delta != NO_DELTA) {
|
||||
if (t->delta < 0)
|
||||
if (DeltaOverride) {
|
||||
/* A positive DeltaOverride takes precedence over everything */
|
||||
dse = dse - DeltaOverride;
|
||||
} else if (t->delta != NO_DELTA) {
|
||||
if (t->delta < 0)
|
||||
dse = dse + t->delta;
|
||||
else {
|
||||
int iter = 0;
|
||||
@@ -1237,7 +1447,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||
}
|
||||
|
||||
/* Should we trigger the reminder? */
|
||||
return (dse <= DSEToday + DeltaOffset);
|
||||
return (dse <= DSEToday);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1251,20 +1461,32 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
{
|
||||
int iter, dse, r, start;
|
||||
Value v;
|
||||
char const *s;
|
||||
char const *t;
|
||||
expr_node *sat_node;
|
||||
int nonconst = 0;
|
||||
|
||||
sat_node = ParseExpr(p, &r);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
if (!sat_node) {
|
||||
return E_SWERR;
|
||||
}
|
||||
|
||||
/* Diagnose if SAT_NODE does not reference trigdate */
|
||||
ensure_satnode_mentions_trigdate(sat_node);
|
||||
|
||||
t = p->pos;
|
||||
iter = 0;
|
||||
start = trig->scanfrom;
|
||||
while (iter++ < MaxSatIter) {
|
||||
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
|
||||
if (r) {
|
||||
free_expr_tree(sat_node);
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
if (dse != start && trig->duration_days) {
|
||||
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
|
||||
if (r) {
|
||||
free_expr_tree(sat_node);
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
} else if (dse == start) {
|
||||
@@ -1277,13 +1499,18 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
SaveAllTriggerInfo(trig, tt, dse, tt->ttime, 1);
|
||||
}
|
||||
if (dse == -1) {
|
||||
free_expr_tree(sat_node);
|
||||
return E_EXPIRED;
|
||||
}
|
||||
s = p->pos;
|
||||
r = EvaluateExpr(p, &v);
|
||||
t = p->pos;
|
||||
if (r) return r;
|
||||
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
|
||||
r = evaluate_expression(sat_node, NULL, &v, &nonconst);
|
||||
if (r) {
|
||||
free_expr_tree(sat_node);
|
||||
return r;
|
||||
}
|
||||
if (v.type != INT_TYPE && v.type != STR_TYPE) {
|
||||
free_expr_tree(sat_node);
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
if ((v.type == INT_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && *v.v.str)) {
|
||||
AdjustTriggerForDuration(trig->scanfrom, dse, trig, tt, 1);
|
||||
@@ -1308,17 +1535,17 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
free_expr_tree(sat_node);
|
||||
return OK;
|
||||
}
|
||||
p->pos = s;
|
||||
if (dse+trig->duration_days < start) {
|
||||
start++;
|
||||
} else {
|
||||
start = dse+trig->duration_days+1;
|
||||
}
|
||||
}
|
||||
p->pos = t;
|
||||
LastTrigValid = 0;
|
||||
free_expr_tree(sat_node);
|
||||
return E_CANT_TRIG;
|
||||
}
|
||||
|
||||
@@ -1368,7 +1595,7 @@ static int ParsePriority(ParsePtr s, Trigger *t)
|
||||
/* Execute the '-k' command, escaping shell chars in message. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoMsgCommand(char const *cmd, char const *msg)
|
||||
int DoMsgCommand(char const *cmd, char const *msg, int is_queued)
|
||||
{
|
||||
int r;
|
||||
int i, l;
|
||||
@@ -1405,7 +1632,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
||||
}
|
||||
r = OK;
|
||||
|
||||
System(DBufValue(&execBuffer));
|
||||
System(DBufValue(&execBuffer), is_queued);
|
||||
|
||||
finished:
|
||||
DBufFree(&buf);
|
||||
|
||||
@@ -6,21 +6,19 @@
|
||||
/* reminders are triggered. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "expr.h"
|
||||
#define L_IN_DOSUBST
|
||||
#include "types.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "protos.h"
|
||||
@@ -33,6 +31,19 @@
|
||||
|
||||
#define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
|
||||
|
||||
static int
|
||||
check_subst_args(UserFunc *f, int n)
|
||||
{
|
||||
if (!f) {
|
||||
return 0;
|
||||
}
|
||||
if (f->nargs == n) {
|
||||
return 1;
|
||||
}
|
||||
Wprint("Function `%s' defined at %s:%d should take %d argument%s, but actually takes %d",
|
||||
f->name, f->filename, f->lineno, n, (n == 1 ? "" : "s"), f->nargs);
|
||||
return 0;
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoSubst */
|
||||
@@ -46,11 +57,11 @@
|
||||
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
|
||||
{
|
||||
int diff = dse - DSEToday;
|
||||
int curtime = SystemTime(0) / 60;
|
||||
int curtime = MinutesPastMidnight(0);
|
||||
int err, done;
|
||||
int c;
|
||||
int d, m, y;
|
||||
int tim = tt->ttime;
|
||||
int tim = NO_TIME;
|
||||
int h, min, hh, ch, cmin, chh;
|
||||
int i;
|
||||
char const *pm, *cpm;
|
||||
@@ -69,9 +80,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
int altmode;
|
||||
int r;
|
||||
Value v;
|
||||
UserFunc *func;
|
||||
|
||||
FromDSE(dse, &y, &m, &d);
|
||||
|
||||
if (tt) {
|
||||
tim = tt->ttime;
|
||||
}
|
||||
if (tim == NO_TIME) tim = curtime;
|
||||
tdiff = tim - curtime;
|
||||
adiff = ABS(tdiff);
|
||||
@@ -99,7 +114,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
L_AMPM_OVERRIDE (pm, h)
|
||||
#else
|
||||
r = -1;
|
||||
if (UserFuncExists("subst_ampm") == 1) {
|
||||
func = FindUserFunc("subst_ampm");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ampm(%d)", h);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -128,7 +144,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
L_AMPM_OVERRIDE (cpm, ch)
|
||||
#else
|
||||
r = -1;
|
||||
if (UserFuncExists("subst_ampm") == 1) {
|
||||
func = FindUserFunc("subst_ampm");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ampm(%d)", ch);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -139,6 +156,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
} else {
|
||||
r = -1;
|
||||
}
|
||||
DestroyValue(v);
|
||||
} else {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
@@ -152,7 +170,8 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
#ifdef L_ORDINAL_OVERRIDE
|
||||
L_ORDINAL_OVERRIDE;
|
||||
#else
|
||||
if (UserFuncExists("subst_ordinal") == 1) {
|
||||
func = FindUserFunc("subst_ordinal");
|
||||
if (func && check_subst_args(func, 1)) {
|
||||
snprintf(s, sizeof(s), "subst_ordinal(%d)", d);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
@@ -163,6 +182,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
} else {
|
||||
r = -1;
|
||||
}
|
||||
DestroyValue(v);
|
||||
} else {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
@@ -239,7 +259,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
break;
|
||||
}
|
||||
if (i < 64) {
|
||||
*ss++ = c;
|
||||
*ss++ = tolower(c);
|
||||
*ss = 0;
|
||||
i++;
|
||||
}
|
||||
@@ -247,7 +267,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
if (!c) {
|
||||
Wprint("Warning: Unterminated %%{...} substitution sequence");
|
||||
}
|
||||
if (UserFuncExists(s) != 3) {
|
||||
func = FindUserFunc(s);
|
||||
if (!func) {
|
||||
Wprint("No substition function `%s' defined", s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!check_subst_args(func, 3)) {
|
||||
continue;
|
||||
}
|
||||
snprintf(ss, sizeof(s) - (ss-s), "(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
@@ -266,10 +292,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
continue;
|
||||
}
|
||||
done = 0;
|
||||
snprintf(uf, sizeof(uf), "subst_%c", c);
|
||||
if (UserFuncExists(uf) == 3) {
|
||||
snprintf(uf, sizeof(uf), "subst_%c", tolower(c));
|
||||
func = FindUserFunc(uf);
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%c(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
c, altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
if (r == OK) {
|
||||
@@ -341,10 +368,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
|
||||
|
||||
if (!done) {
|
||||
snprintf(uf, sizeof(uf), "subst_%cx", c);
|
||||
if (UserFuncExists(uf) == 3) {
|
||||
snprintf(uf, sizeof(uf), "subst_%cx", tolower(c));
|
||||
func = FindUserFunc(uf);
|
||||
if (func && check_subst_args(func, 3)) {
|
||||
snprintf(s, sizeof(s), "subst_%cx(%d,'%04d-%02d-%02d',%02d:%02d)",
|
||||
c, altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
tolower(c), altmode ? 1 : 0, y, m+1, d, h, min);
|
||||
expr = (char const *) s;
|
||||
r = EvalExpr(&expr, &v, NULL);
|
||||
if (r == OK) {
|
||||
@@ -794,7 +822,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
||||
break;
|
||||
|
||||
case '_':
|
||||
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
||||
if (PsCal == PSCAL_LEVEL2 || PsCal == PSCAL_LEVEL3 || DoCalendar || (mode != CAL_MODE && mode != ADVANCE_MODE && !(MsgCommand && *MsgCommand))) {
|
||||
snprintf(s, sizeof(s), "%s", NL);
|
||||
} else {
|
||||
snprintf(s, sizeof(s), " ");
|
||||
@@ -894,7 +922,7 @@ int DoSubstFromString(char const *source, DynamicBuffer *dbuf,
|
||||
int r;
|
||||
|
||||
if (dse == NO_DATE) dse=DSEToday;
|
||||
if (tim == NO_TIME) tim=SystemTime(0)/60;
|
||||
if (tim == NO_TIME) tim=MinutesPastMidnight(0);
|
||||
CreateParser(source, &tempP);
|
||||
tempP.allownested = 0;
|
||||
tempTrig.typ = MSG_TYPE;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* buffers. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -124,7 +124,9 @@ int DBufPuts(DynamicBuffer *dbuf, char const *str)
|
||||
**********************************************************************/
|
||||
void DBufFree(DynamicBuffer *dbuf)
|
||||
{
|
||||
if (dbuf->buffer != dbuf->staticBuf) free(dbuf->buffer);
|
||||
if (dbuf->buffer != NULL && dbuf->buffer != dbuf->staticBuf) {
|
||||
free(dbuf->buffer);
|
||||
}
|
||||
DBufInit(dbuf);
|
||||
}
|
||||
|
||||
@@ -150,7 +152,6 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
|
||||
/* Try reading the first few bytes right into the buffer --
|
||||
we can usually save some unnecessary copying */
|
||||
|
||||
*(dbuf->buffer) = 0;
|
||||
if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Declaration of functions for manipulating dynamic buffers */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <stdio.h> /* For FILE */
|
||||
|
||||
#define DBUF_STATIC_SIZE 128
|
||||
#define DBUF_STATIC_SIZE 32
|
||||
typedef struct {
|
||||
char *buffer;
|
||||
size_t len;
|
||||
|
||||
223
src/err.h
223
src/err.h
@@ -5,7 +5,7 @@
|
||||
/* Error definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -121,6 +121,11 @@
|
||||
#define E_STRING_TOO_LONG 101
|
||||
#define E_TIME_TWICE 102
|
||||
#define E_DURATION_NO_AT 103
|
||||
#define E_EXPECTING_WEEKDAY 104
|
||||
#define E_REPEATED_ARG 105
|
||||
#define E_EXPR_DISABLED 106
|
||||
#define E_TIME_EXCEEDED 107
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
@@ -129,115 +134,123 @@
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define STR(X) STR2(X)
|
||||
#define STR2(X) #X
|
||||
|
||||
|
||||
#ifndef L_ERR_OVERRIDE
|
||||
EXTERN char *ErrMsg[]
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
= {
|
||||
"Ok",
|
||||
"Missing ']'",
|
||||
"Missing quote",
|
||||
"Expression too complex - too many operators",
|
||||
"Expression too complex - too many operands",
|
||||
"Missing ')'",
|
||||
"Undefined function",
|
||||
"Illegal character",
|
||||
"Expecting binary operator",
|
||||
"Out of memory",
|
||||
"Ill-formed number",
|
||||
"Op stack underflow - internal error",
|
||||
"Va stack underflow - internal error",
|
||||
"Can't coerce",
|
||||
"Type mismatch",
|
||||
"Date overflow",
|
||||
"Stack error - internal error",
|
||||
"Division by zero",
|
||||
"Undefined variable",
|
||||
"Unexpected end of line",
|
||||
"Unexpected end of file",
|
||||
"I/O error",
|
||||
"Line too long",
|
||||
"Internal error",
|
||||
"Bad date specification",
|
||||
"Not enough arguments",
|
||||
"Too many arguments",
|
||||
"Ill-formed time",
|
||||
"Number too high",
|
||||
"Number too low",
|
||||
"Can't open file",
|
||||
"INCLUDE nested too deeply",
|
||||
"Parse error",
|
||||
"Can't compute trigger",
|
||||
"Too many nested IFs",
|
||||
"ELSE with no matching IF",
|
||||
"ENDIF with no matching IF",
|
||||
"Can't OMIT every weekday",
|
||||
"Extraneous token(s) on line",
|
||||
"POP-OMIT-CONTEXT without matching PUSH-OMIT-CONTEXT",
|
||||
"RUN disabled",
|
||||
"Domain error",
|
||||
"Invalid identifier",
|
||||
"Recursive function call detected",
|
||||
"",
|
||||
"Cannot modify system variable",
|
||||
"C library function can't represent date/time",
|
||||
"Attempt to redefine built-in function",
|
||||
"Can't nest function definition in expression",
|
||||
"Must fully specify date to use repeat factor",
|
||||
"Year specified twice",
|
||||
"Month specified twice",
|
||||
"Day specified twice",
|
||||
"Unknown token",
|
||||
"Must specify month in OMIT command",
|
||||
"Too many partial OMITs",
|
||||
"Too many full OMITs",
|
||||
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||
"Error reading",
|
||||
"Expecting end-of-line",
|
||||
"Invalid Hebrew date",
|
||||
"IIF needs odd number of arguments",
|
||||
"Warning: Missing ENDIF",
|
||||
"Expecting comma",
|
||||
"Weekday specified twice",
|
||||
"Only use one of BEFORE, AFTER or SKIP",
|
||||
"Can't nest MSG, MSF, RUN, etc. in expression",
|
||||
"Repeat value specified twice",
|
||||
"Delta value specified twice",
|
||||
"Back value specified twice",
|
||||
"ONCE keyword used twice. (Hah.)",
|
||||
"Expecting time after AT",
|
||||
"THROUGH/UNTIL keyword used twice",
|
||||
"Incomplete date specification",
|
||||
"FROM/SCANFROM keyword used twice",
|
||||
"Variable",
|
||||
"Value",
|
||||
"*UNDEFINED*",
|
||||
"Entering UserFN",
|
||||
"Leaving UserFN",
|
||||
"Expired",
|
||||
"fork() failed - can't do queued reminders",
|
||||
"Can't access file",
|
||||
"Illegal system date: Year is less than %d\n",
|
||||
"Unknown debug flag '%c'\n",
|
||||
"Unknown option '%c'\n",
|
||||
"Unknown user '%s'\n",
|
||||
"Could not change gid to %d\n",
|
||||
"Could not change uid to %d\n",
|
||||
"Out of memory for environment\n",
|
||||
"Missing '=' sign",
|
||||
"Missing variable name",
|
||||
"Missing expression",
|
||||
"Can't reset access date of %s\n",
|
||||
"Remind: '-i' option: %s\n",
|
||||
"No reminders.",
|
||||
"%d reminder(s) queued for later today.\n",
|
||||
"Expecting number",
|
||||
"Bad function in WARN clause",
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
/* OK */ "Ok",
|
||||
/* E_MISS_END */ "Missing ']'",
|
||||
/* E_MISS_QUOTE */ "Missing quote",
|
||||
/* E_OP_STK_OVER */ "Expression too complex",
|
||||
/* E_VA_STK_OVER */ "Expression too complex - too many operands",
|
||||
/* E_MISS_RIGHT_PAREN */ "Missing ')'",
|
||||
/* E_UNDEF_FUNC */ "Undefined function",
|
||||
/* E_ILLEGAL_CHAR */ "Illegal character",
|
||||
/* E_EXPECTING_BINOP */ "Expecting binary operator",
|
||||
/* E_NO_MEM */ "Out of memory",
|
||||
/* E_BAD_NUMBER */ "Ill-formed number",
|
||||
/* E_OP_STK_UNDER */ "Op stack underflow - internal error",
|
||||
/* E_VA_STK_UNDER */ "Va stack underflow - internal error",
|
||||
/* E_CANT_COERCE */ "Can't coerce",
|
||||
/* E_BAD_TYPE */ "Type mismatch",
|
||||
/* E_DATE_OVER */ "Date overflow",
|
||||
/* E_STACK_ERR */ "Stack error - internal error",
|
||||
/* E_DIV_ZERO */ "Division by zero",
|
||||
/* E_NOSUCH_VAR */ "Undefined variable",
|
||||
/* E_EOLN */ "Unexpected end of line",
|
||||
/* E_EOF */ "Unexpected end of file",
|
||||
/* E_IO_ERR */ "I/O error",
|
||||
/* E_LINE_2_LONG */ "Line too long",
|
||||
/* E_SWERR */ "Internal error",
|
||||
/* E_BAD_DATE */ "Bad date specification",
|
||||
/* E_2FEW_ARGS */ "Not enough arguments",
|
||||
/* E_2MANY_ARGS */ "Too many arguments",
|
||||
/* E_BAD_TIME */ "Ill-formed time",
|
||||
/* E_2HIGH */ "Number too high",
|
||||
/* E_2LOW */ "Number too low",
|
||||
/* E_CANT_OPEN */ "Can't open file",
|
||||
/* E_NESTED_INCLUDE */ "INCLUDE nested too deeply (max. " STR(INCLUDE_NEST) ")",
|
||||
/* E_PARSE_ERR */ "Parse error",
|
||||
/* E_CANT_TRIG */ "Can't compute trigger",
|
||||
/* E_NESTED_IF */ "Too many nested IFs",
|
||||
/* E_ELSE_NO_IF */ "ELSE with no matching IF",
|
||||
/* E_ENDIF_NO_IF */ "ENDIF with no matching IF",
|
||||
/* E_2MANY_LOCALOMIT */ "Can't OMIT every weekday",
|
||||
/* E_EXTRANEOUS_TOKEN */ "Extraneous token(s) on line",
|
||||
/* E_POP_NO_PUSH */ "POP-OMIT-CONTEXT without matching PUSH-OMIT-CONTEXT",
|
||||
/* E_RUN_DISABLED */ "RUN disabled",
|
||||
/* E_DOMAIN_ERR */ "Domain error",
|
||||
/* E_BAD_ID */ "Invalid identifier",
|
||||
/* E_RECURSIVE */ "Too many recursive function calls",
|
||||
/* E_PARSE_AS_REM */ "",
|
||||
/* E_CANT_MODIFY */ "Cannot modify system variable",
|
||||
/* E_MKTIME_PROBLEM */ "C library function can't represent date/time",
|
||||
/* E_REDEF_FUNC */ "Attempt to redefine built-in function",
|
||||
/* E_CANTNEST_FDEF */ "Can't nest function definition in expression",
|
||||
/* E_REP_FULSPEC */ "Must fully specify date to use repeat factor",
|
||||
/* E_YR_TWICE */ "Year specified twice",
|
||||
/* E_MON_TWICE */ "Month specified twice",
|
||||
/* E_DAY_TWICE */ "Day specified twice",
|
||||
/* E_UNKNOWN_TOKEN */ "Unknown token",
|
||||
/* E_SPEC_MON */ "Must specify month in OMIT command",
|
||||
/* E_2MANY_PART */ "Too many partial OMITs (max. " STR(MAX_PARTIAL_OMITS) ")",
|
||||
/* E_2MANY_FULL */ "Too many full OMITs (max. " STR(MAX_FULL_OMITS) ")",
|
||||
/* E_PUSH_NOPOP */ "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||
/* E_ERR_READING */ "Error reading",
|
||||
/* E_EXPECTING_EOL */ "Expecting end-of-line",
|
||||
/* E_BAD_HEBDATE */ "Invalid Hebrew date",
|
||||
/* E_IIF_ODD */ "iif(): odd number of arguments required",
|
||||
/* E_MISS_ENDIF */ "Warning: Missing ENDIF",
|
||||
/* E_EXPECT_COMMA */ "Expecting comma",
|
||||
/* E_WD_TWICE */ "Weekday specified twice",
|
||||
/* E_SKIP_ERR */ "Only use one of BEFORE, AFTER or SKIP",
|
||||
/* E_CANT_NEST_RTYPE */ "Can't nest MSG, MSF, RUN, etc. in expression",
|
||||
/* E_REP_TWICE */ "Repeat value specified twice",
|
||||
/* E_DELTA_TWICE */ "Delta value specified twice",
|
||||
/* E_BACK_TWICE */ "Back value specified twice",
|
||||
/* E_ONCE_TWICE */ "ONCE keyword used twice. (Hah.)",
|
||||
/* E_EXPECT_TIME */ "Expecting time after AT",
|
||||
/* E_UNTIL_TWICE */ "THROUGH/UNTIL keyword used twice",
|
||||
/* E_INCOMPLETE */ "Incomplete date specification",
|
||||
/* E_SCAN_TWICE */ "FROM/SCANFROM keyword used twice",
|
||||
/* E_VAR */ "Variable",
|
||||
/* E_VAL */ "Value",
|
||||
/* E_UNDEF */ "*UNDEFINED*",
|
||||
/* E_ENTER_FUN */ "Entering UserFN",
|
||||
/* E_LEAVE_FUN */ "Leaving UserFN",
|
||||
/* E_EXPIRED */ "Expired",
|
||||
/* E_CANTFORK */ "fork() failed - can't do queued reminders",
|
||||
/* E_CANTACCESS */ "Can't access file",
|
||||
/* M_BAD_SYS_DATE */ "Illegal system date: Year is less than %d\n",
|
||||
/* M_BAD_DB_FLAG */ "Unknown debug flag '%c'\n",
|
||||
/* M_BAD_OPTION */ "Unknown option '%c'\n",
|
||||
/* M_BAD_USER */ "Unknown user '%s'\n",
|
||||
/* M_NO_CHG_GID */ "Could not change gid to %d\n",
|
||||
/* M_NO_CHG_UID */ "Could not change uid to %d\n",
|
||||
/* M_NOMEM_ENV */ "Out of memory for environment\n",
|
||||
/* E_MISS_EQ */ "Missing '=' sign",
|
||||
/* E_MISS_VAR */ "Missing variable name",
|
||||
/* E_MISS_EXPR */ "Missing expression",
|
||||
/* M_CANTSET_ACCESS */ "Can't reset access date of %s\n",
|
||||
/* M_I_OPTION */ "Remind: '-i' option: %s\n",
|
||||
/* E_NOREMINDERS */ "No reminders.",
|
||||
/* M_QUEUED */ "%d reminder(s) queued for later today.\n",
|
||||
/* E_EXPECTING_NUMBER */ "Expecting number",
|
||||
/* M_BAD_WARN_FUNC */ "Undefined WARN function",
|
||||
/* E_CANT_CONVERT_TZ */ "Can't convert between time zones",
|
||||
/* E_NO_MATCHING_REMS */ "No files matching *.rem",
|
||||
/* E_STRING_TOO_LONG */ "String too long",
|
||||
/* E_TIME_TWICE */ "Time specified twice",
|
||||
/* E_DURATION_NO_AT */ "Cannot specify DURATION without specifying AT",
|
||||
/* E_EXPECTING_WEEKDAY */ "Expecting weekday name",
|
||||
/* E_REPEATED_ARG */ "Duplicate argument name",
|
||||
/* E_EXPR_DISABLED */ "Expression evaluation is disabled",
|
||||
/* E_TIME_EXCEEDED */ "Time limit for expression evaluation exceeded",
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
3680
src/expr.c
3680
src/expr.c
File diff suppressed because it is too large
Load Diff
65
src/expr.h
65
src/expr.h
@@ -1,65 +0,0 @@
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* EXPR.H */
|
||||
/* */
|
||||
/* Contains a few definitions used by expression evaluator. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
/* Define the types of values */
|
||||
#define ERR_TYPE 0
|
||||
#define INT_TYPE 1
|
||||
#define TIME_TYPE 2
|
||||
#define DATE_TYPE 3
|
||||
#define STR_TYPE 4
|
||||
#define DATETIME_TYPE 5
|
||||
#define SPECIAL_TYPE 6 /* Only for system variables */
|
||||
|
||||
/* Define stuff for parsing expressions */
|
||||
#define BEG_OF_EXPR '['
|
||||
#define END_OF_EXPR ']'
|
||||
#define COMMA ','
|
||||
|
||||
#define UN_OP 0 /* Unary operator */
|
||||
#define BIN_OP 1 /* Binary Operator */
|
||||
#define FUNC 2 /* Function */
|
||||
|
||||
/* Make the pushing and popping of values and operators in-line code
|
||||
for speed. BEWARE: These macros invoke return if an error happens ! */
|
||||
|
||||
#define PushOpStack(op) \
|
||||
if (OpStackPtr >= OP_STACK_SIZE) \
|
||||
return E_OP_STK_OVER; \
|
||||
else \
|
||||
OpStack[OpStackPtr++] = (op)
|
||||
|
||||
#define PopOpStack(op) \
|
||||
if (OpStackPtr <= 0) \
|
||||
return E_OP_STK_UNDER; \
|
||||
else \
|
||||
(op) = OpStack[--OpStackPtr]
|
||||
|
||||
#define PushValStack(val) \
|
||||
if (ValStackPtr >= VAL_STACK_SIZE) \
|
||||
return E_VA_STK_OVER; \
|
||||
else \
|
||||
ValStack[ValStackPtr++] = (val)
|
||||
|
||||
#define PopValStack(val) \
|
||||
if (ValStackPtr <= 0) \
|
||||
return E_VA_STK_UNDER; \
|
||||
else \
|
||||
(val) = ValStack[--ValStackPtr]
|
||||
|
||||
/* These functions are in utils.c and are used to detect overflow
|
||||
in various arithmetic operators. They have to be in separate
|
||||
functions with extern linkage to defeat compiler optimizations
|
||||
that would otherwise break the overflow checks. */
|
||||
extern int _private_mul_overflow(int a, int b);
|
||||
extern int _private_add_overflow(int a, int b);
|
||||
extern int _private_sub_overflow(int a, int b);
|
||||
|
||||
55
src/files.c
55
src/files.c
@@ -7,7 +7,7 @@
|
||||
/* files. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
|
||||
/* Convenient macros for closing files */
|
||||
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
#define PCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
#define FCLOSE(fp) ((((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
#define PCLOSE(fp) ((((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||
|
||||
/* Define the structures needed by the file caching system */
|
||||
typedef struct cache {
|
||||
@@ -79,6 +79,7 @@ typedef struct {
|
||||
int LineNo;
|
||||
unsigned int IfFlags;
|
||||
int NumIfs;
|
||||
int IfLinenos[IF_NEST];
|
||||
long offset;
|
||||
CachedLine *CLine;
|
||||
int ownedByMe;
|
||||
@@ -100,6 +101,29 @@ static int CheckSafety (void);
|
||||
static int CheckSafetyAux (struct stat *statbuf);
|
||||
static int PopFile (void);
|
||||
static int IncludeCmd(char const *);
|
||||
|
||||
static void
|
||||
got_a_fresh_line(void)
|
||||
{
|
||||
FreshLine = 1;
|
||||
WarnedAboutImplicit = 0;
|
||||
}
|
||||
|
||||
void set_cloexec(FILE *fp)
|
||||
{
|
||||
int flags;
|
||||
int fd;
|
||||
if (fp) {
|
||||
fd = fileno(fp);
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags >= 0) {
|
||||
flags |= FD_CLOEXEC;
|
||||
fcntl(fd, F_SETFD, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
{
|
||||
DynamicBuffer fname_buf;
|
||||
@@ -123,6 +147,7 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
if (!PurgeFP) {
|
||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
||||
}
|
||||
set_cloexec(PurgeFP);
|
||||
DBufFree(&fname_buf);
|
||||
}
|
||||
|
||||
@@ -164,7 +189,7 @@ int ReadLine(void)
|
||||
CurLine = CLine->text;
|
||||
LineNo = CLine->LineNo;
|
||||
CLine = CLine->next;
|
||||
FreshLine = 1;
|
||||
got_a_fresh_line();
|
||||
clear_callstack();
|
||||
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
||||
return OK;
|
||||
@@ -265,7 +290,7 @@ static int ReadLineFromFile(int use_pclose)
|
||||
CurLine = DBufValue(&LineBuffer);
|
||||
}
|
||||
|
||||
FreshLine = 1;
|
||||
got_a_fresh_line();
|
||||
clear_callstack();
|
||||
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
||||
return OK;
|
||||
@@ -327,6 +352,7 @@ int OpenFile(char const *fname)
|
||||
}
|
||||
} else {
|
||||
fp = fopen(fname, "r");
|
||||
set_cloexec(fp);
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||
}
|
||||
@@ -346,6 +372,7 @@ int OpenFile(char const *fname)
|
||||
if (strcmp(fname, "-")) {
|
||||
fp = fopen(fname, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
set_cloexec(fp);
|
||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||
} else {
|
||||
fp = stdin;
|
||||
@@ -507,8 +534,14 @@ static int NextChainedFile(IncludeStruct *i)
|
||||
static int PopFile(void)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
int j;
|
||||
|
||||
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||
if (!Hush && NumIfs) {
|
||||
Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||
for (j=NumIfs-1; j >=0; j--) {
|
||||
fprintf(ErrFp, "%s(%d): IF without ENDIF\n", FileName, IfLinenos[j]);
|
||||
}
|
||||
}
|
||||
if (!IStackPtr) return E_EOF;
|
||||
i = &IStack[IStackPtr-1];
|
||||
|
||||
@@ -528,6 +561,7 @@ static int PopFile(void)
|
||||
|
||||
LineNo = i->LineNo;
|
||||
IfFlags = i->IfFlags;
|
||||
memcpy(IfLinenos, i->IfLinenos, IF_NEST);
|
||||
NumIfs = i->NumIfs;
|
||||
CLine = i->CLine;
|
||||
fp = NULL;
|
||||
@@ -542,6 +576,7 @@ static int PopFile(void)
|
||||
if (strcmp(i->filename, "-")) {
|
||||
fp = fopen(i->filename, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
set_cloexec(fp);
|
||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||
} else {
|
||||
fp = stdin;
|
||||
@@ -821,7 +856,7 @@ static int IncludeCmd(char const *cmd)
|
||||
char const *fname;
|
||||
int old_flag;
|
||||
|
||||
FreshLine = 1;
|
||||
got_a_fresh_line();
|
||||
clear_callstack();
|
||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
@@ -851,6 +886,7 @@ static int IncludeCmd(char const *cmd)
|
||||
i->LineNo = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
|
||||
i->CLine = CLine;
|
||||
i->offset = -1L;
|
||||
i->chain = NULL;
|
||||
@@ -939,7 +975,7 @@ int IncludeFile(char const *fname)
|
||||
int oldRunDisabled;
|
||||
struct stat statbuf;
|
||||
|
||||
FreshLine = 1;
|
||||
got_a_fresh_line();
|
||||
clear_callstack();
|
||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
@@ -953,6 +989,7 @@ int IncludeFile(char const *fname)
|
||||
i->LineNo = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
memcpy(i->IfLinenos, IfLinenos, IF_NEST);
|
||||
i->CLine = CLine;
|
||||
i->offset = -1L;
|
||||
i->chain = NULL;
|
||||
|
||||
863
src/funcs.c
863
src/funcs.c
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
/* globals.h and err.h */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define INIT(var, val) var
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -39,7 +40,7 @@ EXTERN FILE *ErrFp;
|
||||
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
||||
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
|
||||
|
||||
#define DestroyValue(x) (void) (((x).type == STR_TYPE && (x).v.str) ? (free((x).v.str),(x).v.str = NULL,(x).type = ERR_TYPE) : 0)
|
||||
#define DestroyValue(x) do { if ((x).type == STR_TYPE && (x).v.str) { free((x).v.str); (x).v.str = NULL; } (x).type = ERR_TYPE; } while (0)
|
||||
|
||||
EXTERN int DSEToday;
|
||||
EXTERN int RealToday;
|
||||
@@ -48,8 +49,10 @@ EXTERN int CurMon;
|
||||
EXTERN int CurYear;
|
||||
EXTERN int LineNo;
|
||||
EXTERN int FreshLine;
|
||||
EXTERN int WarnedAboutImplicit;
|
||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||
|
||||
EXTERN INIT( int MaxLateMinutes, 0);
|
||||
EXTERN INIT( int NumTrustedUsers, 0);
|
||||
EXTERN INIT( char const *MsgCommand, NULL);
|
||||
EXTERN INIT( char const *QueuedMsgCommand, NULL);
|
||||
@@ -70,15 +73,22 @@ EXTERN INIT( int Hush, 0);
|
||||
EXTERN INIT( int NextMode, 0);
|
||||
EXTERN INIT( int InfiniteDelta, 0);
|
||||
EXTERN INIT( int DefaultTDelta, 0);
|
||||
EXTERN INIT( int DeltaOffset, 0);
|
||||
EXTERN INIT( int DeltaOverride, 0);
|
||||
EXTERN INIT( int RunDisabled, 0);
|
||||
EXTERN INIT( int ExpressionEvaluationDisabled, 0);
|
||||
EXTERN INIT( int ExpressionEvaluationTimeLimit, 0);
|
||||
EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0);
|
||||
EXTERN INIT( int IgnoreOnce, 0);
|
||||
EXTERN INIT( int SortByTime, 0);
|
||||
EXTERN INIT( int SortByDate, 0);
|
||||
EXTERN INIT( int SortByPrio, 0);
|
||||
EXTERN INIT( char const *OnceFile, NULL);
|
||||
EXTERN INIT( int OnceDate, -1);
|
||||
EXTERN INIT( int ProcessedOnce, 0);
|
||||
EXTERN INIT( int SortByTime, SORT_NONE);
|
||||
EXTERN INIT( int SortByDate, SORT_NONE);
|
||||
EXTERN INIT( int SortByPrio, SORT_NONE);
|
||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||
EXTERN INIT( long SysTime, -1L);
|
||||
EXTERN INIT( int SysTime, -1);
|
||||
EXTERN INIT( int ParseUntriggered, 1);
|
||||
|
||||
EXTERN char const *InitialFile;
|
||||
EXTERN int FileAccessDate;
|
||||
@@ -90,6 +100,7 @@ EXTERN INIT( int DontQueue, 0);
|
||||
EXTERN INIT( int NumQueued, 0);
|
||||
EXTERN INIT( int DontIssueAts, 0);
|
||||
EXTERN INIT( int Daemon, 0);
|
||||
EXTERN INIT( int DaemonJSON, 0);
|
||||
EXTERN INIT( char DateSep, DATESEP);
|
||||
EXTERN INIT( char TimeSep, TIMESEP);
|
||||
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
||||
@@ -100,18 +111,19 @@ EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 1000);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN INIT( int PurgeMode, 0);
|
||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||
EXTERN INIT( FILE *PurgeFP, NULL);
|
||||
EXTERN INIT( int NumIfs, 0);
|
||||
EXTERN INIT( unsigned int IfFlags, 0);
|
||||
EXTERN INIT( int IfLinenos[IF_NEST], {0});
|
||||
EXTERN INIT( int LastTrigValid, 0);
|
||||
EXTERN Trigger LastTrigger;
|
||||
EXTERN TimeTrig LastTimeTrig;
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
EXTERN INIT( int LastTriggerTime, 0);
|
||||
EXTERN INIT( int LastTriggerTime, NO_TIME);
|
||||
EXTERN INIT( int ShouldCache, 0);
|
||||
EXTERN char const *CurLine;
|
||||
EXTERN INIT( int NumTriggered, 0);
|
||||
@@ -155,6 +167,15 @@ EXTERN INIT( char *EndSentIg, "\"')]}>");
|
||||
EXTERN DynamicBuffer Banner;
|
||||
EXTERN DynamicBuffer LineBuffer;
|
||||
EXTERN DynamicBuffer ExprBuf;
|
||||
|
||||
/* User-func recursion level */
|
||||
EXTERN INIT( unsigned int FuncRecursionLevel, 0);
|
||||
|
||||
/* Suppress warnings about implicit REM and MSG */
|
||||
EXTERN INIT( int SuppressImplicitRemWarnings, 0);
|
||||
|
||||
extern int NumFullOmits, NumPartialOmits;
|
||||
|
||||
/* List of months */
|
||||
EXTERN char *EnglishMonthName[]
|
||||
#ifdef MK_GLOBALS
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Hebrew calendar */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||
@@ -20,6 +20,12 @@
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#define HOUR 1080L
|
||||
#define DAY (24L*HOUR)
|
||||
#define WEEK (7L*DAY)
|
||||
|
||||
324
src/init.c
324
src/init.c
@@ -7,7 +7,7 @@
|
||||
/* in normal mode. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -19,16 +19,17 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef HAVE_INITGROUPS
|
||||
#include <grp.h>
|
||||
@@ -37,9 +38,16 @@
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
#include "err.h"
|
||||
|
||||
static int should_guess_terminal_background = 1;
|
||||
|
||||
static void guess_terminal_background(int *r, int *g, int *b);
|
||||
static int tty_init(int fd);
|
||||
static void tty_raw(int fd);
|
||||
static void tty_reset(int fd);
|
||||
|
||||
static void ProcessLongOption(char const *arg);
|
||||
/***************************************************************
|
||||
*
|
||||
* Command line options recognized:
|
||||
@@ -69,6 +77,7 @@
|
||||
* t = Display trigger dates
|
||||
* v = Dump variables at end
|
||||
* l = Display entire line in error messages
|
||||
* s = Display expression-parsing stack usage before exit
|
||||
* -e = Send messages normally sent to stderr to stdout instead
|
||||
* -z[n] = Daemon mode waking up every n (def 1) minutes.
|
||||
* -bn = Time format for cal (0, 1, or 2)
|
||||
@@ -219,7 +228,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
||||
exit(1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse the command-line options */
|
||||
@@ -232,7 +241,6 @@ void InitRemind(int argc, char const *argv[])
|
||||
arg++;
|
||||
if (!*arg) {
|
||||
UseStdin = 1;
|
||||
IgnoreOnce = 1;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
@@ -243,6 +251,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
while(*arg) arg++;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
ProcessLongOption(arg);
|
||||
while(*arg) arg++;
|
||||
break;
|
||||
|
||||
case '@':
|
||||
UseVTColors = 1;
|
||||
if (*arg) {
|
||||
@@ -259,16 +272,24 @@ void InitRemind(int argc, char const *argv[])
|
||||
if (*arg == ',') {
|
||||
arg++;
|
||||
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;
|
||||
if (*arg == 't') {
|
||||
arg++;
|
||||
should_guess_terminal_background = 2;
|
||||
} else {
|
||||
fprintf(ErrFp, "%s: -@n,m,b: m must be 0, 1 or 2 (assuming 2)\n",
|
||||
argv[0]);
|
||||
PARSENUM(x, arg);
|
||||
if (x == 0) {
|
||||
should_guess_terminal_background = 0;
|
||||
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
||||
} else if (x == 1) {
|
||||
should_guess_terminal_background = 0;
|
||||
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
||||
} else if (x == 2) {
|
||||
should_guess_terminal_background = 0;
|
||||
TerminalBackground = TERMINAL_BACKGROUND_UNKNOWN;
|
||||
} else {
|
||||
fprintf(ErrFp, "%s: -@n,m,b: m must be t, 0, 1 or 2 (assuming 2)\n",
|
||||
argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,6 +323,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
NextMode = 1;
|
||||
DontQueue = 1;
|
||||
Daemon = 0;
|
||||
IgnoreOnce = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
@@ -341,10 +363,15 @@ void InitRemind(int argc, char const *argv[])
|
||||
} else if (!*arg) {
|
||||
InfiniteDelta = 1;
|
||||
} else {
|
||||
PARSENUM(DeltaOffset, arg);
|
||||
if (DeltaOffset < 0) {
|
||||
DeltaOffset = 0;
|
||||
}
|
||||
if (*arg == 'z') {
|
||||
DeltaOverride = -1;
|
||||
arg++;
|
||||
} else {
|
||||
PARSENUM(DeltaOverride, arg);
|
||||
if (DeltaOverride < 0) {
|
||||
DeltaOverride = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
@@ -398,7 +425,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'z':
|
||||
case 'Z':
|
||||
DontFork = 1;
|
||||
if (*arg == '0') {
|
||||
if (*arg == 'j' || *arg == 'J') {
|
||||
while (*arg) arg++;
|
||||
Daemon = -1;
|
||||
DaemonJSON = 1;
|
||||
} else if (*arg == '0') {
|
||||
PARSENUM(Daemon, arg);
|
||||
if (Daemon == 0) Daemon = -1;
|
||||
else if (Daemon < 1) Daemon = 1;
|
||||
@@ -426,6 +457,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
IgnoreOnce = 1;
|
||||
DoCalendar = 1;
|
||||
weeks = 0;
|
||||
/* Parse the flags */
|
||||
@@ -470,6 +502,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 's':
|
||||
case 'S':
|
||||
DoSimpleCalendar = 1;
|
||||
IgnoreOnce = 1;
|
||||
weeks = 0;
|
||||
while(*arg) {
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
@@ -496,6 +529,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'p':
|
||||
case 'P':
|
||||
DoSimpleCalendar = 1;
|
||||
IgnoreOnce = 1;
|
||||
PsCal = PSCAL_LEVEL1;
|
||||
while (*arg == 'a' || *arg == 'A' ||
|
||||
*arg == 'q' || *arg == 'Q' ||
|
||||
@@ -532,7 +566,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
arg++;
|
||||
/* -wt means get width from /dev/tty */
|
||||
ttyfd = open("/dev/tty", O_RDONLY);
|
||||
if (!ttyfd) {
|
||||
if (ttyfd < 0) {
|
||||
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n",
|
||||
argv[0], strerror(errno));
|
||||
} else {
|
||||
@@ -543,7 +577,12 @@ void InitRemind(int argc, char const *argv[])
|
||||
PARSENUM(CalWidth, arg);
|
||||
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
|
||||
if (CalWidth == 0) {
|
||||
CalWidth = -1;
|
||||
/* Cal width of 0 means obtain from stdout */
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
InitCalWidthAndFormWidth(STDOUT_FILENO);
|
||||
} else {
|
||||
CalWidth = 80;
|
||||
}
|
||||
}
|
||||
FormWidth = CalWidth - 8;
|
||||
if (FormWidth < 20) FormWidth = 20;
|
||||
@@ -568,6 +607,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'D':
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break;
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||
@@ -677,12 +717,17 @@ void InitRemind(int argc, char const *argv[])
|
||||
break;
|
||||
|
||||
default:
|
||||
if (tok.type == T_Illegal && tok.val < 0) {
|
||||
fprintf(stderr, "%s: `%s'\n", ErrMsg[-tok.val], arg);
|
||||
Usage();
|
||||
}
|
||||
Usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (rep > 0) {
|
||||
Iterations = rep;
|
||||
IgnoreOnce = 1;
|
||||
DontQueue = 1;
|
||||
Daemon = 0;
|
||||
}
|
||||
@@ -721,7 +766,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
/* Figure out the offset from UTC */
|
||||
if (CalculateUTC)
|
||||
(void) CalcMinsFromUTC(DSEToday, SystemTime(0)/60,
|
||||
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||
&MinsFromUTC, NULL);
|
||||
}
|
||||
|
||||
@@ -735,7 +780,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
#ifndef L_USAGE_OVERRIDE
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -768,6 +813,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||
fprintf(ErrFp, "\nRemind home page: %s\n", PACKAGE_URL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif /* L_USAGE_OVERRIDE */
|
||||
@@ -887,7 +933,12 @@ static void InitializeVar(char const *str)
|
||||
r = 0;
|
||||
while (*str && *str != '=') {
|
||||
if (r < VAR_NAME_LEN) {
|
||||
varname[r++] = *str;
|
||||
if (isalpha(*str) || *str == '_' || (r > 0 && *str == '(') || (r == 0 && *str == '$') || (r > 0 && isdigit(*str))) {
|
||||
varname[r++] = *str;
|
||||
} else {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_ILLEGAL_CHAR]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*str == '(') {
|
||||
/* Do a function definition if we see a paren */
|
||||
@@ -897,10 +948,28 @@ static void InitializeVar(char const *str)
|
||||
str++;
|
||||
}
|
||||
varname[r] = 0;
|
||||
if (!*str) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
|
||||
if (!*varname) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
|
||||
return;
|
||||
}
|
||||
if (!*str) {
|
||||
/* Setting a system var does require =expr on the commandline */
|
||||
if (*varname == '$') {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
|
||||
return;
|
||||
}
|
||||
val.type = INT_TYPE;
|
||||
val.v.val = 0;
|
||||
r = SetVar(varname, &val);
|
||||
if (!r) {
|
||||
r = PreserveVar(varname);
|
||||
}
|
||||
if (r) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*varname) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
|
||||
return;
|
||||
@@ -953,3 +1022,204 @@ AddTrustedUser(char const *username)
|
||||
NumTrustedUsers++;
|
||||
}
|
||||
|
||||
static pid_t LimiterPid = (pid_t) -1;
|
||||
|
||||
void unlimit_execution_time(void)
|
||||
{
|
||||
if (LimiterPid != (pid_t) -1) {
|
||||
kill(LimiterPid, SIGTERM);
|
||||
LimiterPid = (pid_t) -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void limit_execution_time(int t)
|
||||
{
|
||||
pid_t parent = getpid();
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
LimiterPid = pid;
|
||||
/* In the parent */
|
||||
return;
|
||||
}
|
||||
|
||||
/* In the child */
|
||||
time_t start = time(NULL);
|
||||
while(1) {
|
||||
sleep(1);
|
||||
if (kill(parent, 0) < 0) {
|
||||
/* Parent has probably exited */
|
||||
exit(0);
|
||||
}
|
||||
if (time(NULL) - start > t) {
|
||||
kill(parent, SIGXCPU);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ProcessLongOption(char const *arg)
|
||||
{
|
||||
int t;
|
||||
if (!strcmp(arg, "version")) {
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (!strcmp(arg, "print-config-cmd")) {
|
||||
printf("%s\n", CONFIG_CMD);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (!strcmp(arg, "print-tokens")) {
|
||||
print_remind_tokens();
|
||||
print_builtinfunc_tokens();
|
||||
print_sysvar_tokens();
|
||||
exit(0);
|
||||
}
|
||||
if (sscanf(arg, "max-execution-time=%d", &t) == 1) {
|
||||
if (t < 0) {
|
||||
fprintf(ErrFp, "%s: --max-execution-time must be non-negative\n", ArgV[0]);
|
||||
return;
|
||||
}
|
||||
if (t > 0) {
|
||||
limit_execution_time(t);
|
||||
}
|
||||
return;
|
||||
}
|
||||
fprintf(ErrFp, "%s: Unknown long option --%s\n", ArgV[0], arg);
|
||||
}
|
||||
|
||||
static void
|
||||
guess_terminal_background(int *r, int *g, int *b)
|
||||
{
|
||||
int ttyfd;
|
||||
struct pollfd p;
|
||||
unsigned int rr, gg, bb;
|
||||
char buf[128];
|
||||
int n;
|
||||
|
||||
*r = -1;
|
||||
*g = -1;
|
||||
*b = -1;
|
||||
|
||||
/* Don't guess if stdout not a terminal unless asked to by @,t */
|
||||
if (should_guess_terminal_background != 2) {
|
||||
if (!isatty(STDOUT_FILENO)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ttyfd = open("/dev/tty", O_RDWR);
|
||||
if (ttyfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isatty(ttyfd)) {
|
||||
/* Not a TTY: Can't guess the color */
|
||||
close(ttyfd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tty_init(ttyfd)) {
|
||||
return;
|
||||
}
|
||||
tty_raw(ttyfd);
|
||||
n = write(ttyfd, "\033]11;?\033\\", 8);
|
||||
|
||||
if (n != 8) {
|
||||
/* write failed... WTF? Not much we can do */
|
||||
tty_reset(ttyfd);
|
||||
close(ttyfd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait up to 0.1s for terminal to respond */
|
||||
p.fd = ttyfd;
|
||||
p.events = POLLIN;
|
||||
if (poll(&p, 1, 100) < 0) {
|
||||
tty_reset(ttyfd);
|
||||
close(ttyfd);
|
||||
return;
|
||||
}
|
||||
if (!(p.revents & POLLIN)) {
|
||||
tty_reset(ttyfd);
|
||||
close(ttyfd);
|
||||
return;
|
||||
}
|
||||
n = read(ttyfd, buf, 127);
|
||||
if (n <= 0) {
|
||||
tty_reset(ttyfd);
|
||||
close(ttyfd);
|
||||
return;
|
||||
}
|
||||
tty_reset(ttyfd);
|
||||
close(ttyfd);
|
||||
buf[n+1] = 0;
|
||||
if (n < 25) {
|
||||
/* Too short */
|
||||
return;
|
||||
}
|
||||
if (sscanf(buf+5, "rgb:%x/%x/%x", &rr, &gg, &bb) != 3) {
|
||||
/* Couldn't scan color codes */
|
||||
return;
|
||||
}
|
||||
*r = (int) ((rr >> 8) & 255);
|
||||
*g = (int) ((gg >> 8) & 255);
|
||||
*b = (int) ((bb >> 8) & 255);
|
||||
}
|
||||
|
||||
static struct termios orig_termios;
|
||||
|
||||
static int
|
||||
tty_init(int fd)
|
||||
{
|
||||
if (tcgetattr(fd, &orig_termios) < 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_raw(int fd)
|
||||
{
|
||||
struct termios raw;
|
||||
|
||||
raw = orig_termios;
|
||||
|
||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
raw.c_oflag &= ~(OPOST);
|
||||
raw.c_cflag |= (CS8);
|
||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||
|
||||
/* put terminal in raw mode after flushing */
|
||||
tcsetattr(fd,TCSAFLUSH,&raw);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_reset(int fd)
|
||||
{
|
||||
tcsetattr(fd, TCSAFLUSH, &orig_termios);
|
||||
}
|
||||
|
||||
int
|
||||
GetTerminalBackground(void)
|
||||
{
|
||||
int r, g, b;
|
||||
if (should_guess_terminal_background) {
|
||||
guess_terminal_background(&r, &g, &b);
|
||||
if (r >= 0 && g >= 0 && b >= 0) {
|
||||
if (r+g+b <= 85*3 && r <= 128 && g <= 128 && b <= 128) {
|
||||
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
||||
} else {
|
||||
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
||||
}
|
||||
}
|
||||
should_guess_terminal_background = 0;
|
||||
}
|
||||
return TerminalBackground;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Header file for language support for various languages. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* Further corrections by Erik-Jan Vens */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the English language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -145,7 +145,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Ok",
|
||||
"Puuttuva ']'",
|
||||
"Puuttuva lainausmerkki",
|
||||
"Liian monimutkainen lauseke - liikaa operaattoreita",
|
||||
"Liian monimutkainen lauseke",
|
||||
"Liian monimutkainen lauseke - liikaa operandeja",
|
||||
"Puuttuva ')'",
|
||||
"Määrittelemätön funktio",
|
||||
@@ -245,7 +245,11 @@ EXTERN char *ErrMsg[] =
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
"Cannot specify DURATION without specifying AT",
|
||||
"Odotettu viikonpäivän nimi",
|
||||
"Päällekkäinen argumentin nimi",
|
||||
"Lausekkeiden arviointi on poistettu käytöstä",
|
||||
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -254,7 +258,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||
#endif
|
||||
@@ -271,12 +275,10 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -o Älä noudata ONCE-lauseita\n");
|
||||
fprintf(ErrFp, " -t Laukaise kaikki viestit deltan arvosta välittämättä\n");
|
||||
fprintf(ErrFp, " -h Suppeat tulostukset\n");
|
||||
#ifdef HAVE_QUEUED
|
||||
fprintf(ErrFp, " -a Älä laukaise viestejä heti - lisää ne jonoon\n");
|
||||
fprintf(ErrFp, " -q Älä lisää viestejä jonoon\n");
|
||||
fprintf(ErrFp, " -f Laukaise viestit, pysy etualalla\n");
|
||||
fprintf(ErrFp, " -z[n] Käynnisty demonina, herätys n:n (5:n) minuutin välein\n");
|
||||
#endif
|
||||
fprintf(ErrFp, " -d... Virheenetsintä: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
|
||||
fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n");
|
||||
fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n");
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||
/* Dianne Skoll. */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
@@ -119,7 +119,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Ok",
|
||||
"']' manquant",
|
||||
"Apostrophe manquant",
|
||||
"Expression trop complexe - trop d'opérateurs",
|
||||
"Expression trop complexe",
|
||||
"Expression trop complexe - trop d'opérandes",
|
||||
"')' manquante",
|
||||
"Fonction non-définie",
|
||||
@@ -219,7 +219,11 @@ EXTERN char *ErrMsg[] =
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
"Cannot specify DURATION without specifying AT",
|
||||
"Nom du jour de la semaine attendu",
|
||||
"Nom de l'argument en double",
|
||||
"L'évaluation de l'expression est désactivée",
|
||||
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -228,7 +232,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -245,12 +249,10 @@ void Usage(void)
|
||||
fprintf(ErrFp, " -o Ignorer instructions ONCE\n");
|
||||
fprintf(ErrFp, " -t Déclencher tous les rappels peu importe le delta\n");
|
||||
fprintf(ErrFp, " -h Mode silencieux\n");
|
||||
#ifdef HAVE_QUEUED
|
||||
fprintf(ErrFp, " -a Ne pas déclencher les rappels minutés immédiatement - les mettre en file\n");
|
||||
fprintf(ErrFp, " -q Ne pas mettre les rappels minutés en file\n");
|
||||
fprintf(ErrFp, " -f Déclencher les rappels minutés immédiatement en restant en avant-plan\n");
|
||||
fprintf(ErrFp, " -z[n] Entrer en mode 'daemon', réveil chaque n (5) minutes\n");
|
||||
#endif
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
|
||||
fprintf(ErrFp, " -e Envoyer les messages de stderr à stdout\n");
|
||||
fprintf(ErrFp, " -b[n] Formats de l'heure pour le calendrier: 0=am/pm, 1=24hr, 2=aucun\n");
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* I don't speak German. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Icelandic language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user