mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 14:59:20 +02:00
Compare commits
438 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
705adbb82a | ||
|
|
269f9788b6 | ||
|
|
5e1c5ae384 | ||
|
|
562eb83bde | ||
|
|
a53db00243 | ||
|
|
11375729db | ||
|
|
9fee354e6c | ||
|
|
ec76554d41 | ||
|
|
ddb0817c99 | ||
|
|
3d6ecd1f72 | ||
|
|
e3ec6565e9 | ||
|
|
8ed49ead7f | ||
|
|
49fbca416f | ||
|
|
82cd438fff | ||
|
|
946e1bca38 | ||
|
|
e40c81b5bf | ||
|
|
f23418480d | ||
|
|
bb4df39c50 | ||
|
|
5fec775863 | ||
|
|
a85980fec2 | ||
|
|
f3ea2962e6 | ||
|
|
3a5af23ab6 | ||
|
|
f9656edc51 | ||
|
|
5134b47d47 | ||
|
|
d4a183f3bf | ||
|
|
87e392de6c | ||
|
|
afc1667e64 | ||
|
|
8d25270c43 | ||
|
|
929866a770 | ||
|
|
395bad96a7 | ||
|
|
cd7be006c9 | ||
|
|
f658ba7ee7 | ||
|
|
7416f4c035 | ||
|
|
2860159ff7 | ||
|
|
64fa71ab09 | ||
|
|
ffbba7d4d1 | ||
|
|
fdcc2d8acf | ||
|
|
f1aa4d16af | ||
|
|
a55c5580f3 | ||
|
|
569e315306 | ||
|
|
acd641845d | ||
|
|
6b7e6f6788 | ||
|
|
4248b9c624 | ||
|
|
6de98d1357 | ||
|
|
18f21693af | ||
|
|
6fa500a860 | ||
|
|
941c02582e | ||
|
|
e56e3924d9 | ||
|
|
d1384a8f69 | ||
|
|
0488d689aa | ||
|
|
988a94e669 | ||
|
|
ac7e93ac1c | ||
|
|
bb7e9ee676 | ||
|
|
ac949ce7bd | ||
|
|
0fa8eed11f | ||
|
|
df8694a128 | ||
|
|
13df3d96e5 | ||
|
|
e345eb15f2 | ||
|
|
e8b2872a87 | ||
|
|
2f196e3c9f | ||
|
|
839b844a10 | ||
|
|
0cea410529 | ||
|
|
90397ece64 | ||
|
|
0b95fc290c | ||
|
|
9a4e8b6070 | ||
|
|
924fd16ade | ||
|
|
0815fe19cc | ||
|
|
7f445e1b66 | ||
|
|
31afc60af4 | ||
|
|
9d34a8aa42 | ||
|
|
91325ff489 | ||
|
|
1f99d6df59 | ||
|
|
8a608a06b8 | ||
|
|
bb34474e59 | ||
|
|
029c054489 | ||
|
|
01400d0672 | ||
|
|
a1eafb2c89 | ||
|
|
af88e393f9 | ||
|
|
3a250ce765 | ||
|
|
d651ac40a8 | ||
|
|
653324e220 | ||
|
|
e5c6703eaa | ||
|
|
1596d9c76a | ||
|
|
4aacf74e25 | ||
|
|
ae58bc7c11 | ||
|
|
387125d983 | ||
|
|
aa5f9297b2 | ||
|
|
8c4a7e766f | ||
|
|
d7f32d3901 | ||
|
|
d4f09e2a31 | ||
|
|
8b5fe4f2a0 | ||
|
|
98fc4a917f | ||
|
|
e633530a36 | ||
|
|
bfea9915b9 | ||
|
|
d68ed6e75d | ||
|
|
a22631d768 | ||
|
|
552bf84e33 | ||
|
|
28d0251093 | ||
|
|
f3d969f658 | ||
|
|
2afe95d090 | ||
|
|
3692a6b265 | ||
|
|
8fc19358bb | ||
|
|
c8f9773d83 | ||
|
|
e1091db82f | ||
|
|
9f8ed13434 | ||
|
|
914f03d5eb | ||
|
|
a801f6d4ce | ||
|
|
fde5a7b4ca | ||
|
|
0e1fff6339 | ||
|
|
60fdeac2e9 | ||
|
|
3b3f10d448 | ||
|
|
48a4314dd2 | ||
|
|
9beff3a24a | ||
|
|
1ef90c7a61 | ||
|
|
5c886d181e | ||
|
|
da4d830163 | ||
|
|
c7abb7986c | ||
|
|
5a3b3d8a06 | ||
|
|
127cee03df | ||
|
|
7455748d54 | ||
|
|
e278d0e768 | ||
|
|
a5acc12239 | ||
|
|
a25afb9771 | ||
|
|
6252a472b5 | ||
|
|
dbe4c662c1 | ||
|
|
b77a261c87 | ||
|
|
351c54cc50 | ||
|
|
72d0b13ad5 | ||
|
|
bea2a6541c | ||
|
|
5258e98f54 | ||
|
|
af9d42721c | ||
|
|
8ed43f5c3e | ||
|
|
ec02a87c2b | ||
|
|
6c2ec04d40 | ||
|
|
9f91cdf0b9 | ||
|
|
8ada68ce54 | ||
|
|
d7975634af | ||
|
|
87be68fecf | ||
|
|
b42d5fd412 | ||
|
|
603228b944 | ||
|
|
c62f676813 | ||
|
|
c7654c27a6 | ||
|
|
b00bf05fea | ||
|
|
29bd07d4ef | ||
|
|
b7047da89e | ||
|
|
f26334e25f | ||
|
|
b80bc5f788 | ||
|
|
91549e18ce | ||
|
|
07fd975935 | ||
|
|
f9d968cf68 | ||
|
|
6a7e696a60 | ||
|
|
6734fae1db | ||
|
|
481fbc20a1 | ||
|
|
3c120bf561 | ||
|
|
ee65e04974 | ||
|
|
4ee6bb0eca | ||
|
|
b9839421f2 | ||
|
|
67601507fa | ||
|
|
c2e5534462 | ||
|
|
f4ea3af6fc | ||
|
|
e0998a3991 | ||
|
|
d67e580d0a | ||
|
|
d6ce54eea4 | ||
|
|
8b9ec43029 | ||
|
|
9d68134f0f | ||
|
|
3d91371870 | ||
|
|
d1c0ef63b0 | ||
|
|
2a59da61e1 | ||
|
|
2bc5e21627 | ||
|
|
7d77bfd12a | ||
|
|
0ff589c288 | ||
|
|
f3cca092be | ||
|
|
7218d55f08 | ||
|
|
ec72c74016 | ||
|
|
c946f08235 | ||
|
|
a8543ac349 | ||
|
|
dd3c0e14ed | ||
|
|
a2bc0acd3c | ||
|
|
a34266741a | ||
|
|
dedb9766c9 | ||
|
|
aedd759f50 | ||
|
|
a24c2f6905 | ||
|
|
fac31a10b8 | ||
|
|
fba9f139ed | ||
|
|
588d9debe8 | ||
|
|
805c2e0c69 | ||
|
|
2c2b1440b3 | ||
|
|
6973f62d74 | ||
|
|
f547c1e714 | ||
|
|
f8ea124b1f | ||
|
|
820e2aec4d | ||
|
|
01ce6b2d8f | ||
|
|
b39e0eab7e | ||
|
|
d6fc451d74 | ||
|
|
ac91556fc2 | ||
|
|
ccf639efe6 | ||
|
|
a8aa3b328b | ||
|
|
74a3b3e73d | ||
|
|
c0e68b57ea | ||
|
|
0ad4ea26eb | ||
|
|
ea7aafaf5e | ||
|
|
18043080ba | ||
|
|
7cd8cf3a77 | ||
|
|
21da52ec36 | ||
|
|
7a0c164843 | ||
|
|
5cf4961f19 | ||
|
|
68926d145b | ||
|
|
fdc3e4d23d | ||
|
|
f179c837e1 | ||
|
|
740bb44956 | ||
|
|
5b953769fe | ||
|
|
1ae00ce778 | ||
|
|
a01e05c1db | ||
|
|
63fb3e99f3 | ||
|
|
6cf7f5d2d8 | ||
|
|
316eb43303 | ||
|
|
576112a39a | ||
|
|
6607223abb | ||
|
|
9e85b1932d | ||
|
|
4ba7f5b1f2 | ||
|
|
fc93ae890a | ||
|
|
8051d01945 | ||
|
|
63430c59f7 | ||
|
|
c646bfc63f | ||
|
|
58dea8f69b | ||
|
|
f1c82dcb37 | ||
|
|
b984b66819 | ||
|
|
44bdae302b | ||
|
|
8eb6b250fb | ||
|
|
d838c41bf2 | ||
|
|
f9dbf36496 | ||
|
|
fe1427db28 | ||
|
|
2621ad5604 | ||
|
|
efecf2e1ea | ||
|
|
8666e6357e | ||
|
|
ae7069c9cb | ||
|
|
0c6ab3e607 | ||
|
|
17d6a60c0a | ||
|
|
e3e0a541dc | ||
|
|
712aa08fbc | ||
|
|
98c5bf511e | ||
|
|
1f9281628f | ||
|
|
8fb15aed17 | ||
|
|
a24c3a8542 | ||
|
|
8f8059e3f3 | ||
|
|
24bb462199 | ||
|
|
38e914f171 | ||
|
|
4a02c54e8d | ||
|
|
5fe169438a | ||
|
|
a7ef6e851a | ||
|
|
4d57b9d0aa | ||
|
|
5a7452d9f6 | ||
|
|
3916887aff | ||
|
|
f84f59fa91 | ||
|
|
1032f8908e | ||
|
|
6c2e8fc608 | ||
|
|
012e527fb5 | ||
|
|
62198c9807 | ||
|
|
de95224d62 | ||
|
|
be374a0464 | ||
|
|
fe9b3186d7 | ||
|
|
8405ea6c53 | ||
|
|
4274d05e10 | ||
|
|
4e80ce1159 | ||
|
|
52f473f2af |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -10,13 +10,19 @@ autom4te.cache
|
|||||||
blib/
|
blib/
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
|
man/rem.1
|
||||||
|
man/rem2ps.1
|
||||||
|
man/remind.1
|
||||||
|
man/tkremind.1
|
||||||
pm_to_blib
|
pm_to_blib
|
||||||
rem2html/Makefile
|
rem2html/Makefile
|
||||||
|
rem2html/rem2html
|
||||||
rem2html/rem2html.1
|
rem2html/rem2html.1
|
||||||
rem2pdf/Makefile.PL
|
rem2pdf/Makefile.PL
|
||||||
rem2pdf/Makefile.old
|
rem2pdf/Makefile.old
|
||||||
rem2pdf/Makefile.top
|
rem2pdf/Makefile.top
|
||||||
rem2pdf/bin/rem2pdf
|
rem2pdf/bin/rem2pdf
|
||||||
|
set-irc-topic
|
||||||
src/*.tar.gz*
|
src/*.tar.gz*
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/config.h
|
src/config.h
|
||||||
@@ -26,3 +32,4 @@ src/test-*.out
|
|||||||
src/version.h
|
src/version.h
|
||||||
tests/test.out
|
tests/test.out
|
||||||
www/Makefile
|
www/Makefile
|
||||||
|
gmon.out
|
||||||
|
|||||||
13
.gitlab-ci.yml
Normal file
13
.gitlab-ci.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
tests:
|
||||||
|
image: 'debian:stable-slim'
|
||||||
|
before_script:
|
||||||
|
- apt update && apt-get -y install gcc make
|
||||||
|
- useradd --create-home testuser
|
||||||
|
- chown -R testuser .
|
||||||
|
- chmod -R go-w .
|
||||||
|
script:
|
||||||
|
- LANG=C.UTF-8 su testuser -c './configure && make all && make test'
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- tests/test.out
|
||||||
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
|||||||
1. REMIND refers to the entire set of files and documentation in the
|
1. REMIND refers to the entire set of files and documentation in the
|
||||||
REMIND package.
|
REMIND package.
|
||||||
|
|
||||||
2. REMIND is Copyright 1992-2022 Dianne Skoll, except where noted in
|
2. REMIND is Copyright 1992-2024 Dianne Skoll, except where noted in
|
||||||
individual files.
|
individual files.
|
||||||
|
|
||||||
3. DISTRIBUTION AND USE
|
3. DISTRIBUTION AND USE
|
||||||
@@ -16,7 +16,7 @@ individual files.
|
|||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
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
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|||||||
26
Makefile
26
Makefile
@@ -1,4 +1,5 @@
|
|||||||
# Top-level Makefile for Remind.
|
# Top-level Makefile for Remind.
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
all: src/Makefile
|
all: src/Makefile
|
||||||
@echo ""
|
@echo ""
|
||||||
@@ -12,25 +13,38 @@ all: src/Makefile
|
|||||||
@$(MAKE) -C rem2pdf -f Makefile.top
|
@$(MAKE) -C rem2pdf -f Makefile.top
|
||||||
install:
|
install:
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "*********************"
|
@echo "**********************************"
|
||||||
@echo "* *"
|
@echo "* *"
|
||||||
@echo "* Installing REMIND *"
|
@echo "* Installing REMIND (unstripped) *"
|
||||||
@echo "* *"
|
@echo "* *"
|
||||||
@echo "*********************"
|
@echo "**********************************"
|
||||||
@echo ""
|
@echo ""
|
||||||
@$(MAKE) -C src install
|
@$(MAKE) -C src install
|
||||||
@$(MAKE) -C rem2html install
|
@$(MAKE) -C rem2html install
|
||||||
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
|
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
|
||||||
clean:
|
clean:
|
||||||
find . -name '*~' -exec rm {} \;
|
find . -name '*~' -exec rm {} \;
|
||||||
|
-rm man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1
|
||||||
-$(MAKE) -C src clean
|
-$(MAKE) -C src clean
|
||||||
-$(MAKE) -C rem2pdf clean
|
-$(MAKE) -C rem2pdf clean
|
||||||
|
|
||||||
|
install-stripped:
|
||||||
|
@echo ""
|
||||||
|
@echo "********************************"
|
||||||
|
@echo "* *"
|
||||||
|
@echo "* Installing REMIND (stripped) *"
|
||||||
|
@echo "* *"
|
||||||
|
@echo "**********************************"
|
||||||
|
@echo ""
|
||||||
|
@$(MAKE) -C src install-stripped
|
||||||
|
@$(MAKE) -C rem2html install
|
||||||
|
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@$(MAKE) -C src -s test
|
@$(MAKE) -C src -s test
|
||||||
|
|
||||||
distclean: clean
|
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
|
src/Makefile: src/Makefile.in
|
||||||
./configure
|
./configure
|
||||||
|
|||||||
40
README
40
README
@@ -34,5 +34,45 @@ If you do NOT have Tcl/Tk or are NOT running X Windows:
|
|||||||
|
|
||||||
5) Type: "make install" -- you may need to be root to do this.
|
5) Type: "make install" -- you may need to be root to do this.
|
||||||
|
|
||||||
|
PREREQUISITES:
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Remind and rem2ps have no prerequisites beyond the standard C library and
|
||||||
|
the standard math library.
|
||||||
|
|
||||||
|
Rem2HTML requires the JSON::MaybeXS Perl module.
|
||||||
|
Rem2PDF requires the JSON::MaybeXS, Pango and Cairo Perl modules.
|
||||||
|
|
||||||
|
- On Debian-like systems, these prerequisites may be installed with:
|
||||||
|
|
||||||
|
apt install libjson-maybexs-perl libpango-perl libcairo-perl
|
||||||
|
|
||||||
|
- On RPM-based systems, you need perl-Pango, perl-Cairo and perl-JSON-MaybeXS
|
||||||
|
|
||||||
|
- On Gentoo, you need dev-perl/Pango, dev-perl/Cairo and dev-perl/JSON-MaybeXS.
|
||||||
|
|
||||||
|
- On Arch linux, you need pango-perl, cairo-perl and perl-json-maybexs
|
||||||
|
|
||||||
|
TkRemind requires Tcl/Tk and the tcllib library.
|
||||||
|
|
||||||
|
- On Debian-like systems, install with:
|
||||||
|
|
||||||
|
apt install tcl tk tcllib
|
||||||
|
|
||||||
|
- On RPM-based systems, you need tcl, tk and tcllib
|
||||||
|
|
||||||
|
- On Arch Linux, you need tk and tcllib. The latter is available at
|
||||||
|
https://aur.archlinux.org/packages/tcllib
|
||||||
|
|
||||||
|
If the little arrows for "Previous Month" and "Next Month" do not display
|
||||||
|
correctly in TkRemind, you may need to install the Noto Fonts. Install
|
||||||
|
all of your distribution's Nonto Font-related packages.
|
||||||
|
|
||||||
|
- On Debian-like systems, install with:
|
||||||
|
|
||||||
|
apt install fonts-noto-core fonts-noto-color-emoji \
|
||||||
|
fonts-noto-extra fonts-noto-ui-core fonts-noto-ui-extra
|
||||||
|
|
||||||
|
==========================================================================
|
||||||
Contact info: mailto:dianne@skoll.ca
|
Contact info: mailto:dianne@skoll.ca
|
||||||
Home page: https://dianne.skoll.ca/projects/remind/
|
Home page: https://dianne.skoll.ca/projects/remind/
|
||||||
|
|||||||
25
build.tk
Normal file → Executable file
25
build.tk
Normal file → Executable file
@@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# -*-Mode: TCL;-*-
|
# -*-Mode: TCL;-*-
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
# BUILD.TK
|
# BUILD.TK
|
||||||
@@ -26,10 +27,10 @@ exec wish "$0" "$@"
|
|||||||
proc SetConfigDefaults {} {
|
proc SetConfigDefaults {} {
|
||||||
global Config
|
global Config
|
||||||
set Config(LAT_DEG) 45
|
set Config(LAT_DEG) 45
|
||||||
set Config(LAT_MIN) 24
|
set Config(LAT_MIN) 25
|
||||||
set Config(LAT_SEC) 14
|
set Config(LAT_SEC) 14
|
||||||
set Config(LON_DEG) 75
|
set Config(LON_DEG) 75
|
||||||
set Config(LON_MIN) 39
|
set Config(LON_MIN) 41
|
||||||
set Config(LON_SEC) 23
|
set Config(LON_SEC) 23
|
||||||
set Config(LOCATION) "Ottawa"
|
set Config(LOCATION) "Ottawa"
|
||||||
set Config(DEFAULT_PAGE) "Letter"
|
set Config(DEFAULT_PAGE) "Letter"
|
||||||
@@ -189,8 +190,8 @@ proc CreateLocationDialog { w } {
|
|||||||
|
|
||||||
grid $w.north $w.west
|
grid $w.north $w.west
|
||||||
grid $w.south $w.east
|
grid $w.south $w.east
|
||||||
grid $w.loclab -sticky e
|
grid $w.loclab -sticky e
|
||||||
grid $w.location -sticky nsew -row 6 -column 1
|
grid $w.location -sticky nsew -row 8 -column 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
@@ -292,9 +293,9 @@ proc BuildRemind {} {
|
|||||||
|
|
||||||
.msgs insert end "\n>>> Creating src/custom.h...\n\n" green
|
.msgs insert end "\n>>> Creating src/custom.h...\n\n" green
|
||||||
CreateCustomH
|
CreateCustomH
|
||||||
.msgs insert end ">>> Calling `./configure'...\n\n" green
|
.msgs insert end "\n>>> Calling `./configure'...\n\n" green
|
||||||
CallConfigure
|
CallConfigure
|
||||||
.msgs insert end ">>> Calling `make'...\n\n" green
|
.msgs insert end "\n>>> Calling `make'...\n\n" green
|
||||||
CallMake
|
CallMake
|
||||||
.msgs insert end "\n----------------------------------------------\n\n"
|
.msgs insert end "\n----------------------------------------------\n\n"
|
||||||
.msgs insert end "Remind" red
|
.msgs insert end "Remind" red
|
||||||
@@ -446,12 +447,12 @@ proc CreateCustomH {} {
|
|||||||
"#define DEFAULT_LATITUDE *" {
|
"#define DEFAULT_LATITUDE *" {
|
||||||
set lat [expr $LAT_DEG + ($LAT_MIN/60.0) + ($LAT_SEC/3600.0)];
|
set lat [expr $LAT_DEG + ($LAT_MIN/60.0) + ($LAT_SEC/3600.0)];
|
||||||
puts $out "#define DEFAULT_LATITUDE $lat"
|
puts $out "#define DEFAULT_LATITUDE $lat"
|
||||||
.msgs insert end "#define DEFAULT_LATITUDE $lat"
|
.msgs insert end "#define DEFAULT_LATITUDE $lat\n"
|
||||||
}
|
}
|
||||||
"#define DEFAULT_LONGITUDE *" {
|
"#define DEFAULT_LONGITUDE *" {
|
||||||
set lon [expr -1.0 * ($LON_DEG + ($LON_MIN/60.0) + ($LON_SEC/3600.0))]
|
set lon [expr -1.0 * ($LON_DEG + ($LON_MIN/60.0) + ($LON_SEC/3600.0))]
|
||||||
puts $out "#define DEFAULT_LONGITUDE $lon"
|
puts $out "#define DEFAULT_LONGITUDE $lon"
|
||||||
.msgs insert end "#define DEFAULT_LONGITUDE $lon"
|
.msgs insert end "#define DEFAULT_LONGITUDE $lon\n"
|
||||||
}
|
}
|
||||||
"#define LOCATION *" {
|
"#define LOCATION *" {
|
||||||
puts $out "#define LOCATION \"$Config(LOCATION)\""
|
puts $out "#define LOCATION \"$Config(LOCATION)\""
|
||||||
@@ -505,7 +506,13 @@ proc CallMake {} {
|
|||||||
"Icelandic" { set lang ICELANDIC }
|
"Icelandic" { set lang ICELANDIC }
|
||||||
default { set lang ENGLISH }
|
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\""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
47
configure.in
47
configure.in
@@ -1,6 +1,7 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_INIT(src/queue.c)
|
AC_INIT
|
||||||
|
AC_CONFIG_SRCDIR([src/queue.c])
|
||||||
|
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ cat <<'EOF'
|
|||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
AC_CONFIG_HEADER(src/config.h)
|
AC_CONFIG_HEADERS([src/config.h])
|
||||||
|
|
||||||
AC_ARG_ENABLE(perl-build-artifacts,
|
AC_ARG_ENABLE(perl-build-artifacts,
|
||||||
[ --disable-perl-build-artifacts
|
[ --disable-perl-build-artifacts
|
||||||
@@ -29,33 +30,46 @@ AC_PATH_PROG([PERL], [perl])
|
|||||||
|
|
||||||
dnl Checks for libraries.
|
dnl Checks for libraries.
|
||||||
AC_CHECK_LIB(m, sqrt)
|
AC_CHECK_LIB(m, sqrt)
|
||||||
|
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||||
|
|
||||||
dnl Integer sizes
|
dnl Integer sizes
|
||||||
AC_CHECK_SIZEOF(unsigned int)
|
AC_CHECK_SIZEOF(unsigned int)
|
||||||
AC_CHECK_SIZEOF(unsigned long)
|
AC_CHECK_SIZEOF(unsigned long)
|
||||||
|
AC_CHECK_SIZEOF(time_t)
|
||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h langinfo.h)
|
AC_CHECK_HEADERS(sys/types.h glob.h wctype.h locale.h langinfo.h sys/inotify.h)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
|
|
||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_FUNC_UTIME_NULL
|
AC_FUNC_UTIME_NULL
|
||||||
AC_HEADER_TIME
|
|
||||||
|
|
||||||
if test "$GCC" = yes; then
|
if test "$GCC" = yes; then
|
||||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||||
# Check for link-time optimization support
|
# Check for link-time optimization support
|
||||||
for f in -flto=auto -ffat-lto-objects; do
|
f=-flto=auto
|
||||||
|
AC_MSG_CHECKING([whether $CC supports $f])
|
||||||
|
if $CC -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])
|
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])
|
AC_MSG_RESULT([yes])
|
||||||
CFLAGS="$CFLAGS $f"
|
CFLAGS="$CFLAGS $f"
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
fi
|
||||||
done
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
if test "$ac_cv_perlartifacts" = "yes" ; then
|
if test "$ac_cv_perlartifacts" = "yes" ; then
|
||||||
@@ -64,10 +78,21 @@ else
|
|||||||
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
|
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
|
RELEASE_DATE=`grep '[[0-9]][[0-9]][[0-9]][[0-9]]-[[0-9]][[0-9]]-[[0-9]][[0-9]]' docs/WHATSNEW | head -n 1 | awk '{print $NF}'`
|
||||||
VERSION=04.00.02
|
|
||||||
|
# Sanity-check release date
|
||||||
|
echo "$RELEASE_DATE" | grep '^....-..-..$' > /dev/null 2>&1
|
||||||
|
if test "$?" != 0 ; then
|
||||||
|
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups inotify_init1)
|
||||||
|
|
||||||
|
VERSION=04.03.01
|
||||||
AC_SUBST(VERSION)
|
AC_SUBST(VERSION)
|
||||||
AC_SUBST(PERL)
|
AC_SUBST(PERL)
|
||||||
AC_SUBST(PERLARTIFACTS)
|
AC_SUBST(PERLARTIFACTS)
|
||||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf)
|
AC_SUBST(RELEASE_DATE)
|
||||||
|
AC_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])
|
||||||
|
AC_OUTPUT
|
||||||
chmod a+x rem2pdf/bin/rem2pdf
|
chmod a+x rem2pdf/bin/rem2pdf
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
|
|
||||||
;; You should have received a copy of the GNU General Public License
|
;; You should have received a copy of the GNU General Public License
|
||||||
;; along with this program; if not, write to the Free Software
|
;; along with this program; if not, write to the Free Software
|
||||||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||||
;; 02111-1307, USA.
|
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
@@ -514,6 +513,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-start) "#")
|
(set (make-local-variable 'comment-start) "#")
|
||||||
(set (make-local-variable 'comment-end) "\n")
|
(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 '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 'fill-column) '100);cause I was having problems with autofill.
|
||||||
(set (make-local-variable 'indent-line-function) 'remind-indent-line)
|
(set (make-local-variable 'indent-line-function) 'remind-indent-line)
|
||||||
|
|||||||
469
docs/WHATSNEW
469
docs/WHATSNEW
@@ -1,8 +1,462 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
|
* 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
|
||||||
|
give a better error message suggesting THROUGH instead of UNTIL.
|
||||||
|
|
||||||
|
- BUG FIX: remind: The fix for the combination of ADDOMIT and SATISFY that
|
||||||
|
appeared in version 04.02.00 was not complete; the bug has finally been
|
||||||
|
properly fixed.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Remove an unnecessary #include <sys/file.h>.
|
||||||
|
Nothing needed that and it broke compilation on FreeBSD.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 4 - 2023-03-15
|
||||||
|
|
||||||
|
- NEW FEATURE: Remind: Add "htmlescape" and "htmlstriptags" built-in
|
||||||
|
functions.
|
||||||
|
|
||||||
|
- NEW FEATURE: Rem2PDF: Add the "--wrap, -y" option to ensure that no
|
||||||
|
printed calendar takes up more than 5 rows. If a calendar would normally
|
||||||
|
require 6 rows, wrap it so the last day or two appear on the first
|
||||||
|
row instead of on a sixth row.
|
||||||
|
|
||||||
|
- NEW FEATURE: Remind: Improve the -k option to allow specification of
|
||||||
|
separate commands for immediately-issued vs. queued reminders. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
remind '-kcmd1 %s' '-k:cmd2 %s' ...
|
||||||
|
|
||||||
|
will use "cmd1" for immediately-issued reminders and "cmd2" for queued
|
||||||
|
ones. If you only use '-k:cmd2 %s' then immediately-issued reminders
|
||||||
|
are simply printed as usual rather than being passed to a command.
|
||||||
|
|
||||||
|
- IMPROVEMENT: Remind: Make "SPECIAL MSG" the same as just "MSG" and
|
||||||
|
the same for MSF, RUN, PS and PSFILE. This effectively lets you use
|
||||||
|
expression-pasting to determine the type of a REM command; see the
|
||||||
|
remind(1) man page for details.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: If "make test" fails, output up to 200 lines of diff
|
||||||
|
so we can see immediately what failed.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Fix some typos; fix TkRemind syntax description.
|
||||||
|
|
||||||
|
- TEST FIX: Make tests run reliably regardless of local machine's time zone.
|
||||||
|
|
||||||
|
- BUG FIX: TkRemind: Don't crash if local installation of Tk lacks the
|
||||||
|
-underlinefg configuration option.
|
||||||
|
|
||||||
|
- BUG FIX: examples/defs.rem: Fix up US Thanksgiving example.
|
||||||
|
|
||||||
|
- BUG FIX: include/holidays/us.rem: Add logic for US holidays that are
|
||||||
|
observed on a Friday if the holiday is a Saturday, or on a Monday if the
|
||||||
|
holiday is a Sunday.
|
||||||
|
|
||||||
|
- BUG FIX: TkRemind: Don't cut off MOON text at the first white-space
|
||||||
|
character.
|
||||||
|
|
||||||
|
- BUG FIX: Remind: prevent functions defined on the command-line (as in
|
||||||
|
remind '-if(x)=whatever') from segfaulting.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 3 - 2023-02-10
|
||||||
|
|
||||||
|
- NEW FEATURE: Remind: add the orthodoxeaster() function to return the
|
||||||
|
date of Orthodox Easter.
|
||||||
|
|
||||||
|
- IMPROVEMENT: Add Greek language support courtesy of JeiEl.
|
||||||
|
|
||||||
|
- IMPROVEMENT: Add Greek holiday file courtesy of JeiEl.
|
||||||
|
|
||||||
|
- IMPROVEMENT: Fix the Perl code (rem2pdf, rem2html) to silence Perl::Critic
|
||||||
|
warnings
|
||||||
|
|
||||||
|
- IMPROVEMENT: Many internal code tweaks to eliminate many cppcheck
|
||||||
|
static analysis warnings.
|
||||||
|
|
||||||
|
- DOCUMENTATION IMPROVEMENT: Clarify the distinction between a "time"
|
||||||
|
and a "duration" as suggested by Ian! D. Allen.
|
||||||
|
|
||||||
|
- BUG FIX: Remind: Fix incorrect interaction between sortbanner() and
|
||||||
|
MSF-type reminders. Bug found by Tim Chase.
|
||||||
|
|
||||||
|
- BUG FIX: examples/defs.rem: Fix the calculation of US Tax Day as per
|
||||||
|
Tavis Ormandy and Tim Chase. Also fixed in include/holidays/us.rem
|
||||||
|
|
||||||
|
- BUG FIX: Remind: Add missing #include <fcntl.h> to funcs.c
|
||||||
|
|
||||||
|
- BUG FIX: Remind: Fix undefined integer-overflow behavior in built-in abs()
|
||||||
|
function. Pointed out on IRC by "ubitux".
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 2 - 2023-01-01
|
||||||
|
|
||||||
|
- NEW FEATURE: Remind: Add the NOQUEUE modifier to the REM statement for
|
||||||
|
explicitly telling Remind not to queue a timed reminder.
|
||||||
|
|
||||||
|
- NEW FEATURE: Remind: Add soleq() function to return the DATETIME of
|
||||||
|
solstices and equinoxes. See $SysInclude/seasons.rem for an example
|
||||||
|
of how to use the function.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: Update examples/astro to include solstices and equinoxes.
|
||||||
|
|
||||||
|
- BUG FIX: TkRemind: Provide better error indication if showing today's
|
||||||
|
reminders fails on startup.
|
||||||
|
|
||||||
|
- BUG FIX: Remind: Refuse to read world-writable directories.
|
||||||
|
|
||||||
|
- BUG FIX: Tests depended on the actual date of the test run. This has
|
||||||
|
been fixed.
|
||||||
|
|
||||||
|
- INTERNAL CHANGE: Remind: Change inappropriately-named "Julian" variables
|
||||||
|
to "DSE" (= Days Since Epoch) since they weren't really holding true
|
||||||
|
Julian dates.
|
||||||
|
|
||||||
|
- INTERNAL CHANGE: Add "SPDX-License-Identifier" tags to most files.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 1 - 2022-12-15
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: TkRemind: If "Extra Remind Options" contains -m, make
|
||||||
|
TkRemind start the calendar with Monday instead of Sunday.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: Sample files: Add French holidays courtesy of
|
||||||
|
Clément Bœsch.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: A few performance fixes, likely not even noticeable in
|
||||||
|
most cases.
|
||||||
|
|
||||||
|
- MINOR FIXES: Fix misleading comments in the source code.
|
||||||
|
|
||||||
|
- MINOR FIX: Remove a bunch of dead code in the moon-phase routines.
|
||||||
|
|
||||||
|
- MINOR FIX: Remove unnecessary %"...%" markers in holidays/us.rem
|
||||||
|
|
||||||
|
- MINOR FIX: Don't use the -ffat-lto-objects command-line option if we're
|
||||||
|
compiling with Clang.
|
||||||
|
|
||||||
|
- MINOR FIX: Remind: Fix a broken printf-format string (need to double up on %
|
||||||
|
to get a literal % in the output.)
|
||||||
|
|
||||||
|
- BUG FIX: Make test suite pass regardless of the date on which it is run.
|
||||||
|
D'oh!!!
|
||||||
|
|
||||||
|
- BUG FIX: Make sure the banner gets printed each time through a "*N"
|
||||||
|
command-line option loop.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 0 - 2022-10-14
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Allow weekdays to be globally-omitted. For example:
|
||||||
|
|
||||||
|
OMIT Saturday Sunday
|
||||||
|
|
||||||
|
globally-omits all Saturdays and Sundays.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add ansicolor() built-in function to make it easier
|
||||||
|
to colorize reminders on the terminal. Suggested by Tim Chase.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add several special variables related to the color
|
||||||
|
mode: $UseVTColors, $UseBGVTColors, $Use256Colors, $UseTrueColors and
|
||||||
|
$TerminalBackground. Based on a suggestion by Tim Chase.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add utctolocal() and localtoutc() built-in functions.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add timezone() built-in function.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add trigtags() function per suggestion from Tim Chase.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The $AddBlankLines system variable controls whether or
|
||||||
|
not a blank line is added after each reminder.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The built-in functions columns() and rows() return the
|
||||||
|
width and height of the terminal (in character positions) respectively.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The built-in function columns("string") returns the
|
||||||
|
number of columns occupied by "string" on the terminal, taking into account
|
||||||
|
double-width Unicode characters and zero-width ANSI escape sequences.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: You can add custom substitution sequences of the form
|
||||||
|
%{name} or %*{name} that end up calling the function subst_name and using
|
||||||
|
its return value as the replacement for the substitution sequence.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add the FUNSET command to undefine a user-defined
|
||||||
|
function.
|
||||||
|
|
||||||
|
- NEW FILES: Add standard include files holidays/jewish.rem and
|
||||||
|
ansitext.rem (the latter defines standard ANSI escape codes for
|
||||||
|
changing text attributes such as bold, underline, etc.)
|
||||||
|
|
||||||
|
- NEW EXAMPLES: add examples/alignmemt.rem, examples/ansitext and
|
||||||
|
examples/astro
|
||||||
|
|
||||||
|
- BUG FIX: remind: Make MSF correctly format UTF-8 text and text with
|
||||||
|
embedded ANSI color-changing codes.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Make ADDOMIT actually work correctly in a SATISFY-type
|
||||||
|
REM command. Bug found by Gunther Reißig
|
||||||
|
|
||||||
|
- BUG FIX: Convert documentation files and src/lang.h to UTF-8. Patch
|
||||||
|
from Jochen Sprickerhof.
|
||||||
|
|
||||||
|
- BUG FIX: Fix tests in non-UTF-8 locales.
|
||||||
|
|
||||||
|
- BUG FIX: Fix a few problems with the include/holidays/us.rem file.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Fix an ancient logic error in DBufPutc that hurt
|
||||||
|
performance.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENT: Clean up code and remove some dead code.
|
||||||
|
|
||||||
|
* VERSION 4.1 Patch 0 - 2022-09-25
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: "remind -c" now supports the MOON special, printing
|
||||||
|
the moon phases in the calendar if the locale supports UTF-8 encoding.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: "remind -c" now supports the SHADE special. Works
|
||||||
|
best with the 256-color extended XTerm palette or 24-bit true-color
|
||||||
|
terminal escape sequences.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: "remind -c" now supports the WEEK special.
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: The new "stdout()" function returns a string describing
|
||||||
|
where stdout is going. Examples of return values are "TTY" if remind's
|
||||||
|
output is going to terminal, "FILE" if it's redirected to a plain file,
|
||||||
|
or "PIPE" if it's going to a pipe. See the man page for all the details.
|
||||||
|
|
||||||
|
- NEW FEATURE: Add the "-wt" option to set the calendar width to the terminal
|
||||||
|
width even if standard output is a pipe. Useful for situations like this:
|
||||||
|
|
||||||
|
remind -wt -c .reminders | less -R
|
||||||
|
|
||||||
|
- CHANGE: "make install" now no longer strips debugging symbols from the
|
||||||
|
remind and rem2ps executables. Use "make install-stripped" if you want
|
||||||
|
them stripped.
|
||||||
|
|
||||||
|
- CHANGE: remind: "remind -c" highlights today's date in bold, if
|
||||||
|
colors are enabled.
|
||||||
|
|
||||||
|
- CHANGE: Dump string values with control characters escaped.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Document behavior of DO and filedir() with respect
|
||||||
|
to symbolic links.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Add home page link to man pages. Suggested by Ian! D.
|
||||||
|
Allen.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Make date in man pages actually be the release date.
|
||||||
|
Include Remind version in man pages. Also suggested by Ian! D. Allen.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Fix inaccuracy in how string constants were documented.
|
||||||
|
|
||||||
|
- BUG FIX: Makefiles: Pass CFLAGS at link-time so link-time optimization
|
||||||
|
actually happens. Pointed out by Zoltan Puskas.
|
||||||
|
|
||||||
|
- BUG FIX: If the first REM command to trigger was a RUN command, the banner
|
||||||
|
would not print. This has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: replace deprecated 'fgrep' with 'grep -F' (Jochen Sprickerhof)
|
||||||
|
|
||||||
|
- BUG FIX: make "make test" depend on "make all" (Jochen Sprickerhof)
|
||||||
|
|
||||||
|
- BUG FIX: make "REM ... SATISFY ... MSG foo" respect $DefaultColor. Bug
|
||||||
|
reported by Gunther Reißig.
|
||||||
|
|
||||||
|
- BUG FIX: Don't consider IFTRIG true if we could not compute a trigger date.
|
||||||
|
Bug noted by Gunther Reißig.
|
||||||
|
|
||||||
|
* VERSION 4.0 Patch 3 - 2022-08-16
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: add plain_body and calendar_body JSON keys in -pp...
|
||||||
|
output.
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: Don't create empty files called '&1' when creating
|
||||||
|
a new reminder.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Don't call signal-unsafe functions from signal handler
|
||||||
|
|
||||||
* VERSION 4.0 Patch 2 - 2022-08-02
|
* VERSION 4.0 Patch 2 - 2022-08-02
|
||||||
|
|
||||||
- IMPROVEMENT: remind: Allow more forms of OMIT as per Ian D. Allen!'s request:
|
- IMPROVEMENT: remind: Allow more forms of OMIT as per Ian! D. Allen's request:
|
||||||
|
|
||||||
OMIT Month [THROUGH Month]
|
OMIT Month [THROUGH Month]
|
||||||
OMIT Day Month [THROUGH Day Month]
|
OMIT Day Month [THROUGH Day Month]
|
||||||
@@ -1057,7 +1511,7 @@ CHANGES TO REMIND
|
|||||||
- Fixed dates for Yom Hazikaron and Yom Ha'atzmaut if 5 Iyar falls on a
|
- Fixed dates for Yom Hazikaron and Yom Ha'atzmaut if 5 Iyar falls on a
|
||||||
Saturday. (Hebrew calendar fix.)
|
Saturday. (Hebrew calendar fix.)
|
||||||
|
|
||||||
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
|
- Added support for the Icelandic language, courtesy of Björn Davíðsson.
|
||||||
|
|
||||||
+ BUG FIXES
|
+ BUG FIXES
|
||||||
|
|
||||||
@@ -1204,7 +1658,7 @@ CHANGES TO REMIND
|
|||||||
- Made parser _very_ forgiving -- the type of reminder now defaults
|
- Made parser _very_ forgiving -- the type of reminder now defaults
|
||||||
to MSG. This lets you have lines in the reminder file like this:
|
to MSG. This lets you have lines in the reminder file like this:
|
||||||
|
|
||||||
Feb 9, 1998 Meeting with Joe.
|
Feb 9, 1998 Meeting with Joe.
|
||||||
|
|
||||||
But I don't recommend abusing it. It's mostly to ease migration from
|
But I don't recommend abusing it. It's mostly to ease migration from
|
||||||
UNIX calendar(1) files.
|
UNIX calendar(1) files.
|
||||||
@@ -1734,7 +2188,7 @@ CHANGES TO REMIND
|
|||||||
of Mikko Silvonen.
|
of Mikko Silvonen.
|
||||||
|
|
||||||
- Changed the date conversion routines to greatly speed up conversion from
|
- Changed the date conversion routines to greatly speed up conversion from
|
||||||
Julian to yyyy/mm/dd form.
|
Days-since-epoch to yyyy/mm/dd form.
|
||||||
|
|
||||||
+ BUG FIXES:
|
+ BUG FIXES:
|
||||||
|
|
||||||
@@ -1795,7 +2249,7 @@ CHANGES TO REMIND
|
|||||||
|
|
||||||
- Removed identifiers in the C source beginning with "_" to conform
|
- Removed identifiers in the C source beginning with "_" to conform
|
||||||
to ANSI practice.
|
to ANSI practice.
|
||||||
|
|
||||||
- Fixed a bug in the -u option which resulted in environment variables
|
- Fixed a bug in the -u option which resulted in environment variables
|
||||||
SHELL and USER not being set correctly. Also made -u set the LOGNAME
|
SHELL and USER not being set correctly. Also made -u set the LOGNAME
|
||||||
environment variable.
|
environment variable.
|
||||||
@@ -1868,7 +2322,7 @@ CHANGES TO REMIND
|
|||||||
|
|
||||||
- Fixed all the source files to include "config.h" first.
|
- Fixed all the source files to include "config.h" first.
|
||||||
|
|
||||||
- Changed the way triggers are calculated so that trigger dates are
|
- Changed the way triggers are calculated so that trigger dates are
|
||||||
always valid if year, month and day are specified, and there is no
|
always valid if year, month and day are specified, and there is no
|
||||||
UNTIL clause. See MAN page section "DETAILS ABOUT TRIGVALID()."
|
UNTIL clause. See MAN page section "DETAILS ABOUT TRIGVALID()."
|
||||||
|
|
||||||
@@ -2010,6 +2464,3 @@ CHANGES TO REMIND
|
|||||||
* Version 1.0
|
* Version 1.0
|
||||||
|
|
||||||
- never publicly released.
|
- never publicly released.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
19
examples/alignment.rem
Normal file
19
examples/alignment.rem
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Demo the columns() function
|
||||||
|
#
|
||||||
|
# Run as: remind -@2 alignment.rem
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
SET $AddBlankLines 0
|
||||||
|
BANNER %
|
||||||
|
|
||||||
|
FSET center(x) pad("", " ", (columns() - columns(x))/2) + x
|
||||||
|
FSET right(x) pad("", " ", columns() - columns(x)) + x
|
||||||
|
|
||||||
|
MSG This is left-aligned.
|
||||||
|
MSG [ansicolor(0,255,0)]🌕 🌕 🌕 🌕 This is also left-aligned.[ansicolor("")]
|
||||||
|
|
||||||
|
MSG [center("This is centered.")]
|
||||||
|
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
|
||||||
|
|
||||||
|
msg [right("This is right-aligned.")]
|
||||||
|
msg [ansicolor(255,0,0) + right("This is also right-aligned. 🌕 🌕 🌕") + ansicolor("")]
|
||||||
36
examples/ansitext
Executable file
36
examples/ansitext
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# A little demo script that displays ANSI text attributes
|
||||||
|
# Not all attributes work on all terminals... your mileage may vary.
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
remind -@2 - <<'EOF'
|
||||||
|
|
||||||
|
SET $AddBlankLines 0
|
||||||
|
BANNER %
|
||||||
|
INCLUDE [$SysInclude]/ansitext.rem
|
||||||
|
MSG This file shows off some ANSI text attributes and colors.
|
||||||
|
MSG Not all attributes work on all terminals.%_
|
||||||
|
|
||||||
|
MSG This is [ansi_bold]bold.[ansi_normal]
|
||||||
|
MSG This is [ansi_faint]faint.[ansi_normal]
|
||||||
|
MSG This is [ansi_italic]italic.[ansi_normal]
|
||||||
|
MSG This is [ansi_underline]underline.[ansi_normal]
|
||||||
|
MSG This is [ansi_underline2]underline2.[ansi_normal]%_
|
||||||
|
MSG This is [ansi_reverse]reverse.[ansi_normal]%_
|
||||||
|
MSG This is [ansi_strikeout]strikeout.[ansi_normal]%_
|
||||||
|
MSG This is [ansi_overline]overline.[ansi_normal]%_
|
||||||
|
|
||||||
|
MSG This is [ansicolor(255,0,0)]red.[ansicolor("")]
|
||||||
|
MSG This is [ansicolor(0,255,0)]green.[ansicolor("")]
|
||||||
|
MSG This is [ansicolor(0,0,255)]blue.[ansicolor("")]
|
||||||
|
MSG This is [ansicolor(255,255,0)]yellow.[ansicolor("")]
|
||||||
|
MSG This is [ansicolor(255,0,255)]magenta.[ansicolor("")]
|
||||||
|
MSG This is [ansicolor(0,255,255)]cyan.[ansicolor("")]%_
|
||||||
|
|
||||||
|
# You can combine attributes
|
||||||
|
MSG This is [ansicolor(0,255,0)][ansicolor(0,0,96,1)][ansi_italic][ansi_bold]Green-Bold-Italic-on-Blue[ansi_normal][ansicolor("")]
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exit 0
|
||||||
69
examples/astro
Executable file
69
examples/astro
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# A little demo script that displays astronomical events
|
||||||
|
#
|
||||||
|
# Best used in a UTF-8 environment.
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
# Set this variable to 1 if your terminal has a dark background or 0 if
|
||||||
|
# it: light.
|
||||||
|
|
||||||
|
# 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 "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||||
|
SET $AddBlankLines 0
|
||||||
|
BANNER %
|
||||||
|
|
||||||
|
INCLUDE [$SysInclude]/ansitext.rem
|
||||||
|
|
||||||
|
MSG Today is [ansi_bold][$T][ansi_normal], being the [ord($T-date(year($T),1,1)+1)] day of [year($T)].%_
|
||||||
|
|
||||||
|
IF $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 "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||||
|
SET $AddBlankLines 0
|
||||||
|
BANNER %
|
||||||
|
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
|
||||||
|
REM [moondatetime(0)] +60 SPECIAL COLOR 128 128 0 New moon: 🌑 [$T] %3 (%b)
|
||||||
|
REM [moondatetime(1)] +60 SPECIAL COLOR 128 128 64 First Quarter: 🌓 [$T] %3 (%b)
|
||||||
|
REM [moondatetime(2)] +60 SPECIAL COLOR 0 0 0 Full moon: 🌕 [$T] %3 (%b)
|
||||||
|
REM [moondatetime(3)] +60 SPECIAL COLOR 128 128 64 Last Quarter: 🌗 [$T] %3 (%b)
|
||||||
|
ENDIF
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
remind -g "-i\$Latitude=\"$latitude\"" "-i\$Longitude=\"$longitude\"" -q -@2 - "$@" <<'EOF'
|
||||||
|
SET $AddBlankLines 0
|
||||||
|
BANNER %
|
||||||
|
|
||||||
|
IF $LatDeg >= 0
|
||||||
|
REM [soleq(0)] +366 MSG Next Vernal Equinox: 🌼 [$T] %3 (%b)
|
||||||
|
REM [soleq(1)] +366 MSG Next Summer Solstice: 😎 [$T] %3 (%b)
|
||||||
|
REM [soleq(2)] +366 MSG Next Autumnal Equinox: 🍂 [$T] %3 (%b)
|
||||||
|
REM [soleq(3)] +366 MSG Next Winter Solstice: ❄️ [$T] %3 (%b)
|
||||||
|
ELSE
|
||||||
|
REM [soleq(0)] +366 MSG Next Autumnal Equinox: 🍂 [$T] %3 (%b)
|
||||||
|
REM [soleq(1)] +366 MSG Next Winter Solstice: ❄️ [$T] %3 (%b)
|
||||||
|
REM [soleq(2)] +366 MSG Next Vernal Equinox: 🌼 [$T] %3 (%b)
|
||||||
|
REM [soleq(3)] +366 MSG Next Summer Solstice: 😎 [$T] %3 (%b)
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
EOF
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
# "#PSSTUFF" for nifty PostScript examples #
|
# "#PSSTUFF" for nifty PostScript examples #
|
||||||
# #
|
# #
|
||||||
# This file is part of REMIND. #
|
# This file is part of REMIND. #
|
||||||
# Copyright (C) 1992-2022 Dianne Skoll #
|
# Copyright (C) 1992-2024 Dianne Skoll #
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# #
|
# #
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
@@ -41,7 +42,6 @@ SET Week_1 1
|
|||||||
SET Week_2 8
|
SET Week_2 8
|
||||||
SET Week_3 15
|
SET Week_3 15
|
||||||
SET Week_4 22
|
SET Week_4 22
|
||||||
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Function that removes a single leading zero from a string... #
|
# Function that removes a single leading zero from a string... #
|
||||||
@@ -77,16 +77,16 @@ REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
|
|||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
# If it falls on a Saturday, bump to previous Friday
|
# If it falls on a Saturday, bump to previous Friday
|
||||||
REM 4 July OMIT SAT SCANFROM -1 BEFORE ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
|
REM 3 JULY SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Independence day (observed)
|
||||||
|
|
||||||
# If it falls on a Sunday, bump to following Monday
|
# If it falls on a Sunday, bump to following Monday
|
||||||
REM 4 July OMIT SUN SCANFROM -7 AFTER ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
|
REM 5 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Independence day (observed)
|
||||||
|
|
||||||
# If it falls on Sat or Sun, note the actual day
|
# If it falls on Sat or Sun, note the actual day
|
||||||
REM 4 July SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
|
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
|
||||||
|
|
||||||
# Otherwise observed and actual is on the 4th
|
# Otherwise observed and actual is on the 4th
|
||||||
REM 4 July OMIT SAT SUN SKIP SCANFROM -7 ADDOMIT MSG Independence Day
|
REM 4 July SCANFROM -7 ADDOMIT SATISFY [$Tw >= 1 && $Tw <= 5] MSG Independence Day
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# #
|
# #
|
||||||
@@ -125,6 +125,8 @@ REM Sat Sun SPECIAL SHADE 220
|
|||||||
# The following holidays were provided by Dave Rickel #
|
# The following holidays were provided by Dave Rickel #
|
||||||
# Modified by D. Skoll to give safe OMITs for moveable holidays #
|
# Modified by D. Skoll to give safe OMITs for moveable holidays #
|
||||||
# #
|
# #
|
||||||
|
# NOTE: See include/holidays/us.rem for more up-to-date definitions #
|
||||||
|
# #
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
SET SaveTrig $NumTrig
|
SET SaveTrig $NumTrig
|
||||||
@@ -156,7 +158,24 @@ REM Last Sunday in October ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST
|
|||||||
REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
||||||
|
|
||||||
REM Apr 1 MSG %"April Fool's%" Day
|
REM Apr 1 MSG %"April Fool's%" Day
|
||||||
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
|
|
||||||
|
# US Tax Day
|
||||||
|
PUSH-OMIT-CONTEXT
|
||||||
|
# Normal case: 16 April falls Mon-Fri
|
||||||
|
REM 16 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw >= 1 && $Tw <= 5] MSG Emancipation Day
|
||||||
|
|
||||||
|
# 16 April falls on Saturday: Observe on the 15th
|
||||||
|
REM 15 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Emancipation Day (observed)
|
||||||
|
|
||||||
|
# 16 April falls on Sunday: Observe on the 17th
|
||||||
|
REM 17 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Emancipation Day (observed)
|
||||||
|
|
||||||
|
# If you live in Maine or Massachussetts, uncomment the next line
|
||||||
|
# REM Third Monday in April SCANFROM -7 ADDOMIT MSG Patriots Day
|
||||||
|
|
||||||
|
REM Apr 15 OMIT Sat Sun AFTER MSG Tax Day
|
||||||
|
POP-OMIT-CONTEXT
|
||||||
|
|
||||||
REM May 5 MSG %"Cinco de Mayo%"
|
REM May 5 MSG %"Cinco de Mayo%"
|
||||||
REM First Sat in May MSG %"Kentucky Derby%"
|
REM First Sat in May MSG %"Kentucky Derby%"
|
||||||
REM Second Sun in May MSG %"Mother's Day%"
|
REM Second Sun in May MSG %"Mother's Day%"
|
||||||
@@ -171,7 +190,7 @@ REM Nov 11 MSG %"Veterans Day%"
|
|||||||
REM Oct 30 MSG %"Mischief Night%"
|
REM Oct 30 MSG %"Mischief Night%"
|
||||||
REM Oct 31 MSG %"Halloween%"
|
REM Oct 31 MSG %"Halloween%"
|
||||||
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
|
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
|
||||||
REM Last Thu in Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
|
REM Thu Nov [Week_4] SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
|
||||||
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
|
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
|
||||||
OMIT Dec 24 MSG %"Christmas Eve%"
|
OMIT Dec 24 MSG %"Christmas Eve%"
|
||||||
OMIT Dec 25 MSG %"Christmas%" Day
|
OMIT Dec 25 MSG %"Christmas%" Day
|
||||||
|
|||||||
35
include/ansitext.rem
Normal file
35
include/ansitext.rem
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Global variables for various ANSI escape-code sequences
|
||||||
|
# Not all sequences are supported by all terminals.
|
||||||
|
|
||||||
|
# This file is part of REMIND
|
||||||
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
if !defined("ansi_bold")
|
||||||
|
# Disable ANSI attributes in calandar mode
|
||||||
|
if $CalMode
|
||||||
|
set ansi_normal ""
|
||||||
|
set ansi_bold ""
|
||||||
|
set ansi_faint ""
|
||||||
|
set ansi_italic ""
|
||||||
|
set ansi_underline ""
|
||||||
|
set ansi_reverse ""
|
||||||
|
set ansi_strikeout ""
|
||||||
|
set ansi_underline2 ""
|
||||||
|
set ansi_overline ""
|
||||||
|
else
|
||||||
|
set ansi_normal char(27) + "[0m"
|
||||||
|
set ansi_bold char(27) + "[1m"
|
||||||
|
set ansi_faint char(27) + "[2m"
|
||||||
|
set ansi_italic char(27) + "[3m"
|
||||||
|
set ansi_underline char(27) + "[4m"
|
||||||
|
set ansi_reverse char(27) + "[7m"
|
||||||
|
set ansi_strikeout char(27) + "[9m"
|
||||||
|
set ansi_underline2 char(27) + "[21m"
|
||||||
|
set ansi_overline char(27) + "[53m"
|
||||||
|
endif
|
||||||
|
preserve ansi_normal ansi_bold ansi_faint ansi_italic ansi_underline2 ansi_reverse ansi_strikeout ansi_underline2 ansi_overline
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Example: REM MSG I must [ansi_bold]emphasize[ansi_normal] \
|
||||||
|
# the [ansi_italic]severity[ansi_normal] of the situation!
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Canadian holidays
|
# Canadian holidays
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
OMIT 1 Jan MSG New Year's Day
|
OMIT 1 Jan MSG New Year's Day
|
||||||
|
|
||||||
|
|||||||
20
include/holidays/fr.rem
Normal file
20
include/holidays/fr.rem
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#
|
||||||
|
# France Holidays
|
||||||
|
#
|
||||||
|
# Source: Article L3133-1
|
||||||
|
# https://www.legifrance.gouv.fr/codes/section_lc/LEGITEXT000006072050/LEGISCTA000006178007/2016-08-10/
|
||||||
|
#
|
||||||
|
|
||||||
|
SET easter EASTERDATE($Uy)
|
||||||
|
|
||||||
|
REM Jan 1 MSG %"Jour de l'an%"
|
||||||
|
REM [easter+1] MSG %"Lundi de Pâques%"
|
||||||
|
REM May 1 MSG %"Fête du Travail%"
|
||||||
|
REM May 8 MSG %"Victoire des alliés%"
|
||||||
|
REM [easter+39] MSG %"Jeudi de l'Ascension%"
|
||||||
|
REM [easter+50] MSG %"Lundi de Pentecôte%"
|
||||||
|
REM Jul 14 MSG %"Fête nationale%"
|
||||||
|
REM Aug 15 MSG %"Assomption%"
|
||||||
|
REM Nov 1 MSG %"La Toussaint%"
|
||||||
|
REM Nov 11 MSG %"Armistice%"
|
||||||
|
REM Dec 25 MSG %"Noël%"
|
||||||
39
include/holidays/gr.rem
Normal file
39
include/holidays/gr.rem
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Greek national holidays
|
||||||
|
# ΑΡΓΙΕΣ (για όλους)
|
||||||
|
|
||||||
|
# fixed
|
||||||
|
REM 1 Jan MSG ΠΡΩΤΟΧΡΟΝΙΑ
|
||||||
|
REM 6 Jan MSG ΤΑ ΦΩΤΑ/ ΘΕΟΦΑΝΕΙΑ
|
||||||
|
REM 25 Mar MSG η 25η Μαρτίου
|
||||||
|
REM 15 Aug MSG 15Αύγουστος
|
||||||
|
REM 28 Oct MSG ΟΧΙ
|
||||||
|
REM 25 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ
|
||||||
|
REM 26 Dec MSG ΧΡΙΣΤΟΥΓΕΝΝΑ2
|
||||||
|
|
||||||
|
REM [orthodoxeaster($Uy)+1] ΔΕΥΤΕΡΑ ΤΟΥ ΠΑΣΧΑ
|
||||||
|
|
||||||
|
|
||||||
|
# May first is a national holiday except if Sunday, day of great week (week before easter) or Monday after easter, then
|
||||||
|
# minister decides moving that holiday. Here is a likely assumption of how this day might be moved.
|
||||||
|
# Uncomment following lines to enable.
|
||||||
|
|
||||||
|
set PM date($Uy,5,1)
|
||||||
|
# IF PM>=orthodoxeaster($Uy)-7 && PM<=orthodoxeaster($Uy)+1
|
||||||
|
# IF PM<orthodoxeaster($Uy)-3
|
||||||
|
# REM orthodoxeaster($Uy) -8 MSG πιθανόν ΕΡΓΑΤΙΚΗ Πρωτομαγιά
|
||||||
|
# ELSE
|
||||||
|
# REM [plusfunc(2)] MSG πιθανόν ΕΡΓΑΤΙΚΗ Πρωτομαγιά
|
||||||
|
# ENDIF
|
||||||
|
# ENDIF
|
||||||
|
# REM [PM] OMIT Sun AFTER MSG Πρωτομαγιά
|
||||||
|
|
||||||
|
REM 1 May MSG Πρωτομαγιά
|
||||||
|
# end of May 1 speculations
|
||||||
|
|
||||||
|
# The following are main national holidays per custom (observed by most but not all)
|
||||||
|
REM [orthodoxeaster($Uy)] -48 MSG Καθαρά Δευτέρα
|
||||||
|
REM [orthodoxeaster($Uy)] -2 MSG Μεγάλη Παρασκευή
|
||||||
|
REM [orthodoxeaster($Uy)] -1 MSG Μεγάλο Σάββατο
|
||||||
|
REM [orthodoxeaster($Uy)+50] MSG Αγίου Πνεύματος
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
112
include/holidays/jewish.rem
Normal file
112
include/holidays/jewish.rem
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# Major Jewish Holidays
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
|
||||||
|
# you get the Diaspora versions of Jewish holidays
|
||||||
|
SET InIsrael value("InIsrael", 0)
|
||||||
|
|
||||||
|
# Set the variable Reform to 1 if you want the Reform version of the
|
||||||
|
# Jewish calendar. Otherwise, you get the traditional version
|
||||||
|
SET Reform value("Reform", 0)
|
||||||
|
|
||||||
|
# Convenient function definition to save typing
|
||||||
|
FSET _h(x, y) HEBDATE(x,y)
|
||||||
|
FSET _h2(x, y) HEBDATE(x, y, $U-7)
|
||||||
|
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
|
||||||
|
FSET _BackTwoFri(x, y) IIF(WKDAYNUM(_h2(x,y))!=5, _h2(x,y), _h2(x,y)-2)
|
||||||
|
FSET _BackTwoSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)-2)
|
||||||
|
# Default values in case InIsrael and Reform are not set
|
||||||
|
SET InIsrael VALUE("InIsrael", 0)
|
||||||
|
SET Reform VALUE("Reform", 0)
|
||||||
|
|
||||||
|
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
|
||||||
|
|
||||||
|
# No RH-2 or Tzom Gedalia in Reform
|
||||||
|
IF !Reform
|
||||||
|
[_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
|
||||||
|
[_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
|
||||||
|
[_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
|
||||||
|
|
||||||
|
IF !InIsrael
|
||||||
|
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(21, "Tishrey")] ++4 MSG %"Hoshana Rabba%" is %b.
|
||||||
|
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
|
||||||
|
|
||||||
|
IF InIsrael
|
||||||
|
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
|
ELSE
|
||||||
|
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
# Because Kislev can change length, we must be more careful about Chanukah
|
||||||
|
FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
|
||||||
|
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||||
|
[_chan(2)] MSG %"Chanukah 2%"
|
||||||
|
[_chan(3)] MSG %"Chanukah 3%"
|
||||||
|
[_chan(4)] MSG %"Chanukah 4%"
|
||||||
|
[_chan(5)] MSG %"Chanukah 5%"
|
||||||
|
[_chan(6)] MSG %"Chanukah 6%"
|
||||||
|
[_chan(7)] MSG %"Chanukah 7%"
|
||||||
|
[_chan(8)] MSG %"Chanukah 8%"
|
||||||
|
|
||||||
|
# Not sure about Reform's position on the next one.
|
||||||
|
IF !Reform
|
||||||
|
# 10 Tevet will never be a Saturday, so whether or not to
|
||||||
|
# move it is moot. (Thanks to Art Werschulz.)
|
||||||
|
[_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
|
||||||
|
[_h(14, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
|
||||||
|
|
||||||
|
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||||
|
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||||
|
REM [_h2(13, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||||
|
ELSE
|
||||||
|
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||||
|
ENDIF
|
||||||
|
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||||
|
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
|
||||||
|
|
||||||
|
IF !InIsrael
|
||||||
|
[_h(16, "Nisan")] MSG %"Pesach 2%"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(21, "Nisan")] MSG %"Pesach 7%"
|
||||||
|
|
||||||
|
IF !InIsrael && !Reform
|
||||||
|
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||||
|
[_BackTwoFri(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
|
||||||
|
[_BackTwoSat(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||||
|
|
||||||
|
# Not sure about Reform's position on Lag B'Omer
|
||||||
|
IF !Reform
|
||||||
|
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
[_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
|
||||||
|
[_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
|
||||||
|
|
||||||
|
IF !InIsrael && !Reform
|
||||||
|
[_h(7, "Sivan")] MSG %"Shavuot 2%"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
# Fairly sure Reform Jews don't observe the next two
|
||||||
|
IF !Reform
|
||||||
|
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
|
||||||
|
# fall on a Saturday
|
||||||
|
[_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
|
||||||
|
[_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
FUNSET _h _h2 _PastSat _BackTwoFri _BackTwoSat _chan
|
||||||
|
|
||||||
@@ -1,49 +1,82 @@
|
|||||||
# US holidays
|
# US holidays
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2022 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
REM [easterdate($Uy)-46] MSG %"Ash Wednesday%"
|
REM [easterdate($Uy)-46] MSG Ash Wednesday
|
||||||
REM [easterdate($Uy)-7] MSG %"Palm Sunday%"
|
REM [easterdate($Uy)-7] MSG Palm Sunday
|
||||||
OMIT [easterdate($Uy)-2] MSG %"Good Friday%"
|
OMIT [easterdate($Uy)-2] MSG Good Friday
|
||||||
OMIT [easterdate($Uy)] MSG %"Easter%" Sunday
|
OMIT [easterdate($Uy)] MSG %"Easter%" Sunday
|
||||||
REM [easterdate($Uy)+39] MSG %"Ascension Day%"
|
REM [easterdate($Uy)+39] MSG Ascension Day
|
||||||
REM [easterdate($Uy)+49] MSG %"Pentecost%"
|
REM [easterdate($Uy)+49] MSG Pentecost
|
||||||
|
|
||||||
# Some holidays are omitted, some are not. You may want to change
|
# Some holidays are omitted, some are not. You may want to change
|
||||||
# which ones are omitted.
|
# which ones are omitted.
|
||||||
|
|
||||||
OMIT Jan 1 MSG %"New Year's Day%"
|
OMIT Jan 1 MSG New Year's Day
|
||||||
|
REM 31 Dec SCANFROM -7 ADDOMIT SATISFY [$Tw==5] MSG New Year's Day (observed)
|
||||||
|
REM 2 Jan SCANFROM -7 ADDOMIT SATISFY [$Tw==1] MSG New Year's Day (observed)
|
||||||
|
|
||||||
REM Third Monday in Jan MSG Martin Luther King - %"MLK Day%"
|
REM Third Monday in Jan MSG Martin Luther King - %"MLK Day%"
|
||||||
REM Feb 2 MSG %"Ground Hog Day%"
|
REM Feb 2 MSG Ground Hog Day
|
||||||
REM Feb 14 MSG %"Valentine's Day%"
|
REM Feb 14 MSG Valentine's Day
|
||||||
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG %"President's Day%"
|
REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG President's Day
|
||||||
REM Mar 17 MSG %"St. Patrick's Day%"
|
REM Mar 17 MSG St. Patrick's Day
|
||||||
|
|
||||||
# The DST rules are accurate for most locations in
|
# These are accurate for most places in North America
|
||||||
# North America
|
REM MAYBE-UNCOMPUTABLE Sun November SATISFY [isdst($T) && !isdst($T+1)] MSG Daylight Saving Time Ends
|
||||||
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
|
REM MAYBE-UNCOMPUTABLE Sun March SATISFY [!isdst($T) && isdst($T+1)] MSG Daylight Saving Time Starts
|
||||||
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
|
|
||||||
|
|
||||||
REM Last Sunday in October ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
|
||||||
REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
|
||||||
|
|
||||||
REM Apr 1 MSG %"April Fool's%" Day
|
REM Apr 1 MSG %"April Fool's%" Day
|
||||||
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
|
|
||||||
REM May 5 MSG %"Cinco de Mayo%"
|
|
||||||
REM First Sat in May MSG %"Kentucky Derby%"
|
|
||||||
REM Second Sun in May MSG %"Mother's Day%"
|
|
||||||
REM Third Sat in May MSG %"Armed Forces Day%"
|
|
||||||
REM Last Monday in May SCANFROM -7 ADDOMIT MSG %"Memorial Day%"
|
|
||||||
REM Jun 14 MSG %"Flag Day%"
|
|
||||||
REM Third Sun in June MSG %"Father's Day%"
|
|
||||||
REM First Mon in Sep SCANFROM -7 ADDOMIT MSG %"Labor Day%"
|
|
||||||
REM Second Mon in Oct MSG %"Columbus Day%"
|
|
||||||
REM Nov 11 MSG %"Veterans Day%"
|
|
||||||
|
|
||||||
REM Oct 30 MSG %"Mischief Night%"
|
PUSH-OMIT-CONTEXT
|
||||||
REM Oct 31 MSG %"Halloween%"
|
# Normal case: 16 April falls Mon-Fri
|
||||||
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
|
REM 16 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw >= 1 && $Tw <= 5] MSG Emancipation Day
|
||||||
REM Last Thu in Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
|
|
||||||
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
|
# 16 April falls on Saturday: Observe on the 15th
|
||||||
REM Dec 24 MSG %"Christmas Eve%"
|
REM 15 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw == 5] MSG Emancipation Day (observed)
|
||||||
|
|
||||||
|
# 16 April falls on Sunday: Observe on the 17th
|
||||||
|
REM 17 Apr SCANFROM -7 ADDOMIT SATISFY [$Tw == 1] MSG Emancipation Day (observed)
|
||||||
|
|
||||||
|
# If you live in Maine or Massachussetts, uncomment the next line
|
||||||
|
# REM Third Monday in April SCANFROM -7 ADDOMIT MSG Patriots Day
|
||||||
|
|
||||||
|
REM Apr 15 OMIT Sat Sun AFTER MSG %"Income tax%" due
|
||||||
|
POP-OMIT-CONTEXT
|
||||||
|
|
||||||
|
REM May 5 MSG Cinco de Mayo
|
||||||
|
REM First Sat in May MSG Kentucky Derby
|
||||||
|
REM Second Sun in May MSG Mother's Day
|
||||||
|
REM Third Sat in May MSG Armed Forces Day
|
||||||
|
REM Last Monday in May SCANFROM -7 ADDOMIT MSG Memorial Day
|
||||||
|
REM Jun 14 MSG Flag Day
|
||||||
|
|
||||||
|
OMIT 19 June MSG Juneteenth
|
||||||
|
REM 18 June SCANFROM -7 ADDOMIT SATISFY [$Tw==5] MSG Juneteenth (observed)
|
||||||
|
REM 20 June SCANFROM -7 ADDOMIT SATISFY [$Tw==1] MSG Juneteenth (observed)
|
||||||
|
|
||||||
|
REM July 4 SCANFROM -7 ADDOMIT MSG Independence Day
|
||||||
|
REM July 3 SCANFROM -7 ADDOMIT SATISFY [$Tw==5] MSG Independence Day (observed)
|
||||||
|
REM July 5 SCANFROM -7 ADDOMIT SATISFY [$Tw==1] MSG Independence Day (observed)
|
||||||
|
|
||||||
|
REM Third Sun in June MSG Father's Day
|
||||||
|
REM First Mon in Sep SCANFROM -7 ADDOMIT MSG Labor Day
|
||||||
|
REM Second Mon in Oct MSG Columbus Day / Indigenous Peoples' Day
|
||||||
|
|
||||||
|
OMIT 11 Nov MSG Veterans Day
|
||||||
|
REM 10 Nov SCANFROM -7 ADDOMIT SATISFY [$Tw==5] MSG Veterans Day (observed)
|
||||||
|
REM 12 Nov SCANFROM -7 ADDOMIT SATISFY [$Tw==1] MSG Veterans Day (observed)
|
||||||
|
|
||||||
|
REM Oct 30 MSG Mischief Night
|
||||||
|
REM Oct 31 MSG Halloween
|
||||||
|
|
||||||
|
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG Election Day
|
||||||
|
|
||||||
|
REM Thu 22 Nov SCANFROM -7 ADDOMIT MSG Thanksgiving Day
|
||||||
|
REM Fri 23 Nov SCANFROM -7 ADDOMIT MSG Thanksgiving (cont.)
|
||||||
|
|
||||||
|
REM Dec 24 MSG Christmas Eve
|
||||||
OMIT Dec 25 MSG %"Christmas%" Day
|
OMIT Dec 25 MSG %"Christmas%" Day
|
||||||
|
REM 24 Dec SCANFROM -7 ADDOMIT SATISFY [$Tw==5] MSG Christmas (observed)
|
||||||
|
REM 26 Dec SCANFROM -7 ADDOMIT SATISFY [$Tw==1] MSG Christmas (observed)
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
SET autolang getenv("LC_ALL")
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
SET autolang getenv("REMIND_LANG")
|
||||||
|
|
||||||
|
IF autolang == ""
|
||||||
|
SET autolang getenv("LC_ALL")
|
||||||
|
ENDIF
|
||||||
IF autolang == ""
|
IF autolang == ""
|
||||||
SET autolang getenv("LANGUAGE")
|
SET autolang getenv("LANGUAGE")
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|||||||
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.
|
# Support for the Danish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mogens Lynnerup.
|
# This file is derived from a translation by Mogens Lynnerup.
|
||||||
|
|
||||||
SET $Sunday "Søndag"
|
SET $Sunday "Søndag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the German language.
|
# Support for the German language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Wolfgang Thronicke
|
# This file is derived from a translation by Wolfgang Thronicke
|
||||||
|
|
||||||
# Day names
|
# Day names
|
||||||
@@ -61,3 +61,29 @@ FSET subst_gx(alt, d, t) iif(alt, subst_g_alt(d), $On + " " + subst_g_alt(d))
|
|||||||
FSET subst_ux(alt, d, t) subst_ax(alt, d, t)
|
FSET subst_ux(alt, d, t) subst_ax(alt, d, t)
|
||||||
FSET subst_vx(alt, d, t) subst_gx(alt, d, t)
|
FSET subst_vx(alt, d, t) subst_gx(alt, d, t)
|
||||||
FSET subst_p(alt, d, t) iif(d == today()+1, "", "en")
|
FSET subst_p(alt, d, t) iif(d == today()+1, "", "en")
|
||||||
|
|
||||||
|
# Localization of various astronomical events
|
||||||
|
|
||||||
|
# Perihelion
|
||||||
|
SET earthseasons_Perihelion_str "Perihel"
|
||||||
|
|
||||||
|
# Vernal equinox
|
||||||
|
SET earthseasons_EquinoxMar_str "Frühlingsanfang"
|
||||||
|
|
||||||
|
# Summer solstice
|
||||||
|
SET earthseasons_SolsticeJun_str "Sommeranfang"
|
||||||
|
|
||||||
|
# Aphelion
|
||||||
|
SET earthseasons_Aphelion_str "Aphel"
|
||||||
|
|
||||||
|
# Autumnal Equinox
|
||||||
|
SET earthseasons_EquinoxSep_str "Herbstanfang"
|
||||||
|
|
||||||
|
# Winter Solstice
|
||||||
|
SET earthseasons_SolsticeDec_str "Winteranfang"
|
||||||
|
|
||||||
|
# Daylight saving time starts
|
||||||
|
SET daylightST_starts_str "Beginn Sommerzeit"
|
||||||
|
|
||||||
|
# Daylight saving time ends
|
||||||
|
SET daylightST_ends_str "Ende Sommerzeit"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Support for the English language.
|
# Support for the English language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# Nothing to do for English since it is the default.
|
# Nothing to do for English since it is the default.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Spanish language.
|
# Support for the Spanish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 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>
|
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
||||||
|
|
||||||
SET $Sunday "Domingo"
|
SET $Sunday "Domingo"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Finnish language.
|
# Support for the Finnish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mikko Silvonen
|
# This file is derived from a translation by Mikko Silvonen
|
||||||
|
|
||||||
SET $Sunday "sunnuntai"
|
SET $Sunday "sunnuntai"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the French language.
|
# Support for the French language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Laurent Duperval
|
# This file is derived from a translation by Laurent Duperval
|
||||||
|
|
||||||
SET $Sunday "dimanche"
|
SET $Sunday "dimanche"
|
||||||
|
|||||||
83
include/lang/gr.rem
Normal file
83
include/lang/gr.rem
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Support for the Hellenic (Greek) language.
|
||||||
|
# This file is part of REMIND.
|
||||||
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
|
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
||||||
|
|
||||||
|
SET $Sunday "Κυριακή"
|
||||||
|
SET $Monday "Δευτέρα"
|
||||||
|
SET $Tuesday "Τρίτη"
|
||||||
|
SET $Wednesday "Τετάρτη"
|
||||||
|
SET $Thursday "Πέμπτη"
|
||||||
|
SET $Friday "Παρασκευή"
|
||||||
|
SET $Saturday "Σάββατο"
|
||||||
|
|
||||||
|
SET $January "Ιανουάρ."
|
||||||
|
SET $February "Φεβρουάρ."
|
||||||
|
SET $March "Μάρτ."
|
||||||
|
SET $April "Απρίλ."
|
||||||
|
SET $May "Μαι."
|
||||||
|
SET $June "Ιούν."
|
||||||
|
SET $July "Ιούλ."
|
||||||
|
SET $August "Αυγουστ."
|
||||||
|
SET $September "Σεπτέμβρ."
|
||||||
|
SET $October "Οκτώβρ."
|
||||||
|
SET $November "Νοέμβρ."
|
||||||
|
SET $December "Δεκέμβρ."
|
||||||
|
|
||||||
|
SET $Today "σήμερα"
|
||||||
|
SET $Tomorrow "αύριο"
|
||||||
|
|
||||||
|
BANNER Υπενθυμίσεις: %w, %d %m, %y%o:
|
||||||
|
|
||||||
|
SET $Am "πμ"
|
||||||
|
SET $Pm "μμ"
|
||||||
|
|
||||||
|
SET $Ago "πριν"
|
||||||
|
SET $Fromnow "από τώρα"
|
||||||
|
|
||||||
|
SET $On "την"
|
||||||
|
|
||||||
|
SET $Now "τώρα"
|
||||||
|
SET $At "στις"
|
||||||
|
SET $Minute "λεπτά"
|
||||||
|
SET $Hour "ώρες"
|
||||||
|
SET $Is "είναι"
|
||||||
|
SET $Was "ήταν"
|
||||||
|
SET $And "και"
|
||||||
|
SET $Hplu ""
|
||||||
|
SET $Mplu ""
|
||||||
|
|
||||||
|
FSET subst_bx(a, d, t) "σε " + (d - today()) + " ημέρες"
|
||||||
|
FSET subst_ordinal(d) "."
|
||||||
|
FSET subst_a_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d) + " " + year(d)
|
||||||
|
FSET subst_ax(alt, d, t) iif(alt, subst_a_alt(d), $On + " " + subst_a_alt(d))
|
||||||
|
FSET subst_g_alt(d) wkday(d) + ", " + day(d) + ". " + mon(d)
|
||||||
|
FSET subst_gx(alt, d, t) iif(alt, subst_g_alt(d), $On + " " + subst_g_alt(d))
|
||||||
|
FSET subst_ux(alt, d, t) subst_ax(alt, d, t)
|
||||||
|
FSET subst_vx(alt, d, t) subst_gx(alt, d, t)
|
||||||
|
|
||||||
|
# Localization of various astronomical events
|
||||||
|
|
||||||
|
# Perihelion
|
||||||
|
SET earthseasons_Perihelion_str "Περιήλιον"
|
||||||
|
|
||||||
|
# Vernal equinox
|
||||||
|
SET earthseasons_EquinoxMar_str "Εαρινή ισημερία"
|
||||||
|
|
||||||
|
# Summer solstice
|
||||||
|
SET earthseasons_SolsticeJun_str "Θερινό ηλιοστάσιο"
|
||||||
|
|
||||||
|
# Aphelion
|
||||||
|
SET earthseasons_Aphelion_str "Αφήλιον"
|
||||||
|
|
||||||
|
# Autumnal Equinox
|
||||||
|
SET earthseasons_EquinoxSep_str "Φθινοπωρινή ισημερία"
|
||||||
|
|
||||||
|
# Winter Solstice
|
||||||
|
SET earthseasons_SolsticeDec_str "Χειμερινό ηλιοστάσιο"
|
||||||
|
|
||||||
|
# Daylight saving time starts
|
||||||
|
SET daylightST_starts_str "Έναρξη θέρους"
|
||||||
|
|
||||||
|
# Daylight saving time ends
|
||||||
|
SET daylightST_ends_str "Τέλος θέρους"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Icelanding language.
|
# Support for the Icelanding language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 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)
|
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
||||||
|
|
||||||
SET $Sunday "sunnudagur"
|
SET $Sunday "sunnudagur"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
# Support for the Italian language.
|
# Support for the Italian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Valerio Aimale
|
# This file is derived from a translation by Valerio Aimale
|
||||||
|
|
||||||
SET $Sunday "Domenica"
|
SET $Sunday "Domenica"
|
||||||
SET $Monday "Lunedí"
|
SET $Monday "Lunedì"
|
||||||
SET $Tuesday "Martedí"
|
SET $Tuesday "Martedì"
|
||||||
SET $Wednesday "Mercoledí"
|
SET $Wednesday "Mercoledì"
|
||||||
SET $Thursday "Giovedí"
|
SET $Thursday "Giovedì"
|
||||||
SET $Friday "Venerdí"
|
SET $Friday "Venerdì"
|
||||||
SET $Saturday "Sabato"
|
SET $Saturday "Sabato"
|
||||||
|
|
||||||
SET $January "Gennaio"
|
SET $January "Gennaio"
|
||||||
@@ -40,7 +40,7 @@ SET $Now "ora"
|
|||||||
SET $At "alle"
|
SET $At "alle"
|
||||||
SET $Minute "minuto"
|
SET $Minute "minuto"
|
||||||
SET $Hour "ora"
|
SET $Hour "ora"
|
||||||
SET $Is "é"
|
SET $Is "è"
|
||||||
SET $Was "era"
|
SET $Was "era"
|
||||||
SET $And "e"
|
SET $And "e"
|
||||||
SET $Hplu "a"
|
SET $Hplu "a"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Dutch language.
|
# Support for the Dutch language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 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
|
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
||||||
|
|
||||||
SET $Sunday "zondag"
|
SET $Sunday "zondag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Norwegian language.
|
# Support for the Norwegian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Trygve Randen
|
# This file is derived from a translation by Trygve Randen
|
||||||
|
|
||||||
SET $Sunday "Søndag"
|
SET $Sunday "Søndag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Polish language.
|
# Support for the Polish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Jerzy Sobczyk
|
# This file is derived from a translation by Jerzy Sobczyk
|
||||||
|
|
||||||
SET $Sunday "Niedziela"
|
SET $Sunday "Niedziela"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the (Brazilian) Portuguese language.
|
# Support for the (Brazilian) Portuguese language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Marco Paganini
|
# This file is derived from a translation by Marco Paganini
|
||||||
|
|
||||||
SET $Sunday "domingo"
|
SET $Sunday "domingo"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Romanian language.
|
# Support for the Romanian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2022 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Liviu Daia
|
# This file is derived from a translation by Liviu Daia
|
||||||
|
|
||||||
SET $Sunday "Duminică"
|
SET $Sunday "Duminică"
|
||||||
|
|||||||
16
include/seasons.rem
Normal file
16
include/seasons.rem
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Equinoxes and solstices
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
IF $LatDeg >= 0
|
||||||
|
# Northern Hemisphere
|
||||||
|
REM NOQUEUE [soleq(0)] MSG %"Vernal Equinox%" is %3.
|
||||||
|
REM NOQUEUE [soleq(1)] MSG %"Summer Solstice%" is %3.
|
||||||
|
REM NOQUEUE [soleq(2)] MSG %"Autumnal Equinox%" is %3.
|
||||||
|
REM NOQUEUE [soleq(3)] MSG %"Winter Solstice%" is %3.
|
||||||
|
ELSE
|
||||||
|
# Southern Hemisphere
|
||||||
|
REM NOQUEUE [soleq(0)] MSG %"Autumnal Equinox%" is %3.
|
||||||
|
REM NOQUEUE [soleq(1)] MSG %"Winter Solstice%" is %3.
|
||||||
|
REM NOQUEUE [soleq(2)] MSG %"Vernal Equinox%" is %3.
|
||||||
|
REM NOQUEUE [soleq(3)] MSG %"Summer Solstice%" is %3.
|
||||||
|
ENDIF
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH REM 1 "14 March 2022"
|
.TH REM 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rem \- Invoke Remind with a default filename
|
rem \- Invoke Remind with a default filename
|
||||||
@@ -16,5 +16,7 @@ the filename $HOME/.reminders
|
|||||||
.PP
|
.PP
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Remind was written by Dianne Skoll <dianne@skoll.ca>
|
Remind was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
.SH HOME PAGE
|
||||||
|
https://dianne.skoll.ca/projects/remind/
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
\fBremind\fR
|
\fBremind\fR(1)
|
||||||
@@ -1,26 +1,29 @@
|
|||||||
.TH REM2PS 1 "14 March 2022"
|
.TH REM2PS 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rem2ps \- draw a PostScript calendar from Remind output
|
rem2ps \- draw a PostScript calendar from Remind output
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B rem2ps [\fIoptions\fR]
|
.B rem2ps [\fIoptions\fR]
|
||||||
.SH DESCRIPTION
|
.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
|
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.
|
emits PostScript code (which draws a calendar) to the standard output.
|
||||||
.PP
|
.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
|
data. This may be useful if you wish to create other \fBRemind\fR
|
||||||
back-ends.
|
back-ends.
|
||||||
.PP
|
.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
|
render characters outside the ASCII character set, see
|
||||||
\fBrem2pdf\fR instead.
|
\fBrem2pdf\fR instead.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.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.
|
to the standard error stream. Normally, it is silent.
|
||||||
.TP
|
.TP
|
||||||
.B \-p file
|
.B \-p file
|
||||||
@@ -133,7 +136,7 @@ numbers.
|
|||||||
|
|
||||||
.PP
|
.PP
|
||||||
Type "rem2ps \-m help" for a list of available media. Note that the media
|
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
|
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"
|
is usually Letter for North America and A4 for Europe. The "\-m help"
|
||||||
option will display the compiled-in default.
|
option will display the compiled-in default.
|
||||||
@@ -193,8 +196,8 @@ for good output:
|
|||||||
rem2ps \-ol 72 \-sh 12
|
rem2ps \-ol 72 \-sh 12
|
||||||
.fi
|
.fi
|
||||||
.SH USAGE
|
.SH USAGE
|
||||||
To use \fBRem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
|
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
|
option to \fBrem2ps\fR, and then send the result to a printer. This is most easily
|
||||||
illustrated with examples:
|
illustrated with examples:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
@@ -228,10 +231,10 @@ calendar entries. This border is normally blank space.
|
|||||||
.TP
|
.TP
|
||||||
BoxWidth and BoxHeight
|
BoxWidth and BoxHeight
|
||||||
The width and height of the calendar box, from center-to-center of the
|
The width and height of the calendar box, from center-to-center of the
|
||||||
black gridlines.
|
black grid lines.
|
||||||
.TP
|
.TP
|
||||||
InBoxHeight
|
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 regular calendar entry area. The space from here to the top
|
||||||
of the box is used only to draw the day number.
|
of the box is used only to draw the day number.
|
||||||
.TP
|
.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
|
viewer before sending it to the printer. You should not use any document
|
||||||
structuring comments in your PostScript code.
|
structuring comments in your PostScript code.
|
||||||
.PP
|
.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:
|
the following PostScript code:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
@@ -320,14 +323,14 @@ For an example, create a file called "myprolog" whose contents are:
|
|||||||
} bind def
|
} bind def
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
|
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
|
with the year and month in large gray letters in the background of the
|
||||||
calendar.
|
calendar.
|
||||||
.PP
|
.PP
|
||||||
.SH REM2PS INPUT FORMAT (-P OPTION)
|
.SH REM2PS INPUT FORMAT (-P OPTION)
|
||||||
The \fB\-p\fR option is an older, simpler interchange format used by
|
The \fB\-p\fR option is an older, simpler interchange format used by
|
||||||
\fBRemind\fR to communicate with back-ends. New back-ends are
|
\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
|
are encouraged to support the older \fB\-p\fR format as well if the
|
||||||
older format contains enough information for them to work properly.
|
older format contains enough information for them to work properly.
|
||||||
.PP
|
.PP
|
||||||
@@ -380,7 +383,7 @@ been set to "-". The consistent use of "/" is designed to ease parsing.
|
|||||||
.PP
|
.PP
|
||||||
\fIspecial\fR is a string used
|
\fIspecial\fR is a string used
|
||||||
for "out-of-band" communication with back-ends. If the reminder
|
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.
|
back-end understands the specials \fBPostScript\fR and \fBPSFile\fR.
|
||||||
Other back-ends may understand other specials. A back end should
|
Other back-ends may understand other specials. A back end should
|
||||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
\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:
|
follows:
|
||||||
.TP
|
.TP
|
||||||
.B date \fIYYYY-MM-DD\fR
|
.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
|
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
||||||
.TP
|
.TP
|
||||||
.B filename \fIf\fR
|
.B filename \fIf\fR
|
||||||
@@ -586,6 +589,18 @@ For a SHADE or COLOR special, the blue color component.
|
|||||||
.B body \fIbody\fR
|
.B body \fIbody\fR
|
||||||
The body of the reminder to issue. Always present.
|
The body of the reminder to issue. Always present.
|
||||||
.TP
|
.TP
|
||||||
|
.B calendar_body \fIbody\fR
|
||||||
|
The text appropriate to include in a calendar. Only present if the
|
||||||
|
original body contains %"...%" sequences and the "q" modifier was used
|
||||||
|
with Remind's "-pp..." flag.
|
||||||
|
.TP
|
||||||
|
.B plain_body \fIbody\fR
|
||||||
|
The "plain" body of the reminder with any %"...%" sequences removed.
|
||||||
|
If your back-end is designed to draw a calendar, then it should
|
||||||
|
use the \fBcalendar_body\fR if present. If not, then it
|
||||||
|
should use the \fBplain_body\fR if present, and if not, then it
|
||||||
|
should fall back on the \fBbody\fR.
|
||||||
|
.TP
|
||||||
.B rawbody \fIraw\fR
|
.B rawbody \fIraw\fR
|
||||||
The "raw" body of the reminder, before any expression-pasting or
|
The "raw" body of the reminder, before any expression-pasting or
|
||||||
substitution-sequence processing. If the raw body would be the same
|
substitution-sequence processing. If the raw body would be the same
|
||||||
@@ -662,18 +677,20 @@ is desired.
|
|||||||
|
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
|
rem2ps was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
.SH BUGS
|
.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
|
Any time you supply
|
||||||
a font name or size, line thickness, or border width, it is treated as a
|
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
|
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.
|
resulting PostScript output will probably not work.
|
||||||
.PP
|
.PP
|
||||||
You should ensure that the values you supply for margin widths are sensible.
|
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.
|
but again, the PostScript output will probably not work.
|
||||||
|
.SH HOME PAGE
|
||||||
|
https://dianne.skoll.ca/projects/remind/
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
\fBremind\fR, \fBrem2pdf\fR, \fBrem2html\fR, \fBtkremind\fR.
|
\fBremind\fR, \fBrem2pdf\fR, \fBrem2html\fR, \fBtkremind\fR.
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
|||||||
.TH TKREMIND 1 "14 March 2022"
|
.TH TKREMIND 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
tkremind \- graphical front-end to Remind calendar program
|
tkremind \- graphical front-end to Remind calendar program
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B tkremind \fR[\fIoptions\fR] [\fIread_file\fR] [\fIwrite_file\fR] [\fIconfig_file\fR]
|
.B tkremind \fR[\fIoptions\fR] [\fIread_file\fR [\fIwrite_file\fR [\fIconfig_file\fR]]]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBTkRemind\fR is a graphical front-end to the \fBRemind\fR program.
|
\fBTkRemind\fR is a graphical front-end to the \fBRemind\fR program.
|
||||||
It provides a friendly graphical interface which allows you to view
|
It provides a friendly graphical interface which allows you to view
|
||||||
@@ -192,7 +192,7 @@ If you create "timed" reminders, \fBTkRemind\fR will queue them in
|
|||||||
the background and pop up boxes as they are triggered. Additionally,
|
the background and pop up boxes as they are triggered. Additionally,
|
||||||
if you created the reminder using \fBTkRemind\fR, you will be given the
|
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.
|
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.
|
\fBRemind\fR in \fIserver mode\fR, described later.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
@@ -301,11 +301,11 @@ Today
|
|||||||
|
|
||||||
.SH IMMEDIATE UPDATES
|
.SH IMMEDIATE UPDATES
|
||||||
|
|
||||||
If you are running \fBTkRemind\fR on Linux and have the
|
If you are running \fBTkRemind\fR on Linux and \fBRemind\fR has been
|
||||||
\fBinotifywait\fR program installed (part of the \fBinotify-tools\fR
|
compiled with \fBinotify\fR(7) support, then \fBTkRemind\fR redraws
|
||||||
or similar package), then \fBTkRemind\fR redraws the calendar window
|
the calendar window \fIimmediately\fR if \fB$HOME/.reminders\fR
|
||||||
\fIimmediately\fR if \fB$HOME/.reminders\fR changes (or, if it is a
|
changes (or, if it is a directory, any files in that directory
|
||||||
directory, any files in that directory change.)
|
change.)
|
||||||
.PP
|
.PP
|
||||||
This lets \fBTkRemind\fR react immediately to hand-edited reminders or
|
This lets \fBTkRemind\fR react immediately to hand-edited reminders or
|
||||||
to reminder files that are imported from another calendar system (for example,
|
to reminder files that are imported from another calendar system (for example,
|
||||||
@@ -366,60 +366,102 @@ 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
|
\fBRemind\fR has a special mode for interacting with programs like
|
||||||
\fBTkRemind\fR. This mode is called \fIserver mode\fR and is
|
\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
|
In server mode, \fBRemind\fR operates similar to daemon mode, except
|
||||||
it reads commands (one per line)
|
it reads commands (one per line) from standard input and writes status
|
||||||
from standard input and writes status lines to standard output.
|
lines to standard output. Each status line is a JSON object.
|
||||||
|
|
||||||
The commands accepted in server mode are:
|
The commands accepted in server mode are:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
EXIT
|
EXIT
|
||||||
Terminate the \fBRemind\fR process. EOF on standard input does the
|
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
|
.TP
|
||||||
STATUS
|
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
|
.TP
|
||||||
REREAD
|
REREAD
|
||||||
Re-read the reminder file
|
Re-read the reminder file. Returns the following status line:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
|
||||||
|
{"response":"reread","command":"REREAD"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
The status lines written are as follows:
|
Additional status lines written are as follows:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
NOTE reminder \fItime\fR \fItag\fR
|
.nf
|
||||||
Signifies the beginning of a timed reminder whose trigger time is
|
|
||||||
\fItime\fR with tag \fItag\fR. If the reminder has no tag, an
|
{"response":"reminder","ttime":tt,"now":now,"tags":tags,"body":body}
|
||||||
asterisk is supplied for \fItag\fR. All lines following this line
|
|
||||||
are the body of the reminder, until the line \fBNOTE endreminder\fR
|
.fi
|
||||||
is transmitted.
|
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.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
NOTE newdate
|
.nf
|
||||||
|
|
||||||
|
{"response":"newdate"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
|
||||||
This line is emitted whenever \fBRemind\fR has detected a rollover of
|
This line is emitted whenever \fBRemind\fR has detected a rollover of
|
||||||
the system date. The front-end program should redraw its calendar
|
the system date. The front-end program should redraw its calendar
|
||||||
or take whatever other action is needed.
|
or take whatever other action is needed.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
NOTE reread
|
.nf
|
||||||
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.
|
|
||||||
|
|
||||||
.TP
|
{"response":"reread","command":"inotify"}
|
||||||
NOTE queued \fIn\fR
|
|
||||||
This line is emitted in response to a \fBSTATUS\fR command. The number
|
.fi
|
||||||
\fIn\fR is the number of reminders in the queue.
|
|
||||||
|
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
|
.SH AUTHOR
|
||||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
|
||||||
\fBTkRemind\fR is Copyright 1996-2022 by Dianne Skoll.
|
\fBTkRemind\fR is Copyright 1996-2024 by Dianne Skoll.
|
||||||
|
|
||||||
.SH FILES
|
.SH FILES
|
||||||
|
|
||||||
@@ -427,6 +469,8 @@ $HOME/.reminders -- default reminder file or directory.
|
|||||||
|
|
||||||
$HOME/.config/tkremindrc -- \fBTkRemind\fR saved options.
|
$HOME/.config/tkremindrc -- \fBTkRemind\fR saved options.
|
||||||
|
|
||||||
|
.SH HOME PAGE
|
||||||
|
https://dianne.skoll.ca/projects/remind/
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
\fBremind\fR, \fBrem2ps\fR, \fBrem2pdf\fR, \fBrem2html\fR
|
\fBremind\fR, \fBrem2ps\fR, \fBrem2pdf\fR, \fBrem2html\fR
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ install:
|
|||||||
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
|
$(PERL) -M$$m -e 1 > /dev/null 2>&1; \
|
||||||
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
||||||
done; \
|
done; \
|
||||||
pod2man rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
|
pod2man --center "VERSION @VERSION@" --date "@RELEASE_DATE@" rem2html > rem2html.1 && mkdir -p $(DESTDIR)$(mandir)/man1 && cp rem2html.1 $(DESTDIR)$(mandir)/man1/rem2html.1 || true; \
|
||||||
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
|
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
|
||||||
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
|
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
|
||||||
exit 1;
|
exit 1;
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
#!perl
|
#!perl
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use JSON::MaybeXS;
|
use JSON::MaybeXS;
|
||||||
|
use Encode;
|
||||||
|
|
||||||
my %Options;
|
my %Options;
|
||||||
|
|
||||||
my $rem2html_version = '2.1';
|
my $rem2html_version = '@VERSION@';
|
||||||
|
|
||||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||||
@@ -43,6 +45,11 @@ Print usage information
|
|||||||
|
|
||||||
Print version
|
Print version
|
||||||
|
|
||||||
|
=item --utf8
|
||||||
|
|
||||||
|
Assume standard input is encoded in UTF-8; write UTF-8 data to standard
|
||||||
|
output.
|
||||||
|
|
||||||
=item --backurl I<url>
|
=item --backurl I<url>
|
||||||
|
|
||||||
When producing the small calendar for the previous month, make the
|
When producing the small calendar for the previous month, make the
|
||||||
@@ -130,6 +137,10 @@ today's date, add the following reminder to your reminders file:
|
|||||||
rem2html was written by Dianne Skoll with much inspiration from an
|
rem2html was written by Dianne Skoll with much inspiration from an
|
||||||
earlier version by Don Schwarz.
|
earlier version by Don Schwarz.
|
||||||
|
|
||||||
|
=head1 HOME PAGE
|
||||||
|
|
||||||
|
L<https://dianne.skoll.ca/projects/remind/>
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
B<remind>, B<rem2ps>, B<rem2pdf>, B<tkremind>
|
B<remind>, B<rem2ps>, B<rem2pdf>, B<tkremind>
|
||||||
@@ -149,6 +160,7 @@ Usage: remind -pp ... | rem2html [options]
|
|||||||
Options:
|
Options:
|
||||||
|
|
||||||
--help, -h Print usage information
|
--help, -h Print usage information
|
||||||
|
--utf8 Assume UTF-8 input and write UTF-8 output
|
||||||
--man Show man page (requires "perldoc")
|
--man Show man page (requires "perldoc")
|
||||||
--version Print version
|
--version Print version
|
||||||
--backurl url Make the title on the previous month's small calendar
|
--backurl url Make the title on the previous month's small calendar
|
||||||
@@ -192,6 +204,7 @@ sub parse_options
|
|||||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||||
if (!GetOptions(\%Options, "help|h",
|
if (!GetOptions(\%Options, "help|h",
|
||||||
"man",
|
"man",
|
||||||
|
"utf8",
|
||||||
"pngs",
|
"pngs",
|
||||||
"version",
|
"version",
|
||||||
"stylesheet=s",
|
"stylesheet=s",
|
||||||
@@ -211,13 +224,22 @@ sub parse_options
|
|||||||
if ($stylesheet) {
|
if ($stylesheet) {
|
||||||
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||||
}
|
}
|
||||||
|
if ($Options{utf8}) {
|
||||||
|
binmode(STDIN, ':encoding(UTF-8)');
|
||||||
|
binmode(STDOUT, ':encoding(UTF-8)');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub start_output
|
sub start_output
|
||||||
{
|
{
|
||||||
return if ($Options{tableonly});
|
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{nostyle}) {
|
||||||
if ($Options{stylesheet}) {
|
if ($Options{stylesheet}) {
|
||||||
print('<link rel="stylesheet" type="text/css" href="' .
|
print('<link rel="stylesheet" type="text/css" href="' .
|
||||||
@@ -305,7 +327,12 @@ sub parse_input
|
|||||||
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||||
} elsif (/\{/) {
|
} 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+)$/);
|
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||||
$y = $1;
|
$y = $1;
|
||||||
$m = $2;
|
$m = $2;
|
||||||
@@ -682,7 +709,7 @@ if ($Options{help}) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-t STDIN) {
|
if (-t STDIN) { ## no critic
|
||||||
print STDERR "$TIDY_PROGNAME: Input should not come from a terminal.\n\n";
|
print STDERR "$TIDY_PROGNAME: Input should not come from a terminal.\n\n";
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,15 @@
|
|||||||
use ExtUtils::MakeMaker;
|
use ExtUtils::MakeMaker;
|
||||||
|
{
|
||||||
|
# Override pod2man options
|
||||||
|
package MY;
|
||||||
|
sub manifypods {
|
||||||
|
my ($self,%attribs) = @_;
|
||||||
|
my $result = $self->SUPER::manifypods(%attribs);
|
||||||
|
$result =~ s/^(POD2MAN_EXE\s*=\s*)(.+)$/$1$2 --center 'VERSION @VERSION@' --date '@RELEASE_DATE@'/m;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WriteMakefile(
|
WriteMakefile(
|
||||||
NAME => 'Remind::PDF',
|
NAME => 'Remind::PDF',
|
||||||
AUTHOR => q{Dianne Skoll <dianne@skoll.ca>},
|
AUTHOR => q{Dianne Skoll <dianne@skoll.ca>},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!@PERL@
|
#!@PERL@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use lib '@prefix@/lib/perl5';
|
use lib '@prefix@/lib/perl5';
|
||||||
@@ -36,7 +37,7 @@ my $settings = {
|
|||||||
numbers_on_left => 0,
|
numbers_on_left => 0,
|
||||||
small_calendars => 0,
|
small_calendars => 0,
|
||||||
fill_entire_page => 0,
|
fill_entire_page => 0,
|
||||||
|
wrap_calendar => 0,
|
||||||
media => 'Letter',
|
media => 'Letter',
|
||||||
width => 0,
|
width => 0,
|
||||||
height => 0,
|
height => 0,
|
||||||
@@ -85,6 +86,7 @@ Options:
|
|||||||
--media=MEDIA, -mMEDIA Size for specified media
|
--media=MEDIA, -mMEDIA Size for specified media
|
||||||
--width=W, -wW Specify media width in 1/72nds of an inch
|
--width=W, -wW Specify media width in 1/72nds of an inch
|
||||||
--height=H, -hH Specify media height in 1/72nds of an inch
|
--height=H, -hH Specify media height in 1/72nds of an inch
|
||||||
|
--wrap, -y Make calendar fit in at most 5 rows
|
||||||
--title-font=FONT Specify font for calendar title
|
--title-font=FONT Specify font for calendar title
|
||||||
--header-font=FONT Specify font for weekday names
|
--header-font=FONT Specify font for weekday names
|
||||||
--daynum-font=FONT Specify font for day numbers
|
--daynum-font=FONT Specify font for day numbers
|
||||||
@@ -113,6 +115,7 @@ my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
|||||||
'fill-page|e' => \$settings->{fill_entire_page},
|
'fill-page|e' => \$settings->{fill_entire_page},
|
||||||
'media|m=s' => \$settings->{media},
|
'media|m=s' => \$settings->{media},
|
||||||
'width|w=i' => \$settings->{width},
|
'width|w=i' => \$settings->{width},
|
||||||
|
'wrap|y' => \$settings->{wrap_calendar},
|
||||||
'height|h=i' => \$settings->{height},
|
'height|h=i' => \$settings->{height},
|
||||||
'title-font=s' => \$settings->{title_font},
|
'title-font=s' => \$settings->{title_font},
|
||||||
'header-font=s' => \$settings->{header_font},
|
'header-font=s' => \$settings->{header_font},
|
||||||
@@ -174,7 +177,7 @@ if ($settings->{landscape}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Don't read from a terminal
|
# Don't read from a terminal
|
||||||
if (-t STDIN) {
|
if (-t STDIN) { ## no critic
|
||||||
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
||||||
print STDERR " remind -pp [options] filename | $me [options] > out.pdf\n";
|
print STDERR " remind -pp [options] filename | $me [options] > out.pdf\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -248,20 +251,21 @@ sub set_media
|
|||||||
sub set_media_from_file
|
sub set_media_from_file
|
||||||
{
|
{
|
||||||
my ($fn) = @_;
|
my ($fn) = @_;
|
||||||
if (!open(IN, '<', $fn)) {
|
my $IN;
|
||||||
|
if (!open($IN, '<', $fn)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while(<IN>) {
|
while(<$IN>) {
|
||||||
chomp;
|
chomp;
|
||||||
s/^\s+//;
|
s/^\s+//;
|
||||||
s/\s+$//;
|
s/\s+$//;
|
||||||
next if ($_ eq '');
|
next if ($_ eq '');
|
||||||
next if ($_ =~ /^#/);
|
next if ($_ =~ /^#/);
|
||||||
my $m = $_;
|
my $m = $_;
|
||||||
close(IN);
|
close($IN);
|
||||||
return set_media($m);
|
return set_media($m);
|
||||||
}
|
}
|
||||||
close(IN);
|
close($IN);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +433,14 @@ The default is 36.
|
|||||||
The size of the margin at the right of the page in 1/72ths of an inch.
|
The size of the margin at the right of the page in 1/72ths of an inch.
|
||||||
The default is 36.
|
The default is 36.
|
||||||
|
|
||||||
|
=item --wrap, -y
|
||||||
|
|
||||||
|
Modify the calendar so that if it would normally require 6 rows to print,
|
||||||
|
then the last day (or last two days, as needed) are moved to the
|
||||||
|
first row of the calendar, and adjust the small calendar positions
|
||||||
|
as needed. This results in a calendar that only requires 5 rows, but
|
||||||
|
with the last day or two appearing in the I<first> row.
|
||||||
|
|
||||||
=item --verbose, -v
|
=item --verbose, -v
|
||||||
|
|
||||||
Print (on STDERR) the name of the month and year for each month that
|
Print (on STDERR) the name of the month and year for each month that
|
||||||
@@ -443,14 +455,14 @@ B<-p>, B<-pp> or B<-ppp> options into B<rem2pdf>. The PDF output
|
|||||||
will be sent to standard output. So for example, to print a 12-month
|
will be sent to standard output. So for example, to print a 12-month
|
||||||
calendar for the year 2030, use:
|
calendar for the year 2030, use:
|
||||||
|
|
||||||
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c=3 | lpr
|
remind -pp12 /dev/null Jan 2030 | rem2pdf -e -l -c3 | lpr
|
||||||
|
|
||||||
You can concatenate multiple B<remind> runs. For example, the following
|
You can concatenate multiple B<remind> runs. For example, the following
|
||||||
will produce a PDF calendar for January through March of 2023, and
|
will produce a PDF calendar for January through March of 2023, and
|
||||||
June of 2023 (for a total of four pages);
|
June of 2023 (for a total of four pages);
|
||||||
|
|
||||||
(remind -pp3 Jan 2023 /dev/null ; \
|
(remind -pp3 /dev/null Jan 2023 ; \
|
||||||
remind -p June 2023 /dev/null) | rem2pdf -e -l -c=3 > cal.pdf
|
remind -pp /dev/null June 2023) | rem2pdf -e -l -c3 > cal.pdf
|
||||||
|
|
||||||
=head1 FORMATTED TEXT
|
=head1 FORMATTED TEXT
|
||||||
|
|
||||||
@@ -504,6 +516,10 @@ of each calendar box:
|
|||||||
|
|
||||||
B<Rem2PDF> was written by Dianne Skoll <dianne@skoll.ca>
|
B<Rem2PDF> was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
|
||||||
|
=head1 HOME PAGE
|
||||||
|
|
||||||
|
L<https://dianne.skoll.ca/projects/remind/>
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
B<remind>, B<rem2ps>, B<rem2html>, B<tkremind>
|
B<remind>, B<rem2ps>, B<rem2html>, B<tkremind>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package Remind::PDF;
|
package Remind::PDF;
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
@@ -109,7 +110,6 @@ sub read_one_month
|
|||||||
$self->{daysinnextmonth} = 0;
|
$self->{daysinnextmonth} = 0;
|
||||||
$self->{prevmonthyear} = 0;
|
$self->{prevmonthyear} = 0;
|
||||||
$self->{nextmonthyear} = 0;
|
$self->{nextmonthyear} = 0;
|
||||||
|
|
||||||
for (my $i=0; $i<=31; $i++) {
|
for (my $i=0; $i<=31; $i++) {
|
||||||
$self->{entries}->[$i] = [];
|
$self->{entries}->[$i] = [];
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ sub read_one_month
|
|||||||
$line = $in->getline();
|
$line = $in->getline();
|
||||||
chomp($line);
|
chomp($line);
|
||||||
if ($line =~ /^\S+ \S+ \S+ \S+ \S+ \S+ \S+$/) {
|
if ($line =~ /^\S+ \S+ \S+ \S+ \S+ \S+ \S+$/) {
|
||||||
@{$self->{daynames}} = map { s/_/ /g; $_; } (split(/ /, $line));
|
@{$self->{daynames}} = map { s/_/ /g; $_; } (split(/ /, $line)); ## no critic
|
||||||
} else {
|
} else {
|
||||||
return (undef, "Cannot interpret line: $line");
|
return (undef, "Cannot interpret line: $line");
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ hash keys found in the newer "remind -pp" JSON output.
|
|||||||
sub parse_oldstyle_line
|
sub parse_oldstyle_line
|
||||||
{
|
{
|
||||||
my ($self, $line) = @_;
|
my ($self, $line) = @_;
|
||||||
return undef unless $line =~ m|^(\d+)/(\d+)/(\d+) (\S+) (\S+) (\S+) (\S+) (.*)$|;
|
return unless $line =~ m|^(\d+)/(\d+)/(\d+) (\S+) (\S+) (\S+) (\S+) (.*)$|;
|
||||||
|
|
||||||
my $hash = {
|
my $hash = {
|
||||||
date => "$1-$2-$3",
|
date => "$1-$2-$3",
|
||||||
@@ -227,20 +227,159 @@ sub parse_oldstyle_line
|
|||||||
|
|
||||||
if ($hash->{passthru}) {
|
if ($hash->{passthru}) {
|
||||||
if ($hash->{passthru} =~ /^(shade|color|colour)$/i) {
|
if ($hash->{passthru} =~ /^(shade|color|colour)$/i) {
|
||||||
if ($hash->{body} =~ /^\s*(\d+)\s+(\d+)\s+(\d+)/) {
|
if ($hash->{body} =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)/) {
|
||||||
$hash->{r} = $1;
|
$hash->{r} = $1;
|
||||||
$hash->{g} = $2;
|
$hash->{g} = $2;
|
||||||
$hash->{b} = $3;
|
$hash->{b} = $3;
|
||||||
} elsif ($hash->{body} =~ /^\s*(\d+)/) {
|
$hash->{body} = $4;
|
||||||
|
} elsif ($hash->{body} =~ /^\s*(\d+)\s*(.*)/) {
|
||||||
$hash->{r} = $1;
|
$hash->{r} = $1;
|
||||||
$hash->{g} = $1;
|
$hash->{g} = $1;
|
||||||
$hash->{b} = $1;
|
$hash->{b} = $1;
|
||||||
|
$hash->{body} = $2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $hash;
|
return $hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=head2 setup_daymap
|
||||||
|
|
||||||
|
Set up the array that maps ($row, $col) to day number (or -1
|
||||||
|
for rows/cols out of range.)
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub setup_daymap
|
||||||
|
{
|
||||||
|
my ($self, $settings) = @_;
|
||||||
|
# First column
|
||||||
|
my $first_col = $self->{firstwkday};
|
||||||
|
if ($self->{mondayfirst}) {
|
||||||
|
$first_col--;
|
||||||
|
if ($first_col < 0) {
|
||||||
|
$first_col = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Last column
|
||||||
|
my $last_col = ($first_col + $self->{daysinmonth} - 1) % 7;
|
||||||
|
|
||||||
|
# Number of rows
|
||||||
|
my $rows = 1;
|
||||||
|
my $last_day_on_row = 7 - $first_col;
|
||||||
|
while ($last_day_on_row < $self->{daysinmonth}) {
|
||||||
|
$last_day_on_row += 7;
|
||||||
|
$rows++;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add a row for small calendars if necessary
|
||||||
|
if (($settings->{small_calendars} != 0) && ($first_col == 0) && ($last_col == 6)) {
|
||||||
|
$rows++;
|
||||||
|
$self->{extra_row} = 1;
|
||||||
|
} else {
|
||||||
|
$self->{extra_row} = 0;
|
||||||
|
}
|
||||||
|
$self->{rows} = $rows;
|
||||||
|
$self->{daymap} = [];
|
||||||
|
$self->{first_col} = $first_col;
|
||||||
|
$self->{last_col} = $last_col;
|
||||||
|
for (my $row=0; $row<$rows; $row++) {
|
||||||
|
for (my $col=0; $col < 7; $col++) {
|
||||||
|
$self->{daymap}->[$row]->[$col] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$self->{nextcal_row} = -1;
|
||||||
|
$self->{prevcal_row} = -1;
|
||||||
|
$self->{nextcal_col} = 6;
|
||||||
|
$self->{prevcal_col} = 0;
|
||||||
|
# Figure out where to draw the small calendars
|
||||||
|
my $extra_row = $self->{extra_row};
|
||||||
|
if ($settings->{small_calendars} == 1) {
|
||||||
|
if ($last_col <= 4 || ($last_col == 6 && $extra_row)) {
|
||||||
|
$self->{prevcal_row} = $rows-1;
|
||||||
|
$self->{prevcal_col} = 5;
|
||||||
|
$self->{nextcal_row} = $rows-1;
|
||||||
|
$self->{nextcal_col} = 6;
|
||||||
|
} else {
|
||||||
|
$self->{prevcal_row} = 0;
|
||||||
|
$self->{prevcal_col} = 0;
|
||||||
|
$self->{nextcal_row} = 0;
|
||||||
|
$self->{nextcal_col} = 1;
|
||||||
|
}
|
||||||
|
} elsif ($settings->{small_calendars} == 2) {
|
||||||
|
if ($first_col >= 2) {
|
||||||
|
$self->{prevcal_row} = 0;
|
||||||
|
$self->{prevcal_col} = 0;
|
||||||
|
$self->{nextcal_row} = 0;
|
||||||
|
$self->{nextcal_col} = 1;
|
||||||
|
} else {
|
||||||
|
$self->{prevcal_row} = $rows-1;
|
||||||
|
$self->{prevcal_col} = 5;
|
||||||
|
$self->{nextcal_row} = $rows-1;
|
||||||
|
$self->{nextcal_col} = 6;
|
||||||
|
}
|
||||||
|
} elsif ($settings->{small_calendars} == 3) {
|
||||||
|
if ($first_col >= 1 && $last_col <= 5) {
|
||||||
|
$self->{prevcal_row} = 0;
|
||||||
|
$self->{prevcal_col} = 0;
|
||||||
|
$self->{nextcal_row} = $rows-1;
|
||||||
|
$self->{nextcal_col} = 6;
|
||||||
|
} else {
|
||||||
|
if ($last_col <= 4 || ($last_col == 6 && $extra_row)) {
|
||||||
|
$self->{prevcal_row} = $rows-1;
|
||||||
|
$self->{prevcal_col} = 5;
|
||||||
|
$self->{nextcal_row} = $rows-1;
|
||||||
|
$self->{nextcal_col} = 6;
|
||||||
|
} else {
|
||||||
|
$self->{prevcal_row} = 0;
|
||||||
|
$self->{prevcal_col} = 0;
|
||||||
|
$self->{nextcal_row} = 0;
|
||||||
|
$self->{nextcal_col} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $col = $first_col;
|
||||||
|
my $row = 0;
|
||||||
|
my $day = 1;
|
||||||
|
while ($day <= $self->{daysinmonth}) {
|
||||||
|
$self->{daymap}->[$row]->[$col] = $day;
|
||||||
|
$day++;
|
||||||
|
$col++;
|
||||||
|
if ($col > 6) {
|
||||||
|
$row++;
|
||||||
|
$col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if we should wrap the calendar
|
||||||
|
if ($self->{rows} == 6 && $settings->{wrap_calendar}) {
|
||||||
|
# Move everything in the last row to the first row
|
||||||
|
my $occupied_col = 0;
|
||||||
|
for (my $col=0; $col<7; $col++) {
|
||||||
|
if ($self->{daymap}->[5]->[$col] > 0) {
|
||||||
|
$self->{daymap}->[0]->[$col] = $self->{daymap}->[5]->[$col];
|
||||||
|
$occupied_col = $col;
|
||||||
|
} else {
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($settings->{small_calendars}) {
|
||||||
|
$self->{prevcal_row} = 0;
|
||||||
|
$self->{prevcal_col} = $occupied_col+1;
|
||||||
|
$self->{nextcal_row} = 0;
|
||||||
|
$self->{nextcal_col} = $occupied_col+2;
|
||||||
|
for (my $col = 6; $col > 0; $col--) {
|
||||||
|
if ($self->{daymap}->[0]->[$col] < 0) {
|
||||||
|
$self->{nextcal_col} = $col;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$self->{rows} = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
=head2 read_one_month_pp($in, $specials_accepted)
|
=head2 read_one_month_pp($in, $specials_accepted)
|
||||||
|
|
||||||
This function reads one month's worth of data from the file handle
|
This function reads one month's worth of data from the file handle
|
||||||
@@ -326,6 +465,7 @@ sub render
|
|||||||
{
|
{
|
||||||
my ($self, $cr, $settings) = @_;
|
my ($self, $cr, $settings) = @_;
|
||||||
|
|
||||||
|
$self->setup_daymap($settings);
|
||||||
$self->{horiz_lines} = [];
|
$self->{horiz_lines} = [];
|
||||||
$cr->set_line_cap('square');
|
$cr->set_line_cap('square');
|
||||||
my $so_far = $self->draw_title($cr, $settings);
|
my $so_far = $self->draw_title($cr, $settings);
|
||||||
@@ -344,111 +484,25 @@ sub render
|
|||||||
$self->{remaining_space} = $settings->{height} - $settings->{margin_bottom} - $so_far;
|
$self->{remaining_space} = $settings->{height} - $settings->{margin_bottom} - $so_far;
|
||||||
|
|
||||||
$self->{minimum_row_height} = $self->{remaining_space} / 9;
|
$self->{minimum_row_height} = $self->{remaining_space} / 9;
|
||||||
# First column
|
|
||||||
my $first_col = $self->{firstwkday};
|
|
||||||
if ($self->{mondayfirst}) {
|
|
||||||
$first_col--;
|
|
||||||
if ($first_col < 0) {
|
|
||||||
$first_col = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Last column
|
|
||||||
my $last_col = ($first_col + $self->{daysinmonth} - 1) % 7;
|
|
||||||
|
|
||||||
# Number of rows
|
|
||||||
my $rows = 1;
|
|
||||||
my $last_day_on_row = 7 - $first_col;
|
|
||||||
while ($last_day_on_row < $self->{daysinmonth}) {
|
|
||||||
$last_day_on_row += 7;
|
|
||||||
$rows++;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $extra_row = 0;
|
|
||||||
# Add a row for small calendars if necessary
|
|
||||||
if (($settings->{small_calendars} != 0) && ($first_col == 0) && ($last_col == 6)) {
|
|
||||||
$rows++;
|
|
||||||
$extra_row++;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Figure out where to draw the small calendars
|
|
||||||
my $prevcal_top = 0;
|
|
||||||
my $nextcal_top = 0;
|
|
||||||
my $prevcal_bottom = 0;
|
|
||||||
my $nextcal_bottom = 0;
|
|
||||||
|
|
||||||
if ($settings->{small_calendars} == 1) {
|
|
||||||
if ($last_col <= 4 || ($last_col == 6 && $extra_row)) {
|
|
||||||
$prevcal_bottom = 1;
|
|
||||||
$nextcal_bottom = 1;
|
|
||||||
} else {
|
|
||||||
$prevcal_top = 1;
|
|
||||||
$nextcal_top = 1;
|
|
||||||
}
|
|
||||||
} elsif ($settings->{small_calendars} == 2) {
|
|
||||||
if ($first_col >= 2) {
|
|
||||||
$prevcal_top = 1;
|
|
||||||
$nextcal_top = 1;
|
|
||||||
} else {
|
|
||||||
$prevcal_bottom = 1;
|
|
||||||
$nextcal_bottom = 1;
|
|
||||||
}
|
|
||||||
} elsif ($settings->{small_calendars} == 3) {
|
|
||||||
if ($first_col >= 1 && $last_col <= 5) {
|
|
||||||
$prevcal_top = 1;
|
|
||||||
$nextcal_bottom = 1;
|
|
||||||
} else {
|
|
||||||
if ($last_col <= 4 || ($last_col == 6 && $extra_row)) {
|
|
||||||
$prevcal_bottom = 1;
|
|
||||||
$nextcal_bottom = 1;
|
|
||||||
} else {
|
|
||||||
$prevcal_top = 1;
|
|
||||||
$nextcal_top = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Row height if we are filling the page
|
# Row height if we are filling the page
|
||||||
$self->{row_height} = $self->{remaining_space} / $rows;
|
$self->{row_height} = $self->{remaining_space} / $self->{rows};
|
||||||
|
|
||||||
my ($start_col, $start_day);
|
for (my $row = 0; $row < $self->{rows}; $row++) {
|
||||||
for (my $row = 0; $row < $rows; $row++) {
|
|
||||||
if ($row == 0) {
|
|
||||||
$start_day = 1;
|
|
||||||
$start_col = $first_col;
|
|
||||||
} else {
|
|
||||||
$start_col = 0;
|
|
||||||
}
|
|
||||||
my $old_so_far = $so_far;
|
my $old_so_far = $so_far;
|
||||||
$so_far = $self->draw_row($cr, $settings, $so_far, $row, $start_day, $start_col);
|
$so_far = $self->draw_row($cr, $settings, $so_far, $row);
|
||||||
$start_day += 7 - $start_col;
|
|
||||||
push(@{$self->{horiz_lines}}, $so_far);
|
push(@{$self->{horiz_lines}}, $so_far);
|
||||||
if ($row == 0) {
|
if ($row == $self->{prevcal_row}) {
|
||||||
if ($prevcal_top) {
|
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, $self->{prevcal_col}, $so_far - $old_so_far, $settings);
|
||||||
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, 0, $so_far - $old_so_far, $settings);
|
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
||||||
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
||||||
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
$settings, $self->{prevmonthname}, $self->{daysinprevmonth}, ($self->{first_col} + 35 - $self->{daysinprevmonth}) % 7);
|
||||||
$settings, $self->{prevmonthname}, $self->{daysinprevmonth}, ($first_col + 35 - $self->{daysinprevmonth}) % 7);
|
}
|
||||||
}
|
if ($row == $self->{nextcal_row}) {
|
||||||
if ($nextcal_top) {
|
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, $self->{nextcal_col}, $so_far - $old_so_far, $settings);
|
||||||
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, 1, $so_far - $old_so_far, $settings);
|
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
||||||
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
||||||
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
$settings, $self->{nextmonthname}, $self->{daysinnextmonth}, ($self->{last_col} + 1) % 7);
|
||||||
$settings, $self->{nextmonthname}, $self->{daysinnextmonth}, ($last_col + 1) % 7);
|
|
||||||
}
|
|
||||||
} elsif ($row == $rows-1) {
|
|
||||||
if ($prevcal_bottom) {
|
|
||||||
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, 5, $so_far - $old_so_far, $settings);
|
|
||||||
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
|
||||||
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
|
||||||
$settings, $self->{prevmonthname}, $self->{daysinprevmonth}, ($first_col + 35 - $self->{daysinprevmonth}) % 7);
|
|
||||||
}
|
|
||||||
if ($nextcal_bottom) {
|
|
||||||
my ($x1, $y1, $x2, $y2) = $self->col_box_coordinates($old_so_far, 6, $so_far - $old_so_far, $settings);
|
|
||||||
$self->draw_small_calendar($cr, $x1 + $settings->{border_size}, $y1 + $settings->{border_size},
|
|
||||||
$x2 - $x1 - 2*$settings->{border_size}, $y2 - $y1 - 2*$settings->{border_size},
|
|
||||||
$settings, $self->{nextmonthname}, $self->{daysinnextmonth}, ($last_col + 1) % 7);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,23 +546,18 @@ calendar row.
|
|||||||
=cut
|
=cut
|
||||||
sub draw_row
|
sub draw_row
|
||||||
{
|
{
|
||||||
my ($self, $cr, $settings, $so_far, $row, $start_day, $start_col) = @_;
|
my ($self, $cr, $settings, $so_far, $row) = @_;
|
||||||
|
|
||||||
my $col = $start_col;
|
|
||||||
my $day = $start_day;
|
|
||||||
my $height = 0;
|
my $height = 0;
|
||||||
|
|
||||||
# Preview them to figure out the row height...
|
# Preview them to figure out the row height...
|
||||||
if (!$settings->{fill_entire_page}) {
|
if (!$settings->{fill_entire_page}) {
|
||||||
while ($col < 7) {
|
for (my $col=0; $col<7; $col++) {
|
||||||
|
my $day = $self->{daymap}->[$row]->[$col];
|
||||||
|
next if ($day < 1);
|
||||||
my $h = $self->draw_day($cr, $settings, $so_far, $day, $col, 0);
|
my $h = $self->draw_day($cr, $settings, $so_far, $day, $col, 0);
|
||||||
$height = $h if ($h > $height);
|
$height = $h if ($h > $height);
|
||||||
$day++;
|
|
||||||
$col++;
|
|
||||||
last if ($day > $self->{daysinmonth});
|
|
||||||
}
|
}
|
||||||
$col = $start_col;
|
|
||||||
$day = $start_day;
|
|
||||||
} else {
|
} else {
|
||||||
$height = $self->{row_height} - $settings->{border_size} * 2;
|
$height = $self->{row_height} - $settings->{border_size} * 2;
|
||||||
}
|
}
|
||||||
@@ -517,10 +566,10 @@ sub draw_row
|
|||||||
$height = $self->{minimum_row_height};
|
$height = $self->{minimum_row_height};
|
||||||
}
|
}
|
||||||
# Now draw for real
|
# Now draw for real
|
||||||
while ($col < 7 && $day <= $self->{daysinmonth}) {
|
for (my $col=0; $col<7; $col++) {
|
||||||
|
my $day = $self->{daymap}->[$row]->[$col];
|
||||||
|
next if ($day < 1);
|
||||||
$self->draw_day($cr, $settings, $so_far, $day, $col, $height);
|
$self->draw_day($cr, $settings, $so_far, $day, $col, $height);
|
||||||
$day++;
|
|
||||||
$col++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $so_far + $height + $settings->{border_size};
|
return $so_far + $height + $settings->{border_size};
|
||||||
@@ -905,7 +954,7 @@ sub create_from_stream
|
|||||||
return(undef, 'Unable to parse JSON stream');
|
return(undef, 'Unable to parse JSON stream');
|
||||||
}
|
}
|
||||||
|
|
||||||
=head2 Remind::PDF::Multi->create_from_stream($json, $specials_accepted)
|
=head2 Remind::PDF::Multi->create_from_json($json, $specials_accepted)
|
||||||
|
|
||||||
This method takes data from a JSON string <$json>. C<$specials_accepted>
|
This method takes data from a JSON string <$json>. C<$specials_accepted>
|
||||||
is a hashref of SPECIAL reminder types to accept; the key is the name of the
|
is a hashref of SPECIAL reminder types to accept; the key is the name of the
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package Remind::PDF::Entry;
|
package Remind::PDF::Entry;
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
@@ -76,7 +77,15 @@ sub render
|
|||||||
|
|
||||||
$layout->set_width(1024 * ($x2 - $x1 - 2 * $settings->{border_size}));
|
$layout->set_width(1024 * ($x2 - $x1 - 2 * $settings->{border_size}));
|
||||||
$layout->set_wrap('word-char');
|
$layout->set_wrap('word-char');
|
||||||
$layout->set_text(Encode::decode('UTF-8', $self->{body}));
|
my $body;
|
||||||
|
if (exists($self->{calendar_body})) {
|
||||||
|
$body = $self->{calendar_body};
|
||||||
|
} elsif (exists($self->{plain_body})) {
|
||||||
|
$body = $self->{plain_body};
|
||||||
|
} else {
|
||||||
|
$body = $self->{body};
|
||||||
|
}
|
||||||
|
$layout->set_text(Encode::decode('UTF-8', $body));
|
||||||
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
|
my $desc = Pango::FontDescription->from_string($settings->{entry_font} . ' ' . $settings->{entry_size} . 'px');
|
||||||
$layout->set_font_description($desc);
|
$layout->set_font_description($desc);
|
||||||
my ($wid, $h) = $layout->get_pixel_size();
|
my ($wid, $h) = $layout->get_pixel_size();
|
||||||
@@ -233,11 +242,9 @@ sub _adjust
|
|||||||
package Remind::PDF::Entry::color;
|
package Remind::PDF::Entry::color;
|
||||||
use base 'Remind::PDF::Entry';
|
use base 'Remind::PDF::Entry';
|
||||||
|
|
||||||
# Strip the RGB prefix from body
|
# Nothing to do for COLOR-type reminder
|
||||||
sub _adjust
|
sub _adjust
|
||||||
{
|
{
|
||||||
my ($self) = @_;
|
|
||||||
$self->{body} =~ s/^\d+\s+\d+\s+\d+\s+//;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
package Remind::PDF::Entry::postscript;
|
package Remind::PDF::Entry::postscript;
|
||||||
|
|||||||
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: 3.1 KiB |
421
scripts/tkremind
421
scripts/tkremind
@@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# -*-Mode: TCL;-*-
|
# -*-Mode: TCL;-*-
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
# TKREMIND
|
# TKREMIND
|
||||||
@@ -7,7 +8,7 @@
|
|||||||
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2022 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
#
|
#
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
@@ -28,31 +29,62 @@ set Hostname [exec hostname]
|
|||||||
# Our icon photo
|
# Our icon photo
|
||||||
catch {
|
catch {
|
||||||
image create photo rpicon -data {
|
image create photo rpicon -data {
|
||||||
R0lGODlhFwAgAOecABUTERYTERYUERcVEhgWExkXFBkXFRoXFRsZFhwZFxwa
|
iVBORw0KGgoAAAANSUhEUgAAAEAAAABbCAYAAADDeIOGAAAACXBIWXMAAAu6AAALugFBTNueAAAA
|
||||||
GB0bGR4cGR4cGh8dGiAeHCEfHCEfHSIgHSIgHiQiHyYkISknJCooJispJywq
|
GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAADANJREFUeJzdnGtsFNcVx38Xr19r
|
||||||
Jy4sKTIwLjUzMDUzMTo4Njs5Nzs5ODw7ODw7OT07OT48OkE/PUJAPkNBP0RC
|
4/BawjPGjcGY2MY8Q+1g05iXKwoihvAQoCJEQoiU0CofWgmpUhIJNVKpSGnUSGmKLEEihcZFQeBW
|
||||||
QEVDQUVEQkdFQ0lIRkpJR01LSU5MSlBPTVFQTlNSUFRSUFRSUVVTUlVUUllY
|
gRJeKQkQisFAsWDxGsdAawjgGGF7Tz/MrrvGuzN3ZmchzV8aeT17zj3n/u+5d87cxyoR4fsMpVQx
|
||||||
VltZV1xaWF1cWmBfXmJgX2RiYGZlY2dmZGppZ2tqaG1ram9tbHFwb3Jwb3Rz
|
MBkYC+QDQ4DBQDtQ7XmEviUESqnBwAKgFHgaGAP0iRC5AWwDtojI1e8FAUqp4cBzwExgBpAVRexb
|
||||||
cXV0c3Z0c3Z1c3Z1dHd1dHh2dXh3dnt5eHx7eXx7en18en59e4B/foGAf4KB
|
4E/AJhG52n1XRP4vL2Ag8DOgFmgDJMYVBPYCT0ct51FXJEbl+gLpMb77IbAZuGpS6fBVD6wys6W+
|
||||||
f4SDgYWEgoWEg4eGhIiHhouKiI2Mio6Ni46NjJCQj5KRkJSTkZeWlpiXlpmY
|
C4OgUiodeBGYC4zHaN1OoAU4CxzGaOVFwHR69ulo+Bb4HfCmiNw1lfwOtPY84AzWral7HQfKtO0/
|
||||||
l5qZmJybmp6dnKCfnqGgoKKhoKOioaSjoqinp6qpqKurqq+urbCvrrCwr7Gw
|
4sqvA+66VPFO4PeA15YPj7Dyz4VC1Y3KtwIvOvLjEVW+CPi3TuUyMzOtZC4DJY59eQSVTwL26VR+
|
||||||
r7OysbW1tLi3tri3t7u6ur28vMTDw8TEw8XFxMbFxcfGxsfHxsrJycrKyczM
|
48aNcu/ePXn++edjyVwAiuPy5xEQ8Gvdlr97966IiLz99tvRZPzA2Hj9sXqcuAql1CLgVR3Ze/fu
|
||||||
y83My83MzM3NzdDQz9LR0dPS0tPT09fX19jY19ra2dvb29zc29zc3Ojn5+jo
|
ce7cOUSE/fv39/oaeFVEzsft1ENs+TwggI3BbcSIEVJcXBztu39iEFkBpGra7xtN9qEkQqFE568Y
|
||||||
6Orq6uzs7O/v7/T09PX19fb29vf39/r6+vv7+/7+/v//////////////////
|
SYzbuAU0YHQJP0aGeBODKICRQAHQCPxCHqzwQ2r93+BeomM3NzgCVMXyLeERoJSaDewC0hJqyEAb
|
||||||
////////////////////////////////////////////////////////////
|
xpPhLHAa+LuInDBTSCgBSql+wCGMEEwULgN/AfYDB0Xkti3tBIf+H0hQeCulBKgG+n4nH4NKqXnA
|
||||||
////////////////////////////////////////////////////////////
|
mkSUnZmZyaZNmxgyZMhgEbkTV2EJavlU4CQWrejz+SQjI0O71VNTU2XBggXyxRdfiIhIZWXlN0BK
|
||||||
////////////////////////////////////////////////////////////
|
PL4makpsIzDBSmjz5s3Mnz+fQ4cOceHCBQKBAM3Nzdy+fZs7d+6glGLAgAH4fD6Ki4uZNWsWeXl5
|
||||||
////////////////////////////////////////////////////////////
|
3fqTJk3K2rt372xgt2NPE9D6+RhvZ6atmZubK/fv35d48MknnwiwOR5/EzEGvAn0txKqqqoiOTk5
|
||||||
////////////////////////////////////////////////////////////
|
LkPPPvss/fv3/1E8ZbhKgFJqDjBfR7a0tDRue16vl/z8/LGhx60juEaAUkoBvwTrcSUzM5NnnnnG
|
||||||
////////////////////////////////////////////////////////////
|
Fbv5+flpQLlTfTcj4KdoOpKXl0f//pa9RAsFBQUAE53qu0KAUioF2KArP2DAADfMAvDkk0+CMZPs
|
||||||
/////////////////////yH5BAEKAP8ALAAAAAAXACAAAAj+AP8JHEiwoMGD
|
CG5FwAsY01xaSE9Pd8ksFBUV4fF4xjrVj5sApVQSsNqOjsfjXvqRnZ3NsGHDRimlHPUpNyJgNTb7
|
||||||
CAcusRAAQEKDBQIcEBAAwUODAQJAsBGAwsWCBzJuUBLgI0ENGVM2dACg5UWV
|
YEtLiwtm/4fs7OxUYIoT3bgICI38tvN9v98fTppcwdChQwFynejGGwFVwDS7Si0tLWzdupWvv/46
|
||||||
KU+Y/JfRQBknPoq8ATQz4wxOQIFa6vMx5ZSgQetczJDSClKgcF6mFDEnE9I2
|
TvMGfD4fwAgnuvESsNKJUjAY5JVXXmHMmDEsXLiQHTt2EAwGHTsxePBggKGOlOPI+Qsxdlm48n4/
|
||||||
D0fADOChUdA1D7dmTBEUTditDQRQAnomIQaxICpoAmomoUoAGS2YIBIUDEIu
|
depU+fjjjx29E7zzzjsC1DqqRxwEbHGr8uHL4/HI+vXrpb293RYB27dvF+DUQyMAYweGzvq8o2vR
|
||||||
YndI8FAJaBaEMlIuSEkloxugUBBOSLkh44AvGfkAPYJQpYqMLIQEILB205DO
|
okXS0dGhTUBNTY0ATU7q4nQMWAYMc6hriZ07d/LGG29oy2dkZAD0VUrZTjCcEqD1xhcPtm7dyqVL
|
||||||
KW9kJHMhQAmgkaKgzsgjggM5GbEAxaNmdoAPOoz8CCAgEVAtg3wPEPMnQQAU
|
l7RkQwRkAo/ZtWObAKVULhDXO7gOWltb2blzp5as1+sFoy62nwROImA54F4yH4GsrJ6buw4fPqyl
|
||||||
QWsg5AAzDZSMbIBeaoHwAUwSDAI2XMAENA8ThAPEBvAStEkc3yonrOW0aUMk
|
16dPdzUG2bXpJCmf50DHEsOHD+f+/fs97ukmShEE2J5ishUBSqnxaEx2OsG4ceO4detWj3t37ujN
|
||||||
+BkBVAlaKATC8Fsp8Igid5ABgxMHtaTgggy6ZFBAADs= }
|
eEcQoOzatdsFFuAsaizh8/no6Ojoca+wsFBLNyJykuzatUvATLsGdPH444/3ujdtmt5rRkSk2B7T
|
||||||
|
tBWUUqOBqXYN6CAjI4ORI0f2uJeWlkZlZaWWfnt7u2Pbdhj7McaKj+soKirq1f8rKysZN26cln4E
|
||||||
|
Affs2rZDQIndwnUxceJEmpqaetxbvHixtn4EAbZDQYuAUIqZMAImTJhAY2Njj3vNzc3a+q2treGP
|
||||||
|
5ttio0A3AmbicMLBCklJSZSUlBAIBHrcf++997h586ZWGRHd5xu79nUJcGcVIwrGjx9PVlYWly9f
|
||||||
|
7nH//PnzvPbaa1plhIj6Frhu174uAZPsFBp6OdFCWVkZx44d65UFAmzbto13333XsoxQF7glIu6P
|
||||||
|
AUqpZGxmf6E5Oi2Ul5dTX18f9btgMMgHH3xgWUYoZb5lJRcNOhEwA+idpZggNEenJTd37lzOnTsX
|
||||||
|
UyY7O9uynKtXr4KxNc42dAiwFf4Ajz2m91peXl5OWloaZ86ciSnzYIL0IILBYPiJ8R8bLnZDh4Bi
|
||||||
|
u4XqLn3NmDGDixcvmkbAE088YVpGY2NjeAxwtNqiQ8BTtgrs00dr8TM1NZXKykoOHDjQ6yUoEqNG
|
||||||
|
jTItp66uLjyl7miRwZQApdQQYLSdAlNTU7UImDx5Mjk5OXz55ZcxZbxeLxMnmq+6RUybuU8Axgkt
|
||||||
|
W/l/V1eX1mOwoqICwJSAwsJCBg0yn+SJyB+u6foYCSsCbIU/GNPsVk+B5ORkqqqqOH36tOkAOGmS
|
||||||
|
9fgbigABHG2dtyIgz+L7Xujs7CQzM9NUpqSkhKKiInbv3k1nZ2dMueJi6/H34sWLYGSA/7LnqQEr
|
||||||
|
An5gt0ARYeDAgabdYN48Y1px3759MWWSkpKYPt18d73f76ehoQHgiog4WlyMSYBSqg8OCAAjCmK9
|
||||||
|
y2dlZbF06VIaGxv5/PPPY5ZRUFDA2LHmGz+OHj0ajiC/Ez/BPALGYTMDDOPatWuMHx992878+fMZ
|
||||||
|
MWIENTU1pjM5s2bNsrQTMX40OHATMCcgHwezrGAMTLEIWLZsGQA1NTWmZcyePdvSTl1dXfjjBTv+
|
||||||
|
9YDJAujPcbi4WVVVJUeOHOl1f/LkyRIMBuX48ePi8Xhi6o8ePVq6urpMF0SDwaCMGjVKME6HFzpZ
|
||||||
|
GLVaHHW8+NnQ0MC0adN6bGwGWLVqFUopPvzwQ9PRv6KiInKuPyrq6+u5cuUKQBPG2WNnMImA7TiM
|
||||||
|
gJSUFAkEAvLyyy9338vJyZG2tjbp6OiQ3NxcU/29e/daLom///77Yfm/OW19qwhwtuUEY6HiwIED
|
||||||
|
PQaylStX4vV6qa6uDj+6omLChAnMmTPH0kbEABjf2UGTCDhHHJscNmzYIB0dHZKdnS3Dhg2T69ev
|
||||||
|
i4hIeXm5qd7rr79u2foiImVlZWGd9fFEQNRlrtAskOMIAOMZ7fF4mDlzJkOHDsXn81FbW8uhQ4di
|
||||||
|
6ni9XpYuXWpZ9vXr1zlxovsw2Nl4/IzV+k/hwn6furo6qa2tlRs3boiIyOLFi011Fi5cqNX61dXV
|
||||||
|
YZ2baJ4cjRnpMQj4SbwEAPLWW291O338+HFJS0szla+pqdEiYN26dWGdA/FU3oyAF9wgoKKiotvp
|
||||||
|
JUuWmMpOmTJFgsGgFgFFRUVhvd8mioBfuUFAcnKynDx5Ug4fPiwpKSmmslu2bNGqfH19vSQlJYX1
|
||||||
|
VsZLQKy1fsdHUCLR0dHBRx99xNmzZ6PO+4cxcuRIVq/W23D+6aef0tXVBXAf41RqXIhFQLRfYnKE
|
||||||
|
6upqy93hK1asoG/fvlrlHT16NPyxXkT8cTkHMbvATlzoAjpXv379xO/3a4V/V1dXOP8X4I/xhr+Y
|
||||||
|
ZIKuRYAVli9frrX4AcYEit/vD/970g37sQiwveHQCdLT03nppZe05ffs2RP+KMA/XHEiRheIKw3W
|
||||||
|
vZYvX64V+mEUFhaGdS8ROvof7xWLgOZEVz4pKUk+++wz7cofPHgwfGRegB1uVD7qGKCUSuUhdIG5
|
||||||
|
c+dSVlamLb9nz55w44Bb4U/0McBHgrbCRmLt2rW25CNmkIPAQdcciQj7EmATxs9RJDT8S0tLtdNe
|
||||||
|
EZFTp05FTqHVuxX+IoJHKTUIeBtYgsuHqWNh7dq1GAfO9LBr167IKbTYc+kO8WceUtIDSEFBga3T
|
||||||
|
ICIi06dPjyzjBVcjANiKsQBiex+AE6xZsybmydG2tja++uorrly5QlNTE4FAgEAgwLFjx8IiHRg/
|
||||||
|
xOYalIiEDz+vBVZgbIdNSFfIyclh9+7dNDU1dVcw8q/f76etrc2siBMiMtlNn3r9jpBSqhSYjTEo
|
||||||
|
5mNMjztaIHkQKSkpdHZ2Wp0RvI2x2NkS+tsc+nsNqBMRV8cA0x9SCh2NHYtxRnA0MBwYgJEnhC+z
|
||||||
|
17h2jP27d0Kf2zH2893G2NNzM3S1YvzAYgDj9Ffsd2eX8V/DpporbFKohAAAAABJRU5ErkJggg== }
|
||||||
|
|
||||||
wm iconphoto . -default rpicon
|
wm iconphoto . -default rpicon
|
||||||
}
|
}
|
||||||
@@ -78,6 +110,19 @@ if {$tcl_platform(platform) == "windows"} {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# GetRemindVersion
|
||||||
|
# Arguments:
|
||||||
|
# none
|
||||||
|
# Returns:
|
||||||
|
# The version of Remind
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
proc GetRemindVersion {} {
|
||||||
|
global Remind
|
||||||
|
set ver [exec sh -c "(echo \"banner %\"; echo \"msg \[version()\]%\") | $Remind -"]
|
||||||
|
return $ver
|
||||||
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# GLOBAL VARIABLES
|
# GLOBAL VARIABLES
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -171,9 +216,6 @@ set ConfigFile ""
|
|||||||
|
|
||||||
set EditorPid -1
|
set EditorPid -1
|
||||||
|
|
||||||
# Inotify file
|
|
||||||
set InotifyFP ""
|
|
||||||
|
|
||||||
# Errors from last remind run
|
# Errors from last remind run
|
||||||
set RemindErrors ""
|
set RemindErrors ""
|
||||||
|
|
||||||
@@ -239,6 +281,9 @@ set Option(PrintOrient) landscape
|
|||||||
set OptDescr(PrintFill) "(0/1) If 1, fill entire page when printing"
|
set OptDescr(PrintFill) "(0/1) If 1, fill entire page when printing"
|
||||||
set Option(PrintFill) 1
|
set Option(PrintFill) 1
|
||||||
|
|
||||||
|
set OptDescr(WrapCal) "(0/1) If 1, make printed calendars occupy at most 5 rows"
|
||||||
|
set Option(WrapCal) 0
|
||||||
|
|
||||||
set OptDescr(PrintDaysRight) "(0/1) If 1, put day numbers in the top-right of each calendar box"
|
set OptDescr(PrintDaysRight) "(0/1) If 1, put day numbers in the top-right of each calendar box"
|
||||||
set Option(PrintDaysRight) 1
|
set Option(PrintDaysRight) 1
|
||||||
|
|
||||||
@@ -254,11 +299,19 @@ set Option(PrintSmallCalendars) 1
|
|||||||
set OptDescr(PrintFormat) "Print format: pdf or ps"
|
set OptDescr(PrintFormat) "Print format: pdf or ps"
|
||||||
set Option(PrintFormat) ps
|
set Option(PrintFormat) ps
|
||||||
|
|
||||||
set WarningHeaders [list "# Lines staring with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
set WarningHeaders [list "# Lines starting with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
||||||
|
|
||||||
# Highest tag seen so far. Array of tags is stored in ReminderTags()
|
# Highest tag seen so far. Array of tags is stored in ReminderTags()
|
||||||
set HighestTagSoFar 0
|
set HighestTagSoFar 0
|
||||||
|
|
||||||
|
# Check Remind version
|
||||||
|
set ver [GetRemindVersion]
|
||||||
|
|
||||||
|
if {"$ver" < "04.03.00"} {
|
||||||
|
tk_dialog .error Error "This version of TkRemind requires Remind version 04.03.00 or newer; you have version $ver" error 0 OK
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
proc get_weekday { yyyymmdd } {
|
proc get_weekday { yyyymmdd } {
|
||||||
global EnglishDayNames
|
global EnglishDayNames
|
||||||
return [lindex $EnglishDayNames [clock format [clock scan $yyyymmdd] -format %w -locale C]]
|
return [lindex $EnglishDayNames [clock format [clock scan $yyyymmdd] -format %w -locale C]]
|
||||||
@@ -277,6 +330,10 @@ proc is_warning_header { line } {
|
|||||||
if {"$line" == "$h"} {
|
if {"$line" == "$h"} {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
# Ignore prior typo line too
|
||||||
|
if {"$line" == "# Lines staring with REM TAG TKTAGnnn ... were created by tkremind"} {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -955,6 +1012,7 @@ proc WriteOptionsToFile {} {
|
|||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc LoadOptions {} {
|
proc LoadOptions {} {
|
||||||
global Option ConfigFile
|
global Option ConfigFile
|
||||||
|
global MondayFirst
|
||||||
set problem [catch {set f [open "$ConfigFile" "r"]}]
|
set problem [catch {set f [open "$ConfigFile" "r"]}]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
return
|
return
|
||||||
@@ -974,6 +1032,9 @@ proc LoadOptions {} {
|
|||||||
set Option($key) $val
|
set Option($key) $val
|
||||||
}
|
}
|
||||||
close $f
|
close $f
|
||||||
|
if {[regexp -- {-m.*} $Option(ExtraRemindArgs)]} {
|
||||||
|
set MondayFirst 1
|
||||||
|
}
|
||||||
font configure CalboxFont {*}$Option(CalboxFont)
|
font configure CalboxFont {*}$Option(CalboxFont)
|
||||||
font configure HeadingFont {*}$Option(HeadingFont)
|
font configure HeadingFont {*}$Option(HeadingFont)
|
||||||
}
|
}
|
||||||
@@ -1091,8 +1152,13 @@ proc FillCalWindow {} {
|
|||||||
} else {
|
} else {
|
||||||
set tag "*"
|
set tag "*"
|
||||||
}
|
}
|
||||||
set stuff [dict get $obj body]
|
if {[dict exists $obj calendar_body]} {
|
||||||
|
set stuff [dict get $obj calendar_body]
|
||||||
|
} elseif {[dict exists $obj plain_body]} {
|
||||||
|
set stuff [dict get $obj plain_body]
|
||||||
|
} else {
|
||||||
|
set stuff [dict get $obj body]
|
||||||
|
}
|
||||||
set day [string trimleft $day 0]
|
set day [string trimleft $day 0]
|
||||||
set n [expr $day+$offset]
|
set n [expr $day+$offset]
|
||||||
set month [string trimleft $month 0]
|
set month [string trimleft $month 0]
|
||||||
@@ -1116,30 +1182,31 @@ proc FillCalWindow {} {
|
|||||||
}
|
}
|
||||||
"COLOUR" -
|
"COLOUR" -
|
||||||
"COLOR" {
|
"COLOR" {
|
||||||
if {[regexp {^ *([0-9]+) +([0-9]+) +([0-9]+) +(.*)$} $stuff all r g b rest]} {
|
set r [dict get $obj r]
|
||||||
if {$r > 255} {
|
set g [dict get $obj g]
|
||||||
set r 255
|
set b [dict get $obj b]
|
||||||
} elseif {$r < 0} {
|
if {$r > 255} {
|
||||||
set r 0
|
set r 255
|
||||||
}
|
} elseif {$r < 0} {
|
||||||
if {$g > 255} {
|
set r 0
|
||||||
set g 255
|
}
|
||||||
} elseif {$g < 0} {
|
if {$g > 255} {
|
||||||
set g 0
|
set g 255
|
||||||
}
|
} elseif {$g < 0} {
|
||||||
if {$b > 255} {
|
set g 0
|
||||||
set b 255
|
}
|
||||||
} elseif {$b < 0} {
|
if {$b > 255} {
|
||||||
set b 0
|
set b 255
|
||||||
}
|
} elseif {$b < 0} {
|
||||||
set color [format "%02X%02X%02X" $r $g $b]
|
set b 0
|
||||||
set extratags "clr$color"
|
}
|
||||||
.cal.t$n configure -state normal
|
set color [format "%02X%02X%02X" $r $g $b]
|
||||||
.cal.t$n tag configure $extratags -foreground "#$color"
|
set extratags "clr$color"
|
||||||
.cal.t$n configure -state disabled -takefocus 0
|
.cal.t$n configure -state normal
|
||||||
set stuff $rest
|
.cal.t$n tag configure $extratags -foreground "#$color"
|
||||||
set type "COLOR"
|
.cal.t$n configure -state disabled -takefocus 0
|
||||||
}
|
set stuff $stuff
|
||||||
|
set type "COLOR"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if { $type != "*" && $type != "COLOR" && $type != "COLOUR"} {
|
if { $type != "*" && $type != "COLOR" && $type != "COLOUR"} {
|
||||||
@@ -1235,7 +1302,7 @@ proc Status { stuff } {
|
|||||||
# None
|
# None
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc DoPrint {} {
|
proc DoPrint {} {
|
||||||
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus
|
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus RemindErrors
|
||||||
global CurMonth CurYear MonthNames
|
global CurMonth CurYear MonthNames
|
||||||
|
|
||||||
catch {destroy .p}
|
catch {destroy .p}
|
||||||
@@ -1279,6 +1346,7 @@ proc DoPrint {} {
|
|||||||
radiobutton .p.portrait -text "Portrait" -variable Option(PrintOrient) -value portrait
|
radiobutton .p.portrait -text "Portrait" -variable Option(PrintOrient) -value portrait
|
||||||
|
|
||||||
checkbutton .p.fill -text "Fill page" -variable Option(PrintFill)
|
checkbutton .p.fill -text "Fill page" -variable Option(PrintFill)
|
||||||
|
checkbutton .p.wrap -text "Use at most 5 rows (PDF only)" -variable Option(WrapCal)
|
||||||
checkbutton .p.right -text "Day numbers at top-right" -variable Option(PrintDaysRight)
|
checkbutton .p.right -text "Day numbers at top-right" -variable Option(PrintDaysRight)
|
||||||
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable Option(PrintEncoding)
|
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable Option(PrintEncoding)
|
||||||
checkbutton .p.calendars -text "Print small calendars" -variable Option(PrintSmallCalendars)
|
checkbutton .p.calendars -text "Print small calendars" -variable Option(PrintSmallCalendars)
|
||||||
@@ -1289,12 +1357,14 @@ proc DoPrint {} {
|
|||||||
if {$HaveRem2PDF} {
|
if {$HaveRem2PDF} {
|
||||||
pack .p.f1 .p.ff .p.f2 .p.f2a .p.f3 .p.f3a \
|
pack .p.f1 .p.ff .p.f2 .p.f2a .p.f3 .p.f3a \
|
||||||
-side top -fill both -expand 1 -anchor w
|
-side top -fill both -expand 1 -anchor w
|
||||||
|
pack .p.fill .p.wrap .p.right .p.encoding .p.calendars -in .p.f3a \
|
||||||
|
-side top -anchor w -fill none -expand 0
|
||||||
} else {
|
} else {
|
||||||
pack .p.f1 .p.f2 .p.f2a .p.f3 .p.f3a \
|
pack .p.f1 .p.f2 .p.f2a .p.f3 .p.f3a \
|
||||||
-side top -fill both -expand 1 -anchor w
|
-side top -fill both -expand 1 -anchor w
|
||||||
}
|
pack .p.fill .p.right .p.encoding .p.calendars -in .p.f3a \
|
||||||
pack .p.fill .p.right .p.encoding .p.calendars -in .p.f3a \
|
|
||||||
-side top -anchor w -fill none -expand 0
|
-side top -anchor w -fill none -expand 0
|
||||||
|
}
|
||||||
pack .p.f4 -side top -fill both -expand 1 -anchor w
|
pack .p.f4 -side top -fill both -expand 1 -anchor w
|
||||||
pack .p.f11 .p.f12 -in .p.f1 -side top -fill none -expand 0 -anchor w
|
pack .p.f11 .p.f12 -in .p.f1 -side top -fill none -expand 0 -anchor w
|
||||||
pack .p.tofile .p.filename .p.browse -in .p.f11 -side left -fill none -expand 0 -anchor w
|
pack .p.tofile .p.filename .p.browse -in .p.f11 -side left -fill none -expand 0 -anchor w
|
||||||
@@ -1387,6 +1457,11 @@ proc DoPrint {} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if {$Option(WrapCal)} {
|
||||||
|
if {$Option(PrintFormat) == "pdf"} {
|
||||||
|
append cmd " --wrap"
|
||||||
|
}
|
||||||
|
}
|
||||||
if {$Option(PrintOrient) == "landscape"} {
|
if {$Option(PrintOrient) == "landscape"} {
|
||||||
append cmd " -l"
|
append cmd " -l"
|
||||||
}
|
}
|
||||||
@@ -1413,7 +1488,8 @@ proc DoPrint {} {
|
|||||||
append cmd " $fname"
|
append cmd " $fname"
|
||||||
Status "Printing..."
|
Status "Printing..."
|
||||||
if {[catch {eval "exec $cmd"} err]} {
|
if {[catch {eval "exec $cmd"} err]} {
|
||||||
tk_dialog .error Error "Error during printing: $err" error 0 Ok
|
set RemindErrors [unique_lines $err]
|
||||||
|
set_button_to_errors
|
||||||
}
|
}
|
||||||
DisplayTime
|
DisplayTime
|
||||||
}
|
}
|
||||||
@@ -1470,9 +1546,7 @@ proc GotoDialog {} {
|
|||||||
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
||||||
CenterWindow .g .
|
CenterWindow .g .
|
||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
grab .g
|
|
||||||
focus .g.y.e
|
focus .g.y.e
|
||||||
tkwait window .g
|
|
||||||
catch {focus $oldFocus}
|
catch {focus $oldFocus}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1493,7 +1567,7 @@ proc DoGoto {} {
|
|||||||
set month [lsearch -exact $MonthNames [.g.mon cget -text]]
|
set month [lsearch -exact $MonthNames [.g.mon cget -text]]
|
||||||
set CurMonth $month
|
set CurMonth $month
|
||||||
set CurYear $year
|
set CurYear $year
|
||||||
destroy .g
|
catch { destroy .g }
|
||||||
FillCalWindow
|
FillCalWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1502,19 +1576,14 @@ proc DoGoto {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc Quit {} {
|
proc Quit {} {
|
||||||
global Option
|
global Option
|
||||||
global InotifyFP
|
|
||||||
if { !$Option(ConfirmQuit) } {
|
if { !$Option(ConfirmQuit) } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
catch { exec kill [pid $InotifyFP] }
|
|
||||||
catch { close $InotifyFP }
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
catch { exec kill [pid $InotifyFP] }
|
|
||||||
catch { close $InotifyFP }
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2106,7 +2175,7 @@ proc CreateReminder {w} {
|
|||||||
|
|
||||||
# Check it out!
|
# Check it out!
|
||||||
global Remind
|
global Remind
|
||||||
set f [open "|$Remind -arq -e - 2>&1" r+]
|
set f [open "|$Remind -arq -e - 2>@1" r+]
|
||||||
puts $f "BANNER %"
|
puts $f "BANNER %"
|
||||||
puts $f "$rem MSG %"
|
puts $f "$rem MSG %"
|
||||||
puts $f "MSG %_%_%_%_"
|
puts $f "MSG %_%_%_%_"
|
||||||
@@ -2545,7 +2614,6 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
cd $cwd
|
cd $cwd
|
||||||
$w.entry delete 0 end
|
$w.entry delete 0 end
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# StartBackgroundRemindDaemon
|
# StartBackgroundRemindDaemon
|
||||||
# Arguments:
|
# Arguments:
|
||||||
@@ -2558,9 +2626,9 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
proc StartBackgroundRemindDaemon {} {
|
proc StartBackgroundRemindDaemon {} {
|
||||||
global Remind DaemonFile ReminderFile Option TwentyFourHourMode
|
global Remind DaemonFile ReminderFile Option TwentyFourHourMode
|
||||||
if {$TwentyFourHourMode} {
|
if {$TwentyFourHourMode} {
|
||||||
set problem [catch { set DaemonFile [open "|$Remind -b1 -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
set problem [catch { set DaemonFile [open "|$Remind -b1 -zj -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||||
} else {
|
} else {
|
||||||
set problem [catch { set DaemonFile [open "|$Remind -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
set problem [catch { set DaemonFile [open "|$Remind -zj -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||||
}
|
}
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
||||||
@@ -2616,19 +2684,19 @@ proc RestartBackgroundRemindDaemon {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# ShowQueue
|
# ShowQueue
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# file -- file channel that is readable
|
# queue - the queue
|
||||||
# Returns:
|
# Returns:
|
||||||
# nothing
|
# nothing
|
||||||
# Description:
|
# Description:
|
||||||
# Dumps the debugging queue listing
|
# Dumps the debugging queue listing
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc ShowQueue { file } {
|
proc ShowQueue { queue } {
|
||||||
set w .queuedbg
|
set w .queuedbg
|
||||||
catch { destroy $w }
|
catch { destroy $w }
|
||||||
toplevel $w
|
toplevel $w
|
||||||
wm title $w "Queue (Debugging Output)"
|
wm title $w "Queue (Debugging Output)"
|
||||||
wm iconname $w "Queue Dbg"
|
wm iconname $w "Queue Dbg"
|
||||||
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
text $w.t -fg black -bg white -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
||||||
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
||||||
button $w.ok -text "OK" -command "destroy $w"
|
button $w.ok -text "OK" -command "destroy $w"
|
||||||
grid $w.t -row 0 -column 0 -sticky nsew
|
grid $w.t -row 0 -column 0 -sticky nsew
|
||||||
@@ -2639,26 +2707,34 @@ proc ShowQueue { file } {
|
|||||||
grid rowconfigure $w 0 -weight 1
|
grid rowconfigure $w 0 -weight 1
|
||||||
grid rowconfigure $w 1 -weight 0
|
grid rowconfigure $w 1 -weight 0
|
||||||
CenterWindow $w .
|
CenterWindow $w .
|
||||||
while (1) {
|
set obj [lsort -command sort_q $queue]
|
||||||
# We should only get one line
|
set did 0
|
||||||
gets $file line
|
$w.t tag configure grey -background "#DDDDDD" -selectbackground "#999999"
|
||||||
if {$line == "NOTE ENDJSONQUEUE"} {
|
set toggle 0
|
||||||
break
|
foreach q $obj {
|
||||||
}
|
if { $did > 0 } {
|
||||||
if {[catch {set obj [::json::json2dict $line]}]} {
|
$w.t insert end "\n"
|
||||||
continue;
|
}
|
||||||
}
|
foreach r $q {
|
||||||
set obj [lsort -command sort_q $obj]
|
if { $toggle != 0 } {
|
||||||
foreach q $obj {
|
$w.t insert end "$r " grey
|
||||||
$w.t insert end "$q\n"
|
} else {
|
||||||
}
|
$w.t insert end "$r "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$w.t insert end "\n"
|
||||||
|
set toggle [expr 1 - $toggle]
|
||||||
|
set did 1
|
||||||
|
}
|
||||||
|
if { $did == 0 } {
|
||||||
|
$w.t insert end "(Queue is empty)\n"
|
||||||
}
|
}
|
||||||
$w.t configure -state disabled
|
$w.t configure -state disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
proc sort_q { a b } {
|
proc sort_q { a b } {
|
||||||
set a_ttime [dict get $a nextttime]
|
set a_ttime [dict get $a nexttime]
|
||||||
set b_ttime [dict get $b nextttime]
|
set b_ttime [dict get $b nexttime]
|
||||||
if {$a_ttime < $b_ttime} {
|
if {$a_ttime < $b_ttime} {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@@ -2685,43 +2761,63 @@ proc DaemonReadable { file } {
|
|||||||
catch { close $file }
|
catch { close $file }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch -glob -- $line {
|
if {[catch {set obj [::json::json2dict $line]}]} {
|
||||||
"NOTE reminder*" {
|
return;
|
||||||
scan $line "NOTE reminder %s %s %s" time now tag
|
}
|
||||||
IssueBackgroundReminder $file $time $now $tag
|
if (![dict exists $obj response]) {
|
||||||
}
|
return;
|
||||||
"NOTE JSONQUEUE" {
|
}
|
||||||
ShowQueue $file
|
set response [dict get $obj response]
|
||||||
}
|
switch -- $response {
|
||||||
"NOTE newdate" {
|
"queued" {
|
||||||
# Date has rolled over -- clear "ignore" list
|
set n [dict get $obj nqueued]
|
||||||
catch { unset Ignore}
|
|
||||||
Initialize
|
|
||||||
FillCalWindow
|
|
||||||
ShowTodaysReminders
|
|
||||||
}
|
|
||||||
"NOTE reread" {
|
|
||||||
puts $file "STATUS"
|
|
||||||
flush $file
|
|
||||||
}
|
|
||||||
"NOTE queued*" {
|
|
||||||
scan $line "NOTE queued %d" n
|
|
||||||
if {$n == 1} {
|
if {$n == 1} {
|
||||||
.b.nqueued configure -text "1 reminder queued"
|
.b.nqueued configure -text "1 reminder queued"
|
||||||
} else {
|
} else {
|
||||||
.b.nqueued configure -text "$n reminders queued"
|
.b.nqueued configure -text "$n reminders queued"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default {
|
"reminder" {
|
||||||
puts stderr "Unknown message from daemon: $line\n"
|
set time [dict get $obj ttime]
|
||||||
}
|
set now [dict get $obj now]
|
||||||
|
set tag "*"
|
||||||
|
if {[dict exists $obj tags]} {
|
||||||
|
set tag [dict get $obj tags]
|
||||||
|
}
|
||||||
|
set body [dict get $obj body]
|
||||||
|
IssueBackgroundReminder $body $time $now $tag
|
||||||
|
}
|
||||||
|
"queue" {
|
||||||
|
set queue [dict get $obj queue]
|
||||||
|
ShowQueue $queue
|
||||||
|
}
|
||||||
|
"newdate" {
|
||||||
|
# Date has rolled over -- clear "ignore" list
|
||||||
|
catch { unset Ignore}
|
||||||
|
Initialize
|
||||||
|
FillCalWindow
|
||||||
|
ShowTodaysReminders
|
||||||
|
}
|
||||||
|
"reread" {
|
||||||
|
if {[dict exists $obj command]} {
|
||||||
|
set cmd [dict get $obj command]
|
||||||
|
if {"$cmd" == "inotify"} {
|
||||||
|
FillCalWindow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts $file "STATUS"
|
||||||
|
flush $file
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
puts stderr "Unknown message from daemon: $line\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# IssueBackgroundReminder
|
# IssueBackgroundReminder
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# file -- file channel that is readable
|
# body -- body of reminder
|
||||||
# time -- time of reminder
|
# time -- time of reminder
|
||||||
# now -- current time according to Remind daemon
|
# now -- current time according to Remind daemon
|
||||||
# tag -- tag for reminder, or "*" if no tag
|
# tag -- tag for reminder, or "*" if no tag
|
||||||
@@ -2730,26 +2826,14 @@ proc DaemonReadable { file } {
|
|||||||
# Description:
|
# Description:
|
||||||
# Reads a background reminder from daemon and pops up window.
|
# Reads a background reminder from daemon and pops up window.
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc IssueBackgroundReminder { file time now tag } {
|
proc IssueBackgroundReminder { body time now tag } {
|
||||||
global BgCounter Option Ignore
|
global BgCounter Option Ignore
|
||||||
if {$Option(Deiconify)} {
|
if {$Option(Deiconify)} {
|
||||||
wm deiconify .
|
wm deiconify .
|
||||||
}
|
}
|
||||||
|
|
||||||
set msg ""
|
|
||||||
set line ""
|
|
||||||
while (1) {
|
|
||||||
gets $file line
|
|
||||||
if {$line == "NOTE endreminder"} {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if {$msg != ""} {
|
|
||||||
append msg "\n";
|
|
||||||
}
|
|
||||||
append msg $line
|
|
||||||
}
|
|
||||||
# Do nothing if it's blank -- was probably a RUN-type reminder.
|
# Do nothing if it's blank -- was probably a RUN-type reminder.
|
||||||
if {$msg == ""} {
|
if {$body == ""} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2764,17 +2848,17 @@ proc IssueBackgroundReminder { file time now tag } {
|
|||||||
wm iconname $w "Reminder"
|
wm iconname $w "Reminder"
|
||||||
wm title $w "Timed reminder ($time)"
|
wm title $w "Timed reminder ($time)"
|
||||||
label $w.l -text "Reminder for $time issued at $now"
|
label $w.l -text "Reminder for $time issued at $now"
|
||||||
message $w.msg -width 6i -text $msg
|
message $w.msg -width 6i -text $body
|
||||||
frame $w.b
|
frame $w.b
|
||||||
|
|
||||||
# Automatically shut down window after a minute if option says so
|
# Automatically shut down window after a minute if option says so
|
||||||
set after_token [after 60000 [list ClosePopup $w "" $Option(MailAddr) $Option(AutoClose) "" $tag $msg $time]]
|
set after_token [after 60000 [list ClosePopup $w "" $Option(MailAddr) $Option(AutoClose) "" $tag $body $time]]
|
||||||
|
|
||||||
wm protocol $w WM_DELETE_WINDOW [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
|
wm protocol $w WM_DELETE_WINDOW [list ClosePopup $w $after_token "" 1 "" $tag $body $time]
|
||||||
button $w.ok -text "OK" -command [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
|
button $w.ok -text "OK" -command [list ClosePopup $w $after_token "" 1 "" $tag $body $time]
|
||||||
if {$tag != "*"} {
|
if {$tag != "*"} {
|
||||||
button $w.nomore -text "Don't remind me again today" -command [list ClosePopup $w $after_token "" 1 "ignore" $tag $msg $time]
|
button $w.nomore -text "Don't remind me again today" -command [list ClosePopup $w $after_token "" 1 "ignore" $tag $body $time]
|
||||||
button $w.kill -text "Delete this reminder completely" -command [list ClosePopup $w $after_token "" 1 "kill" $tag $msg $time]
|
button $w.kill -text "Delete this reminder completely" -command [list ClosePopup $w $after_token "" 1 "kill" $tag $body $time]
|
||||||
}
|
}
|
||||||
pack $w.l -side top
|
pack $w.l -side top
|
||||||
pack $w.msg -side top -expand 1 -fill both
|
pack $w.msg -side top -expand 1 -fill both
|
||||||
@@ -2792,17 +2876,11 @@ proc IssueBackgroundReminder { file time now tag } {
|
|||||||
}
|
}
|
||||||
if {$Option(RunCmd) != ""} {
|
if {$Option(RunCmd) != ""} {
|
||||||
if {$Option(FeedReminder)} {
|
if {$Option(FeedReminder)} {
|
||||||
FeedReminderToCommand $Option(RunCmd) "$time: $msg"
|
FeedReminderToCommand $Option(RunCmd) "$time: $body"
|
||||||
} else {
|
} else {
|
||||||
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# reread status
|
|
||||||
if {$file != "stdin"} {
|
|
||||||
puts $file "STATUS"
|
|
||||||
flush $file
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
@@ -2848,7 +2926,7 @@ proc main {} {
|
|||||||
|
|
||||||
global AppendFile HighestTagSoFar DayNames
|
global AppendFile HighestTagSoFar DayNames
|
||||||
catch {
|
catch {
|
||||||
puts "\nTkRemind Copyright (C) 1996-2021 Dianne Skoll"
|
puts "\nTkRemind Copyright (C) 1996-2024 Dianne Skoll"
|
||||||
}
|
}
|
||||||
catch { SetFonts }
|
catch { SetFonts }
|
||||||
Initialize
|
Initialize
|
||||||
@@ -2867,7 +2945,6 @@ proc main {} {
|
|||||||
CreateCalWindow $DayNames
|
CreateCalWindow $DayNames
|
||||||
FillCalWindow
|
FillCalWindow
|
||||||
StartBackgroundRemindDaemon
|
StartBackgroundRemindDaemon
|
||||||
SetupInotify
|
|
||||||
DisplayTimeContinuously
|
DisplayTimeContinuously
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3315,7 +3392,9 @@ proc EditableEnter { w } {
|
|||||||
set c [$w tag cget $ctag -foreground]
|
set c [$w tag cget $ctag -foreground]
|
||||||
}
|
}
|
||||||
if {"$c" != ""} {
|
if {"$c" != ""} {
|
||||||
$w tag configure $tag -underline 1 -underlinefg $c
|
$w tag configure $tag -underline 1
|
||||||
|
# underlinefg not supported on older versions of Tk
|
||||||
|
eval { $w tag configure $tag -underlinefg $c }
|
||||||
} else {
|
} else {
|
||||||
$w tag configure $tag -underline 1
|
$w tag configure $tag -underline 1
|
||||||
}
|
}
|
||||||
@@ -3622,7 +3701,9 @@ proc DoShadeSpecial { n r g b } {
|
|||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc DoMoonSpecial { n stuff fntag day } {
|
proc DoMoonSpecial { n stuff fntag day } {
|
||||||
set msg ""
|
set msg ""
|
||||||
set num [scan $stuff "%d %d %d %s" phase junk1 junk2 msg]
|
# Yes, this is gross, but the odds of ctrl-A appearing
|
||||||
|
# in the text associated with a MOON are small.
|
||||||
|
set num [scan $stuff {%d %d %d %[^]} phase junk1 junk2 msg]
|
||||||
if {$num < 1} {
|
if {$num < 1} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -3683,7 +3764,7 @@ proc DoMoonSpecial { n stuff fntag day } {
|
|||||||
# Displays current date and time in status window
|
# Displays current date and time in status window
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc DisplayTime {} {
|
proc DisplayTime {} {
|
||||||
global TwentyFourHourMode
|
global TwentyFourHourMode DaemonFile
|
||||||
if {$TwentyFourHourMode} {
|
if {$TwentyFourHourMode} {
|
||||||
set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
|
set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
|
||||||
} else {
|
} else {
|
||||||
@@ -3813,13 +3894,19 @@ proc ShowTodaysReminders {} {
|
|||||||
append cmdline "-b1 "
|
append cmdline "-b1 "
|
||||||
}
|
}
|
||||||
append cmdline $Option(ExtraRemindArgs);
|
append cmdline $Option(ExtraRemindArgs);
|
||||||
append cmdline " $ReminderFile 2>/dev/null"
|
append cmdline " $ReminderFile 2>@1"
|
||||||
set f [open $cmdline r]
|
set f [open $cmdline r]
|
||||||
while {[gets $f line] >= 0} {
|
while {[gets $f line] >= 0} {
|
||||||
append stuff "$line\n"
|
append stuff "$line\n"
|
||||||
}
|
}
|
||||||
close $f
|
if {[catch { close $f } err]} {
|
||||||
$w.text insert end $stuff
|
$w.text insert end "Error running Remind\n\n"
|
||||||
|
$w.text insert end $stuff
|
||||||
|
$w.text insert end "\n"
|
||||||
|
$w.text insert end $err
|
||||||
|
} else {
|
||||||
|
$w.text insert end $stuff
|
||||||
|
}
|
||||||
$w.text configure -state disabled
|
$w.text configure -state disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3889,30 +3976,6 @@ proc SetFonts {} {
|
|||||||
set SetFontsWorked 1
|
set SetFontsWorked 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set up inotify to watch for changes to reminder file/directory
|
|
||||||
proc SetupInotify {} {
|
|
||||||
global InotifyFP
|
|
||||||
global ReminderFile
|
|
||||||
set failed [catch {set InotifyFP [open "|inotifywait -r -q -m -e close_write -e move -e create -e delete $ReminderFile < /dev/null 2>/dev/null" "r"] } ]
|
|
||||||
if {$failed} {
|
|
||||||
# inotifywait probably not available... meh.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fileevent $InotifyFP readable [list InotifyReadable $InotifyFP]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Called when inotifywait reports an event. Schedule a calendar update
|
|
||||||
# and daemon reload.
|
|
||||||
proc InotifyReadable { fp } {
|
|
||||||
catch { set num [gets $fp line] }
|
|
||||||
if {$num < 0} {
|
|
||||||
catch { exec kill [pid $fp] }
|
|
||||||
close $fp
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ScheduleUpdateForChanges
|
|
||||||
}
|
|
||||||
|
|
||||||
### Balloon help
|
### Balloon help
|
||||||
set Balloon(HelpTime) 400
|
set Balloon(HelpTime) 400
|
||||||
set Balloon(StayTime) 3500
|
set Balloon(StayTime) 3500
|
||||||
@@ -3985,13 +4048,17 @@ bind Balloon <Destroy> {
|
|||||||
catch { unset Balloon(helptext%W) }
|
catch { unset Balloon(helptext%W) }
|
||||||
}
|
}
|
||||||
|
|
||||||
proc balloon_add_help { w txt } {
|
proc balloon_set_help { w txt } {
|
||||||
global Balloon
|
global Balloon
|
||||||
if {"$txt" == ""} {
|
if {"$txt" == ""} {
|
||||||
catch { unset Balloon(helptext$w) }
|
catch { unset Balloon(helptext$w) }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set Balloon(helptext$w) $txt
|
set Balloon(helptext$w) $txt
|
||||||
|
}
|
||||||
|
|
||||||
|
proc balloon_add_help { w txt } {
|
||||||
|
balloon_set_help $w $txt
|
||||||
bindtags $w "Balloon [bindtags $w]"
|
bindtags $w "Balloon [bindtags $w]"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4143,9 +4210,11 @@ proc update_color_buttons { w } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc set_button_to_queue {} {
|
proc set_button_to_queue {} {
|
||||||
|
balloon_set_help .b.queue "See the queue of pending reminders (debugging purposes only)"
|
||||||
.b.queue configure -text {Queue...} -command {DoQueue}
|
.b.queue configure -text {Queue...} -command {DoQueue}
|
||||||
}
|
}
|
||||||
proc set_button_to_errors {} {
|
proc set_button_to_errors {} {
|
||||||
|
balloon_set_help .b.queue "See the list of errors from the most recent operation"
|
||||||
.b.queue configure -text {Errors...} -command {ShowErrors}
|
.b.queue configure -text {Errors...} -command {ShowErrors}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ REMINDOBJS= $(REMINDSRCS:.c=.o)
|
|||||||
|
|
||||||
all: remind rem2ps
|
all: remind rem2ps
|
||||||
|
|
||||||
test: remind
|
test: all
|
||||||
@sh ../tests/test-rem
|
@sh ../tests/test-rem
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
@@ -45,12 +45,12 @@ test: remind
|
|||||||
$(REMINDOBJS): $(REMINDHDRS)
|
$(REMINDOBJS): $(REMINDHDRS)
|
||||||
|
|
||||||
rem2ps: rem2ps.o dynbuf.o json.o
|
rem2ps: rem2ps.o dynbuf.o json.o
|
||||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
|
@CC@ @CFLAGS@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
|
||||||
|
|
||||||
remind: $(REMINDOBJS)
|
remind: $(REMINDOBJS)
|
||||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
|
@CC@ @CFLAGS@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
|
||||||
|
|
||||||
install-nostripped: all
|
install: all
|
||||||
-mkdir -p $(DESTDIR)$(bindir) || true
|
-mkdir -p $(DESTDIR)$(bindir) || true
|
||||||
for prog in $(PROGS) $(SCRIPTS) ; do \
|
for prog in $(PROGS) $(SCRIPTS) ; do \
|
||||||
$(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir) || exit 1; \
|
$(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir) || exit 1; \
|
||||||
@@ -63,14 +63,26 @@ install-nostripped: all
|
|||||||
done
|
done
|
||||||
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
|
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
|
||||||
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
|
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
|
||||||
|
-mkdir -p $(DESTDIR)$(prefix)/icons
|
||||||
|
-mkdir -p $(DESTDIR)$(prefix)/applications
|
||||||
|
$(INSTALL_DATA) $(srcdir)/../resources/tkremind.png $(DESTDIR)$(prefix)/icons
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/../resources/tkremind.desktop $(DESTDIR)$(prefix)/applications
|
||||||
|
-if test "$(DESTDIR)" = ""; then \
|
||||||
|
update-desktop-database < /dev/null > /dev/null 2>&1 ; \
|
||||||
|
xdg-icon-resource install --novendor --size 64 $(DESTDIR)$(prefix)/icons/tkremind.png < /dev/null > /dev/null 2>&1; \
|
||||||
|
xdg-desktop-menu install --novendor $(DESTDIR)$(prefix)/applications/tkremind.desktop < /dev/null > /dev/null 2>&1 ; \
|
||||||
|
fi
|
||||||
|
|
||||||
install: install-nostripped
|
install-stripped: install
|
||||||
strip $(DESTDIR)$(bindir)/remind || true
|
strip $(DESTDIR)$(bindir)/remind || true
|
||||||
strip $(DESTDIR)$(bindir)/rem2ps || true
|
strip $(DESTDIR)$(bindir)/rem2ps || true
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ core *.bak $(PROGS)
|
rm -f *.o *~ core *.bak $(PROGS)
|
||||||
|
|
||||||
|
cppcheck:
|
||||||
|
cppcheck --force --enable=all --suppress=variableScope --suppress=ConfigurationNotChecked *.c
|
||||||
|
|
||||||
clobber:
|
clobber:
|
||||||
rm -f *.o *~ remind rem2ps test.out core *.bak
|
rm -f *.o *~ remind rem2ps test.out core *.bak
|
||||||
|
|
||||||
|
|||||||
760
src/calendar.c
760
src/calendar.c
File diff suppressed because it is too large
Load Diff
@@ -7,12 +7,12 @@
|
|||||||
/* Define if your <sys/time.h> declares struct tm. */
|
/* Define if your <sys/time.h> declares struct tm. */
|
||||||
#undef TM_IN_SYS_TIME
|
#undef TM_IN_SYS_TIME
|
||||||
|
|
||||||
/* Define if you have the <sys/file.h> header file. */
|
|
||||||
#undef HAVE_SYS_FILE_H
|
|
||||||
|
|
||||||
/* Define if you have the <sys/types.h> header file. */
|
/* Define if you have the <sys/types.h> header file. */
|
||||||
#undef HAVE_SYS_TYPES_H
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define if you have the <sys/inotify.h> header file. */
|
||||||
|
#undef HAVE_SYS_INOTIFY_H
|
||||||
|
|
||||||
/* Define if you have the <glob.h> header file */
|
/* Define if you have the <glob.h> header file */
|
||||||
#undef HAVE_GLOB_H
|
#undef HAVE_GLOB_H
|
||||||
|
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#undef HAVE_LOCALE_H
|
#undef HAVE_LOCALE_H
|
||||||
|
|
||||||
|
#undef HAVE_INOTIFY_INIT1
|
||||||
|
|
||||||
#undef HAVE_LANGINFO_H
|
#undef HAVE_LANGINFO_H
|
||||||
|
|
||||||
#undef HAVE_GLOB
|
#undef HAVE_GLOB
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
275
src/dorem.c
275
src/dorem.c
@@ -7,7 +7,8 @@
|
|||||||
/* commands. */
|
/* commands. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
|||||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||||
static int ParseUntil (ParsePtr s, Trigger *t, int type);
|
static int ParseUntil (ParsePtr s, Trigger *t, int type);
|
||||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
|
static int ShouldTriggerBasedOnWarn (Trigger *t, int dse, int *err);
|
||||||
static int ComputeTrigDuration(TimeTrig *t);
|
static int ComputeTrigDuration(TimeTrig *t);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -55,7 +56,7 @@ int DoRem(ParsePtr p)
|
|||||||
Trigger trig;
|
Trigger trig;
|
||||||
TimeTrig tim;
|
TimeTrig tim;
|
||||||
int r, err;
|
int r, err;
|
||||||
int jul;
|
int dse;
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
Token tok;
|
Token tok;
|
||||||
|
|
||||||
@@ -96,9 +97,13 @@ int DoRem(ParsePtr p)
|
|||||||
FindToken(DBufValue(&buf), &tok);
|
FindToken(DBufValue(&buf), &tok);
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||||
|
r = OK;
|
||||||
|
if (trig.addomit) {
|
||||||
|
r = AddGlobalOmit(LastTriggerDate);
|
||||||
|
}
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return OK;
|
return r;
|
||||||
}
|
}
|
||||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -118,16 +123,20 @@ int DoRem(ParsePtr p)
|
|||||||
}
|
}
|
||||||
StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN);
|
StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN);
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
}
|
}
|
||||||
trig.typ = tok.val;
|
trig.typ = tok.val;
|
||||||
jul = LastTriggerDate;
|
|
||||||
|
/* Convert some SPECIALs back to plain types */
|
||||||
|
FixSpecialType(&trig);
|
||||||
|
|
||||||
|
dse = LastTriggerDate;
|
||||||
if (!LastTrigValid || PurgeMode) {
|
if (!LastTrigValid || PurgeMode) {
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Calculate the trigger date */
|
/* Calculate the trigger date */
|
||||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (PurgeMode) {
|
if (PurgeMode) {
|
||||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||||
@@ -143,14 +152,14 @@ int DoRem(ParsePtr p)
|
|||||||
|
|
||||||
/* Add to global OMITs if so indicated */
|
/* Add to global OMITs if so indicated */
|
||||||
if (trig.addomit) {
|
if (trig.addomit) {
|
||||||
r = AddGlobalOmit(jul);
|
r = AddGlobalOmit(dse);
|
||||||
if (r) {
|
if (r) {
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (PurgeMode) {
|
if (PurgeMode) {
|
||||||
if (trig.expired || jul < JulianToday) {
|
if (trig.expired || dse < DSEToday) {
|
||||||
if (p->expr_happened) {
|
if (p->expr_happened) {
|
||||||
if (p->nonconst_expr) {
|
if (p->nonconst_expr) {
|
||||||
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
||||||
@@ -170,10 +179,10 @@ int DoRem(ParsePtr p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Queue the reminder, if necessary */
|
/* Queue the reminder, if necessary */
|
||||||
if (jul == JulianToday &&
|
if (dse == DSEToday &&
|
||||||
!(!IgnoreOnce &&
|
!(!IgnoreOnce &&
|
||||||
trig.once != NO_ONCE &&
|
trig.once != NO_ONCE &&
|
||||||
FileAccessDate == JulianToday))
|
FileAccessDate == DSEToday))
|
||||||
QueueReminder(p, &trig, &tim, trig.sched);
|
QueueReminder(p, &trig, &tim, trig.sched);
|
||||||
/* If we're in daemon mode, do nothing over here */
|
/* If we're in daemon mode, do nothing over here */
|
||||||
if (Daemon) {
|
if (Daemon) {
|
||||||
@@ -182,17 +191,19 @@ int DoRem(ParsePtr p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = OK;
|
r = OK;
|
||||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
|
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0, NULL)) ) {
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Parse the rest of the line to catch any potential
|
/* Parse the rest of the line to catch any potential
|
||||||
expression-pasting errors */
|
expression-pasting errors */
|
||||||
while (ParseChar(p, &r, 0)) {
|
if (ParseUntriggered) {
|
||||||
if (r != 0) {
|
while (ParseChar(p, &r, 0)) {
|
||||||
break;
|
if (r != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,6 +241,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
trig->skip = NO_SKIP;
|
trig->skip = NO_SKIP;
|
||||||
trig->once = NO_ONCE;
|
trig->once = NO_ONCE;
|
||||||
trig->addomit = 0;
|
trig->addomit = 0;
|
||||||
|
trig->noqueue = 0;
|
||||||
trig->typ = NO_TYPE;
|
trig->typ = NO_TYPE;
|
||||||
trig->scanfrom = NO_DATE;
|
trig->scanfrom = NO_DATE;
|
||||||
trig->from = NO_DATE;
|
trig->from = NO_DATE;
|
||||||
@@ -287,7 +299,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||||
FromJulian(tok.val, &y, &m, &d);
|
FromDSE(tok.val, &y, &m, &d);
|
||||||
trig->y = y;
|
trig->y = y;
|
||||||
trig->m = m;
|
trig->m = m;
|
||||||
trig->d = d;
|
trig->d = d;
|
||||||
@@ -298,7 +310,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||||
FromJulian(tok.val / MINUTES_PER_DAY, &y, &m, &d);
|
FromDSE(tok.val / MINUTES_PER_DAY, &y, &m, &d);
|
||||||
trig->y = y;
|
trig->y = y;
|
||||||
trig->m = m;
|
trig->m = m;
|
||||||
trig->d = d;
|
trig->d = d;
|
||||||
@@ -338,6 +350,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
if (r) return r;
|
if (r) return r;
|
||||||
break;
|
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, save_in_globals);
|
||||||
|
if (r) return r;
|
||||||
|
trig->duration_days = ComputeTrigDuration(tim);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_At:
|
case T_At:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||||
@@ -364,6 +386,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
}
|
}
|
||||||
StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN);
|
StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN);
|
||||||
}
|
}
|
||||||
|
FixSpecialType(trig);
|
||||||
parsing = 0;
|
parsing = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -431,6 +454,11 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
trig->addomit = 1;
|
trig->addomit = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_NoQueue:
|
||||||
|
DBufFree(&buf);
|
||||||
|
trig->noqueue = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case T_Omit:
|
case T_Omit:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
if (trig->omitfunc[0]) {
|
if (trig->omitfunc[0]) {
|
||||||
@@ -470,7 +498,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
case T_Tag:
|
case T_Tag:
|
||||||
r = ParseToken(s, &buf);
|
r = ParseToken(s, &buf);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
|
if (strchr(DBufValue(&buf), ',')) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
AppendTag(&(trig->tags), DBufValue(&buf));
|
AppendTag(&(trig->tags), DBufValue(&buf));
|
||||||
|
DBufFree(&buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Duration:
|
case T_Duration:
|
||||||
@@ -543,7 +576,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
/* Check for some warning conditions */
|
/* Check for some warning conditions */
|
||||||
if (!s->nonconst_expr) {
|
if (!s->nonconst_expr) {
|
||||||
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
|
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
|
||||||
if (Julian(trig->y, trig->m, trig->d) > trig->until) {
|
if (DSE(trig->y, trig->m, trig->d) > trig->until) {
|
||||||
Wprint("Warning: UNTIL/THROUGH date earlier than start date");
|
Wprint("Warning: UNTIL/THROUGH date earlier than start date");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -564,7 +597,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
|
|
||||||
/* Set scanfrom to default if not set explicitly */
|
/* Set scanfrom to default if not set explicitly */
|
||||||
if (trig->scanfrom == NO_DATE) {
|
if (trig->scanfrom == NO_DATE) {
|
||||||
trig->scanfrom = JulianToday;
|
trig->scanfrom = DSEToday;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@@ -723,7 +756,7 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
|||||||
Eprint("%s: %s", which, ErrMsg[E_DAY_TWICE]);
|
Eprint("%s: %s", which, ErrMsg[E_DAY_TWICE]);
|
||||||
return E_DAY_TWICE;
|
return E_DAY_TWICE;
|
||||||
}
|
}
|
||||||
FromJulian(tok.val, &y, &m, &d);
|
FromDSE(tok.val, &y, &m, &d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -736,7 +769,7 @@ static int ParseUntil(ParsePtr s, Trigger *t, int type)
|
|||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return E_BAD_DATE;
|
return E_BAD_DATE;
|
||||||
}
|
}
|
||||||
t->until = Julian(y, m, d);
|
t->until = DSE(y, m, d);
|
||||||
PushToken(DBufValue(&buf), s);
|
PushToken(DBufValue(&buf), s);
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -815,7 +848,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
|
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
|
||||||
return E_DAY_TWICE;
|
return E_DAY_TWICE;
|
||||||
}
|
}
|
||||||
FromJulian(tok.val, &y, &m, &d);
|
FromDSE(tok.val, &y, &m, &d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Back:
|
case T_Back:
|
||||||
@@ -839,7 +872,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
if (tok.val < 0) {
|
if (tok.val < 0) {
|
||||||
tok.val = -tok.val;
|
tok.val = -tok.val;
|
||||||
}
|
}
|
||||||
FromJulian(JulianToday - tok.val, &y, &m, &d);
|
FromDSE(DSEToday - tok.val, &y, &m, &d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -852,11 +885,11 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return E_BAD_DATE;
|
return E_BAD_DATE;
|
||||||
}
|
}
|
||||||
t->scanfrom = Julian(y, m, d);
|
t->scanfrom = DSE(y, m, d);
|
||||||
if (type == FROM_TYPE) {
|
if (type == FROM_TYPE) {
|
||||||
t->from = t->scanfrom;
|
t->from = t->scanfrom;
|
||||||
if (t->scanfrom < JulianToday) {
|
if (t->scanfrom < DSEToday) {
|
||||||
t->scanfrom = JulianToday;
|
t->scanfrom = DSEToday;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
t->from = NO_DATE;
|
t->from = NO_DATE;
|
||||||
@@ -868,6 +901,8 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* TriggerReminder */
|
/* TriggerReminder */
|
||||||
@@ -875,7 +910,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
/* Trigger the reminder if it's a RUN or MSG type. */
|
/* Trigger the reminder if it's a RUN or MSG type. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
int r, y, m, d;
|
int r, y, m, d;
|
||||||
char PrioExpr[VAR_NAME_LEN+25];
|
char PrioExpr[VAR_NAME_LEN+25];
|
||||||
@@ -883,8 +918,21 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
DynamicBuffer buf, calRow;
|
DynamicBuffer buf, calRow;
|
||||||
DynamicBuffer pre_buf;
|
DynamicBuffer pre_buf;
|
||||||
char const *s;
|
char const *s;
|
||||||
|
char const *msg_command = NULL;
|
||||||
Value v;
|
Value v;
|
||||||
|
|
||||||
|
if (MsgCommand) {
|
||||||
|
msg_command = MsgCommand;
|
||||||
|
}
|
||||||
|
if (is_queued && QueuedMsgCommand) {
|
||||||
|
msg_command = QueuedMsgCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A null command is no command */
|
||||||
|
if (msg_command && !*msg_command) {
|
||||||
|
msg_command = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int red = -1, green = -1, blue = -1;
|
int red = -1, green = -1, blue = -1;
|
||||||
int is_color = 0;
|
int is_color = 0;
|
||||||
|
|
||||||
@@ -929,25 +977,26 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
}
|
}
|
||||||
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
|
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
|
||||||
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
|
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
|
||||||
&& !NumTriggered && !NextMode && !MsgCommand) {
|
&& !DidMsgReminder && !NextMode && !msg_command && !is_queued) {
|
||||||
|
DidMsgReminder = 1;
|
||||||
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
||||||
JulianToday, NO_TIME) &&
|
DSEToday, NO_TIME) &&
|
||||||
DBufLen(&buf)) {
|
DBufLen(&buf)) {
|
||||||
printf("%s\n", DBufValue(&buf));
|
printf("%s\n", DBufValue(&buf));
|
||||||
}
|
}
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
|
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
|
||||||
simple-calendar format. */
|
simple-calendar format. */
|
||||||
if (NextMode) {
|
if (NextMode) {
|
||||||
if ( (r=DoSubst(p, &buf, t, tim, jul, ADVANCE_MODE)) ) return r;
|
if ( (r=DoSubst(p, &buf, t, tim, dse, ADVANCE_MODE)) ) return r;
|
||||||
if (!DBufLen(&buf)) {
|
if (!DBufLen(&buf)) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
DBufFree(&pre_buf);
|
DBufFree(&pre_buf);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(tmpBuf, "%04d/%02d/%02d ", y, m+1, d);
|
sprintf(tmpBuf, "%04d/%02d/%02d ", y, m+1, d);
|
||||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
@@ -995,11 +1044,18 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
return E_NO_MEM;
|
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(&buf);
|
||||||
DBufFree(&pre_buf);
|
DBufFree(&pre_buf);
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
return OK;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Correct colors */
|
/* Correct colors */
|
||||||
@@ -1030,7 +1086,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
if (!r) {
|
if (!r) {
|
||||||
if (!DoCoerce(STR_TYPE, &v)) {
|
if (!DoCoerce(STR_TYPE, &v)) {
|
||||||
if (is_color) {
|
if (is_color) {
|
||||||
DBufPuts(&buf, Colorize(red, green, blue));
|
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
|
||||||
}
|
}
|
||||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -1044,9 +1100,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_color) {
|
if (is_color) {
|
||||||
DBufPuts(&buf, Colorize(red, green, blue));
|
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
|
||||||
}
|
}
|
||||||
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
|
if ( (r=DoSubst(p, &buf, t, tim, dse, NORMAL_MODE)) ) return r;
|
||||||
if (t->typ != RUN_TYPE) {
|
if (t->typ != RUN_TYPE) {
|
||||||
if (UserFuncExists("msgsuffix") == 1) {
|
if (UserFuncExists("msgsuffix") == 1) {
|
||||||
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
||||||
@@ -1055,7 +1111,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
if (!r) {
|
if (!r) {
|
||||||
if (!DoCoerce(STR_TYPE, &v)) {
|
if (!DoCoerce(STR_TYPE, &v)) {
|
||||||
if (is_color) {
|
if (is_color) {
|
||||||
DBufPuts(&buf, Colorize(red, green, blue));
|
DBufPuts(&buf, Colorize(red, green, blue, 0, 1));
|
||||||
}
|
}
|
||||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -1069,10 +1125,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_color) {
|
if (is_color) {
|
||||||
DBufPuts(&buf, Decolorize(red, green, blue));
|
DBufPuts(&buf, Decolorize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
|
if ((!msg_command && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
|
||||||
if (DBufPutc(&buf, '\n') != OK) {
|
if (DBufPutc(&buf, '\n') != OK) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
@@ -1081,7 +1137,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
|
|
||||||
/* If we are sorting, just queue it up in the sort buffer */
|
/* If we are sorting, just queue it up in the sort buffer */
|
||||||
if (SortByDate) {
|
if (SortByDate) {
|
||||||
if (InsertIntoSortBuffer(jul, tim->ttime, DBufValue(&buf),
|
if (InsertIntoSortBuffer(dse, tim->ttime, DBufValue(&buf),
|
||||||
t->typ, t->priority) == OK) {
|
t->typ, t->priority) == OK) {
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
NumTriggered++;
|
NumTriggered++;
|
||||||
@@ -1094,19 +1150,28 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
switch(t->typ) {
|
switch(t->typ) {
|
||||||
case MSG_TYPE:
|
case MSG_TYPE:
|
||||||
case PASSTHRU_TYPE:
|
case PASSTHRU_TYPE:
|
||||||
if (MsgCommand) {
|
if (msg_command) {
|
||||||
DoMsgCommand(MsgCommand, DBufValue(&buf));
|
DoMsgCommand(msg_command, DBufValue(&buf), is_queued);
|
||||||
} else {
|
} 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;
|
break;
|
||||||
|
|
||||||
case MSF_TYPE:
|
case MSF_TYPE:
|
||||||
FillParagraph(DBufValue(&buf));
|
FillParagraph(DBufValue(&buf), output);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
System(DBufValue(&buf));
|
System(DBufValue(&buf), is_queued);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* Unknown/illegal type? */
|
default: /* Unknown/illegal type? */
|
||||||
@@ -1128,24 +1193,24 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
/* triggered. Sets *err non-zero in event of an error. */
|
/* triggered. Sets *err non-zero in event of an error. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
||||||
{
|
{
|
||||||
int r, omit;
|
int r, omit;
|
||||||
*err = 0;
|
*err = 0;
|
||||||
|
|
||||||
/* Handle the ONCE modifier in the reminder. */
|
/* Handle the ONCE modifier in the reminder. */
|
||||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
|
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == DSEToday)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (jul < JulianToday) return 0;
|
if (dse < DSEToday) return 0;
|
||||||
|
|
||||||
/* Don't trigger timed reminders if DontIssueAts is true, and if the
|
/* Don't trigger timed reminders if DontIssueAts is true, and if the
|
||||||
reminder is for today */
|
reminder is for today */
|
||||||
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) {
|
if (dse == DSEToday && DontIssueAts && tim->ttime != NO_TIME) {
|
||||||
if (DontIssueAts > 1) {
|
if (DontIssueAts > 1) {
|
||||||
/* If two or more -a options, then *DO* issue ats that are in the
|
/* If two or more -a options, then *DO* issue ats that are in the
|
||||||
future */
|
future */
|
||||||
if (tim->ttime < SystemTime(0) / 60) {
|
if (tim->ttime < MinutesPastMidnight(0)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1153,41 +1218,43 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't trigger "old" timed reminders */
|
|
||||||
/*** REMOVED...
|
|
||||||
if (jul == JulianToday &&
|
|
||||||
tim->ttime != NO_TIME &&
|
|
||||||
tim->ttime < SystemTime(0) / 60) return 0;
|
|
||||||
*** ...UNTIL HERE */
|
|
||||||
|
|
||||||
/* If "infinite delta" option is chosen, always trigger future reminders */
|
/* If "infinite delta" option is chosen, always trigger future reminders */
|
||||||
if (InfiniteDelta || NextMode) return 1;
|
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 (t->warn[0] != 0) {
|
||||||
if (DeltaOffset) {
|
if (DeltaOverride > 0) {
|
||||||
if (jul <= JulianToday + DeltaOffset) {
|
if (dse <= DSEToday + DeltaOverride) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ShouldTriggerBasedOnWarn(t, jul, err);
|
return ShouldTriggerBasedOnWarn(t, dse, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero delta */
|
||||||
|
if (DeltaOverride < 0) {
|
||||||
|
return dse == DSEToday;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move back by delta days, if any */
|
/* Move back by delta days, if any */
|
||||||
if (t->delta != NO_DELTA) {
|
if (DeltaOverride) {
|
||||||
if (t->delta < 0)
|
/* A positive DeltaOverride takes precedence over everything */
|
||||||
jul = jul + t->delta;
|
dse = dse - DeltaOverride;
|
||||||
|
} else if (t->delta != NO_DELTA) {
|
||||||
|
if (t->delta < 0)
|
||||||
|
dse = dse + t->delta;
|
||||||
else {
|
else {
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
int max = MaxSatIter;
|
int max = MaxSatIter;
|
||||||
r = t->delta;
|
r = t->delta;
|
||||||
if (max < r*2) max = r*2;
|
if (max < r*2) max = r*2;
|
||||||
while(iter++ < max) {
|
while(iter++ < max) {
|
||||||
if (!r || (jul <= JulianToday)) {
|
if (!r || (dse <= DSEToday)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
jul--;
|
dse--;
|
||||||
*err = IsOmitted(jul, t->localomit, t->omitfunc, &omit);
|
*err = IsOmitted(dse, t->localomit, t->omitfunc, &omit);
|
||||||
if (*err) return 0;
|
if (*err) return 0;
|
||||||
if (!omit) r--;
|
if (!omit) r--;
|
||||||
}
|
}
|
||||||
@@ -1200,7 +1267,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Should we trigger the reminder? */
|
/* Should we trigger the reminder? */
|
||||||
return (jul <= JulianToday + DeltaOffset);
|
return (dse <= DSEToday);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -1212,7 +1279,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||||
{
|
{
|
||||||
int iter, jul, r, start;
|
int iter, dse, r, start;
|
||||||
Value v;
|
Value v;
|
||||||
char const *s;
|
char const *s;
|
||||||
char const *t;
|
char const *t;
|
||||||
@@ -1221,25 +1288,25 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
|||||||
iter = 0;
|
iter = 0;
|
||||||
start = trig->scanfrom;
|
start = trig->scanfrom;
|
||||||
while (iter++ < MaxSatIter) {
|
while (iter++ < MaxSatIter) {
|
||||||
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
|
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, 0);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (r == E_CANT_TRIG) return OK; else return r;
|
if (r == E_CANT_TRIG) return OK; else return r;
|
||||||
}
|
}
|
||||||
if (jul != start && trig->duration_days) {
|
if (dse != start && trig->duration_days) {
|
||||||
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
|
dse = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1, trig->duration_days);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (r == E_CANT_TRIG) return OK; else return r;
|
if (r == E_CANT_TRIG) return OK; else return r;
|
||||||
}
|
}
|
||||||
} else if (jul == start) {
|
} else if (dse == start) {
|
||||||
if (tt->ttime != NO_TIME) {
|
if (tt->ttime != NO_TIME) {
|
||||||
trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
|
trig->eventstart = MINUTES_PER_DAY * r + tt->ttime;
|
||||||
if (tt->duration != NO_TIME) {
|
if (tt->duration != NO_TIME) {
|
||||||
trig->eventduration = tt->duration;
|
trig->eventduration = tt->duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SaveAllTriggerInfo(trig, tt, jul, tt->ttime, 1);
|
SaveAllTriggerInfo(trig, tt, dse, tt->ttime, 1);
|
||||||
}
|
}
|
||||||
if (jul == -1) {
|
if (dse == -1) {
|
||||||
return E_EXPIRED;
|
return E_EXPIRED;
|
||||||
}
|
}
|
||||||
s = p->pos;
|
s = p->pos;
|
||||||
@@ -1249,10 +1316,10 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
|||||||
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
|
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
|
||||||
if ((v.type == INT_TYPE && v.v.val) ||
|
if ((v.type == INT_TYPE && v.v.val) ||
|
||||||
(v.type == STR_TYPE && *v.v.str)) {
|
(v.type == STR_TYPE && *v.v.str)) {
|
||||||
AdjustTriggerForDuration(trig->scanfrom, jul, trig, tt, 1);
|
AdjustTriggerForDuration(trig->scanfrom, dse, trig, tt, 1);
|
||||||
if (DebugFlag & DB_PRTTRIG) {
|
if (DebugFlag & DB_PRTTRIG) {
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||||
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
|
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
|
||||||
FileName, LineNo,
|
FileName, LineNo,
|
||||||
get_day_name(LastTriggerDate % 7),
|
get_day_name(LastTriggerDate % 7),
|
||||||
@@ -1274,10 +1341,10 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
p->pos = s;
|
p->pos = s;
|
||||||
if (jul+trig->duration_days < start) {
|
if (dse+trig->duration_days < start) {
|
||||||
start++;
|
start++;
|
||||||
} else {
|
} else {
|
||||||
start = jul+trig->duration_days+1;
|
start = dse+trig->duration_days+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->pos = t;
|
p->pos = t;
|
||||||
@@ -1331,7 +1398,7 @@ static int ParsePriority(ParsePtr s, Trigger *t)
|
|||||||
/* Execute the '-k' command, escaping shell chars in message. */
|
/* 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 r;
|
||||||
int i, l;
|
int i, l;
|
||||||
@@ -1368,7 +1435,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
|||||||
}
|
}
|
||||||
r = OK;
|
r = OK;
|
||||||
|
|
||||||
System(DBufValue(&execBuffer));
|
System(DBufValue(&execBuffer), is_queued);
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
@@ -1384,7 +1451,7 @@ finished:
|
|||||||
/* function. */
|
/* function. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
static int ShouldTriggerBasedOnWarn(Trigger *t, int dse, int *err)
|
||||||
{
|
{
|
||||||
char buffer[VAR_NAME_LEN+32];
|
char buffer[VAR_NAME_LEN+32];
|
||||||
int i;
|
int i;
|
||||||
@@ -1396,7 +1463,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
|||||||
/* If no proper function exists, barf... */
|
/* If no proper function exists, barf... */
|
||||||
if (UserFuncExists(t->warn) != 1) {
|
if (UserFuncExists(t->warn) != 1) {
|
||||||
Eprint("%s: `%s'", ErrMsg[M_BAD_WARN_FUNC], t->warn);
|
Eprint("%s: `%s'", ErrMsg[M_BAD_WARN_FUNC], t->warn);
|
||||||
return (jul == JulianToday);
|
return (dse == DSEToday);
|
||||||
}
|
}
|
||||||
for (i=1; ; i++) {
|
for (i=1; ; i++) {
|
||||||
sprintf(buffer, "%s(%d)", t->warn, i);
|
sprintf(buffer, "%s(%d)", t->warn, i);
|
||||||
@@ -1405,28 +1472,28 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
|||||||
if (r) {
|
if (r) {
|
||||||
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
||||||
t->warn, ErrMsg[r]);
|
t->warn, ErrMsg[r]);
|
||||||
return (jul == JulianToday);
|
return (dse == DSEToday);
|
||||||
}
|
}
|
||||||
if (v.type != INT_TYPE) {
|
if (v.type != INT_TYPE) {
|
||||||
DestroyValue(v);
|
DestroyValue(v);
|
||||||
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
||||||
t->warn, ErrMsg[E_BAD_TYPE]);
|
t->warn, ErrMsg[E_BAD_TYPE]);
|
||||||
return (jul == JulianToday);
|
return (dse == DSEToday);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If absolute value of return is not monotonically
|
/* If absolute value of return is not monotonically
|
||||||
decreasing, exit */
|
decreasing, exit */
|
||||||
if (i > 1 && abs(v.v.val) >= lastReturnVal) {
|
if (i > 1 && abs(v.v.val) >= lastReturnVal) {
|
||||||
return (jul == JulianToday);
|
return (dse == DSEToday);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastReturnVal = abs(v.v.val);
|
lastReturnVal = abs(v.v.val);
|
||||||
/* Positive values: Just subtract. Negative values:
|
/* Positive values: Just subtract. Negative values:
|
||||||
skip omitted days. */
|
skip omitted days. */
|
||||||
if (v.v.val >= 0) {
|
if (v.v.val >= 0) {
|
||||||
if (JulianToday + v.v.val == jul) return 1;
|
if (DSEToday + v.v.val == dse) return 1;
|
||||||
} else {
|
} else {
|
||||||
int j = jul;
|
int j = dse;
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
int max = MaxSatIter;
|
int max = MaxSatIter;
|
||||||
if (max < v.v.val * 2) max = v.v.val*2;
|
if (max < v.v.val * 2) max = v.v.val*2;
|
||||||
@@ -1443,7 +1510,29 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
|||||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (j == JulianToday) return 1;
|
if (j == DSEToday) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixSpecialType(Trigger *t)
|
||||||
|
{
|
||||||
|
if (t->typ != PASSTHRU_TYPE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert SPECIAL MSG / MSF / RUN / CAL to just plain MSG / MSF / etc */
|
||||||
|
if (!StrCmpi(t->passthru, "MSG")) {
|
||||||
|
t->typ = MSG_TYPE;
|
||||||
|
} else if (!StrCmpi(t->passthru, "MSF")) {
|
||||||
|
t->typ = MSF_TYPE;
|
||||||
|
} else if (!StrCmpi(t->passthru, "RUN")) {
|
||||||
|
t->typ = RUN_TYPE;
|
||||||
|
} else if (!StrCmpi(t->passthru, "CAL")) {
|
||||||
|
t->typ = CAL_TYPE;
|
||||||
|
} else if (!StrCmpi(t->passthru, "PS")) {
|
||||||
|
t->typ = PS_TYPE;
|
||||||
|
} else if (!StrCmpi(t->passthru, "PSFILE")) {
|
||||||
|
t->typ = PSF_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
978
src/dosubst.c
978
src/dosubst.c
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,8 @@
|
|||||||
/* buffers. */
|
/* buffers. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
/* Declaration of functions for manipulating dynamic buffers */
|
/* Declaration of functions for manipulating dynamic buffers */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -31,6 +32,8 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp);
|
|||||||
#define DBufValue(bufPtr) ((bufPtr)->buffer)
|
#define DBufValue(bufPtr) ((bufPtr)->buffer)
|
||||||
#define DBufLen(bufPtr) ((bufPtr)->len)
|
#define DBufLen(bufPtr) ((bufPtr)->len)
|
||||||
|
|
||||||
#define DBufPutc(dbuf, c) ( (dbuf)->allocatedLen < (dbuf)->len+1 ) ? (dbuf)->buffer[(dbuf)->len++] = c, (dbuf)->buffer[(dbuf)->len] = 0, OK : DBufPutcFN((dbuf), c)
|
#define DBufPutc(dbuf, c) ( ( (dbuf)->allocatedLen <= (dbuf)->len+1 ) ? \
|
||||||
|
DBufPutcFN( (dbuf), c) : \
|
||||||
|
( (dbuf)->buffer[(dbuf)->len++] = c, (dbuf)->buffer[(dbuf)->len] = 0, OK) )
|
||||||
|
|
||||||
#endif /* DYNBUF_H */
|
#endif /* DYNBUF_H */
|
||||||
|
|||||||
13
src/err.h
13
src/err.h
@@ -5,7 +5,8 @@
|
|||||||
/* Error definitions. */
|
/* Error definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -128,6 +129,10 @@
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define STR(X) STR2(X)
|
||||||
|
#define STR2(X) #X
|
||||||
|
|
||||||
|
|
||||||
#ifndef L_ERR_OVERRIDE
|
#ifndef L_ERR_OVERRIDE
|
||||||
EXTERN char *ErrMsg[]
|
EXTERN char *ErrMsg[]
|
||||||
|
|
||||||
@@ -164,7 +169,7 @@ EXTERN char *ErrMsg[]
|
|||||||
"Number too high",
|
"Number too high",
|
||||||
"Number too low",
|
"Number too low",
|
||||||
"Can't open file",
|
"Can't open file",
|
||||||
"INCLUDE nested too deeply",
|
"INCLUDE nested too deeply (max. " STR(INCLUDE_NEST) ")",
|
||||||
"Parse error",
|
"Parse error",
|
||||||
"Can't compute trigger",
|
"Can't compute trigger",
|
||||||
"Too many nested IFs",
|
"Too many nested IFs",
|
||||||
@@ -188,8 +193,8 @@ EXTERN char *ErrMsg[]
|
|||||||
"Day specified twice",
|
"Day specified twice",
|
||||||
"Unknown token",
|
"Unknown token",
|
||||||
"Must specify month in OMIT command",
|
"Must specify month in OMIT command",
|
||||||
"Too many partial OMITs",
|
"Too many partial OMITs (max. " STR(MAX_PARTIAL_OMITS) ")",
|
||||||
"Too many full OMITs",
|
"Too many full OMITs (max. " STR(MAX_FULL_OMITS) ")",
|
||||||
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||||
"Error reading",
|
"Error reading",
|
||||||
"Expecting end-of-line",
|
"Expecting end-of-line",
|
||||||
|
|||||||
130
src/expr.c
130
src/expr.c
@@ -5,7 +5,8 @@
|
|||||||
/* This file contains routines to parse and evaluate */
|
/* This file contains routines to parse and evaluate */
|
||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* Copyright 1992-2022 by Dianne Skoll */
|
/* Copyright 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -253,6 +254,10 @@ static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
|||||||
DBufFree(buf);
|
DBufFree(buf);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
if (!**in) {
|
||||||
|
DBufFree(buf);
|
||||||
|
return E_MISS_QUOTE;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c = *(*in)++;
|
c = *(*in)++;
|
||||||
@@ -371,12 +376,10 @@ int Evaluate(char const **s, Var *locals, ParsePtr p)
|
|||||||
DBufFree(&ExprBuf);
|
DBufFree(&ExprBuf);
|
||||||
r = Evaluate(s, locals, p); /* Leaves the last parsed token in ExprBuf */
|
r = Evaluate(s, locals, p); /* Leaves the last parsed token in ExprBuf */
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
r = OK;
|
if (*DBufValue(&ExprBuf) != ')') {
|
||||||
if (*DBufValue(&ExprBuf) != ')') {
|
|
||||||
DBufFree(&ExprBuf);
|
DBufFree(&ExprBuf);
|
||||||
return E_MISS_RIGHT_PAREN;
|
return E_MISS_RIGHT_PAREN;
|
||||||
}
|
}
|
||||||
if (r) return r;
|
|
||||||
} else if (*DBufValue(&ExprBuf) == '+') {
|
} else if (*DBufValue(&ExprBuf) == '+') {
|
||||||
continue; /* Ignore unary + */
|
continue; /* Ignore unary + */
|
||||||
}
|
}
|
||||||
@@ -658,13 +661,13 @@ int DoCoerce(char type, Value *v)
|
|||||||
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
|
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
|
||||||
TimeSep, v->v.val % 60);
|
TimeSep, v->v.val % 60);
|
||||||
break;
|
break;
|
||||||
case DATE_TYPE: FromJulian(v->v.val, &y, &m, &d);
|
case DATE_TYPE: FromDSE(v->v.val, &y, &m, &d);
|
||||||
sprintf(coerce_buf, "%04d%c%02d%c%02d",
|
sprintf(coerce_buf, "%04d%c%02d%c%02d",
|
||||||
y, DateSep, m+1, DateSep, d);
|
y, DateSep, m+1, DateSep, d);
|
||||||
break;
|
break;
|
||||||
case DATETIME_TYPE:
|
case DATETIME_TYPE:
|
||||||
i = v->v.val / MINUTES_PER_DAY;
|
i = v->v.val / MINUTES_PER_DAY;
|
||||||
FromJulian(i, &y, &m, &d);
|
FromDSE(i, &y, &m, &d);
|
||||||
k = v->v.val % MINUTES_PER_DAY;
|
k = v->v.val % MINUTES_PER_DAY;
|
||||||
h = k / 60;
|
h = k / 60;
|
||||||
i = k % 60;
|
i = k % 60;
|
||||||
@@ -941,7 +944,8 @@ static int Subtract(void)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int Multiply(void)
|
static int Multiply(void)
|
||||||
{
|
{
|
||||||
Value v1, v2;
|
Value v1, v2, v3;
|
||||||
|
char *ptr;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
PopValStack(v2);
|
PopValStack(v2);
|
||||||
@@ -961,6 +965,61 @@ static int Multiply(void)
|
|||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* String times int means repeat the string that many times */
|
||||||
|
if ((v1.type == INT_TYPE && v2.type == STR_TYPE) ||
|
||||||
|
(v1.type == STR_TYPE && v2.type == INT_TYPE)) {
|
||||||
|
int rep = (v1.type == INT_TYPE ? v1.v.val : v2.v.val);
|
||||||
|
char const *str = (v1.type == INT_TYPE ? v2.v.str : v1.v.str);
|
||||||
|
int l;
|
||||||
|
|
||||||
|
/* Can't multiply by a negative number */
|
||||||
|
if (rep < 0) {
|
||||||
|
return E_2LOW;
|
||||||
|
}
|
||||||
|
if (rep == 0 || !str || !*str) {
|
||||||
|
/* Empty string */
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
v3.type = STR_TYPE;
|
||||||
|
v3.v.str = malloc(1);
|
||||||
|
if (!v3.v.str) {
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
*v3.v.str = 0;
|
||||||
|
PushValStack(v3);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the new value */
|
||||||
|
l = (int) strlen(str);
|
||||||
|
if (l * rep < 0) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
if ((unsigned long) l * (unsigned long) rep >= (unsigned long) INT_MAX) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
if (MaxStringLen > 0 && ((unsigned long) l * (unsigned long) rep) > (unsigned long)MaxStringLen) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
v3.type = STR_TYPE;
|
||||||
|
v3.v.str = malloc(l * rep + 1);
|
||||||
|
if (!v3.v.str) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
*v3.v.str = 0;
|
||||||
|
ptr = v3.v.str;
|
||||||
|
for (int i=0; i<rep; i++) {
|
||||||
|
strcat(ptr, str);
|
||||||
|
ptr += l;
|
||||||
|
}
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
PushValStack(v3);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
DestroyValue(v1); DestroyValue(v2);
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
return E_BAD_TYPE;
|
return E_BAD_TYPE;
|
||||||
}
|
}
|
||||||
@@ -1190,9 +1249,9 @@ static int LogNot(void)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FindFunc */
|
/* FindOperator */
|
||||||
/* */
|
/* */
|
||||||
/* Find a function. */
|
/* Find an operator. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
Operator *FindOperator(char const *name, Operator where[], int num)
|
Operator *FindOperator(char const *name, Operator where[], int num)
|
||||||
@@ -1201,7 +1260,7 @@ Operator *FindOperator(char const *name, Operator where[], int num)
|
|||||||
int mid, r;
|
int mid, r;
|
||||||
while (top >= bot) {
|
while (top >= bot) {
|
||||||
mid = (top + bot) / 2;
|
mid = (top + bot) / 2;
|
||||||
r = StrCmpi(name, where[mid].name);
|
r = strcmp(name, where[mid].name);
|
||||||
if (!r) return &where[mid];
|
if (!r) return &where[mid];
|
||||||
else if (r > 0) bot = mid+1;
|
else if (r > 0) bot = mid+1;
|
||||||
else top = mid-1;
|
else top = mid-1;
|
||||||
@@ -1209,6 +1268,20 @@ Operator *FindOperator(char const *name, Operator where[], int num)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compare two strings case-insensitively, where we KNOW
|
||||||
|
that the second string is definitely lower-case */
|
||||||
|
static int strcmp_lcfirst(char const *s1, char const *s2)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
while (*s1 && *s2) {
|
||||||
|
r = tolower(*s1) - *s2;
|
||||||
|
if (r) return r;
|
||||||
|
s1++;
|
||||||
|
s2++;
|
||||||
|
}
|
||||||
|
return tolower(*s1) - *s2;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FindFunc */
|
/* FindFunc */
|
||||||
@@ -1222,7 +1295,7 @@ BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
|
|||||||
int mid, r;
|
int mid, r;
|
||||||
while (top >= bot) {
|
while (top >= bot) {
|
||||||
mid = (top + bot) / 2;
|
mid = (top + bot) / 2;
|
||||||
r = StrCmpi(name, where[mid].name);
|
r = strcmp_lcfirst(name, where[mid].name);
|
||||||
if (!r) return &where[mid];
|
if (!r) return &where[mid];
|
||||||
else if (r > 0) bot = mid+1;
|
else if (r > 0) bot = mid+1;
|
||||||
else top = mid-1;
|
else top = mid-1;
|
||||||
@@ -1240,12 +1313,31 @@ BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
|
|||||||
void PrintValue (Value *v, FILE *fp)
|
void PrintValue (Value *v, FILE *fp)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
char const *s;
|
unsigned char const *s;
|
||||||
|
|
||||||
if (v->type == STR_TYPE) {
|
if (v->type == STR_TYPE) {
|
||||||
s=v->v.str;
|
s = (unsigned char const *) v->v.str;
|
||||||
putc('"', fp);
|
putc('"', fp);
|
||||||
for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, fp);
|
for (y=0; y<MAX_PRT_LEN && *s; y++) {
|
||||||
|
switch(*s) {
|
||||||
|
case '\a': fprintf(ErrFp, "\\a"); break;
|
||||||
|
case '\b': fprintf(ErrFp, "\\b"); break;
|
||||||
|
case '\f': fprintf(ErrFp, "\\f"); break;
|
||||||
|
case '\n': fprintf(ErrFp, "\\n"); break;
|
||||||
|
case '\r': fprintf(ErrFp, "\\r"); break;
|
||||||
|
case '\t': fprintf(ErrFp, "\\t"); break;
|
||||||
|
case '\v': fprintf(ErrFp, "\\v"); break;
|
||||||
|
case '"': fprintf(ErrFp, "\\\""); break;
|
||||||
|
case '\\': fprintf(ErrFp, "\\\\"); break;
|
||||||
|
default:
|
||||||
|
if (*s < 32) {
|
||||||
|
fprintf(ErrFp, "\\x%02x", (unsigned int) *s);
|
||||||
|
} else {
|
||||||
|
putc(*s, ErrFp); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
putc('"',fp);
|
putc('"',fp);
|
||||||
if (*s) fprintf(fp, "...");
|
if (*s) fprintf(fp, "...");
|
||||||
}
|
}
|
||||||
@@ -1253,11 +1345,11 @@ void PrintValue (Value *v, FILE *fp)
|
|||||||
else if (v->type == TIME_TYPE) fprintf(fp, "%02d%c%02d", v->v.val / 60,
|
else if (v->type == TIME_TYPE) fprintf(fp, "%02d%c%02d", v->v.val / 60,
|
||||||
TimeSep, v->v.val % 60);
|
TimeSep, v->v.val % 60);
|
||||||
else if (v->type == DATE_TYPE) {
|
else if (v->type == DATE_TYPE) {
|
||||||
FromJulian(v->v.val, &y, &m, &d);
|
FromDSE(v->v.val, &y, &m, &d);
|
||||||
fprintf(fp, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
fprintf(fp, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
||||||
}
|
}
|
||||||
else if (v->type == DATETIME_TYPE) {
|
else if (v->type == DATETIME_TYPE) {
|
||||||
FromJulian(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
|
FromDSE(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
|
||||||
fprintf(fp, "%04d%c%02d%c%02d%c%02d%c%02d", y, DateSep, m+1, DateSep, d, DateTimeSep,
|
fprintf(fp, "%04d%c%02d%c%02d%c%02d%c%02d", y, DateSep, m+1, DateSep, d, DateTimeSep,
|
||||||
(v->v.val % MINUTES_PER_DAY) / 60, TimeSep, (v->v.val % MINUTES_PER_DAY) % 60);
|
(v->v.val % MINUTES_PER_DAY) / 60, TimeSep, (v->v.val % MINUTES_PER_DAY) % 60);
|
||||||
}
|
}
|
||||||
@@ -1330,11 +1422,11 @@ int ParseLiteralTime(char const **s, int *tim)
|
|||||||
/* */
|
/* */
|
||||||
/* ParseLiteralDate */
|
/* ParseLiteralDate */
|
||||||
/* */
|
/* */
|
||||||
/* Parse a literal date or datetime. Return result in jul */
|
/* Parse a literal date or datetime. Return result in dse */
|
||||||
/* and tim; update s. */
|
/* and tim; update s. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int ParseLiteralDate(char const **s, int *jul, int *tim)
|
int ParseLiteralDate(char const **s, int *dse, int *tim)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
int r;
|
int r;
|
||||||
@@ -1364,7 +1456,7 @@ int ParseLiteralDate(char const **s, int *jul, int *tim)
|
|||||||
}
|
}
|
||||||
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
if (!DateOK(y, m, d)) return E_BAD_DATE;
|
||||||
|
|
||||||
*jul = Julian(y, m, d);
|
*dse = DSE(y, m, d);
|
||||||
|
|
||||||
/* Do we have a time part as well? */
|
/* Do we have a time part as well? */
|
||||||
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {
|
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {
|
||||||
|
|||||||
18
src/expr.h
18
src/expr.h
@@ -5,18 +5,20 @@
|
|||||||
/* Contains a few definitions used by expression evaluator. */
|
/* Contains a few definitions used by expression evaluator. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
/* Define the types of values */
|
/* Define the types of values */
|
||||||
#define ERR_TYPE 0
|
#define ERR_TYPE 0
|
||||||
#define INT_TYPE 1
|
#define INT_TYPE 1
|
||||||
#define TIME_TYPE 2
|
#define TIME_TYPE 2
|
||||||
#define DATE_TYPE 3
|
#define DATE_TYPE 3
|
||||||
#define STR_TYPE 4
|
#define STR_TYPE 4
|
||||||
#define DATETIME_TYPE 5
|
#define DATETIME_TYPE 5
|
||||||
#define SPECIAL_TYPE 6 /* Only for system variables */
|
#define SPECIAL_TYPE 6 /* Only for system variables */
|
||||||
|
#define CONST_INT_TYPE 7 /* Only for system variables */
|
||||||
|
|
||||||
/* Define stuff for parsing expressions */
|
/* Define stuff for parsing expressions */
|
||||||
#define BEG_OF_EXPR '['
|
#define BEG_OF_EXPR '['
|
||||||
|
|||||||
74
src/files.c
74
src/files.c
@@ -7,14 +7,15 @@
|
|||||||
/* files. */
|
/* files. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -96,8 +97,21 @@ static int ReadLineFromFile (int use_pclose);
|
|||||||
static int CacheFile (char const *fname, int use_pclose);
|
static int CacheFile (char const *fname, int use_pclose);
|
||||||
static void DestroyCache (CachedFile *cf);
|
static void DestroyCache (CachedFile *cf);
|
||||||
static int CheckSafety (void);
|
static int CheckSafety (void);
|
||||||
|
static int CheckSafetyAux (struct stat *statbuf);
|
||||||
static int PopFile (void);
|
static int PopFile (void);
|
||||||
static int IncludeCmd(char const *);
|
static int IncludeCmd(char const *);
|
||||||
|
|
||||||
|
void set_cloexec(int fd)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
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)
|
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||||
{
|
{
|
||||||
DynamicBuffer fname_buf;
|
DynamicBuffer fname_buf;
|
||||||
@@ -121,6 +135,7 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
|||||||
if (!PurgeFP) {
|
if (!PurgeFP) {
|
||||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
||||||
}
|
}
|
||||||
|
set_cloexec(fileno(PurgeFP));
|
||||||
DBufFree(&fname_buf);
|
DBufFree(&fname_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +340,7 @@ int OpenFile(char const *fname)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
if (fp) set_cloexec(fileno(fp));
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||||
}
|
}
|
||||||
@@ -344,6 +360,7 @@ int OpenFile(char const *fname)
|
|||||||
if (strcmp(fname, "-")) {
|
if (strcmp(fname, "-")) {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||||
|
set_cloexec(fileno(fp));
|
||||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||||
} else {
|
} else {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
@@ -540,6 +557,7 @@ static int PopFile(void)
|
|||||||
if (strcmp(i->filename, "-")) {
|
if (strcmp(i->filename, "-")) {
|
||||||
fp = fopen(i->filename, "r");
|
fp = fopen(i->filename, "r");
|
||||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||||
|
set_cloexec(fileno(fp));
|
||||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||||
} else {
|
} else {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
@@ -971,6 +989,11 @@ int IncludeFile(char const *fname)
|
|||||||
if (stat(fname, &statbuf) == 0) {
|
if (stat(fname, &statbuf) == 0) {
|
||||||
FilenameChain *fc;
|
FilenameChain *fc;
|
||||||
if (S_ISDIR(statbuf.st_mode)) {
|
if (S_ISDIR(statbuf.st_mode)) {
|
||||||
|
/* Check safety */
|
||||||
|
if (!CheckSafetyAux(&statbuf)) {
|
||||||
|
PopFile();
|
||||||
|
return E_NO_MATCHING_REMS;
|
||||||
|
}
|
||||||
if (SetupGlobChain(fname, i) == OK) { /* Glob succeeded */
|
if (SetupGlobChain(fname, i) == OK) { /* Glob succeeded */
|
||||||
if (!i->chain) { /* Oops... no matching files */
|
if (!i->chain) { /* Oops... no matching files */
|
||||||
if (!Hush) {
|
if (!Hush) {
|
||||||
@@ -1031,7 +1054,7 @@ int GetAccessDate(char const *file)
|
|||||||
if (t1->tm_year + 1900 < BASE)
|
if (t1->tm_year + 1900 < BASE)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return Julian(t1->tm_year+1900, t1->tm_mon, t1->tm_mday);
|
return DSE(t1->tm_year+1900, t1->tm_mon, t1->tm_mday);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -1084,8 +1107,8 @@ int TopLevel(void)
|
|||||||
/* CheckSafety */
|
/* CheckSafety */
|
||||||
/* */
|
/* */
|
||||||
/* Returns 1 if current file is safe to read; 0 otherwise. */
|
/* Returns 1 if current file is safe to read; 0 otherwise. */
|
||||||
/* Currently only meaningful for UNIX. If we are running as */
|
/* If we are running as root, we refuse to open files not */
|
||||||
/* root, we refuse to open files not owned by root. */
|
/* owned by root. */
|
||||||
/* We also reject world-writable files, no matter */
|
/* We also reject world-writable files, no matter */
|
||||||
/* who we're running as. */
|
/* who we're running as. */
|
||||||
/* As a side effect, if we don't own the file, or it's not */
|
/* As a side effect, if we don't own the file, or it's not */
|
||||||
@@ -1105,25 +1128,44 @@ static int CheckSafety(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CheckSafetyAux(&statbuf)) {
|
||||||
|
fclose(fp);
|
||||||
|
fp = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* CheckSafetyAux */
|
||||||
|
/* */
|
||||||
|
/* Returns 1 if file whos info is in statbuf is safe to read; */
|
||||||
|
/* 0 otherwise. If we are running as */
|
||||||
|
/* root, we refuse to open files not owned by root. */
|
||||||
|
/* We also reject world-writable files, no matter */
|
||||||
|
/* who we're running as. */
|
||||||
|
/* As a side effect, if we don't own the file, or it's not */
|
||||||
|
/* owned by a trusted user, we disable RUN */
|
||||||
|
/***************************************************************/
|
||||||
|
|
||||||
|
static int CheckSafetyAux(struct stat *statbuf)
|
||||||
|
{
|
||||||
/* Under UNIX, take extra precautions if running as root */
|
/* Under UNIX, take extra precautions if running as root */
|
||||||
if (!geteuid()) {
|
if (!geteuid()) {
|
||||||
/* Reject files not owned by root or group/world writable */
|
/* Reject files not owned by root or group/world writable */
|
||||||
if (statbuf.st_uid != 0) {
|
if (statbuf->st_uid != 0) {
|
||||||
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file when running as root!\n");
|
fprintf(ErrFp, "SECURITY: Won't read non-root-owned file or directory when running as root!\n");
|
||||||
fclose(fp);
|
|
||||||
fp = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Sigh... /dev/null is usually world-writable, so ignore devices,
|
/* Sigh... /dev/null is usually world-writable, so ignore devices,
|
||||||
FIFOs, sockets, etc. */
|
FIFOs, sockets, etc. */
|
||||||
if (!S_ISREG(statbuf.st_mode)) {
|
if (!S_ISREG(statbuf->st_mode) && !S_ISDIR(statbuf->st_mode)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ((statbuf.st_mode & S_IWOTH)) {
|
if ((statbuf->st_mode & S_IWOTH)) {
|
||||||
fprintf(ErrFp, "SECURITY: Won't read world-writable file!\n");
|
fprintf(ErrFp, "SECURITY: Won't read world-writable file or directory!\n");
|
||||||
fclose(fp);
|
|
||||||
fp = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1131,13 +1173,13 @@ static int CheckSafety(void)
|
|||||||
|
|
||||||
/* Assume unsafe */
|
/* Assume unsafe */
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
if (statbuf.st_uid == geteuid()) {
|
if (statbuf->st_uid == geteuid()) {
|
||||||
/* Owned by me... safe */
|
/* Owned by me... safe */
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<NumTrustedUsers; i++) {
|
for (i=0; i<NumTrustedUsers; i++) {
|
||||||
if (statbuf.st_uid == TrustedUsers[i]) {
|
if (statbuf->st_uid == TrustedUsers[i]) {
|
||||||
/* Owned by a trusted user... safe */
|
/* Owned by a trusted user... safe */
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
break;
|
break;
|
||||||
|
|||||||
925
src/funcs.c
925
src/funcs.c
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,8 @@
|
|||||||
/* globals.h and err.h */
|
/* globals.h and err.h */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -38,9 +39,9 @@ EXTERN FILE *ErrFp;
|
|||||||
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
||||||
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
|
#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).type = ERR_TYPE) : 0)
|
#define DestroyValue(x) (void) (((x).type == STR_TYPE && (x).v.str) ? (free((x).v.str),(x).v.str = NULL,(x).type = ERR_TYPE) : 0)
|
||||||
|
|
||||||
EXTERN int JulianToday;
|
EXTERN int DSEToday;
|
||||||
EXTERN int RealToday;
|
EXTERN int RealToday;
|
||||||
EXTERN int CurDay;
|
EXTERN int CurDay;
|
||||||
EXTERN int CurMon;
|
EXTERN int CurMon;
|
||||||
@@ -49,8 +50,10 @@ EXTERN int LineNo;
|
|||||||
EXTERN int FreshLine;
|
EXTERN int FreshLine;
|
||||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||||
|
|
||||||
|
EXTERN INIT( int MaxLateMinutes, 0);
|
||||||
EXTERN INIT( int NumTrustedUsers, 0);
|
EXTERN INIT( int NumTrustedUsers, 0);
|
||||||
EXTERN INIT( char const *MsgCommand, NULL);
|
EXTERN INIT( char const *MsgCommand, NULL);
|
||||||
|
EXTERN INIT( char const *QueuedMsgCommand, NULL);
|
||||||
EXTERN INIT( int ShowAllErrors, 0);
|
EXTERN INIT( int ShowAllErrors, 0);
|
||||||
EXTERN INIT( int DebugFlag, 0);
|
EXTERN INIT( int DebugFlag, 0);
|
||||||
EXTERN INIT( int DoCalendar, 0);
|
EXTERN INIT( int DoCalendar, 0);
|
||||||
@@ -58,16 +61,17 @@ EXTERN INIT( int DoSimpleCalendar, 0);
|
|||||||
EXTERN INIT( int DoSimpleCalDelta, 0);
|
EXTERN INIT( int DoSimpleCalDelta, 0);
|
||||||
EXTERN INIT( int DoPrefixLineNo, 0);
|
EXTERN INIT( int DoPrefixLineNo, 0);
|
||||||
EXTERN INIT( int MondayFirst, 0);
|
EXTERN INIT( int MondayFirst, 0);
|
||||||
|
EXTERN INIT( int AddBlankLines, 1);
|
||||||
EXTERN INIT( int Iterations, 1);
|
EXTERN INIT( int Iterations, 1);
|
||||||
EXTERN INIT( int PsCal, 0);
|
EXTERN INIT( int PsCal, 0);
|
||||||
EXTERN INIT( int CalWidth, -1);
|
EXTERN INIT( int CalWidth, 80);
|
||||||
EXTERN INIT( int CalWeeks, 0);
|
EXTERN INIT( int CalWeeks, 0);
|
||||||
EXTERN INIT( int CalMonths, 0);
|
EXTERN INIT( int CalMonths, 0);
|
||||||
EXTERN INIT( int Hush, 0);
|
EXTERN INIT( int Hush, 0);
|
||||||
EXTERN INIT( int NextMode, 0);
|
EXTERN INIT( int NextMode, 0);
|
||||||
EXTERN INIT( int InfiniteDelta, 0);
|
EXTERN INIT( int InfiniteDelta, 0);
|
||||||
EXTERN INIT( int DefaultTDelta, 0);
|
EXTERN INIT( int DefaultTDelta, 0);
|
||||||
EXTERN INIT( int DeltaOffset, 0);
|
EXTERN INIT( int DeltaOverride, 0);
|
||||||
EXTERN INIT( int RunDisabled, 0);
|
EXTERN INIT( int RunDisabled, 0);
|
||||||
EXTERN INIT( int IgnoreOnce, 0);
|
EXTERN INIT( int IgnoreOnce, 0);
|
||||||
EXTERN INIT( int SortByTime, 0);
|
EXTERN INIT( int SortByTime, 0);
|
||||||
@@ -75,17 +79,20 @@ EXTERN INIT( int SortByDate, 0);
|
|||||||
EXTERN INIT( int SortByPrio, 0);
|
EXTERN INIT( int SortByPrio, 0);
|
||||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
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 char const *InitialFile;
|
||||||
EXTERN int FileAccessDate;
|
EXTERN int FileAccessDate;
|
||||||
|
|
||||||
|
EXTERN INIT( int WeekdayOmits, 0);
|
||||||
EXTERN INIT( int DontSuppressQuoteMarkers, 0);
|
EXTERN INIT( int DontSuppressQuoteMarkers, 0);
|
||||||
EXTERN INIT( int DontFork, 0);
|
EXTERN INIT( int DontFork, 0);
|
||||||
EXTERN INIT( int DontQueue, 0);
|
EXTERN INIT( int DontQueue, 0);
|
||||||
EXTERN INIT( int NumQueued, 0);
|
EXTERN INIT( int NumQueued, 0);
|
||||||
EXTERN INIT( int DontIssueAts, 0);
|
EXTERN INIT( int DontIssueAts, 0);
|
||||||
EXTERN INIT( int Daemon, 0);
|
EXTERN INIT( int Daemon, 0);
|
||||||
|
EXTERN INIT( int DaemonJSON, 0);
|
||||||
EXTERN INIT( char DateSep, DATESEP);
|
EXTERN INIT( char DateSep, DATESEP);
|
||||||
EXTERN INIT( char TimeSep, TIMESEP);
|
EXTERN INIT( char TimeSep, TIMESEP);
|
||||||
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
||||||
@@ -96,7 +103,7 @@ EXTERN INIT( int SynthesizeTags, 0);
|
|||||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||||
EXTERN INIT( int MaxSatIter, 1000);
|
EXTERN INIT( int MaxSatIter, 1000);
|
||||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
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 UseStdin, 0);
|
||||||
EXTERN INIT( int PurgeMode, 0);
|
EXTERN INIT( int PurgeMode, 0);
|
||||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||||
@@ -111,11 +118,13 @@ EXTERN INIT( int LastTriggerTime, 0);
|
|||||||
EXTERN INIT( int ShouldCache, 0);
|
EXTERN INIT( int ShouldCache, 0);
|
||||||
EXTERN char const *CurLine;
|
EXTERN char const *CurLine;
|
||||||
EXTERN INIT( int NumTriggered, 0);
|
EXTERN INIT( int NumTriggered, 0);
|
||||||
|
EXTERN INIT( int DidMsgReminder, 0);
|
||||||
EXTERN int ArgC;
|
EXTERN int ArgC;
|
||||||
EXTERN char const **ArgV;
|
EXTERN char const **ArgV;
|
||||||
EXTERN INIT( int CalLines, CAL_LINES);
|
EXTERN INIT( int CalLines, CAL_LINES);
|
||||||
EXTERN INIT( int CalPad, 1);
|
EXTERN INIT( int CalPad, 1);
|
||||||
EXTERN INIT( int UseVTChars, 0);
|
EXTERN INIT( int UseVTChars, 0);
|
||||||
|
EXTERN INIT( int UseBGVTColors, 0);
|
||||||
EXTERN INIT( int UseUTF8Chars, 0);
|
EXTERN INIT( int UseUTF8Chars, 0);
|
||||||
EXTERN INIT( int UseVTColors, 0);
|
EXTERN INIT( int UseVTColors, 0);
|
||||||
EXTERN INIT( int Use256Colors, 0);
|
EXTERN INIT( int Use256Colors, 0);
|
||||||
@@ -149,6 +158,9 @@ EXTERN INIT( char *EndSentIg, "\"')]}>");
|
|||||||
EXTERN DynamicBuffer Banner;
|
EXTERN DynamicBuffer Banner;
|
||||||
EXTERN DynamicBuffer LineBuffer;
|
EXTERN DynamicBuffer LineBuffer;
|
||||||
EXTERN DynamicBuffer ExprBuf;
|
EXTERN DynamicBuffer ExprBuf;
|
||||||
|
|
||||||
|
extern int NumFullOmits, NumPartialOmits;
|
||||||
|
|
||||||
/* List of months */
|
/* List of months */
|
||||||
EXTERN char *EnglishMonthName[]
|
EXTERN char *EnglishMonthName[]
|
||||||
#ifdef MK_GLOBALS
|
#ifdef MK_GLOBALS
|
||||||
|
|||||||
45
src/hbcal.c
45
src/hbcal.c
@@ -5,7 +5,8 @@
|
|||||||
/* Support for the Hebrew calendar */
|
/* Support for the Hebrew calendar */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 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 */
|
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||||
/* 1985. */
|
/* 1985. */
|
||||||
@@ -67,7 +68,7 @@ static char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
|
|||||||
/* */
|
/* */
|
||||||
/* RoshHashana */
|
/* RoshHashana */
|
||||||
/* */
|
/* */
|
||||||
/* Return the Julian date for Rosh Hashana of specified */
|
/* Return DSE date for Rosh Hashana of specified */
|
||||||
/* Hebrew year. (ie, 5751, not 1990) */
|
/* Hebrew year. (ie, 5751, not 1990) */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -155,14 +156,14 @@ char const *DaysInHebMonths(int ylen)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* HebToJul */
|
/* HebToDSE */
|
||||||
/* */
|
/* */
|
||||||
/* Convert a Hebrew date to Julian. */
|
/* Convert a Hebrew date to DSE. */
|
||||||
/* Hebrew months range from 0-12, but Adar A has 0 length in */
|
/* Hebrew months range from 0-12, but Adar A has 0 length in */
|
||||||
/* non-leap-years. */
|
/* non-leap-years. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int HebToJul(int hy, int hm, int hd)
|
int HebToDSE(int hy, int hm, int hd)
|
||||||
{
|
{
|
||||||
int ylen;
|
int ylen;
|
||||||
char const *monlens;
|
char const *monlens;
|
||||||
@@ -188,39 +189,39 @@ int HebToJul(int hy, int hm, int hd)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* JulToHeb */
|
/* DSEToHeb */
|
||||||
/* */
|
/* */
|
||||||
/* Convert a Julian date to Hebrew. */
|
/* Convert a DSE to Hebrew. */
|
||||||
/* Hebrew months range from 0-12, but Adar A has 0 length in */
|
/* Hebrew months range from 0-12, but Adar A has 0 length in */
|
||||||
/* non-leap-years. */
|
/* non-leap-years. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
void JulToHeb(int jul, int *hy, int *hm, int *hd)
|
void DSEToHeb(int dse, int *hy, int *hm, int *hd)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
int rh;
|
int rh;
|
||||||
int ylen;
|
int ylen;
|
||||||
char const *monlen;
|
char const *monlen;
|
||||||
/* Get the common year */
|
/* Get the common year */
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
y += 3763; /* Over-estimate a bit to be on the safe side below... */
|
y += 3763; /* Over-estimate a bit to be on the safe side below... */
|
||||||
|
|
||||||
/* Find the RH just before desired date */
|
/* Find the RH just before desired date */
|
||||||
while ((rh=RoshHashana(y))>jul) y--;
|
while ((rh=RoshHashana(y))>dse) y--;
|
||||||
|
|
||||||
/* Got the year - now find the month */
|
/* Got the year - now find the month */
|
||||||
jul -= rh;
|
dse -= rh;
|
||||||
ylen = DaysInHebYear(y);
|
ylen = DaysInHebYear(y);
|
||||||
monlen = DaysInHebMonths(ylen);
|
monlen = DaysInHebMonths(ylen);
|
||||||
m = 0;
|
m = 0;
|
||||||
while((jul >= monlen[m]) || !monlen[m]) {
|
while((dse >= monlen[m]) || !monlen[m]) {
|
||||||
jul -= monlen[m];
|
dse -= monlen[m];
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*hy = y;
|
*hy = y;
|
||||||
*hm = m;
|
*hm = m;
|
||||||
*hd = jul+1;
|
*hd = dse+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -389,20 +390,20 @@ int GetValidHebDate(int yin, int min, int din, int adarbehave,
|
|||||||
/* Returns 0 for success, non-zero for failure. */
|
/* Returns 0 for success, non-zero for failure. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int GetNextHebrewDate(int julstart, int hm, int hd,
|
int GetNextHebrewDate(int dsestart, int hm, int hd,
|
||||||
int jahr, int adarbehave, int *ans)
|
int jahr, int adarbehave, int *ans)
|
||||||
{
|
{
|
||||||
int r, yout, mout, dout, jul=1;
|
int r, yout, mout, dout, dse=1;
|
||||||
int adarflag = adarbehave;
|
int adarflag = adarbehave;
|
||||||
|
|
||||||
/* I initialize jul above to stop gcc from complaining about
|
/* I initialize dse above to stop gcc from complaining about
|
||||||
possible use of uninitialized variable. You can take it
|
possible use of uninitialized variable. You can take it
|
||||||
out if the small inefficiency really bothers you. */
|
out if the small inefficiency really bothers you. */
|
||||||
|
|
||||||
/* If adarbehave == ADAR2BOTH, set adarflag to ADAR2ADARA for now */
|
/* If adarbehave == ADAR2BOTH, set adarflag to ADAR2ADARA for now */
|
||||||
if (adarbehave == ADAR2BOTH) adarflag = ADAR2ADARA;
|
if (adarbehave == ADAR2BOTH) adarflag = ADAR2ADARA;
|
||||||
|
|
||||||
JulToHeb(julstart, &yout, &mout, &dout);
|
DSEToHeb(dsestart, &yout, &mout, &dout);
|
||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
while(r) {
|
while(r) {
|
||||||
@@ -419,9 +420,9 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
|
|||||||
} else yout++;
|
} else yout++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
jul = HebToJul(yout, mout, dout);
|
dse = HebToDSE(yout, mout, dout);
|
||||||
if (jul < 0) return E_DATE_OVER;
|
if (dse < 0) return E_DATE_OVER;
|
||||||
if (jul >= julstart) break;
|
if (dse >= dsestart) break;
|
||||||
else {
|
else {
|
||||||
if (adarbehave == ADAR2BOTH && hm == ADAR) {
|
if (adarbehave == ADAR2BOTH && hm == ADAR) {
|
||||||
if (adarflag == ADAR2ADARA) {
|
if (adarflag == ADAR2ADARA) {
|
||||||
@@ -434,7 +435,7 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
|
|||||||
r=1; /* Force loop to continue */
|
r=1; /* Force loop to continue */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ans = jul;
|
*ans = dse;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
326
src/init.c
326
src/init.c
@@ -7,7 +7,8 @@
|
|||||||
/* in normal mode. */
|
/* in normal mode. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -21,9 +22,14 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#ifdef HAVE_INITGROUPS
|
#ifdef HAVE_INITGROUPS
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
@@ -35,6 +41,14 @@
|
|||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "err.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:
|
* Command line options recognized:
|
||||||
@@ -43,7 +57,8 @@
|
|||||||
* simple calendar format.
|
* simple calendar format.
|
||||||
* -r = Disallow RUN mode
|
* -r = Disallow RUN mode
|
||||||
* -c[n] = Produce a calendar for n months (default = 1)
|
* -c[n] = Produce a calendar for n months (default = 1)
|
||||||
* -@[n,m] = Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
|
* -@[n,m,b]= Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
|
||||||
|
* b=0 ignore SHADE b=1 respect SHADE
|
||||||
* -w[n,n,n] = Specify output device width, padding and spacing
|
* -w[n,n,n] = Specify output device width, padding and spacing
|
||||||
* -s[n] = Produce calendar in "simple calendar" format
|
* -s[n] = Produce calendar in "simple calendar" format
|
||||||
* -p[n] = Produce calendar in format compatible with rem2ps
|
* -p[n] = Produce calendar in format compatible with rem2ps
|
||||||
@@ -94,6 +109,25 @@ static void AddTrustedUser(char const *username);
|
|||||||
|
|
||||||
static DynamicBuffer default_filename_buf;
|
static DynamicBuffer default_filename_buf;
|
||||||
|
|
||||||
|
static void
|
||||||
|
InitCalWidthAndFormWidth(int fd)
|
||||||
|
{
|
||||||
|
struct winsize w;
|
||||||
|
|
||||||
|
if (!isatty(fd)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ioctl(fd, TIOCGWINSZ, &w) == 0) {
|
||||||
|
CalWidth = w.ws_col;
|
||||||
|
if (CalWidth < 71) {
|
||||||
|
CalWidth = 71;
|
||||||
|
}
|
||||||
|
FormWidth = w.ws_col - 8;
|
||||||
|
if (FormWidth < 20) FormWidth = 20;
|
||||||
|
if (FormWidth > 500) FormWidth = 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* DefaultFilename */
|
/* DefaultFilename */
|
||||||
@@ -140,20 +174,14 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
char const *s;
|
char const *s;
|
||||||
int weeks;
|
int weeks;
|
||||||
int x;
|
int x;
|
||||||
int jul;
|
int dse;
|
||||||
|
int ttyfd;
|
||||||
|
|
||||||
jul = NO_DATE;
|
dse = NO_DATE;
|
||||||
|
|
||||||
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
|
/* If stdout is a terminal, initialize $FormWidth to terminal width-8,
|
||||||
but clamp to [20, 500] */
|
but clamp to [20, 500] */
|
||||||
if (isatty(STDOUT_FILENO)) {
|
InitCalWidthAndFormWidth(STDOUT_FILENO);
|
||||||
struct winsize w;
|
|
||||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
|
|
||||||
FormWidth = w.ws_col - 8;
|
|
||||||
if (FormWidth < 20) FormWidth = 20;
|
|
||||||
if (FormWidth > 500) FormWidth = 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize global dynamic buffers */
|
/* Initialize global dynamic buffers */
|
||||||
DBufInit(&Banner);
|
DBufInit(&Banner);
|
||||||
@@ -181,8 +209,8 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
JulianToday = RealToday;
|
DSEToday = RealToday;
|
||||||
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
FromDSE(DSEToday, &CurYear, &CurMon, &CurDay);
|
||||||
|
|
||||||
/* Initialize Latitude and Longitude */
|
/* Initialize Latitude and Longitude */
|
||||||
set_components_from_lat_and_long();
|
set_components_from_lat_and_long();
|
||||||
@@ -200,7 +228,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
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 */
|
/* Parse the command-line options */
|
||||||
@@ -224,6 +252,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
while(*arg) arg++;
|
while(*arg) arg++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
ProcessLongOption(arg);
|
||||||
|
while(*arg) arg++;
|
||||||
|
break;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
UseVTColors = 1;
|
UseVTColors = 1;
|
||||||
if (*arg) {
|
if (*arg) {
|
||||||
@@ -233,22 +266,44 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
} else if (x == 2) {
|
} else if (x == 2) {
|
||||||
UseTrueColors = 1;
|
UseTrueColors = 1;
|
||||||
} else if (x != 0) {
|
} else if (x != 0) {
|
||||||
fprintf(ErrFp, "%s: -@n,m: n must be 0, 1 or 2 (assuming 0)\n",
|
fprintf(ErrFp, "%s: -@n,m,b: n must be 0, 1 or 2 (assuming 0)\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*arg == ',') {
|
if (*arg == ',') {
|
||||||
arg++;
|
arg++;
|
||||||
PARSENUM(x, arg);
|
if (*arg != ',') {
|
||||||
if (x == 0) {
|
if (*arg == 't') {
|
||||||
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
arg++;
|
||||||
} else if (x == 1) {
|
should_guess_terminal_background = 2;
|
||||||
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
} else {
|
||||||
} else {
|
PARSENUM(x, arg);
|
||||||
fprintf(ErrFp, "%s: -@n,m: m must be 0 or 1\n",
|
if (x == 0) {
|
||||||
argv[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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (*arg == ',') {
|
||||||
|
arg++;
|
||||||
|
PARSENUM(x, arg);
|
||||||
|
if (x != 0 && x != 1) {
|
||||||
|
fprintf(ErrFp, "%s: -@n,m,b: b must be 0 or 1 (assuming 0)\n",
|
||||||
|
argv[0]);
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
UseBGVTColors = x;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'j':
|
case 'j':
|
||||||
@@ -308,10 +363,15 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
} else if (!*arg) {
|
} else if (!*arg) {
|
||||||
InfiniteDelta = 1;
|
InfiniteDelta = 1;
|
||||||
} else {
|
} else {
|
||||||
PARSENUM(DeltaOffset, arg);
|
if (*arg == 'z') {
|
||||||
if (DeltaOffset < 0) {
|
DeltaOverride = -1;
|
||||||
DeltaOffset = 0;
|
arg++;
|
||||||
}
|
} else {
|
||||||
|
PARSENUM(DeltaOverride, arg);
|
||||||
|
if (DeltaOverride < 0) {
|
||||||
|
DeltaOverride = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
@@ -365,7 +425,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 'z':
|
case 'z':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
DontFork = 1;
|
DontFork = 1;
|
||||||
if (*arg == '0') {
|
if (*arg == 'j' || *arg == 'J') {
|
||||||
|
while (*arg) arg++;
|
||||||
|
Daemon = -1;
|
||||||
|
DaemonJSON = 1;
|
||||||
|
} else if (*arg == '0') {
|
||||||
PARSENUM(Daemon, arg);
|
PARSENUM(Daemon, arg);
|
||||||
if (Daemon == 0) Daemon = -1;
|
if (Daemon == 0) Daemon = -1;
|
||||||
else if (Daemon < 1) Daemon = 1;
|
else if (Daemon < 1) Daemon = 1;
|
||||||
@@ -495,11 +559,32 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 'w':
|
case 'w':
|
||||||
case 'W':
|
case 'W':
|
||||||
if (*arg != ',') {
|
if (*arg != ',') {
|
||||||
PARSENUM(CalWidth, arg);
|
if (*arg == 't') {
|
||||||
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
|
arg++;
|
||||||
if (CalWidth == 0) {
|
/* -wt means get width from /dev/tty */
|
||||||
CalWidth = -1;
|
ttyfd = open("/dev/tty", O_RDONLY);
|
||||||
}
|
if (ttyfd < 0) {
|
||||||
|
fprintf(stderr, "%s: `-wt': Cannot open /dev/tty: %s\n",
|
||||||
|
argv[0], strerror(errno));
|
||||||
|
} else {
|
||||||
|
InitCalWidthAndFormWidth(ttyfd);
|
||||||
|
close(ttyfd);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PARSENUM(CalWidth, arg);
|
||||||
|
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
|
||||||
|
if (CalWidth == 0) {
|
||||||
|
/* 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;
|
||||||
|
if (FormWidth > 500) FormWidth = 500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (*arg == ',') {
|
if (*arg == ',') {
|
||||||
arg++;
|
arg++;
|
||||||
@@ -551,7 +636,12 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
case 'k':
|
case 'k':
|
||||||
case 'K':
|
case 'K':
|
||||||
MsgCommand = arg;
|
if (*arg == ':') {
|
||||||
|
arg++;
|
||||||
|
QueuedMsgCommand = arg;
|
||||||
|
} else {
|
||||||
|
MsgCommand = arg;
|
||||||
|
}
|
||||||
while (*arg) arg++; /* Chew up remaining chars in this arg */
|
while (*arg) arg++; /* Chew up remaining chars in this arg */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -590,30 +680,30 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
case T_DateTime:
|
case T_DateTime:
|
||||||
if (SysTime != -1L) Usage();
|
if (SysTime != -1L) Usage();
|
||||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
if (m != NO_MON || d != NO_DAY || y != NO_YR || dse != NO_DATE) Usage();
|
||||||
SysTime = (tok.val % MINUTES_PER_DAY) * 60;
|
SysTime = (tok.val % MINUTES_PER_DAY) * 60;
|
||||||
DontQueue = 1;
|
DontQueue = 1;
|
||||||
Daemon = 0;
|
Daemon = 0;
|
||||||
jul = tok.val / MINUTES_PER_DAY;
|
dse = tok.val / MINUTES_PER_DAY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Date:
|
case T_Date:
|
||||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
if (m != NO_MON || d != NO_DAY || y != NO_YR || dse != NO_DATE) Usage();
|
||||||
jul = tok.val;
|
dse = tok.val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Month:
|
case T_Month:
|
||||||
if (m != NO_MON || jul != NO_DATE) Usage();
|
if (m != NO_MON || dse != NO_DATE) Usage();
|
||||||
else m = tok.val;
|
else m = tok.val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Day:
|
case T_Day:
|
||||||
if (d != NO_DAY || jul != NO_DATE) Usage();
|
if (d != NO_DAY || dse != NO_DATE) Usage();
|
||||||
else d = tok.val;
|
else d = tok.val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Year:
|
case T_Year:
|
||||||
if (y != NO_YR || jul != NO_DATE) Usage();
|
if (y != NO_YR || dse != NO_DATE) Usage();
|
||||||
else y = tok.val;
|
else y = tok.val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -633,8 +723,8 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
Daemon = 0;
|
Daemon = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jul != NO_DATE) {
|
if (dse != NO_DATE) {
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
}
|
}
|
||||||
/* Must supply date in the form: day, mon, yr OR mon, yr */
|
/* Must supply date in the form: day, mon, yr OR mon, yr */
|
||||||
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
|
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
|
||||||
@@ -652,22 +742,22 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
fprintf(ErrFp, "%s", BadDate);
|
fprintf(ErrFp, "%s", BadDate);
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
JulianToday = Julian(y, m, d);
|
DSEToday = DSE(y, m, d);
|
||||||
if (JulianToday == -1) {
|
if (DSEToday == -1) {
|
||||||
fprintf(ErrFp, "%s", BadDate);
|
fprintf(ErrFp, "%s", BadDate);
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
CurYear = y;
|
CurYear = y;
|
||||||
CurMon = m;
|
CurMon = m;
|
||||||
CurDay = d;
|
CurDay = d;
|
||||||
if (JulianToday != RealToday) IgnoreOnce = 1;
|
if (DSEToday != RealToday) IgnoreOnce = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out the offset from UTC */
|
/* Figure out the offset from UTC */
|
||||||
if (CalculateUTC)
|
if (CalculateUTC)
|
||||||
(void) CalcMinsFromUTC(JulianToday, SystemTime(0)/60,
|
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||||
&MinsFromUTC, NULL);
|
&MinsFromUTC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,7 +771,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
#ifndef L_USAGE_OVERRIDE
|
#ifndef L_USAGE_OVERRIDE
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -689,7 +779,7 @@ void Usage(void)
|
|||||||
fprintf(ErrFp, "Options:\n");
|
fprintf(ErrFp, "Options:\n");
|
||||||
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
|
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
|
||||||
fprintf(ErrFp, " -r Disable RUN directives\n");
|
fprintf(ErrFp, " -r Disable RUN directives\n");
|
||||||
fprintf(ErrFp, " -@[n,m] Colorize COLOR reminders\n");
|
fprintf(ErrFp, " -@[n,m,b] Colorize COLOR/SHADE reminders\n");
|
||||||
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
|
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
|
||||||
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
|
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
|
||||||
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
|
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
|
||||||
@@ -899,3 +989,139 @@ AddTrustedUser(char const *username)
|
|||||||
NumTrustedUsers++;
|
NumTrustedUsers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ProcessLongOption(char const *arg)
|
||||||
|
{
|
||||||
|
if (!strcmp(arg, "version")) {
|
||||||
|
printf("%s\n", VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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 */
|
||||||
|
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);
|
||||||
|
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 = (rr >> 8) & 255;
|
||||||
|
*g = (gg >> 8) & 255;
|
||||||
|
*b = (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;
|
||||||
|
}
|
||||||
|
|||||||
44
src/json.c
44
src/json.c
@@ -249,7 +249,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
const json_char * end;
|
const json_char * end;
|
||||||
json_value * top, * root, * alloc = 0;
|
json_value * top, * root, * alloc = 0;
|
||||||
json_state state = { 0 };
|
json_state state = { 0 };
|
||||||
long flags = 0;
|
long flags;
|
||||||
double num_digits = 0, num_e = 0;
|
double num_digits = 0, num_e = 0;
|
||||||
double num_fraction = 0;
|
double num_fraction = 0;
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (flags & flag_string)
|
if (flags & flag_string)
|
||||||
{
|
{
|
||||||
if (!b)
|
if (!b)
|
||||||
{ sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
|
{ sprintf (error, "Unexpected EOF in string (at %u:%u)", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,7 +325,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||||
{
|
{
|
||||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
|
sprintf (error, "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||||
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
(uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
|
||||||
{
|
{
|
||||||
sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
|
sprintf (error, "Invalid character value `%c` (at %u:%u)", b, line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +472,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (flags & flag_block_comment)
|
if (flags & flag_block_comment)
|
||||||
{
|
{
|
||||||
if (!b)
|
if (!b)
|
||||||
{ sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
|
{ sprintf (error, "%u:%u: Unexpected EOF in block comment", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,12 +488,12 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else if (b == '/')
|
else if (b == '/')
|
||||||
{
|
{
|
||||||
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
|
||||||
{ sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
|
{ sprintf (error, "%u:%u: Comment not allowed here", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++ state.ptr == end)
|
if (++ state.ptr == end)
|
||||||
{ sprintf (error, "%d:%d: EOF unexpected", line_and_col);
|
{ sprintf (error, "%u:%u: EOF unexpected", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
sprintf (error, "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -526,7 +526,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
sprintf (error, "%d:%d: Trailing garbage: `%c`",
|
sprintf (error, "%u:%u: Trailing garbage: `%c`",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -545,7 +545,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (top && top->type == json_array)
|
if (top && top->type == json_array)
|
||||||
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
|
||||||
else
|
else
|
||||||
{ sprintf (error, "%d:%d: Unexpected ]", line_and_col);
|
{ sprintf (error, "%u:%u: Unexpected ]", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +561,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf (error, "%d:%d: Expected , before %c",
|
sprintf (error, "%u:%u: Expected , before %c",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -576,7 +576,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf (error, "%d:%d: Expected : before %c",
|
sprintf (error, "%u:%u: Expected : before %c",
|
||||||
state.cur_line, state.cur_col, b);
|
state.cur_line, state.cur_col, b);
|
||||||
|
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
@@ -702,7 +702,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
|
{ sprintf (error, "%u:%u: Unexpected %c when seeking value", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -722,7 +722,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
case '"':
|
case '"':
|
||||||
|
|
||||||
if (flags & flag_need_comma)
|
if (flags & flag_need_comma)
|
||||||
{ sprintf (error, "%d:%d: Expected , before \"", line_and_col);
|
{ sprintf (error, "%u:%u: Expected , before \"", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,7 +747,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
|
sprintf (error, "%u:%u: Unexpected `%c` in object", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -765,7 +765,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (! (flags & flag_num_e))
|
if (! (flags & flag_num_e))
|
||||||
{
|
{
|
||||||
if (flags & flag_num_zero)
|
if (flags & flag_num_zero)
|
||||||
{ sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
|
{ sprintf (error, "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +814,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else if (b == '.' && top->type == json_integer)
|
else if (b == '.' && top->type == json_integer)
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
|
{ sprintf (error, "%u:%u: Expected digit before `.`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +831,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
if (top->type == json_double)
|
if (top->type == json_double)
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
|
{ sprintf (error, "%u:%u: Expected digit after `.`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,11 +857,11 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!num_digits)
|
if (!num_digits)
|
||||||
{ sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
|
{ sprintf (error, "%u:%u: Expected digit after `e`", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
top->u.dbl *= pow (10.0, (flags & flag_num_e_negative ? - num_e : num_e));
|
top->u.dbl *= pow (10.0, ((flags & flag_num_e_negative) ? - num_e : num_e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & flag_num_negative)
|
if (flags & flag_num_negative)
|
||||||
@@ -942,7 +942,7 @@ json_value * json_parse_ex (json_settings * settings,
|
|||||||
|
|
||||||
e_unknown_value:
|
e_unknown_value:
|
||||||
|
|
||||||
sprintf (error, "%d:%d: Unknown value", line_and_col);
|
sprintf (error, "%u:%u: Unknown value", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
|
|
||||||
e_alloc_failure:
|
e_alloc_failure:
|
||||||
@@ -952,7 +952,7 @@ e_alloc_failure:
|
|||||||
|
|
||||||
e_overflow:
|
e_overflow:
|
||||||
|
|
||||||
sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
|
sprintf (error, "%u:%u: Too long (caught overflow)", line_and_col);
|
||||||
goto e_failed;
|
goto e_failed;
|
||||||
|
|
||||||
e_failed:
|
e_failed:
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
/* Header file for language support for various languages. */
|
/* Header file for language support for various languages. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
#define ITALIAN 9 /* translated by Valerio Aimale */
|
#define ITALIAN 9 /* translated by Valerio Aimale */
|
||||||
#define ROMANIAN 10 /* translated by Liviu Daia */
|
#define ROMANIAN 10 /* translated by Liviu Daia */
|
||||||
#define SPANISH 11 /* translated by Rafa Couto */
|
#define SPANISH 11 /* translated by Rafa Couto */
|
||||||
#define ICELANDIC 12 /* translated by Björn Davíðsson */
|
#define ICELANDIC 12 /* translated by Björn Davíðsson */
|
||||||
|
|
||||||
/* Add more languages here - but please e-mail dianne@skoll.ca
|
/* Add more languages here - but please e-mail dianne@skoll.ca
|
||||||
to have your favorite language assigned a number. If you add a
|
to have your favorite language assigned a number. If you add a
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -80,10 +81,10 @@
|
|||||||
|
|
||||||
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " om natten" : " om formiddagen" : (hour > 17) ? " om aftenen" : " om eftermiddagen";
|
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " om natten" : " om formiddagen" : (hour > 17) ? " om aftenen" : " om eftermiddagen";
|
||||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
|
||||||
#define L_E_OVER sprintf(s, "den %02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
#define L_E_OVER sprintf(s, "den %02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
||||||
#define L_F_OVER sprintf(s, "den %02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
#define L_F_OVER sprintf(s, "den %02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
|
||||||
#define L_H_OVER sprintf(s, "den %02d%c%02d", d, DateSep, m+1);
|
#define L_H_OVER sprintf(s, "den %02d%c%02d", d, DateSep, m+1);
|
||||||
#define L_I_OVER sprintf(s, "den %02d%c%02d", m+1, DateSep, d);
|
#define L_I_OVER sprintf(s, "den %02d%c%02d", m+1, DateSep, d);
|
||||||
#define L_U_OVER L_A_OVER
|
#define L_U_OVER L_A_OVER
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
/* Further corrections by Erik-Jan Vens */
|
/* Further corrections by Erik-Jan Vens */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
/* Support for the English language. */
|
/* Support for the English language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||||
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -103,19 +104,19 @@
|
|||||||
default: plu = ":ntenä"; break; \
|
default: plu = ":ntenä"; break; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s%s %d. %s%s %d", DayName[jul%7], L_ON, d, MonthName[m], L_PARTIT, y); }
|
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s%s %d. %s%s %d", DayName[dse%7], L_ON, d, MonthName[m], L_PARTIT, y); }
|
||||||
#define L_C_OVER if (altmode == '*') { sprintf(s, "%s", DayName[jul%7]); } else { sprintf(s, "%s%s", DayName[jul%7], L_ON); }
|
#define L_C_OVER if (altmode == '*') { sprintf(s, "%s", DayName[dse%7]); } else { sprintf(s, "%s%s", DayName[dse%7], L_ON); }
|
||||||
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
||||||
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s%s %d. %s%s", DayName[jul%7], L_ON, d, MonthName[m], L_PARTIT); }
|
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s%s %d. %s%s", DayName[dse%7], L_ON, d, MonthName[m], L_PARTIT); }
|
||||||
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
||||||
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
||||||
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s %d", DayName[jul%7], MonthName[m], d, plu, y); } else { sprintf(s, "%s%s %sn %d%s %d", DayName[jul%7], L_ON, MonthName[m], d, plu, y); }
|
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s %d", DayName[dse%7], MonthName[m], d, plu, y); } else { sprintf(s, "%s%s %sn %d%s %d", DayName[dse%7], L_ON, MonthName[m], d, plu, y); }
|
||||||
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s", DayName[jul%7], MonthName[m], d, plu); } else { sprintf(s, "%s%s %sn %d%s", DayName[jul%7], L_ON, MonthName[m], d, plu); }
|
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s", DayName[dse%7], MonthName[m], d, plu); } else { sprintf(s, "%s%s %sn %d%s", DayName[dse%7], L_ON, MonthName[m], d, plu); }
|
||||||
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
||||||
#define L_Q_OVER sprintf(s, "n");
|
#define L_Q_OVER sprintf(s, "n");
|
||||||
#define L_U_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s %d", DayName[jul%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s%s %d%s %s%s %d", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT, y); }
|
#define L_U_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s %d", DayName[dse%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s%s %d%s %s%s %d", DayName[dse%7], L_ON, d, plu, MonthName[m], L_PARTIT, y); }
|
||||||
#define L_V_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s", DayName[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s%s %d%s %s%s", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT); }
|
#define L_V_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s", DayName[dse%7], d, plu, MonthName[m]); } else { sprintf(s, "%s%s %d%s %s%s", DayName[dse%7], L_ON, d, plu, MonthName[m], L_PARTIT); }
|
||||||
#define L_1_OVER \
|
#define L_1_OVER \
|
||||||
if (tdiff == 0) \
|
if (tdiff == 0) \
|
||||||
sprintf(s, "%s", L_NOW); \
|
sprintf(s, "%s", L_NOW); \
|
||||||
@@ -253,7 +254,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -106,9 +107,9 @@ else if (tdiff < 0) { \
|
|||||||
sprintf(s, "dans %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
|
sprintf(s, "dans %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s, %d", DayName[jul%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d, plu, MonthName[m], y); }
|
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s, %d", DayName[dse%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[dse%7], d, plu, MonthName[m], y); }
|
||||||
|
|
||||||
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s", DayName[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu, MonthName[m]); }
|
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s, %d%s %s", DayName[dse%7], d, plu, MonthName[m]); } else { sprintf(s, "%s %s, %d%s %s", L_ON, DayName[dse%7], d, plu, MonthName[m]); }
|
||||||
|
|
||||||
/* The next ones are used only when MK_GLOBALS is set */
|
/* The next ones are used only when MK_GLOBALS is set */
|
||||||
#ifdef MK_GLOBALS
|
#ifdef MK_GLOBALS
|
||||||
@@ -227,7 +228,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
/* I don't speak German. */
|
/* I don't speak German. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@
|
|||||||
See the file dosubst.c for more info. */
|
See the file dosubst.c for more info. */
|
||||||
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
|
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
|
||||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
|
||||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
|
||||||
#define L_U_OVER L_A_OVER
|
#define L_U_OVER L_A_OVER
|
||||||
#define L_V_OVER L_G_OVER
|
#define L_V_OVER L_G_OVER
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
/* Support for the Icelandic language. */
|
/* Support for the Icelandic language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||||
/* */
|
/* */
|
||||||
/* Remind is copyright (C) 1992-2022 by Dianne Skoll */
|
/* Remind is copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -16,11 +17,11 @@
|
|||||||
|
|
||||||
/* Day names */
|
/* Day names */
|
||||||
#define L_SUNDAY "Domenica"
|
#define L_SUNDAY "Domenica"
|
||||||
#define L_MONDAY "Lunedí"
|
#define L_MONDAY "Lunedì"
|
||||||
#define L_TUESDAY "Martedí"
|
#define L_TUESDAY "Martedì"
|
||||||
#define L_WEDNESDAY "Mercoledí"
|
#define L_WEDNESDAY "Mercoledì"
|
||||||
#define L_THURSDAY "Giovedí"
|
#define L_THURSDAY "Giovedì"
|
||||||
#define L_FRIDAY "Venerdí"
|
#define L_FRIDAY "Venerdì"
|
||||||
#define L_SATURDAY "Sabato"
|
#define L_SATURDAY "Sabato"
|
||||||
|
|
||||||
/* Month names */
|
/* Month names */
|
||||||
@@ -67,7 +68,7 @@
|
|||||||
#define L_AT "alle"
|
#define L_AT "alle"
|
||||||
#define L_MINUTE "minut"
|
#define L_MINUTE "minut"
|
||||||
#define L_HOUR "or"
|
#define L_HOUR "or"
|
||||||
#define L_IS "é"
|
#define L_IS "è"
|
||||||
#define L_WAS "era"
|
#define L_WAS "era"
|
||||||
#define L_AND "e"
|
#define L_AND "e"
|
||||||
/* What to add to make "hour" plural */
|
/* What to add to make "hour" plural */
|
||||||
@@ -84,30 +85,30 @@
|
|||||||
#define L_HPLU_OVER hplu = (hdiff == 1 ? "a" : "e");
|
#define L_HPLU_OVER hplu = (hdiff == 1 ? "a" : "e");
|
||||||
#define L_MPLU_OVER mplu = (mdiff == 1 ? "o" : "i");
|
#define L_MPLU_OVER mplu = (mdiff == 1 ? "o" : "i");
|
||||||
|
|
||||||
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d,\
|
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d,\
|
||||||
MonthName[m], y);
|
MonthName[m], y);
|
||||||
#define L_C_OVER sprintf(s, "%s", DayName[jul%7]);
|
#define L_C_OVER sprintf(s, "%s", DayName[dse%7]);
|
||||||
|
|
||||||
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep,\
|
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep,\
|
||||||
m+1, DateSep, y);
|
m+1, DateSep, y);
|
||||||
|
|
||||||
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||||
|
|
||||||
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
|
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
|
||||||
|
|
||||||
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
||||||
|
|
||||||
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
||||||
|
|
||||||
#define L_J_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, \
|
#define L_J_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, \
|
||||||
MonthName[m], y);
|
MonthName[m], y);
|
||||||
|
|
||||||
#define L_K_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, \
|
#define L_K_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, \
|
||||||
MonthName[m]);
|
MonthName[m]);
|
||||||
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
||||||
|
|
||||||
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, \
|
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, \
|
||||||
MonthName[m], y);
|
MonthName[m], y);
|
||||||
|
|
||||||
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, \
|
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, \
|
||||||
MonthName[m]);
|
MonthName[m]);
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||||
/* Remind is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Remind is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
|
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
|
||||||
See the file dosubst.c for more info. */
|
See the file dosubst.c for more info. */
|
||||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
|
||||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
|
||||||
#define L_U_OVER L_A_OVER
|
#define L_U_OVER L_A_OVER
|
||||||
#define L_V_OVER L_G_OVER
|
#define L_V_OVER L_G_OVER
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
/* Polish. */
|
/* Polish. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -95,8 +96,8 @@ ampm = (hour<12) ? \
|
|||||||
: (hour<22) ? " wieczorem" \
|
: (hour<22) ? " wieczorem" \
|
||||||
: " w nocy";
|
: " w nocy";
|
||||||
#define L_ORDINAL_OVERRIDE plu = "";
|
#define L_ORDINAL_OVERRIDE plu = "";
|
||||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s %d", DayName[dse%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[dse%7], d, MonthName[m], y); }
|
||||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s", DayName[dse%7], d, MonthName[m]); } else { sprintf(s, "%s %s, %d. %s", L_ON, DayName[dse%7], d, MonthName[m]); }
|
||||||
#define L_U_OVER L_A_OVER
|
#define L_U_OVER L_A_OVER
|
||||||
#define L_V_OVER L_G_OVER
|
#define L_V_OVER L_G_OVER
|
||||||
|
|
||||||
@@ -243,7 +244,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -88,26 +89,26 @@
|
|||||||
#define _ON_WEEKDAY(x) ((x % 7) < 2) ? "no" : "na"
|
#define _ON_WEEKDAY(x) ((x % 7) < 2) ? "no" : "na"
|
||||||
|
|
||||||
#define L_A_OVER \
|
#define L_A_OVER \
|
||||||
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
|
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
|
||||||
|
|
||||||
#define L_C_OVER \
|
#define L_C_OVER \
|
||||||
sprintf(s, "%s %s", _ON_WEEKDAY(jul), DayName[jul%7]);
|
sprintf(s, "%s %s", _ON_WEEKDAY(dse), DayName[dse%7]);
|
||||||
|
|
||||||
#define L_G_OVER \
|
#define L_G_OVER \
|
||||||
sprintf(s, "%s %s, %d %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
|
sprintf(s, "%s %s, %d %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
|
||||||
|
|
||||||
#define L_J_OVER \
|
#define L_J_OVER \
|
||||||
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
|
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
|
||||||
|
|
||||||
#define L_K_OVER \
|
#define L_K_OVER \
|
||||||
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
|
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
|
||||||
|
|
||||||
/* Portuguese does not use some suffixes, some some %u and %j are the same */
|
/* Portuguese does not use some suffixes, some some %u and %j are the same */
|
||||||
#define L_U_OVER \
|
#define L_U_OVER \
|
||||||
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m], y);
|
sprintf(s, "%s %s, %d de %s de %d", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m], y);
|
||||||
|
|
||||||
#define L_V_OVER \
|
#define L_V_OVER \
|
||||||
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(jul), DayName[jul%7], d, MonthName[m]);
|
sprintf(s, "%s %s, %d de %s", _ON_WEEKDAY(dse), DayName[dse%7], d, MonthName[m]);
|
||||||
|
|
||||||
#define L_1_OVER \
|
#define L_1_OVER \
|
||||||
{ \
|
{ \
|
||||||
@@ -252,7 +253,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2022 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,8 +8,9 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2022 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -84,14 +85,14 @@
|
|||||||
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<4) ? " noaptea" : " dimineaţa" : (hour > 17) ? " seara" : " după-amiaza";
|
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<4) ? " noaptea" : " dimineaţa" : (hour > 17) ? " seara" : " după-amiaza";
|
||||||
#define L_ORDINAL_OVERRIDE plu = "";
|
#define L_ORDINAL_OVERRIDE plu = "";
|
||||||
|
|
||||||
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, MonthName[m], y);
|
#define L_A_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, MonthName[m], y);
|
||||||
#define L_C_OVER sprintf(s, "%s", DayName[jul%7]);
|
#define L_C_OVER sprintf(s, "%s", DayName[dse%7]);
|
||||||
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
|
#define L_G_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
|
||||||
#define L_J_OVER sprintf(s, "%s, %s %d, %d", DayName[jul%7], MonthName[m], d, y);
|
#define L_J_OVER sprintf(s, "%s, %s %d, %d", DayName[dse%7], MonthName[m], d, y);
|
||||||
#define L_K_OVER sprintf(s, "%s, %s %d", DayName[jul%7], MonthName[m], d);
|
#define L_K_OVER sprintf(s, "%s, %s %d", DayName[dse%7], MonthName[m], d);
|
||||||
#define L_S_OVER
|
#define L_S_OVER
|
||||||
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[jul%7], d, MonthName[m], y);
|
#define L_U_OVER sprintf(s, "%s, %d %s %d", DayName[dse%7], d, MonthName[m], y);
|
||||||
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[jul%7], d, MonthName[m]);
|
#define L_V_OVER sprintf(s, "%s, %d %s", DayName[dse%7], d, MonthName[m]);
|
||||||
#define L_1_OVER \
|
#define L_1_OVER \
|
||||||
if (tdiff == 0) \
|
if (tdiff == 0) \
|
||||||
sprintf(s, L_NOW); \
|
sprintf(s, L_NOW); \
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
404
src/main.c
404
src/main.c
@@ -6,12 +6,17 @@
|
|||||||
/* routines, etc. */
|
/* routines, etc. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
#define _XOPEN_SOURCE 600
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -23,18 +28,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#ifdef TIME_WITH_SYS_TIME
|
#if defined(HAVE_SYS_TIME_H)
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#else
|
#endif
|
||||||
#if defined(HAVE_SYS_TIME_H) || defined (TIME_WITH_SYS_TIME)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#else
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
@@ -44,6 +47,9 @@
|
|||||||
|
|
||||||
static void DoReminders(void);
|
static void DoReminders(void);
|
||||||
|
|
||||||
|
/* Macro for simplifying common block so as not to litter code */
|
||||||
|
#define OUTPUT(c) do { if (output) { DBufPutc(output, c); } else { putchar(c); } } while(0)
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/** **/
|
/** **/
|
||||||
@@ -67,6 +73,7 @@ int main(int argc, char *argv[])
|
|||||||
ArgV = (char const **) argv;
|
ArgV = (char const **) argv;
|
||||||
|
|
||||||
InitRemind(argc, (char const **) argv);
|
InitRemind(argc, (char const **) argv);
|
||||||
|
DBufInit(&(LastTrigger.tags));
|
||||||
ClearLastTriggers();
|
ClearLastTriggers();
|
||||||
|
|
||||||
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
||||||
@@ -124,7 +131,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (Iterations) {
|
if (Iterations) {
|
||||||
PerIterationInit();
|
PerIterationInit();
|
||||||
JulianToday++;
|
DSEToday++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -169,22 +176,24 @@ static void DoReminders(void)
|
|||||||
Parser p;
|
Parser p;
|
||||||
int purge_handled;
|
int purge_handled;
|
||||||
|
|
||||||
|
DidMsgReminder = 0;
|
||||||
|
|
||||||
if (!UseStdin) {
|
if (!UseStdin) {
|
||||||
FileAccessDate = GetAccessDate(InitialFile);
|
FileAccessDate = GetAccessDate(InitialFile);
|
||||||
} else {
|
} else {
|
||||||
FileAccessDate = JulianToday;
|
FileAccessDate = DSEToday;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileAccessDate < 0) {
|
if (FileAccessDate < 0) {
|
||||||
fprintf(ErrFp, "%s: `%s'.\n", ErrMsg[E_CANTACCESS], InitialFile);
|
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
r=IncludeFile(InitialFile);
|
r=IncludeFile(InitialFile);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
||||||
InitialFile, ErrMsg[r]);
|
InitialFile, ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
@@ -192,7 +201,7 @@ static void DoReminders(void)
|
|||||||
if (r == E_EOF) return;
|
if (r == E_EOF) return;
|
||||||
if (r) {
|
if (r) {
|
||||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
s = FindInitialToken(&tok, CurLine);
|
s = FindInitialToken(&tok, CurLine);
|
||||||
|
|
||||||
@@ -253,6 +262,7 @@ static void DoReminders(void)
|
|||||||
case T_Flush: r=DoFlush(&p); break;
|
case T_Flush: r=DoFlush(&p); break;
|
||||||
case T_Set: r=DoSet(&p); break;
|
case T_Set: r=DoSet(&p); break;
|
||||||
case T_Fset: r=DoFset(&p); break;
|
case T_Fset: r=DoFset(&p); break;
|
||||||
|
case T_Funset: r=DoFunset(&p); break;
|
||||||
case T_UnSet: r=DoUnset(&p); break;
|
case T_UnSet: r=DoUnset(&p); break;
|
||||||
case T_Clr: r=DoClear(&p); break;
|
case T_Clr: r=DoClear(&p); break;
|
||||||
case T_Debug: r=DoDebug(&p); break;
|
case T_Debug: r=DoDebug(&p); break;
|
||||||
@@ -307,13 +317,16 @@ static void DoReminders(void)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* Julian */
|
/* DSE */
|
||||||
/* */
|
/* */
|
||||||
/* Given day, month, year, return Julian date in days since */
|
/* DSE stands for "Days Since Epoch"; the Remind epoch is */
|
||||||
|
/* midnight on 1990-01-01 */
|
||||||
|
/* */
|
||||||
|
/* Given day, month, year, return DSE date in days since */
|
||||||
/* 1 January 1990. */
|
/* 1 January 1990. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int Julian(int year, int month, int day)
|
int DSE(int year, int month, int day)
|
||||||
{
|
{
|
||||||
int y1 = BASE-1, y2 = year-1;
|
int y1 = BASE-1, y2 = year-1;
|
||||||
|
|
||||||
@@ -327,14 +340,15 @@ int Julian(int year, int month, int day)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FromJulian */
|
/* FromDSE */
|
||||||
/* */
|
/* */
|
||||||
/* Convert a Julian date to year, month, day. */
|
/* Convert a DSE date to year, month, day. You may supply */
|
||||||
|
/* NULL for y, m or d if you're not interested in that value */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
void FromJulian(int jul, int *y, int *m, int *d)
|
void FromDSE(int dse, int *y, int *m, int *d)
|
||||||
{
|
{
|
||||||
int try_yr = (jul / 365) + BASE;
|
int try_yr = (dse / 365) + BASE;
|
||||||
int try_mon = 0;
|
int try_mon = 0;
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
@@ -344,26 +358,49 @@ void FromJulian(int jul, int *y, int *m, int *d)
|
|||||||
int y100 = (y2 / 100) - (y1 / 100); /* Don't count multiples of 100... */
|
int y100 = (y2 / 100) - (y1 / 100); /* Don't count multiples of 100... */
|
||||||
int y400 = (y2 / 400) - (y1 / 400); /* ... but do count multiples of 400 */
|
int y400 = (y2 / 400) - (y1 / 400); /* ... but do count multiples of 400 */
|
||||||
|
|
||||||
int try_jul= 365 * (try_yr-BASE) + y4 - y100 + y400;
|
int try_dse= 365 * (try_yr-BASE) + y4 - y100 + y400;
|
||||||
|
|
||||||
while (try_jul > jul) {
|
while (try_dse > dse) {
|
||||||
try_yr--;
|
try_yr--;
|
||||||
try_jul -= DaysInYear(try_yr);
|
try_dse -= DaysInYear(try_yr);
|
||||||
}
|
}
|
||||||
jul -= try_jul;
|
dse -= try_dse;
|
||||||
|
|
||||||
t = DaysInMonth(try_mon, try_yr);
|
t = DaysInMonth(try_mon, try_yr);
|
||||||
while (jul >= t) {
|
while (dse >= t) {
|
||||||
jul -= t;
|
dse -= t;
|
||||||
try_mon++;
|
try_mon++;
|
||||||
t = DaysInMonth(try_mon, try_yr);
|
t = DaysInMonth(try_mon, try_yr);
|
||||||
}
|
}
|
||||||
*y = try_yr;
|
if (y) {
|
||||||
*m = try_mon;
|
*y = try_yr;
|
||||||
*d = jul + 1;
|
}
|
||||||
|
if (m) {
|
||||||
|
*m = try_mon;
|
||||||
|
}
|
||||||
|
if (d) {
|
||||||
|
*d = dse + 1;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int JulianToGregorianOffset(int y, int m)
|
||||||
|
{
|
||||||
|
int offset = 13;
|
||||||
|
int centuries;
|
||||||
|
int four_centuries;
|
||||||
|
if (y >= 2100) {
|
||||||
|
centuries = (y - 2000) / 100;
|
||||||
|
four_centuries = (y - 2000) / 400;
|
||||||
|
offset += centuries - four_centuries;
|
||||||
|
if (!(y%100) && (y % 400)) {
|
||||||
|
if (m < 2) {
|
||||||
|
offset--; /* Offset increments in March */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* ParseChar */
|
/* ParseChar */
|
||||||
@@ -715,41 +752,54 @@ int PushToken(char const *tok, ParsePtr p)
|
|||||||
/* Return the system time in seconds past midnight */
|
/* Return the system time in seconds past midnight */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
long SystemTime(int realtime)
|
int SystemTime(int realtime)
|
||||||
{
|
{
|
||||||
time_t tloc;
|
time_t now;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
|
|
||||||
if (!realtime && (SysTime != -1L)) return SysTime;
|
if (!realtime && (SysTime != -1)) return SysTime;
|
||||||
|
|
||||||
(void) time(&tloc);
|
now = time(NULL);
|
||||||
t = localtime(&tloc);
|
t = localtime(&now);
|
||||||
return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
|
return t->tm_hour * 3600L + t->tm_min * 60L +
|
||||||
(long) t->tm_sec;
|
t->tm_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* MinutesPastMidnight */
|
||||||
|
/* */
|
||||||
|
/* Return the system time in minutes past midnight */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int MinutesPastMidnight(int realtime)
|
||||||
|
{
|
||||||
|
return (SystemTime(realtime) / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* SystemDate */
|
/* SystemDate */
|
||||||
/* */
|
/* */
|
||||||
/* Obtains today's date. Returns Julian date or -1 for */
|
/* Obtains today's date. Returns DSE date or -1 for */
|
||||||
/* failure. (Failure happens if sys date is before BASE */
|
/* failure. (Failure happens if sys date is before BASE */
|
||||||
/* year.) */
|
/* year.) */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int SystemDate(int *y, int *m, int *d)
|
int SystemDate(int *y, int *m, int *d)
|
||||||
{
|
{
|
||||||
time_t tloc;
|
time_t now;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
|
|
||||||
(void) time(&tloc);
|
now = time(NULL);
|
||||||
t = localtime(&tloc);
|
t = localtime(&now);
|
||||||
|
|
||||||
*d = t->tm_mday;
|
*d = t->tm_mday;
|
||||||
*m = t->tm_mon;
|
*m = t->tm_mon;
|
||||||
*y = t->tm_year + 1900;
|
*y = t->tm_year + 1900;
|
||||||
|
|
||||||
return Julian(*y, *m, *d);
|
return DSE(*y, *m, *d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -842,7 +892,7 @@ int DoIfTrig(ParsePtr p)
|
|||||||
unsigned syndrome;
|
unsigned syndrome;
|
||||||
Trigger trig;
|
Trigger trig;
|
||||||
TimeTrig tim;
|
TimeTrig tim;
|
||||||
int jul;
|
int dse;
|
||||||
|
|
||||||
|
|
||||||
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
|
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||||
@@ -850,26 +900,26 @@ int DoIfTrig(ParsePtr p)
|
|||||||
else {
|
else {
|
||||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
dse = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
|
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
|
||||||
if (!Hush || r != E_RUN_DISABLED) {
|
if (!Hush || r != E_RUN_DISABLED) {
|
||||||
Eprint("%s", ErrMsg[r]);
|
Eprint("%s", ErrMsg[r]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||||
} else {
|
} else {
|
||||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||||
if (PurgeMode) {
|
|
||||||
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
|
|
||||||
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (syndrome == (IF_FALSE | BEFORE_ELSE) && PurgeMode) {
|
||||||
|
PurgeEchoLine("%s\n", "#!P: The next IFTRIG did not trigger.");
|
||||||
|
PurgeEchoLine("%s\n", "#!P: REM statements in IFTRIG block not checked for purging.");
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
}
|
}
|
||||||
NumIfs++;
|
NumIfs++;
|
||||||
@@ -1124,7 +1174,7 @@ int DoErrMsg(ParsePtr p)
|
|||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
t.typ = MSG_TYPE;
|
t.typ = MSG_TYPE;
|
||||||
tt.ttime = SystemTime(0) / 60;
|
tt.ttime = SystemTime(0) / 60;
|
||||||
if ( (r=DoSubst(p, &buf, &t, &tt, JulianToday, NORMAL_MODE)) ) {
|
if ( (r=DoSubst(p, &buf, &t, &tt, DSEToday, NORMAL_MODE)) ) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
s = DBufValue(&buf);
|
s = DBufValue(&buf);
|
||||||
@@ -1154,28 +1204,30 @@ static int FoldArray[2][7] = {
|
|||||||
{2024, 2008, 2020, 2004, 2016, 2000, 2012}
|
{2024, 2008, 2020, 2004, 2016, 2000, 2012}
|
||||||
};
|
};
|
||||||
|
|
||||||
int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
|
int CalcMinsFromUTC(int dse, int tim, int *mins, int *isdst)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Convert jul and tim to an Unix tm struct */
|
/* Convert dse and tim to an Unix tm struct */
|
||||||
int yr, mon, day;
|
int yr, mon, day;
|
||||||
int tdiff;
|
int tdiff;
|
||||||
struct tm local, utc, *temp;
|
struct tm local, utc, *temp;
|
||||||
time_t loc_t, utc_t;
|
time_t loc_t, utc_t;
|
||||||
int isdst_tmp;
|
int isdst_tmp;
|
||||||
|
|
||||||
FromJulian(jul, &yr, &mon, &day);
|
FromDSE(dse, &yr, &mon, &day);
|
||||||
|
|
||||||
/* If the year is greater than 2037, some Unix machines have problems.
|
/* If the year is greater than 2037, some Unix machines have problems.
|
||||||
Fold it back to a "similar" year and trust that the UTC calculations
|
Fold it back to a "similar" year and trust that the UTC calculations
|
||||||
are still valid... */
|
are still valid... */
|
||||||
if (FoldYear && yr>2037) {
|
if (FoldYear && yr>2037) {
|
||||||
jul = Julian(yr, 0, 1);
|
dse = DSE(yr, 0, 1);
|
||||||
yr = FoldArray[IsLeapYear(yr)][jul%7];
|
yr = FoldArray[IsLeapYear(yr)][dse%7];
|
||||||
}
|
}
|
||||||
local.tm_sec = 0;
|
local.tm_sec = 0;
|
||||||
local.tm_min = tim % 60;
|
local.tm_min = tim % 60;
|
||||||
local.tm_hour = tim / 60;
|
local.tm_hour = tim / 60;
|
||||||
|
|
||||||
|
|
||||||
local.tm_mday = day;
|
local.tm_mday = day;
|
||||||
local.tm_mon = mon;
|
local.tm_mon = mon;
|
||||||
local.tm_year = yr-1900;
|
local.tm_year = yr-1900;
|
||||||
@@ -1204,6 +1256,144 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char const *OutputEscapeSequences(char const *s, int print, DynamicBuffer *output)
|
||||||
|
{
|
||||||
|
while (*s == 0x1B && *(s+1) == '[') {
|
||||||
|
if (print) OUTPUT(*s);
|
||||||
|
s++;
|
||||||
|
if (print) OUTPUT(*s);
|
||||||
|
s++;
|
||||||
|
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
||||||
|
if (print) OUTPUT(*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (*s) {
|
||||||
|
if (print) OUTPUT(*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
|
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
|
||||||
|
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print, DynamicBuffer *output)
|
||||||
|
{
|
||||||
|
while (*s == 0x1B && *(s+1) == '[') {
|
||||||
|
if (print) PutWideChar(*s, output);
|
||||||
|
s++;
|
||||||
|
if (print) PutWideChar(*s, output);
|
||||||
|
s++;
|
||||||
|
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
||||||
|
if (print) PutWideChar(*s, output);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (*s) {
|
||||||
|
if (print) PutWideChar(*s, output);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
FillParagraphWCAux(wchar_t const *s, DynamicBuffer *output)
|
||||||
|
{
|
||||||
|
int line = 0;
|
||||||
|
int i, j;
|
||||||
|
int doublespace = 1;
|
||||||
|
int pendspace;
|
||||||
|
int len;
|
||||||
|
wchar_t const *t;
|
||||||
|
|
||||||
|
int roomleft;
|
||||||
|
/* Start formatting */
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
/* If it's a carriage return, output it and start new paragraph */
|
||||||
|
if (*s == '\n') {
|
||||||
|
OUTPUT('\n');
|
||||||
|
s++;
|
||||||
|
line = 0;
|
||||||
|
while(ISWBLANK(*s)) s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!*s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Over here, we're at the beginning of a line. Emit the correct
|
||||||
|
number of spaces */
|
||||||
|
j = line ? SubsIndent : FirstIndent;
|
||||||
|
for (i=0; i<j; i++) {
|
||||||
|
OUTPUT(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the amount of room left on this line */
|
||||||
|
roomleft = FormWidth - j;
|
||||||
|
pendspace = 0;
|
||||||
|
|
||||||
|
/* Emit words until the next one won't fit */
|
||||||
|
while(1) {
|
||||||
|
while(ISWBLANK(*s)) s++;
|
||||||
|
if (*s == '\n') break;
|
||||||
|
while(1) {
|
||||||
|
t = s;
|
||||||
|
s = OutputEscapeSequencesWS(s, 1, output);
|
||||||
|
if (s == t) break;
|
||||||
|
while(ISWBLANK(*s)) s++;
|
||||||
|
}
|
||||||
|
t = s;
|
||||||
|
len = 0;
|
||||||
|
while(*s && !iswspace(*s)) {
|
||||||
|
if (*s == 0x1B && *(s+1) == '[') {
|
||||||
|
s = OutputEscapeSequencesWS(s, 0, output);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
len += wcwidth(*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (s == t) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pendspace || len+pendspace <= roomleft) {
|
||||||
|
for (i=0; i<pendspace; i++) {
|
||||||
|
OUTPUT(' ');
|
||||||
|
}
|
||||||
|
while(t < s) {
|
||||||
|
PutWideChar(*t, output);
|
||||||
|
if (strchr(EndSent, *t)) doublespace = 2;
|
||||||
|
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s = t;
|
||||||
|
OUTPUT('\n');
|
||||||
|
line++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
roomleft -= len+doublespace;
|
||||||
|
pendspace = doublespace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
FillParagraphWC(char const *s, DynamicBuffer *output)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
wchar_t *buf;
|
||||||
|
|
||||||
|
len = mbstowcs(NULL, s, 0);
|
||||||
|
if (len == (size_t) -1) return E_NO_MEM;
|
||||||
|
buf = calloc(len+1, sizeof(wchar_t));
|
||||||
|
if (!buf) return E_NO_MEM;
|
||||||
|
(void) mbstowcs(buf, s, len+1);
|
||||||
|
FillParagraphWCAux(buf, output);
|
||||||
|
free(buf);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FillParagraph */
|
/* FillParagraph */
|
||||||
@@ -1219,7 +1409,7 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
|
|||||||
/* A macro safe ONLY if used with arg with no side effects! */
|
/* A macro safe ONLY if used with arg with no side effects! */
|
||||||
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
||||||
|
|
||||||
void FillParagraph(char const *s)
|
void FillParagraph(char const *s, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
|
|
||||||
int line = 0;
|
int line = 0;
|
||||||
@@ -1230,18 +1420,24 @@ void FillParagraph(char const *s)
|
|||||||
char const *t;
|
char const *t;
|
||||||
|
|
||||||
int roomleft;
|
int roomleft;
|
||||||
|
|
||||||
if (!s || !*s) return;
|
if (!s || !*s) return;
|
||||||
|
|
||||||
/* Skip leading spaces */
|
/* Skip leading spaces */
|
||||||
while(ISBLANK(*s)) s++;
|
while(ISBLANK(*s)) s++;
|
||||||
|
if (!*s) return;
|
||||||
|
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
|
if (FillParagraphWC(s, output) == OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Start formatting */
|
/* Start formatting */
|
||||||
while(1) {
|
while(1) {
|
||||||
|
|
||||||
/* If it's a carriage return, output it and start new paragraph */
|
/* If it's a carriage return, output it and start new paragraph */
|
||||||
if (*s == '\n') {
|
if (*s == '\n') {
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
s++;
|
s++;
|
||||||
line = 0;
|
line = 0;
|
||||||
while(ISBLANK(*s)) s++;
|
while(ISBLANK(*s)) s++;
|
||||||
@@ -1254,7 +1450,7 @@ void FillParagraph(char const *s)
|
|||||||
number of spaces */
|
number of spaces */
|
||||||
j = line ? SubsIndent : FirstIndent;
|
j = line ? SubsIndent : FirstIndent;
|
||||||
for (i=0; i<j; i++) {
|
for (i=0; i<j; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the amount of room left on this line */
|
/* Calculate the amount of room left on this line */
|
||||||
@@ -1265,25 +1461,38 @@ void FillParagraph(char const *s)
|
|||||||
while(1) {
|
while(1) {
|
||||||
while(ISBLANK(*s)) s++;
|
while(ISBLANK(*s)) s++;
|
||||||
if (*s == '\n') break;
|
if (*s == '\n') break;
|
||||||
|
while(1) {
|
||||||
|
t = s;
|
||||||
|
s = OutputEscapeSequences(s, 1, output);
|
||||||
|
if (s == t) break;
|
||||||
|
while(ISBLANK(*s)) s++;
|
||||||
|
}
|
||||||
t = s;
|
t = s;
|
||||||
while(*s && !isspace(*s)) s++;
|
len = 0;
|
||||||
len = s - t;
|
while(*s && !isspace(*s)) {
|
||||||
if (!len) {
|
if (*s == 0x1B && *(s+1) == '[') {
|
||||||
|
s = OutputEscapeSequences(s, 0, output);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if (s == t) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pendspace || len+pendspace <= roomleft) {
|
if (!pendspace || len+pendspace <= roomleft) {
|
||||||
for (i=0; i<pendspace; i++) {
|
for (i=0; i<pendspace; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
while(t < s) {
|
while(t < s) {
|
||||||
putchar(*t);
|
OUTPUT(*t);
|
||||||
if (strchr(EndSent, *t)) doublespace = 2;
|
if (strchr(EndSent, *t)) doublespace = 2;
|
||||||
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
||||||
t++;
|
t++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = t;
|
s = t;
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
line++;
|
line++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1357,13 +1566,23 @@ void UTCToLocal(int utcdate, int utctime, int *locdate, int *loctime)
|
|||||||
/* command-line flag is supplied. */
|
/* command-line flag is supplied. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
static sig_atomic_t got_sigint = 0;
|
||||||
|
|
||||||
void SigIntHandler(int d)
|
void
|
||||||
|
SigIntHandler(int d)
|
||||||
{
|
{
|
||||||
UNUSED(d);
|
UNUSED(d);
|
||||||
signal(SIGINT, SigIntHandler);
|
got_sigint = 1;
|
||||||
GotSigInt();
|
}
|
||||||
exit(0);
|
|
||||||
|
int
|
||||||
|
GotSigInt(void)
|
||||||
|
{
|
||||||
|
if (got_sigint) {
|
||||||
|
got_sigint = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1404,6 +1623,7 @@ ClearLastTriggers(void)
|
|||||||
LastTrigger.warn[0] = 0;
|
LastTrigger.warn[0] = 0;
|
||||||
LastTrigger.omitfunc[0] = 0;
|
LastTrigger.omitfunc[0] = 0;
|
||||||
LastTrigger.passthru[0] = 0;
|
LastTrigger.passthru[0] = 0;
|
||||||
|
DBufFree(&(LastTrigger.tags));
|
||||||
|
|
||||||
LastTimeTrig.ttime = NO_TIME;
|
LastTimeTrig.ttime = NO_TIME;
|
||||||
LastTimeTrig.delta = NO_DELTA;
|
LastTimeTrig.delta = NO_DELTA;
|
||||||
@@ -1424,8 +1644,10 @@ SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigt
|
|||||||
void
|
void
|
||||||
SaveLastTrigger(Trigger const *t)
|
SaveLastTrigger(Trigger const *t)
|
||||||
{
|
{
|
||||||
|
DBufFree(&(LastTrigger.tags));
|
||||||
memcpy(&LastTrigger, t, sizeof(LastTrigger));
|
memcpy(&LastTrigger, t, sizeof(LastTrigger));
|
||||||
DBufInit(&(LastTrigger.tags));
|
DBufInit(&(LastTrigger.tags));
|
||||||
|
DBufPuts(&(LastTrigger.tags), DBufValue(&(t->tags)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1434,14 +1656,48 @@ SaveLastTimeTrig(TimeTrig const *t)
|
|||||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrapper to ignore warnings about ignoring return value of system() */
|
/* Wrapper to ignore warnings about ignoring return value of system()
|
||||||
|
Also redirects stdin and stdout to /dev/null for queued reminders */
|
||||||
|
|
||||||
void
|
void
|
||||||
System(char const *cmd)
|
System(char const *cmd, int is_queued)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
pid_t kid;
|
||||||
|
int fd;
|
||||||
|
int status;
|
||||||
|
if (is_queued && IsServerMode()) {
|
||||||
|
/* Server mode... redirect stdin and stdout to /dev/null */
|
||||||
|
kid = fork();
|
||||||
|
if (kid == (pid_t) -1) {
|
||||||
|
/* Fork failed... nothing we can do */
|
||||||
|
return;
|
||||||
|
} else if (kid == 0) {
|
||||||
|
/* In the child */
|
||||||
|
(void) close(STDIN_FILENO);
|
||||||
|
(void) close(STDOUT_FILENO);
|
||||||
|
fd = open("/dev/null", O_RDONLY);
|
||||||
|
if (fd >= 0 && fd != STDIN_FILENO) {
|
||||||
|
dup2(fd, STDIN_FILENO);
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
}
|
||||||
|
fd = open("/dev/null", O_WRONLY);
|
||||||
|
if (fd >= 0 && fd != STDOUT_FILENO) {
|
||||||
|
dup2(fd, STDOUT_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* In the parent */
|
||||||
|
while (waitpid(kid, &status, 0) != kid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* This is the child process or original if we never forked */
|
||||||
r = system(cmd);
|
r = system(cmd);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
r = 1;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
src/moon.c
45
src/moon.c
@@ -5,7 +5,8 @@
|
|||||||
/* Calculations for figuring out moon phases. */
|
/* Calculations for figuring out moon phases. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -143,7 +144,7 @@ static double phase (double, double *, double *, double *, double *, double *, d
|
|||||||
/* */
|
/* */
|
||||||
/* jdate */
|
/* jdate */
|
||||||
/* */
|
/* */
|
||||||
/* Convert a date and time to Julian day and fraction. */
|
/* Convert a date and time to DSE day and fraction. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static long jdate(int y, int mon, int day)
|
static long jdate(int y, int mon, int day)
|
||||||
@@ -400,9 +401,9 @@ static double phase(double pdate,
|
|||||||
double *suangdia)
|
double *suangdia)
|
||||||
{
|
{
|
||||||
|
|
||||||
double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
|
double Day, N, M, Ec, Lambdasun, ml, MM, Ev, Ae, A3, MmP,
|
||||||
mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon,
|
mEc, A4, lP, V, lPP,
|
||||||
MoonAge, MoonPhase,
|
MoonAge, Phase,
|
||||||
MoonDist, MoonDFrac, MoonAng,
|
MoonDist, MoonDFrac, MoonAng,
|
||||||
F, SunDist, SunAng;
|
F, SunDist, SunAng;
|
||||||
|
|
||||||
@@ -411,7 +412,7 @@ static double phase(double pdate,
|
|||||||
Day = pdate - epoch; /* Date within epoch */
|
Day = pdate - epoch; /* Date within epoch */
|
||||||
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
|
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
|
||||||
M = fixangle(N + elonge - elongp); /* Convert from perigee
|
M = fixangle(N + elonge - elongp); /* Convert from perigee
|
||||||
co-ordinates to epoch 1980.0 */
|
coordinates to epoch 1980.0 */
|
||||||
Ec = kepler(M, eccent); /* Solve equation of Kepler */
|
Ec = kepler(M, eccent); /* Solve equation of Kepler */
|
||||||
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
|
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
|
||||||
Ec = 2 * todeg(atan(Ec)); /* 1 anomaly */
|
Ec = 2 * todeg(atan(Ec)); /* 1 anomaly */
|
||||||
@@ -431,9 +432,6 @@ static double phase(double pdate,
|
|||||||
/* Moon's mean anomaly */
|
/* Moon's mean anomaly */
|
||||||
MM = fixangle(ml - 0.1114041 * Day - mmlongp);
|
MM = fixangle(ml - 0.1114041 * Day - mmlongp);
|
||||||
|
|
||||||
/* Moon's ascending node mean longitude */
|
|
||||||
MN = fixangle(mlnode - 0.0529539 * Day);
|
|
||||||
|
|
||||||
/* Evection */
|
/* Evection */
|
||||||
Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
|
Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
|
||||||
|
|
||||||
@@ -461,26 +459,13 @@ static double phase(double pdate,
|
|||||||
/* 1 longitude */
|
/* 1 longitude */
|
||||||
lPP = lP + V;
|
lPP = lP + V;
|
||||||
|
|
||||||
/* Corrected longitude of the node */
|
|
||||||
NP = MN - 0.16 * sin(torad(M));
|
|
||||||
|
|
||||||
/* Y inclination coordinate */
|
|
||||||
y = sin(torad(lPP - NP)) * cos(torad(minc));
|
|
||||||
|
|
||||||
/* X inclination coordinate */
|
|
||||||
x = cos(torad(lPP - NP));
|
|
||||||
|
|
||||||
/* Ecliptic longitude */
|
|
||||||
Lambdamoon = todeg(atan2(y, x));
|
|
||||||
Lambdamoon += NP;
|
|
||||||
|
|
||||||
/* Calculation of the phase of the Moon */
|
/* Calculation of the phase of the Moon */
|
||||||
|
|
||||||
/* Age of the Moon in degrees */
|
/* Age of the Moon in degrees */
|
||||||
MoonAge = lPP - Lambdasun;
|
MoonAge = lPP - Lambdasun;
|
||||||
|
|
||||||
/* Phase of the Moon */
|
/* Phase of the Moon */
|
||||||
MoonPhase = (1 - cos(torad(MoonAge))) / 2;
|
Phase = (1 - cos(torad(MoonAge))) / 2;
|
||||||
|
|
||||||
/* Calculate distance of moon from the centre of the Earth */
|
/* Calculate distance of moon from the centre of the Earth */
|
||||||
|
|
||||||
@@ -492,7 +477,7 @@ static double phase(double pdate,
|
|||||||
MoonDFrac = MoonDist / msmax;
|
MoonDFrac = MoonDist / msmax;
|
||||||
MoonAng = mangsiz / MoonDFrac;
|
MoonAng = mangsiz / MoonDFrac;
|
||||||
|
|
||||||
if(pphase) *pphase = MoonPhase;
|
if(pphase) *pphase = Phase;
|
||||||
if(mage) *mage = synmonth * (fixangle(MoonAge) / 360.0);
|
if(mage) *mage = synmonth * (fixangle(MoonAge) / 360.0);
|
||||||
if(dist) *dist = MoonDist;
|
if(dist) *dist = MoonDist;
|
||||||
if(angdia) *angdia = MoonAng;
|
if(angdia) *angdia = MoonAng;
|
||||||
@@ -520,10 +505,10 @@ int MoonPhase(int date, int time)
|
|||||||
LocalToUTC(date, time, &utcd, &utct);
|
LocalToUTC(date, time, &utcd, &utct);
|
||||||
|
|
||||||
/* Convert from Remind representation to year/mon/day */
|
/* Convert from Remind representation to year/mon/day */
|
||||||
FromJulian(utcd, &y, &m, &d);
|
FromDSE(utcd, &y, &m, &d);
|
||||||
|
|
||||||
/* Convert to a true Julian date -- sorry for the name clashes! */
|
/* Convert to a Julian date */
|
||||||
jd = jtime(y, m, d, (utct / 60), (utct % 60), 0);
|
jd = jtime(y, m, d, (utct / 60), (utct % 60), 0);
|
||||||
|
|
||||||
/* Calculate moon phase */
|
/* Calculate moon phase */
|
||||||
mp = 360.0 * phase(jd, NULL, NULL, NULL, NULL, NULL, NULL);
|
mp = 360.0 * phase(jd, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
@@ -553,8 +538,8 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
|
|||||||
LocalToUTC(startdate, starttim, &utcd, &utct);
|
LocalToUTC(startdate, starttim, &utcd, &utct);
|
||||||
|
|
||||||
/* Convert from Remind representation to year/mon/day */
|
/* Convert from Remind representation to year/mon/day */
|
||||||
FromJulian(utcd, &y, &m, &d);
|
FromDSE(utcd, &y, &m, &d);
|
||||||
/* Convert to a true Julian date -- sorry for the name clashes! */
|
/* Convert to a true Julian date */
|
||||||
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
|
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
|
||||||
jd = jdorig - 45.0;
|
jd = jdorig - 45.0;
|
||||||
nt1 = meanphase(jd, 0.0, &k1);
|
nt1 = meanphase(jd, 0.0, &k1);
|
||||||
@@ -572,7 +557,7 @@ void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
|
|||||||
jyear(jd, &y, &m, &d);
|
jyear(jd, &y, &m, &d);
|
||||||
jhms(jd, &h, &min, &s);
|
jhms(jd, &h, &min, &s);
|
||||||
|
|
||||||
d1 = Julian(y, m, d);
|
d1 = DSE(y, m, d);
|
||||||
t1 = h*60 + min;
|
t1 = h*60 + min;
|
||||||
UTCToLocal(d1, t1, date, time);
|
UTCToLocal(d1, t1, date, time);
|
||||||
}
|
}
|
||||||
|
|||||||
86
src/omit.c
86
src/omit.c
@@ -6,7 +6,8 @@
|
|||||||
/* the data structures for OMITted dates. */
|
/* the data structures for OMITted dates. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -28,8 +29,10 @@ static void InsertIntoSortedArray (int *array, int num, int key);
|
|||||||
static int FullOmitArray[MAX_FULL_OMITS];
|
static int FullOmitArray[MAX_FULL_OMITS];
|
||||||
static int PartialOmitArray[MAX_PARTIAL_OMITS];
|
static int PartialOmitArray[MAX_PARTIAL_OMITS];
|
||||||
|
|
||||||
|
/* WeekdayOmits is declared in global.h */
|
||||||
|
|
||||||
/* How many of each omit types do we have? */
|
/* How many of each omit types do we have? */
|
||||||
static int NumFullOmits, NumPartialOmits;
|
int NumFullOmits, NumPartialOmits;
|
||||||
|
|
||||||
/* The structure for saving and restoring OMIT contexts */
|
/* The structure for saving and restoring OMIT contexts */
|
||||||
typedef struct omitcontext {
|
typedef struct omitcontext {
|
||||||
@@ -37,6 +40,7 @@ typedef struct omitcontext {
|
|||||||
int numfull, numpart;
|
int numfull, numpart;
|
||||||
int *fullsave;
|
int *fullsave;
|
||||||
int *partsave;
|
int *partsave;
|
||||||
|
int weekdaysave;
|
||||||
} OmitContext;
|
} OmitContext;
|
||||||
|
|
||||||
/* The stack of saved omit contexts */
|
/* The stack of saved omit contexts */
|
||||||
@@ -52,6 +56,7 @@ static OmitContext *SavedOmitContexts = NULL;
|
|||||||
int ClearGlobalOmits(void)
|
int ClearGlobalOmits(void)
|
||||||
{
|
{
|
||||||
NumFullOmits = NumPartialOmits = 0;
|
NumFullOmits = NumPartialOmits = 0;
|
||||||
|
WeekdayOmits = 0;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +118,7 @@ int PushOmitContext(ParsePtr p)
|
|||||||
|
|
||||||
context->numfull = NumFullOmits;
|
context->numfull = NumFullOmits;
|
||||||
context->numpart = NumPartialOmits;
|
context->numpart = NumPartialOmits;
|
||||||
|
context->weekdaysave = WeekdayOmits;
|
||||||
context->fullsave = malloc(NumFullOmits * sizeof(int));
|
context->fullsave = malloc(NumFullOmits * sizeof(int));
|
||||||
if (NumFullOmits && !context->fullsave) {
|
if (NumFullOmits && !context->fullsave) {
|
||||||
free(context);
|
free(context);
|
||||||
@@ -154,6 +160,7 @@ int PopOmitContext(ParsePtr p)
|
|||||||
if (!c) return E_POP_NO_PUSH;
|
if (!c) return E_POP_NO_PUSH;
|
||||||
NumFullOmits = c->numfull;
|
NumFullOmits = c->numfull;
|
||||||
NumPartialOmits = c->numpart;
|
NumPartialOmits = c->numpart;
|
||||||
|
WeekdayOmits = c->weekdaysave;
|
||||||
|
|
||||||
/* Copy the context over */
|
/* Copy the context over */
|
||||||
for (i=0; i<NumFullOmits; i++)
|
for (i=0; i<NumFullOmits; i++)
|
||||||
@@ -181,7 +188,7 @@ int PopOmitContext(ParsePtr p)
|
|||||||
/* OK or an error code. */
|
/* OK or an error code. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
|
|
||||||
@@ -193,7 +200,7 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
|||||||
int r;
|
int r;
|
||||||
Value v;
|
Value v;
|
||||||
|
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
sprintf(expr, "%s('%04d-%02d-%02d')",
|
||||||
omitfunc, y, m+1, d);
|
omitfunc, y, m+1, d);
|
||||||
s = expr;
|
s = expr;
|
||||||
@@ -208,18 +215,24 @@ int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Is it omitted because of local omits? */
|
/* Is it omitted because of local omits? */
|
||||||
if (localomit & (1 << (jul % 7))) {
|
if (localomit & (1 << (dse % 7))) {
|
||||||
*omit = 1;
|
*omit = 1;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is it omitted because of global weekday omits? */
|
||||||
|
if (WeekdayOmits & (1 << (dse % 7))) {
|
||||||
|
*omit = 1;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is it omitted because of fully-specified omits? */
|
/* Is it omitted because of fully-specified omits? */
|
||||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
|
if (BexistsIntArray(FullOmitArray, NumFullOmits, dse)) {
|
||||||
*omit = 1;
|
*omit = 1;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
||||||
*omit = 1;
|
*omit = 1;
|
||||||
return OK;
|
return OK;
|
||||||
@@ -289,6 +302,7 @@ int DoOmit(ParsePtr p)
|
|||||||
int syndrome;
|
int syndrome;
|
||||||
int not_first_token = -1;
|
int not_first_token = -1;
|
||||||
int start, end, tmp;
|
int start, end, tmp;
|
||||||
|
int wd = 0;
|
||||||
|
|
||||||
int mc, dc;
|
int mc, dc;
|
||||||
|
|
||||||
@@ -301,9 +315,15 @@ int DoOmit(ParsePtr p)
|
|||||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||||
FindToken(DBufValue(&buf), &tok);
|
FindToken(DBufValue(&buf), &tok);
|
||||||
switch (tok.type) {
|
switch (tok.type) {
|
||||||
case T_Dumpvars:
|
case T_WkDay:
|
||||||
if (not_first_token) return E_PARSE_ERR;
|
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
|
if (wd & (1 << tok.val)) return E_WD_TWICE;
|
||||||
|
wd |= (1 << tok.val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Dumpvars:
|
||||||
|
DBufFree(&buf);
|
||||||
|
if (not_first_token) return E_PARSE_ERR;
|
||||||
r = VerifyEoln(p);
|
r = VerifyEoln(p);
|
||||||
if (r != OK) return r;
|
if (r != OK) return r;
|
||||||
DumpOmits();
|
DumpOmits();
|
||||||
@@ -314,7 +334,7 @@ int DoOmit(ParsePtr p)
|
|||||||
if (y[seen_through] != NO_YR) return E_YR_TWICE;
|
if (y[seen_through] != NO_YR) return E_YR_TWICE;
|
||||||
if (m[seen_through] != NO_MON) return E_MON_TWICE;
|
if (m[seen_through] != NO_MON) return E_MON_TWICE;
|
||||||
if (d[seen_through] != NO_DAY) return E_DAY_TWICE;
|
if (d[seen_through] != NO_DAY) return E_DAY_TWICE;
|
||||||
FromJulian(tok.val, &y[seen_through], &m[seen_through], &d[seen_through]);
|
FromDSE(tok.val, &y[seen_through], &m[seen_through], &d[seen_through]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_Year:
|
case T_Year:
|
||||||
@@ -341,6 +361,7 @@ int DoOmit(ParsePtr p)
|
|||||||
|
|
||||||
case T_Through:
|
case T_Through:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
|
if (wd) return E_PARSE_ERR;
|
||||||
if (seen_through) return E_UNTIL_TWICE;
|
if (seen_through) return E_UNTIL_TWICE;
|
||||||
seen_through = 1;
|
seen_through = 1;
|
||||||
break;
|
break;
|
||||||
@@ -356,13 +377,29 @@ int DoOmit(ParsePtr p)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
if (tok.type == T_Until) {
|
||||||
DBufValue(&buf));
|
Eprint("OMIT: UNTIL not allowed; did you mean THROUGH?");
|
||||||
|
} else {
|
||||||
|
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
||||||
|
DBufValue(&buf));
|
||||||
|
}
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return E_UNKNOWN_TOKEN;
|
return E_UNKNOWN_TOKEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wd) {
|
||||||
|
if (y[0] != NO_YR || m[0] != NO_MON || d[0] != NO_DAY) {
|
||||||
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
|
if ((WeekdayOmits | wd) == 0x7F) {
|
||||||
|
return E_2MANY_LOCALOMIT;
|
||||||
|
}
|
||||||
|
WeekdayOmits |= wd;
|
||||||
|
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (!seen_through) {
|
if (!seen_through) {
|
||||||
/* We must have at least a month */
|
/* We must have at least a month */
|
||||||
if (m[0] == NO_MON) return E_SPEC_MON;
|
if (m[0] == NO_MON) return E_SPEC_MON;
|
||||||
@@ -408,6 +445,9 @@ int DoOmit(ParsePtr p)
|
|||||||
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
|
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
|
||||||
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
||||||
NumPartialOmits++;
|
NumPartialOmits++;
|
||||||
|
if (NumPartialOmits == 366) {
|
||||||
|
Wprint("You have OMITted everything! The space-time continuum is at risk.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mc == m[1] && dc == d[1]) {
|
if (mc == m[1] && dc == d[1]) {
|
||||||
break;
|
break;
|
||||||
@@ -425,8 +465,8 @@ int DoOmit(ParsePtr p)
|
|||||||
/* Full OMITs */
|
/* Full OMITs */
|
||||||
if (d[0] > DaysInMonth(m[0], y[0])) return E_BAD_DATE;
|
if (d[0] > DaysInMonth(m[0], y[0])) return E_BAD_DATE;
|
||||||
if (d[1] > DaysInMonth(m[1], y[1])) return E_BAD_DATE;
|
if (d[1] > DaysInMonth(m[1], y[1])) return E_BAD_DATE;
|
||||||
start = Julian(y[0], m[0], d[0]);
|
start = DSE(y[0], m[0], d[0]);
|
||||||
end = Julian(y[1], m[1], d[1]);
|
end = DSE(y[1], m[1], d[1]);
|
||||||
if (end < start) {
|
if (end < start) {
|
||||||
Eprint("Error: THROUGH date earlier than start date");
|
Eprint("Error: THROUGH date earlier than start date");
|
||||||
return E_BAD_DATE;
|
return E_BAD_DATE;
|
||||||
@@ -447,11 +487,11 @@ int DoOmit(ParsePtr p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AddGlobalOmit(int jul)
|
AddGlobalOmit(int dse)
|
||||||
{
|
{
|
||||||
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
|
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
|
||||||
if (!BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
|
if (!BexistsIntArray(FullOmitArray, NumFullOmits, dse)) {
|
||||||
InsertIntoSortedArray(FullOmitArray, NumFullOmits, jul);
|
InsertIntoSortedArray(FullOmitArray, NumFullOmits, dse);
|
||||||
NumFullOmits++;
|
NumFullOmits++;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@@ -467,7 +507,7 @@ DumpOmits(void)
|
|||||||
printf("\tNone.\n");
|
printf("\tNone.\n");
|
||||||
} else {
|
} else {
|
||||||
for (i=0; i<NumFullOmits; i++) {
|
for (i=0; i<NumFullOmits; i++) {
|
||||||
FromJulian(FullOmitArray[i], &y, &m, &d);
|
FromDSE(FullOmitArray[i], &y, &m, &d);
|
||||||
printf("\t%04d%c%02d%c%02d\n",
|
printf("\t%04d%c%02d%c%02d\n",
|
||||||
y, DateSep, m+1, DateSep, d);
|
y, DateSep, m+1, DateSep, d);
|
||||||
}
|
}
|
||||||
@@ -482,5 +522,15 @@ DumpOmits(void)
|
|||||||
printf("\t%02d%c%02d\n", m+1, DateSep, d);
|
printf("\t%02d%c%02d\n", m+1, DateSep, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("Global Weekday OMITs:\n");
|
||||||
|
if (WeekdayOmits == 0) {
|
||||||
|
printf("\tNone.\n");
|
||||||
|
} else {
|
||||||
|
for (i=0; i<7; i++) {
|
||||||
|
if (WeekdayOmits & (1<<i)) {
|
||||||
|
printf("\t%s\n", EnglishDayName[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
71
src/protos.h
71
src/protos.h
@@ -5,7 +5,8 @@
|
|||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -21,10 +22,15 @@
|
|||||||
/* Characters to ignore */
|
/* Characters to ignore */
|
||||||
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
||||||
|
|
||||||
|
#define IsServerMode() (Daemon < 0)
|
||||||
|
#define ShouldFork (!DontFork)
|
||||||
|
|
||||||
#include "dynbuf.h"
|
#include "dynbuf.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
int CallUserFunc (char const *name, int nargs, ParsePtr p);
|
int CallUserFunc (char const *name, int nargs, ParsePtr p);
|
||||||
int DoFset (ParsePtr p);
|
int DoFset (ParsePtr p);
|
||||||
|
int DoFunset (ParsePtr p);
|
||||||
void ProduceCalendar (void);
|
void ProduceCalendar (void);
|
||||||
char const *SimpleTime (int tim);
|
char const *SimpleTime (int tim);
|
||||||
char const *CalendarTime (int tim, int duration);
|
char const *CalendarTime (int tim, int duration);
|
||||||
@@ -32,11 +38,11 @@ int DoRem (ParsePtr p);
|
|||||||
int DoFlush (ParsePtr p);
|
int DoFlush (ParsePtr p);
|
||||||
void DoExit (ParsePtr p);
|
void DoExit (ParsePtr p);
|
||||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul);
|
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output);
|
||||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
|
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
|
||||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
|
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
|
||||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
|
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
|
||||||
int ParseLiteralDate (char const **s, int *jul, int *tim);
|
int ParseLiteralDate (char const **s, int *dse, int *tim);
|
||||||
int ParseLiteralTime (char const **s, int *tim);
|
int ParseLiteralTime (char const **s, int *tim);
|
||||||
int EvalExpr (char const **e, Value *v, ParsePtr p);
|
int EvalExpr (char const **e, Value *v, ParsePtr p);
|
||||||
int DoCoerce (char type, Value *v);
|
int DoCoerce (char type, Value *v);
|
||||||
@@ -48,13 +54,14 @@ int DoInclude (ParsePtr p, enum TokTypes tok);
|
|||||||
int DoIncludeCmd (ParsePtr p);
|
int DoIncludeCmd (ParsePtr p);
|
||||||
int IncludeFile (char const *fname);
|
int IncludeFile (char const *fname);
|
||||||
int GetAccessDate (char const *file);
|
int GetAccessDate (char const *file);
|
||||||
int SetAccessDate (char const *fname, int jul);
|
int SetAccessDate (char const *fname, int dse);
|
||||||
int TopLevel (void);
|
int TopLevel (void);
|
||||||
int CallFunc (BuiltinFunc *f, int nargs);
|
int CallFunc (BuiltinFunc *f, int nargs);
|
||||||
void InitRemind (int argc, char const *argv[]);
|
void InitRemind (int argc, char const *argv[]);
|
||||||
void Usage (void);
|
void Usage (void);
|
||||||
int Julian (int year, int month, int day);
|
int DSE (int year, int month, int day);
|
||||||
void FromJulian (int jul, int *y, int *m, int *d);
|
void FromDSE (int dse, int *y, int *m, int *d);
|
||||||
|
int JulianToGregorianOffset(int y, int m);
|
||||||
int ParseChar (ParsePtr p, int *err, int peek);
|
int ParseChar (ParsePtr p, int *err, int peek);
|
||||||
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
||||||
@@ -67,7 +74,8 @@ void OutputLine (FILE *fp);
|
|||||||
void CreateParser (char const *s, ParsePtr p);
|
void CreateParser (char const *s, ParsePtr p);
|
||||||
void DestroyParser (ParsePtr p);
|
void DestroyParser (ParsePtr p);
|
||||||
int PushToken (char const *tok, ParsePtr p);
|
int PushToken (char const *tok, ParsePtr p);
|
||||||
long SystemTime (int realtime);
|
int SystemTime (int realtime);
|
||||||
|
int MinutesPastMidnight (int realtime);
|
||||||
int SystemDate (int *y, int *m, int *d);
|
int SystemDate (int *y, int *m, int *d);
|
||||||
int DoIf (ParsePtr p);
|
int DoIf (ParsePtr p);
|
||||||
int DoElse (ParsePtr p);
|
int DoElse (ParsePtr p);
|
||||||
@@ -84,7 +92,7 @@ int DoClear (ParsePtr p);
|
|||||||
int DestroyOmitContexts (void);
|
int DestroyOmitContexts (void);
|
||||||
int PushOmitContext (ParsePtr p);
|
int PushOmitContext (ParsePtr p);
|
||||||
int PopOmitContext (ParsePtr p);
|
int PopOmitContext (ParsePtr p);
|
||||||
int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
|
int IsOmitted (int dse, int localomit, char const *omitfunc, int *omit);
|
||||||
int DoOmit (ParsePtr p);
|
int DoOmit (ParsePtr p);
|
||||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
||||||
void HandleQueuedReminders (void);
|
void HandleQueuedReminders (void);
|
||||||
@@ -94,9 +102,7 @@ void FindNumericToken (char const *s, Token *t);
|
|||||||
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
||||||
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals, int duration_days);
|
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals, int duration_days);
|
||||||
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||||
int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt);
|
|
||||||
char *StrnCpy (char *dest, char const *source, int n);
|
char *StrnCpy (char *dest, char const *source, int n);
|
||||||
int StrMatch (char const *s1, char const *s2, int n);
|
|
||||||
int StrinCmp (char const *s1, char const *s2, int n);
|
int StrinCmp (char const *s1, char const *s2, int n);
|
||||||
char *StrDup (char const *s);
|
char *StrDup (char const *s);
|
||||||
int StrCmpi (char const *s1, char const *s2);
|
int StrCmpi (char const *s1, char const *s2);
|
||||||
@@ -112,38 +118,38 @@ void DestroyVars (int all);
|
|||||||
int PreserveVar (char const *name);
|
int PreserveVar (char const *name);
|
||||||
int DoPreserve (Parser *p);
|
int DoPreserve (Parser *p);
|
||||||
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
||||||
int DoMsgCommand (char const *cmd, char const *msg);
|
int DoMsgCommand (char const *cmd, char const *msg, int is_queued);
|
||||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||||
unsigned int HashVal (char const *str);
|
unsigned int HashVal (char const *str);
|
||||||
int DateOK (int y, int m, int d);
|
int DateOK (int y, int m, int d);
|
||||||
Operator *FindOperator (char const *name, Operator where[], int num);
|
Operator *FindOperator (char const *name, Operator where[], int num);
|
||||||
BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
|
BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
|
||||||
int InsertIntoSortBuffer (int jul, int tim, char const *body, int typ, int prio);
|
int InsertIntoSortBuffer (int dse, int tim, char const *body, int typ, int prio);
|
||||||
void IssueSortedReminders (void);
|
void IssueSortedReminders (void);
|
||||||
int UserFuncExists (char const *fn);
|
int UserFuncExists (char const *fn);
|
||||||
void JulToHeb (int jul, int *hy, int *hm, int *hd);
|
void DSEToHeb (int dse, int *hy, int *hm, int *hd);
|
||||||
int HebNameToNum (char const *mname);
|
int HebNameToNum (char const *mname);
|
||||||
char const *HebMonthName (int m, int y);
|
char const *HebMonthName (int m, int y);
|
||||||
int RoshHashana (int i);
|
int RoshHashana (int i);
|
||||||
long DaysToHebYear (int y);
|
long DaysToHebYear (int y);
|
||||||
int DaysInHebYear (int y);
|
int DaysInHebYear (int y);
|
||||||
char const *DaysInHebMonths (int ylen);
|
char const *DaysInHebMonths (int ylen);
|
||||||
int HebToJul (int hy, int hm, int hd);
|
int HebToDSE (int hy, int hm, int hd);
|
||||||
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
|
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
|
||||||
int GetNextHebrewDate (int julstart, int hm, int hd, int yahr, int adarbehave, int *ans);
|
int GetNextHebrewDate (int dsestart, int hm, int hd, int yahr, int adarbehave, int *ans);
|
||||||
int ComputeJahr (int y, int m, int d, int *ans);
|
int ComputeJahr (int y, int m, int d, int *ans);
|
||||||
int GetSysVar (char const *name, Value *val);
|
int GetSysVar (char const *name, Value *val);
|
||||||
int SetSysVar (char const *name, Value *val);
|
int SetSysVar (char const *name, Value *val);
|
||||||
void DumpSysVarByName (char const *name);
|
void DumpSysVarByName (char const *name);
|
||||||
int CalcMinsFromUTC (int jul, int tim, int *mins, int *isdst);
|
int CalcMinsFromUTC (int dse, int tim, int *mins, int *isdst);
|
||||||
void FillParagraph (char const *s);
|
void FillParagraph (char const *s, DynamicBuffer *output);
|
||||||
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||||
int MoonPhase (int date, int time);
|
int MoonPhase (int date, int time);
|
||||||
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
||||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
||||||
void SigIntHandler (int d);
|
void SigIntHandler (int d);
|
||||||
void GotSigInt (void);
|
int GotSigInt (void);
|
||||||
void PurgeEchoLine(char const *fmt, ...);
|
void PurgeEchoLine(char const *fmt, ...);
|
||||||
void FreeTrig(Trigger *t);
|
void FreeTrig(Trigger *t);
|
||||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||||
@@ -154,25 +160,36 @@ void SaveLastTimeTrig(TimeTrig const *t);
|
|||||||
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
|
void SaveAllTriggerInfo(Trigger const *t, TimeTrig const *tt, int trigdate, int trigtime, int valid);
|
||||||
|
|
||||||
void PerIterationInit(void);
|
void PerIterationInit(void);
|
||||||
char const *Decolorize(int r, int g, int b);
|
char const *Decolorize(void);
|
||||||
char const *Colorize(int r, int g, int b);
|
char const *Colorize(int r, int g, int b, int bg, int clamp);
|
||||||
void PrintJSONString(char const *s);
|
void PrintJSONString(char const *s);
|
||||||
void PrintJSONKeyPairInt(char const *name, int val);
|
void PrintJSONKeyPairInt(char const *name, int val);
|
||||||
void PrintJSONKeyPairString(char const *name, char const *val);
|
void PrintJSONKeyPairString(char const *name, char const *val);
|
||||||
void PrintJSONKeyPairDate(char const *name, int jul);
|
void PrintJSONKeyPairDate(char const *name, int dse);
|
||||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||||
void PrintJSONKeyPairTime(char const *name, int t);
|
void PrintJSONKeyPairTime(char const *name, int t);
|
||||||
void System(char const *cmd);
|
void System(char const *cmd, int queued);
|
||||||
int ShellEscape(char const *in, DynamicBuffer *out);
|
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||||
int AddGlobalOmit(int jul);
|
int AddGlobalOmit(int dse);
|
||||||
void set_lat_and_long_from_components(void);
|
void set_lat_and_long_from_components(void);
|
||||||
void set_components_from_lat_and_long(void);
|
void set_components_from_lat_and_long(void);
|
||||||
|
|
||||||
|
int GetTerminalBackground(void);
|
||||||
|
|
||||||
char const *get_day_name(int wkday);
|
char const *get_day_name(int wkday);
|
||||||
char const *get_month_name(int mon);
|
char const *get_month_name(int mon);
|
||||||
|
|
||||||
|
void set_cloexec(int fd);
|
||||||
int push_call(char const *filename, char const *func, int lineno);
|
int push_call(char const *filename, char const *func, int lineno);
|
||||||
void clear_callstack(void);
|
void clear_callstack(void);
|
||||||
int have_callstack(void);
|
|
||||||
int print_callstack(FILE *fp);
|
int print_callstack(FILE *fp);
|
||||||
void pop_call(void);
|
void pop_call(void);
|
||||||
|
void FixSpecialType(Trigger *trig);
|
||||||
|
void WriteJSONTrigger(Trigger const *t, int include_tags, int today);
|
||||||
|
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
|
#define _XOPEN_SOURCE 600
|
||||||
|
#include <wctype.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
void PutWideChar(wchar_t const wc, DynamicBuffer *output);
|
||||||
|
#endif
|
||||||
|
|||||||
509
src/queue.c
509
src/queue.c
@@ -5,7 +5,8 @@
|
|||||||
/* Queue up reminders for subsequent execution. */
|
/* Queue up reminders for subsequent execution. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -23,16 +24,35 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
|
#undef USE_INOTIFY
|
||||||
|
#if defined(HAVE_SYS_INOTIFY_H) && defined(HAVE_INOTIFY_INIT1)
|
||||||
|
#define USE_INOTIFY 1
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
|
int watch_fd = -1;
|
||||||
|
static void consume_inotify_events(int fd);
|
||||||
|
static int setup_inotify_watch(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* A list of filenames associated with queued reminders */
|
||||||
|
typedef struct queuedfname {
|
||||||
|
struct queuedfname *next;
|
||||||
|
char const *fname;
|
||||||
|
} QueuedFilename;
|
||||||
|
|
||||||
|
|
||||||
/* List structure for holding queued reminders */
|
/* List structure for holding queued reminders */
|
||||||
typedef struct queuedrem {
|
typedef struct queuedrem {
|
||||||
struct queuedrem *next;
|
struct queuedrem *next;
|
||||||
@@ -40,16 +60,18 @@ typedef struct queuedrem {
|
|||||||
int RunDisabled;
|
int RunDisabled;
|
||||||
int ntrig;
|
int ntrig;
|
||||||
char const *text;
|
char const *text;
|
||||||
|
char const *fname;
|
||||||
|
int lineno;
|
||||||
char passthru[PASSTHRU_LEN+1];
|
char passthru[PASSTHRU_LEN+1];
|
||||||
char sched[VAR_NAME_LEN+1];
|
char sched[VAR_NAME_LEN+1];
|
||||||
DynamicBuffer tags;
|
|
||||||
Trigger t;
|
Trigger t;
|
||||||
TimeTrig tt;
|
TimeTrig tt;
|
||||||
} QueuedRem;
|
} QueuedRem;
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
|
|
||||||
static QueuedRem *QueueHead;
|
static QueuedRem *QueueHead = NULL;
|
||||||
|
static QueuedFilename *Files = NULL;
|
||||||
static time_t FileModTime;
|
static time_t FileModTime;
|
||||||
static struct stat StatBuf;
|
static struct stat StatBuf;
|
||||||
|
|
||||||
@@ -59,6 +81,78 @@ static QueuedRem *FindNextReminder (void);
|
|||||||
static int CalculateNextTimeUsingSched (QueuedRem *q);
|
static int CalculateNextTimeUsingSched (QueuedRem *q);
|
||||||
static void DaemonWait (struct timeval *sleep_tv);
|
static void DaemonWait (struct timeval *sleep_tv);
|
||||||
static void reread (void);
|
static void reread (void);
|
||||||
|
static void PrintQueue(void);
|
||||||
|
static char const *QueueFilename(char const *fname);
|
||||||
|
|
||||||
|
static void chomp(DynamicBuffer *buf)
|
||||||
|
{
|
||||||
|
char *s = DBufValue(buf);
|
||||||
|
int l = DBufLen(buf);
|
||||||
|
while (l) {
|
||||||
|
if (s[l-1] == '\n') {
|
||||||
|
s[l-1] = 0;
|
||||||
|
DBufLen(buf)--;
|
||||||
|
l--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *SimpleTimeNoSpace(int tim)
|
||||||
|
{
|
||||||
|
char *s = (char *) SimpleTime(tim);
|
||||||
|
if (s && *s) {
|
||||||
|
size_t l = strlen(s);
|
||||||
|
if (l > 0 && s[l-1] == ' ') {
|
||||||
|
s[l-1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* QueueFilename */
|
||||||
|
/* */
|
||||||
|
/* Add fname to the list of queued filenames if it's not */
|
||||||
|
/* already present. Either way, return a pointer to the */
|
||||||
|
/* filename. Returns NULL if out of memory */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static QueuedFilename *last_file_found = NULL;
|
||||||
|
static char const *QueueFilename(char const *fname)
|
||||||
|
{
|
||||||
|
QueuedFilename *elem = Files;
|
||||||
|
|
||||||
|
/* Optimization: We are very likely in the same file as
|
||||||
|
before... */
|
||||||
|
if (last_file_found && !strcmp(fname, last_file_found->fname)) {
|
||||||
|
return last_file_found->fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No such luck; search the list */
|
||||||
|
while(elem) {
|
||||||
|
if (!strcmp(elem->fname, fname)) {
|
||||||
|
last_file_found = elem;
|
||||||
|
return elem->fname;
|
||||||
|
}
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
/* Not found... queue it */
|
||||||
|
elem = NEW(QueuedFilename);
|
||||||
|
if (!elem) return NULL;
|
||||||
|
elem->fname = StrDup(fname);
|
||||||
|
if (!elem->fname) {
|
||||||
|
free(elem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
elem->next = Files;
|
||||||
|
Files = elem;
|
||||||
|
last_file_found = elem;
|
||||||
|
return elem->fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -69,14 +163,15 @@ static void reread (void);
|
|||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int QueueReminder(ParsePtr p, Trigger *trig,
|
int QueueReminder(ParsePtr p, Trigger *trig,
|
||||||
TimeTrig *tim, char const *sched)
|
TimeTrig *tim, char const *sched)
|
||||||
{
|
{
|
||||||
QueuedRem *qelem;
|
QueuedRem *qelem;
|
||||||
|
|
||||||
if (DontQueue ||
|
if (DontQueue ||
|
||||||
|
trig->noqueue ||
|
||||||
tim->ttime == NO_TIME ||
|
tim->ttime == NO_TIME ||
|
||||||
trig->typ == CAL_TYPE ||
|
trig->typ == CAL_TYPE ||
|
||||||
tim->ttime < SystemTime(0) / 60 ||
|
tim->ttime < MinutesPastMidnight(0) ||
|
||||||
((trig->typ == RUN_TYPE) && RunDisabled)) return OK;
|
((trig->typ == RUN_TYPE) && RunDisabled)) return OK;
|
||||||
|
|
||||||
qelem = NEW(QueuedRem);
|
qelem = NEW(QueuedRem);
|
||||||
@@ -88,25 +183,84 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
|||||||
free(qelem);
|
free(qelem);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
qelem->fname = QueueFilename(FileName);
|
||||||
|
if (!qelem->fname) {
|
||||||
|
free((void *) qelem->text);
|
||||||
|
free(qelem);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
qelem->lineno = LineNo;
|
||||||
NumQueued++;
|
NumQueued++;
|
||||||
qelem->typ = trig->typ;
|
qelem->typ = trig->typ;
|
||||||
strcpy(qelem->passthru, trig->passthru);
|
strcpy(qelem->passthru, trig->passthru);
|
||||||
qelem->tt = *tim;
|
qelem->tt = *tim;
|
||||||
qelem->t = *trig;
|
qelem->t = *trig;
|
||||||
DBufInit(&(qelem->t.tags));
|
DBufInit(&(qelem->t.tags));
|
||||||
|
DBufPuts(&(qelem->t.tags), DBufValue(&(trig->tags)));
|
||||||
|
if (SynthesizeTags) {
|
||||||
|
AppendTag(&(qelem->t.tags), SynthesizeTag());
|
||||||
|
}
|
||||||
qelem->next = QueueHead;
|
qelem->next = QueueHead;
|
||||||
qelem->RunDisabled = RunDisabled;
|
qelem->RunDisabled = RunDisabled;
|
||||||
qelem->ntrig = 0;
|
qelem->ntrig = 0;
|
||||||
strcpy(qelem->sched, sched);
|
strcpy(qelem->sched, sched);
|
||||||
DBufInit(&(qelem->tags));
|
|
||||||
DBufPuts(&(qelem->tags), DBufValue(&(trig->tags)));
|
|
||||||
if (SynthesizeTags) {
|
|
||||||
AppendTag(&(qelem->tags), SynthesizeTag());
|
|
||||||
}
|
|
||||||
QueueHead = qelem;
|
QueueHead = qelem;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_close(int fd)
|
||||||
|
{
|
||||||
|
int new_fd;
|
||||||
|
/* Don't close descriptors connected to a TTY, except for stdin */
|
||||||
|
if (fd && isatty(fd)) return;
|
||||||
|
|
||||||
|
(void) close(fd);
|
||||||
|
if (fd != STDIN_FILENO) {
|
||||||
|
new_fd = open("/dev/null", O_WRONLY);
|
||||||
|
} else {
|
||||||
|
new_fd = open("/dev/null", O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the open failed... well... not much we can do */
|
||||||
|
if (new_fd < 0) return;
|
||||||
|
|
||||||
|
/* If we got back the same fd as what we just closed, aces! */
|
||||||
|
if (fd == new_fd) return;
|
||||||
|
|
||||||
|
(void) dup2(new_fd, fd);
|
||||||
|
(void) close(new_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SigContHandler(int d)
|
||||||
|
{
|
||||||
|
UNUSED(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_num_queued(void)
|
||||||
|
{
|
||||||
|
int nqueued = 0;
|
||||||
|
QueuedRem *q = QueueHead;
|
||||||
|
while(q) {
|
||||||
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
|
nqueued++;
|
||||||
|
}
|
||||||
|
q = q->next;
|
||||||
|
}
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{");
|
||||||
|
PrintJSONKeyPairString("response", "queued");
|
||||||
|
PrintJSONKeyPairInt("nqueued", nqueued);
|
||||||
|
printf("\"command\":\"STATUS\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE queued %d\n", nqueued);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* HandleQueuedReminders */
|
/* HandleQueuedReminders */
|
||||||
@@ -120,16 +274,19 @@ void HandleQueuedReminders(void)
|
|||||||
int TimeToSleep;
|
int TimeToSleep;
|
||||||
unsigned SleepTime;
|
unsigned SleepTime;
|
||||||
Parser p;
|
Parser p;
|
||||||
Trigger trig;
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timeval sleep_tv;
|
struct timeval sleep_tv;
|
||||||
|
struct sigaction sa;
|
||||||
/* Suppress the BANNER from being issued */
|
|
||||||
NumTriggered = 1;
|
|
||||||
|
|
||||||
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
|
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
|
||||||
SortByDate = 0;
|
SortByDate = 0;
|
||||||
|
|
||||||
|
/* Free FileName if necessary */
|
||||||
|
if (FileName) {
|
||||||
|
free(FileName);
|
||||||
|
FileName = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we are not connected to a tty, then we must close the
|
/* If we are not connected to a tty, then we must close the
|
||||||
* standard file descriptors. This is to prevent someone
|
* standard file descriptors. This is to prevent someone
|
||||||
* doing:
|
* doing:
|
||||||
@@ -139,9 +296,10 @@ void HandleQueuedReminders(void)
|
|||||||
* processed correctly are RUN commands, provided they mail
|
* processed correctly are RUN commands, provided they mail
|
||||||
* the result back or use their own resource (as a window).
|
* the result back or use their own resource (as a window).
|
||||||
*/
|
*/
|
||||||
if (!DontFork && (!isatty(1) || !isatty(2))) {
|
if (ShouldFork) {
|
||||||
close(1);
|
maybe_close(STDIN_FILENO);
|
||||||
close(2);
|
maybe_close(STDOUT_FILENO);
|
||||||
|
maybe_close(STDERR_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're a daemon, get the mod time of initial file */
|
/* If we're a daemon, get the mod time of initial file */
|
||||||
@@ -156,13 +314,24 @@ void HandleQueuedReminders(void)
|
|||||||
/* Initialize the queue - initialize all the entries time of issue */
|
/* Initialize the queue - initialize all the entries time of issue */
|
||||||
|
|
||||||
while (q) {
|
while (q) {
|
||||||
q->tt.nexttime = (int) (SystemTime(1)/60 - 1);
|
q->tt.nexttime = MinutesPastMidnight(1) - 1;
|
||||||
q->tt.nexttime = CalculateNextTime(q);
|
q->tt.nexttime = CalculateNextTime(q);
|
||||||
q = q->next;
|
q = q->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
|
if (ShouldFork || Daemon) {
|
||||||
|
sa.sa_handler = SigIntHandler;
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
(void) sigaction(SIGINT, &sa, NULL);
|
||||||
|
sa.sa_handler = SigContHandler;
|
||||||
|
(void) sigaction(SIGCONT, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (IsServerMode()) {
|
||||||
|
watch_fd = setup_inotify_watch();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Sit in a loop, issuing reminders when necessary */
|
/* Sit in a loop, issuing reminders when necessary */
|
||||||
while(1) {
|
while(1) {
|
||||||
q = FindNextReminder();
|
q = FindNextReminder();
|
||||||
@@ -171,7 +340,7 @@ void HandleQueuedReminders(void)
|
|||||||
if (!q && !Daemon) break;
|
if (!q && !Daemon) break;
|
||||||
|
|
||||||
if (Daemon && !q) {
|
if (Daemon && !q) {
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Sleep until midnight */
|
/* Sleep until midnight */
|
||||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -190,7 +359,7 @@ void HandleQueuedReminders(void)
|
|||||||
|
|
||||||
/* Wake up once a minute to recalibrate sleep time in
|
/* Wake up once a minute to recalibrate sleep time in
|
||||||
case of laptop hibernation */
|
case of laptop hibernation */
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Wake up on the next exact minute */
|
/* Wake up on the next exact minute */
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
sleep_tv.tv_sec = 60 - (tv.tv_sec % 60);
|
sleep_tv.tv_sec = 60 - (tv.tv_sec % 60);
|
||||||
@@ -205,19 +374,23 @@ void HandleQueuedReminders(void)
|
|||||||
sleep(SleepTime);
|
sleep(SleepTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GotSigInt()) {
|
||||||
|
PrintQueue();
|
||||||
|
}
|
||||||
|
|
||||||
/* If not in daemon mode and day has rolled around,
|
/* If not in daemon mode and day has rolled around,
|
||||||
exit -- not much we can do. */
|
exit -- not much we can do. */
|
||||||
if (!Daemon) {
|
if (!Daemon) {
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
if (RealToday != SystemDate(&y, &m, &d)) {
|
if (RealToday != SystemDate(&y, &m, &d)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Daemon > 0 && SleepTime) CheckInitialFile();
|
if (Daemon > 0 && SleepTime) CheckInitialFile();
|
||||||
|
|
||||||
if (Daemon && !q) {
|
if (Daemon && !q) {
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Sleep until midnight */
|
/* Sleep until midnight */
|
||||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -232,31 +405,53 @@ void HandleQueuedReminders(void)
|
|||||||
/* Do NOT trigger the reminder if tt.nexttime is more than a
|
/* Do NOT trigger the reminder if tt.nexttime is more than a
|
||||||
minute in the past. This can happen if the clock is
|
minute in the past. This can happen if the clock is
|
||||||
changed or a laptop awakes from hibernation.
|
changed or a laptop awakes from hibernation.
|
||||||
However, DO trigger if tt.nexttime == tt.ttime so all
|
However, DO trigger if tt.nexttime == tt.ttime and we're
|
||||||
|
within MaxLateTrigger minutes so all
|
||||||
queued reminders are triggered at least once. */
|
queued reminders are triggered at least once. */
|
||||||
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
||||||
(q->tt.nexttime == q->tt.ttime)) {
|
(q->tt.nexttime == q->tt.ttime &&
|
||||||
|
(MaxLateMinutes == 0 || SystemTime(1) - (q->tt.nexttime * 60) <= 60 * MaxLateMinutes))) {
|
||||||
/* Trigger the reminder */
|
/* Trigger the reminder */
|
||||||
CreateParser(q->text, &p);
|
CreateParser(q->text, &p);
|
||||||
trig.typ = q->typ;
|
|
||||||
strcpy(trig.passthru, q->passthru);
|
|
||||||
RunDisabled = q->RunDisabled;
|
RunDisabled = q->RunDisabled;
|
||||||
if (Daemon < 0) {
|
if (IsServerMode() && q->typ != RUN_TYPE) {
|
||||||
printf("NOTE reminder %s",
|
if (DaemonJSON) {
|
||||||
SimpleTime(q->tt.ttime));
|
printf("{\"response\":\"reminder\",");
|
||||||
printf("%s", SimpleTime(SystemTime(1)/60));
|
PrintJSONKeyPairString("ttime", SimpleTimeNoSpace(q->tt.ttime));
|
||||||
if (!*DBufValue(&q->tags)) {
|
PrintJSONKeyPairString("now", SimpleTimeNoSpace(MinutesPastMidnight(1)));
|
||||||
printf("*\n");
|
PrintJSONKeyPairString("tags", DBufValue(&q->t.tags));
|
||||||
} else {
|
} else {
|
||||||
printf("%s\n", DBufValue(&(q->tags)));
|
printf("NOTE reminder %s",
|
||||||
}
|
SimpleTime(q->tt.ttime));
|
||||||
|
printf("%s", SimpleTime(MinutesPastMidnight(1)));
|
||||||
|
if (!*DBufValue(&q->t.tags)) {
|
||||||
|
printf("*\n");
|
||||||
|
} else {
|
||||||
|
printf("%s\n", DBufValue(&(q->t.tags)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up global variables so some functions like trigdate()
|
/* Set up global variables so some functions like trigdate()
|
||||||
and trigtime() work correctly */
|
and trigtime() work correctly */
|
||||||
SaveAllTriggerInfo(&(q->t), &(q->tt), JulianToday, q->tt.ttime, 1);
|
SaveAllTriggerInfo(&(q->t), &(q->tt), DSEToday, q->tt.ttime, 1);
|
||||||
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
|
FileName = (char *) q->fname;
|
||||||
if (Daemon < 0) {
|
if (DaemonJSON) {
|
||||||
|
DynamicBuffer out;
|
||||||
|
DBufInit(&out);
|
||||||
|
(void) TriggerReminder(&p, &q->t, &q->tt, DSEToday, 1, &out);
|
||||||
|
if (q->typ != RUN_TYPE) {
|
||||||
|
printf("\"body\":\"");
|
||||||
|
chomp(&out);
|
||||||
|
PrintJSONString(DBufValue(&out));
|
||||||
|
printf("\"}\n");
|
||||||
|
}
|
||||||
|
DBufFree(&out);
|
||||||
|
} else {
|
||||||
|
(void) TriggerReminder(&p, &q->t, &q->tt, DSEToday, 1, NULL);
|
||||||
|
}
|
||||||
|
FileName = NULL;
|
||||||
|
if (IsServerMode() && !DaemonJSON && q->typ != RUN_TYPE) {
|
||||||
printf("NOTE endreminder\n");
|
printf("NOTE endreminder\n");
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@@ -265,8 +460,23 @@ void HandleQueuedReminders(void)
|
|||||||
|
|
||||||
/* Calculate the next trigger time */
|
/* Calculate the next trigger time */
|
||||||
q->tt.nexttime = CalculateNextTime(q);
|
q->tt.nexttime = CalculateNextTime(q);
|
||||||
|
|
||||||
|
/* If it's dequeued, update num_queued */
|
||||||
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
|
/* If trigger time is way in the past because computer has been
|
||||||
|
suspended or hibernated, remove from queue */
|
||||||
|
if (q->tt.ttime < MinutesPastMidnight(1) - MaxLateMinutes &&
|
||||||
|
q->tt.nexttime < MinutesPastMidnight(1) - MaxLateMinutes) {
|
||||||
|
q->tt.nexttime = NO_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have dequeued a reminder, update controlling process */
|
||||||
|
if (q->tt.nexttime == NO_TIME && IsServerMode()) {
|
||||||
|
print_num_queued();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -337,13 +547,13 @@ static QueuedRem *FindNextReminder(void)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* GotSigInt */
|
/* PrintQueue */
|
||||||
/* */
|
/* */
|
||||||
/* Split out what's done on a SIGINT from the SIGINT Handler. */
|
/* For debugging: Print queue contents to STDOUT */
|
||||||
/* This will be necessary for OS/2 multithreaded. */
|
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
void GotSigInt(void)
|
static
|
||||||
|
void PrintQueue(void)
|
||||||
{
|
{
|
||||||
QueuedRem *q = QueueHead;
|
QueuedRem *q = QueueHead;
|
||||||
|
|
||||||
@@ -368,6 +578,7 @@ void GotSigInt(void)
|
|||||||
q = q->next;
|
q = q->next;
|
||||||
}
|
}
|
||||||
printf(NL);
|
printf(NL);
|
||||||
|
printf("To terminate program, send SIGQUIT (probably Ctrl-\\ on the keyboard.)%s", NL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -461,6 +672,9 @@ static void
|
|||||||
json_queue(QueuedRem const *q)
|
json_queue(QueuedRem const *q)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"queue\",\"queue\":");
|
||||||
|
}
|
||||||
printf("[");
|
printf("[");
|
||||||
while(q) {
|
while(q) {
|
||||||
if (q->tt.nexttime == NO_TIME) {
|
if (q->tt.nexttime == NO_TIME) {
|
||||||
@@ -472,6 +686,12 @@ json_queue(QueuedRem const *q)
|
|||||||
}
|
}
|
||||||
done = 1;
|
done = 1;
|
||||||
printf("{");
|
printf("{");
|
||||||
|
WriteJSONTrigger(&(q->t), 1, DSEToday);
|
||||||
|
WriteJSONTimeTrigger(&(q->tt));
|
||||||
|
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
||||||
|
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
||||||
|
PrintJSONKeyPairString("filename", q->fname);
|
||||||
|
PrintJSONKeyPairInt("lineno", q->lineno);
|
||||||
switch(q->typ) {
|
switch(q->typ) {
|
||||||
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
|
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
|
||||||
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
|
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
|
||||||
@@ -484,26 +704,6 @@ json_queue(QueuedRem const *q)
|
|||||||
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
|
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
|
||||||
default: PrintJSONKeyPairString("type", "?"); break;
|
default: PrintJSONKeyPairString("type", "?"); break;
|
||||||
}
|
}
|
||||||
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
|
||||||
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
|
||||||
PrintJSONKeyPairTime("ttime", q->tt.ttime);
|
|
||||||
PrintJSONKeyPairTime("nextttime", q->tt.nexttime);
|
|
||||||
PrintJSONKeyPairInt("delta", q->tt.delta);
|
|
||||||
if (q->tt.rep != NO_TIME) {
|
|
||||||
PrintJSONKeyPairInt("rep", q->tt.rep);
|
|
||||||
}
|
|
||||||
if (q->tt.duration != NO_TIME) {
|
|
||||||
PrintJSONKeyPairInt("duration", q->tt.duration);
|
|
||||||
}
|
|
||||||
if (q->passthru[0]) {
|
|
||||||
PrintJSONKeyPairString("passthru", q->passthru);
|
|
||||||
}
|
|
||||||
if (q->sched[0]) {
|
|
||||||
PrintJSONKeyPairString("sched", q->sched);
|
|
||||||
}
|
|
||||||
if (DBufLen(&(q->tags))) {
|
|
||||||
PrintJSONKeyPairString("tags", DBufValue(&(q->tags)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Last one is a special case - no trailing comma */
|
/* Last one is a special case - no trailing comma */
|
||||||
printf("\"");
|
printf("\"");
|
||||||
@@ -517,7 +717,12 @@ json_queue(QueuedRem const *q)
|
|||||||
printf("\"}");
|
printf("\"}");
|
||||||
q = q->next;
|
q = q->next;
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]");
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf(",\"command\":\"QUEUE\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -532,15 +737,28 @@ static void DaemonWait(struct timeval *sleep_tv)
|
|||||||
fd_set readSet;
|
fd_set readSet;
|
||||||
int retval;
|
int retval;
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
|
int max = 1;
|
||||||
char cmdLine[256];
|
char cmdLine[256];
|
||||||
|
|
||||||
FD_ZERO(&readSet);
|
FD_ZERO(&readSet);
|
||||||
FD_SET(0, &readSet);
|
FD_SET(0, &readSet);
|
||||||
retval = select(1, &readSet, NULL, NULL, sleep_tv);
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (watch_fd >= 0) {
|
||||||
|
FD_SET(watch_fd, &readSet);
|
||||||
|
if (watch_fd > max-1)
|
||||||
|
max = watch_fd+1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
retval = select(max, &readSet, NULL, NULL, sleep_tv);
|
||||||
|
|
||||||
/* If date has rolled around, restart */
|
/* If date has rolled around, restart */
|
||||||
if (RealToday != SystemDate(&y, &m, &d)) {
|
if (RealToday != SystemDate(&y, &m, &d)) {
|
||||||
printf("NOTE newdate\nNOTE reread\n");
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"newdate\"}\n{\"response\":\"reread\",\"command\":\"newdate\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE newdate\nNOTE reread\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
reread();
|
reread();
|
||||||
}
|
}
|
||||||
@@ -548,70 +766,101 @@ static void DaemonWait(struct timeval *sleep_tv)
|
|||||||
/* If nothing readable or interrupted system call, return */
|
/* If nothing readable or interrupted system call, return */
|
||||||
if (retval <= 0) return;
|
if (retval <= 0) return;
|
||||||
|
|
||||||
|
/* If inotify watch descriptor is readable, handle it */
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (watch_fd >= 0) {
|
||||||
|
if (FD_ISSET(watch_fd, &readSet)) {
|
||||||
|
consume_inotify_events(watch_fd);
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"reread\",\"command\":\"inotify\"}\n");
|
||||||
|
} else {
|
||||||
|
/* In deprecated server mode, we need to spit out
|
||||||
|
a NOTE newdate to force the front-end to redraw
|
||||||
|
the calendar */
|
||||||
|
printf("NOTE newdate\nNOTE reread\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
reread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* If stdin not readable, return */
|
/* If stdin not readable, return */
|
||||||
if (!FD_ISSET(0, &readSet)) return;
|
if (!FD_ISSET(0, &readSet)) return;
|
||||||
|
|
||||||
/* If EOF on stdin, exit */
|
/* If EOF on stdin, exit */
|
||||||
if (feof(stdin)) {
|
if (feof(stdin)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a line from stdin and interpret it */
|
/* Read a line from stdin and interpret it */
|
||||||
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
|
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cmdLine, "EXIT\n")) {
|
if (!strcmp(cmdLine, "EXIT\n")) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (!strcmp(cmdLine, "STATUS\n")) {
|
} else if (!strcmp(cmdLine, "STATUS\n")) {
|
||||||
int nqueued = 0;
|
print_num_queued();
|
||||||
QueuedRem *q = QueueHead;
|
|
||||||
while(q) {
|
|
||||||
if (q->tt.nexttime != NO_TIME) {
|
|
||||||
nqueued++;
|
|
||||||
}
|
|
||||||
q = q->next;
|
|
||||||
}
|
|
||||||
printf("NOTE queued %d\n", nqueued);
|
|
||||||
fflush(stdout);
|
|
||||||
} else if (!strcmp(cmdLine, "QUEUE\n")) {
|
} else if (!strcmp(cmdLine, "QUEUE\n")) {
|
||||||
printf("NOTE queue\n");
|
if (DaemonJSON) {
|
||||||
QueuedRem *q = QueueHead;
|
json_queue(QueueHead);
|
||||||
while (q) {
|
} else {
|
||||||
if (q->tt.nexttime != NO_TIME) {
|
printf("NOTE queue\n");
|
||||||
switch (q->typ) {
|
QueuedRem *q = QueueHead;
|
||||||
case NO_TYPE: printf("NO_TYPE "); break;
|
while (q) {
|
||||||
case MSG_TYPE: printf("MSG_TYPE "); break;
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
case RUN_TYPE: printf("RUN_TYPE "); break;
|
switch (q->typ) {
|
||||||
case CAL_TYPE: printf("CAL_TYPE "); break;
|
case NO_TYPE: printf("NO_TYPE"); break;
|
||||||
case SAT_TYPE: printf("SAT_TYPE "); break;
|
case MSG_TYPE: printf("MSG_TYPE"); break;
|
||||||
case PS_TYPE: printf("PS_TYPE "); break;
|
case RUN_TYPE: printf("RUN_TYPE"); break;
|
||||||
case PSF_TYPE: printf("PSF_TYPE "); break;
|
case CAL_TYPE: printf("CAL_TYPE"); break;
|
||||||
case MSF_TYPE: printf("MSF_TYPE "); break;
|
case SAT_TYPE: printf("SAT_TYPE"); break;
|
||||||
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE "); break;
|
case PS_TYPE: printf("PS_TYPE"); break;
|
||||||
default: printf("? "); break;
|
case PSF_TYPE: printf("PSF_TYPE"); break;
|
||||||
}
|
case MSF_TYPE: printf("MSF_TYPE"); break;
|
||||||
printf("RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
|
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE"); break;
|
||||||
printf("%s %s %s\n",
|
default: printf("?"); break;
|
||||||
(q->passthru[0] ? q->passthru : "*"),
|
}
|
||||||
(q->sched[0] ? q->sched : "*"),
|
printf(" RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
|
||||||
q->text ? q->text : "NULL");
|
printf("%s %s %s\n",
|
||||||
|
(q->passthru[0] ? q->passthru : "*"),
|
||||||
|
(q->sched[0] ? q->sched : "*"),
|
||||||
|
q->text ? q->text : "NULL");
|
||||||
|
}
|
||||||
|
q = q->next;
|
||||||
}
|
}
|
||||||
q = q->next;
|
printf("NOTE endqueue\n");
|
||||||
}
|
}
|
||||||
printf("NOTE endqueue\n");
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
|
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
|
||||||
printf("NOTE JSONQUEUE\n");
|
if (!DaemonJSON) {
|
||||||
|
printf("NOTE JSONQUEUE\n");
|
||||||
|
}
|
||||||
json_queue(QueueHead);
|
json_queue(QueueHead);
|
||||||
printf("NOTE ENDJSONQUEUE\n");
|
if (!DaemonJSON) {
|
||||||
|
printf("NOTE ENDJSONQUEUE\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!strcmp(cmdLine, "REREAD\n")) {
|
} else if (!strcmp(cmdLine, "REREAD\n")) {
|
||||||
printf("NOTE reread\n");
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"reread\",\"command\":\"REREAD\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE reread\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
reread();
|
reread();
|
||||||
} else {
|
} else {
|
||||||
printf("ERR Invalid daemon command: %s", cmdLine);
|
if (DaemonJSON) {
|
||||||
|
size_t l = strlen(cmdLine);
|
||||||
|
if (l && cmdLine[l-1] == '\n') {
|
||||||
|
cmdLine[l-1] = 0;
|
||||||
|
}
|
||||||
|
printf("{\"response\":\"error\",\"error\":\"Unknown command\",\"command\":\"");
|
||||||
|
PrintJSONString(cmdLine);
|
||||||
|
printf("\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("ERR Invalid daemon command: %s", cmdLine);
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -628,3 +877,47 @@ static void reread(void)
|
|||||||
execvp(ArgV[0], (char **) ArgV);
|
execvp(ArgV[0], (char **) ArgV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
static void consume_inotify_events(int fd)
|
||||||
|
{
|
||||||
|
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
struct timespec sleeptime;
|
||||||
|
/* HACK: sleep for 0.2 seconds to let multiple events queue up so we
|
||||||
|
only do a single reread */
|
||||||
|
sleeptime.tv_sec = 0;
|
||||||
|
sleeptime.tv_nsec = 200000000;
|
||||||
|
nanosleep(&sleeptime, NULL);
|
||||||
|
|
||||||
|
/* Consume all the inotify events */
|
||||||
|
while(1) {
|
||||||
|
n = read(fd, buf, sizeof(buf));
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_inotify_watch(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* Don't inotify_watch stdin */
|
||||||
|
if (!strcmp(InitialFile, "-")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
if (inotify_add_watch(fd, InitialFile, IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
35
src/rem2ps.c
35
src/rem2ps.c
@@ -5,7 +5,8 @@
|
|||||||
/* Print a PostScript calendar. */
|
/* Print a PostScript calendar. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -185,19 +186,19 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
val = json_parse(DBufValue(buf), DBufLen(buf));
|
val = json_parse(DBufValue(buf), DBufLen(buf));
|
||||||
if (!val) {
|
if (!val) {
|
||||||
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val->type != json_object) {
|
if (val->type != json_object) {
|
||||||
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
||||||
DBufValue(buf));
|
DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = NEW(CalEntry);
|
c = NEW(CalEntry);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
c->special = SPECIAL_NORMAL;
|
c->special = SPECIAL_NORMAL;
|
||||||
@@ -220,7 +221,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
c->entry = malloc(strlen(s)+1);
|
c->entry = malloc(strlen(s)+1);
|
||||||
if (!c->entry) {
|
if (!c->entry) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strcpy(c->entry, s);
|
strcpy(c->entry, s);
|
||||||
got_body = 1;
|
got_body = 1;
|
||||||
@@ -252,7 +253,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
|
|
||||||
if (!got_body || !got_date) {
|
if (!got_body || !got_date) {
|
||||||
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -271,7 +272,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
|||||||
CalEntry *c = NEW(CalEntry);
|
CalEntry *c = NEW(CalEntry);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
c->special = SPECIAL_NORMAL;
|
c->special = SPECIAL_NORMAL;
|
||||||
@@ -295,7 +296,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
|||||||
c->entry = malloc(strlen(startOfBody) + 1);
|
c->entry = malloc(strlen(startOfBody) + 1);
|
||||||
if (!c->entry) {
|
if (!c->entry) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strcpy(c->entry, startOfBody);
|
strcpy(c->entry, startOfBody);
|
||||||
|
|
||||||
@@ -342,14 +343,14 @@ int main(int argc, char *argv[])
|
|||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
||||||
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
first_line = 0;
|
first_line = 0;
|
||||||
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
||||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2022 by Dianne Skoll\n\n", VERSION);
|
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2024 by Dianne Skoll\n\n", VERSION);
|
||||||
fprintf(stderr, "Generating PostScript calendar\n");
|
fprintf(stderr, "Generating PostScript calendar\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,7 +361,7 @@ int main(int argc, char *argv[])
|
|||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
|
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
|
||||||
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
|
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
printf("%%%%Trailer\n");
|
printf("%%%%Trailer\n");
|
||||||
printf("%%%%Pages: %d\n", validfile);
|
printf("%%%%Pages: %d\n", validfile);
|
||||||
@@ -389,7 +390,7 @@ void DoPsCal(void)
|
|||||||
month */
|
month */
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
sscanf(DBufValue(&buf), "%s %s %d %d %d", month, year, &days, &wkday,
|
sscanf(DBufValue(&buf), "%39s %39s %d %d %d", month, year, &days, &wkday,
|
||||||
&MondayFirst);
|
&MondayFirst);
|
||||||
|
|
||||||
/* Replace underscores in month name with spaces */
|
/* Replace underscores in month name with spaces */
|
||||||
@@ -421,9 +422,9 @@ void DoPsCal(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
sscanf(DBufValue(&buf), "%s %d", prevm, &prevdays);
|
sscanf(DBufValue(&buf), "%39s %d", prevm, &prevdays);
|
||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
sscanf(DBufValue(&buf), "%s %d", nextm, &nextdays);
|
sscanf(DBufValue(&buf), "%39s %d", nextm, &nextdays);
|
||||||
|
|
||||||
/* Replace underscores with spaces in names of next/prev month */
|
/* Replace underscores with spaces in names of next/prev month */
|
||||||
s = prevm;
|
s = prevm;
|
||||||
@@ -485,7 +486,7 @@ void DoPsCal(void)
|
|||||||
while(1) {
|
while(1) {
|
||||||
if (feof(stdin)) {
|
if (feof(stdin)) {
|
||||||
fprintf(stderr, "Input from REMIND is corrupt!\n");
|
fprintf(stderr, "Input from REMIND is corrupt!\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
@@ -951,7 +952,7 @@ void Init(int argc, char *argv[])
|
|||||||
fprintf(stderr, " WxHin Specify size in inches (W and H are decimal numbers)\n");
|
fprintf(stderr, " WxHin Specify size in inches (W and H are decimal numbers)\n");
|
||||||
fprintf(stderr, " WxHcm Specify size in centimetres (W and H are decimal numbers)\n");
|
fprintf(stderr, " WxHcm Specify size in centimetres (W and H are decimal numbers)\n");
|
||||||
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
|
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1032,7 +1033,7 @@ void Usage(char const *s)
|
|||||||
fprintf(stderr, "-e Make calendar fill entire page\n");
|
fprintf(stderr, "-e Make calendar fill entire page\n");
|
||||||
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
||||||
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
/* Define the PostScript prologue */
|
/* Define the PostScript prologue */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ char *PSProlog1[] =
|
|||||||
{
|
{
|
||||||
"% This file was produced by Remind and Rem2PS, written by",
|
"% This file was produced by Remind and Rem2PS, written by",
|
||||||
"% Dianne Skoll.",
|
"% Dianne Skoll.",
|
||||||
"% Remind and Rem2PS are Copyright 1992-2022 Dianne Skoll.",
|
"% Remind and Rem2PS are Copyright 1992-2024 Dianne Skoll.",
|
||||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||||
|
|||||||
33
src/sort.c
33
src/sort.c
@@ -5,7 +5,8 @@
|
|||||||
/* Routines for sorting reminders by trigger date */
|
/* Routines for sorting reminders by trigger date */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -34,8 +35,8 @@ typedef struct sortrem {
|
|||||||
/* The sorted reminder queue */
|
/* The sorted reminder queue */
|
||||||
static Sortrem *SortedQueue = (Sortrem *) NULL;
|
static Sortrem *SortedQueue = (Sortrem *) NULL;
|
||||||
|
|
||||||
static Sortrem *MakeSortRem (int jul, int tim, char const *body, int typ, int prio);
|
static Sortrem *MakeSortRem (int dse, int tim, char const *body, int typ, int prio);
|
||||||
static void IssueSortBanner (int jul);
|
static void IssueSortBanner (int dse);
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -44,7 +45,7 @@ static void IssueSortBanner (int jul);
|
|||||||
/* Create a new Sortrem entry - return NULL on failure. */
|
/* Create a new Sortrem entry - return NULL on failure. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int prio)
|
static Sortrem *MakeSortRem(int dse, int tim, char const *body, int typ, int prio)
|
||||||
{
|
{
|
||||||
Sortrem *new = NEW(Sortrem);
|
Sortrem *new = NEW(Sortrem);
|
||||||
if (!new) return NULL;
|
if (!new) return NULL;
|
||||||
@@ -55,7 +56,7 @@ static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int pri
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new->trigdate = jul;
|
new->trigdate = dse;
|
||||||
new->trigtime = tim;
|
new->trigtime = tim;
|
||||||
new->typ = typ;
|
new->typ = typ;
|
||||||
new->priority = prio;
|
new->priority = prio;
|
||||||
@@ -70,9 +71,9 @@ static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int pri
|
|||||||
/* Insert a reminder into the sort buffer */
|
/* Insert a reminder into the sort buffer */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
int InsertIntoSortBuffer(int dse, int tim, char const *body, int typ, int prio)
|
||||||
{
|
{
|
||||||
Sortrem *new = MakeSortRem(jul, tim, body, typ, prio);
|
Sortrem *new = MakeSortRem(dse, tim, body, typ, prio);
|
||||||
Sortrem *cur = SortedQueue, *prev = NULL;
|
Sortrem *cur = SortedQueue, *prev = NULL;
|
||||||
int ShouldGoAfter;
|
int ShouldGoAfter;
|
||||||
|
|
||||||
@@ -134,8 +135,8 @@ void IssueSortedReminders(void)
|
|||||||
next = cur->next;
|
next = cur->next;
|
||||||
switch(cur->typ) {
|
switch(cur->typ) {
|
||||||
case MSG_TYPE:
|
case MSG_TYPE:
|
||||||
if (MsgCommand) {
|
if (MsgCommand && *MsgCommand) {
|
||||||
DoMsgCommand(MsgCommand, cur->text);
|
DoMsgCommand(MsgCommand, cur->text, 0);
|
||||||
} else {
|
} else {
|
||||||
if (cur->trigdate != olddate) {
|
if (cur->trigdate != olddate) {
|
||||||
IssueSortBanner(cur->trigdate);
|
IssueSortBanner(cur->trigdate);
|
||||||
@@ -146,11 +147,15 @@ void IssueSortedReminders(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MSF_TYPE:
|
case MSF_TYPE:
|
||||||
FillParagraph(cur->text);
|
if (cur->trigdate != olddate) {
|
||||||
|
IssueSortBanner(cur->trigdate);
|
||||||
|
olddate = cur->trigdate;
|
||||||
|
}
|
||||||
|
FillParagraph(cur->text, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
System(cur->text);
|
System(cur->text, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +173,7 @@ void IssueSortedReminders(void)
|
|||||||
/* defined to take one argument. */
|
/* defined to take one argument. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static void IssueSortBanner(int jul)
|
static void IssueSortBanner(int dse)
|
||||||
{
|
{
|
||||||
char BanExpr[64];
|
char BanExpr[64];
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
@@ -178,13 +183,13 @@ static void IssueSortBanner(int jul)
|
|||||||
|
|
||||||
if (UserFuncExists("sortbanner") != 1) return;
|
if (UserFuncExists("sortbanner") != 1) return;
|
||||||
|
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
||||||
y = EvalExpr(&s, &v, NULL);
|
y = EvalExpr(&s, &v, NULL);
|
||||||
if (y) return;
|
if (y) return;
|
||||||
if (DoCoerce(STR_TYPE, &v)) return;
|
if (DoCoerce(STR_TYPE, &v)) return;
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
if (!DoSubstFromString(v.v.str, &buf, jul, NO_TIME)) {
|
if (!DoSubstFromString(v.v.str, &buf, dse, NO_TIME)) {
|
||||||
if (*DBufValue(&buf)) printf("%s\n", DBufValue(&buf));
|
if (*DBufValue(&buf)) printf("%s\n", DBufValue(&buf));
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/token.c
19
src/token.c
@@ -6,7 +6,8 @@
|
|||||||
/* classifying the tokens parsed. */
|
/* classifying the tokens parsed. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ Token TokArray[] = {
|
|||||||
{ "friday", 3, T_WkDay, 4 },
|
{ "friday", 3, T_WkDay, 4 },
|
||||||
{ "from", 4, T_Scanfrom, FROM_TYPE },
|
{ "from", 4, T_Scanfrom, FROM_TYPE },
|
||||||
{ "fset", 4, T_Fset, 0 },
|
{ "fset", 4, T_Fset, 0 },
|
||||||
|
{ "funset", 6, T_Funset, 0 },
|
||||||
{ "if", 2, T_If, 0 },
|
{ "if", 2, T_If, 0 },
|
||||||
{ "iftrig", 6, T_IfTrig, 0 },
|
{ "iftrig", 6, T_IfTrig, 0 },
|
||||||
{ "in", 2, T_In, 0 },
|
{ "in", 2, T_In, 0 },
|
||||||
@@ -79,6 +81,7 @@ Token TokArray[] = {
|
|||||||
{ "monday", 3, T_WkDay, 0 },
|
{ "monday", 3, T_WkDay, 0 },
|
||||||
{ "msf", 3, T_RemType, MSF_TYPE },
|
{ "msf", 3, T_RemType, MSF_TYPE },
|
||||||
{ "msg", 3, T_RemType, MSG_TYPE },
|
{ "msg", 3, T_RemType, MSG_TYPE },
|
||||||
|
{ "noqueue", 7, T_NoQueue, 0 },
|
||||||
{ "november", 3, T_Month, 10 },
|
{ "november", 3, T_Month, 10 },
|
||||||
{ "october", 3, T_Month, 9 },
|
{ "october", 3, T_Month, 9 },
|
||||||
{ "omit", 3, T_Omit, 0 },
|
{ "omit", 3, T_Omit, 0 },
|
||||||
@@ -238,16 +241,16 @@ void FindNumericToken(char const *s, Token *t)
|
|||||||
/* If we hit a '-' or a '/', we may have a date or a datetime */
|
/* If we hit a '-' or a '/', we may have a date or a datetime */
|
||||||
if (*s == '-' || *s == '/') {
|
if (*s == '-' || *s == '/') {
|
||||||
char const *p = s_orig;
|
char const *p = s_orig;
|
||||||
int jul, tim;
|
int dse, tim;
|
||||||
if (ParseLiteralDate(&p, &jul, &tim) == OK) {
|
if (ParseLiteralDate(&p, &dse, &tim) == OK) {
|
||||||
if (*p) return;
|
if (*p) return;
|
||||||
if (tim == NO_TIME) {
|
if (tim == NO_TIME) {
|
||||||
t->type = T_Date;
|
t->type = T_Date;
|
||||||
t->val = jul;
|
t->val = dse;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t->type = T_DateTime;
|
t->type = T_DateTime;
|
||||||
t->val = MINUTES_PER_DAY * jul + tim;
|
t->val = MINUTES_PER_DAY * dse + tim;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -255,7 +258,6 @@ void FindNumericToken(char const *s, Token *t)
|
|||||||
/* If we hit a comma, swallow it. This allows stuff
|
/* If we hit a comma, swallow it. This allows stuff
|
||||||
like Jan 6, 1998 */
|
like Jan 6, 1998 */
|
||||||
if (*s == ',') {
|
if (*s == ',') {
|
||||||
s++;
|
|
||||||
/* Classify the number we've got */
|
/* Classify the number we've got */
|
||||||
if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
|
if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
|
||||||
else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
|
else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
|
||||||
@@ -354,7 +356,8 @@ static int TokStrCmp(Token const *t, char const *s)
|
|||||||
register int r;
|
register int r;
|
||||||
char const *tk = t->name;
|
char const *tk = t->name;
|
||||||
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
|
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
|
||||||
r = tolower(*tk) - tolower(*s);
|
/* t->name is already lower-case */
|
||||||
|
r = *tk - tolower(*s);
|
||||||
tk++;
|
tk++;
|
||||||
s++;
|
s++;
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
@@ -362,5 +365,5 @@ static int TokStrCmp(Token const *t, char const *s)
|
|||||||
/* Ignore trailing commas on s */
|
/* Ignore trailing commas on s */
|
||||||
|
|
||||||
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
||||||
return (tolower(*tk) - tolower(*s));
|
return (*tk - tolower(*s));
|
||||||
}
|
}
|
||||||
|
|||||||
166
src/trigger.c
166
src/trigger.c
@@ -5,7 +5,8 @@
|
|||||||
/* Routines for figuring out the trigger date of a reminder */
|
/* Routines for figuring out the trigger date of a reminder */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@
|
|||||||
|
|
||||||
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
||||||
|
|
||||||
static int JYear(int jul);
|
static int DSEYear(int dse);
|
||||||
static int JMonth(int jul);
|
static int DSEMonth(int dse);
|
||||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
||||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart);
|
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart);
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
|||||||
/* ONLY the day of week, day, month and year components. */
|
/* ONLY the day of week, day, month and year components. */
|
||||||
/* Normally, returns -1 if the trigger has expired. As a */
|
/* Normally, returns -1 if the trigger has expired. As a */
|
||||||
/* special case, if D, M, Y [WD] are specified, returns the */
|
/* special case, if D, M, Y [WD] are specified, returns the */
|
||||||
/* Julian date, regardless of whether it's expired. This is */
|
/* DSE date, regardless of whether it's expired. This is */
|
||||||
/* so that dates with a REP can be handled properly. */
|
/* so that dates with a REP can be handled properly. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -49,7 +50,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
int d, m, y, j, d2, m2, y2;
|
int d, m, y, j, d2, m2, y2;
|
||||||
|
|
||||||
*err = 0;
|
*err = 0;
|
||||||
FromJulian(startdate, &y, &m, &d);
|
FromDSE(startdate, &y, &m, &d);
|
||||||
d2 = d;
|
d2 = d;
|
||||||
m2 = m;
|
m2 = m;
|
||||||
y2 = y;
|
y2 = y;
|
||||||
@@ -71,18 +72,21 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m++;
|
m++;
|
||||||
if (m == 12) { m = 0; y++; }
|
if (m == 12) { m = 0; y++; }
|
||||||
}
|
}
|
||||||
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
while (trig->d > DaysInMonth(m, y)) {
|
||||||
j = Julian(y, m, trig->d);
|
m++;
|
||||||
|
if (m == 12) { m = 0; y++; }
|
||||||
|
}
|
||||||
|
j = DSE(y, m, trig->d);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_MON:
|
case GOT_MON:
|
||||||
if (m == trig->m) return startdate;
|
if (m == trig->m) return startdate;
|
||||||
else if (m > trig->m) return Julian(y+1, trig->m, 1);
|
else if (m > trig->m) return DSE(y+1, trig->m, 1);
|
||||||
else return Julian(y, trig->m, 1);
|
else return DSE(y, trig->m, 1);
|
||||||
|
|
||||||
case GOT_YR:
|
case GOT_YR:
|
||||||
if (y == trig->y) return startdate;
|
if (y == trig->y) return startdate;
|
||||||
else if (y < trig->y) return Julian(trig->y, 0, 1);
|
else if (y < trig->y) return DSE(trig->y, 0, 1);
|
||||||
else return -1;
|
else return -1;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON:
|
case GOT_DAY+GOT_MON:
|
||||||
@@ -94,10 +98,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
||||||
/* Take care of Feb. 29 */
|
/* Take care of Feb. 29 */
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
return Julian(y, trig->m, trig->d);
|
return DSE(y, trig->m, trig->d);
|
||||||
|
|
||||||
case GOT_DAY+GOT_YR:
|
case GOT_DAY+GOT_YR:
|
||||||
if (y < trig->y) return Julian(trig->y, 0, trig->d);
|
if (y < trig->y) return DSE(trig->y, 0, trig->d);
|
||||||
else if (y > trig->y) return -1;
|
else if (y > trig->y) return -1;
|
||||||
|
|
||||||
if (d > trig->d) {
|
if (d > trig->d) {
|
||||||
@@ -105,37 +109,37 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m == 12) return -1;
|
if (m == 12) return -1;
|
||||||
}
|
}
|
||||||
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
||||||
return Julian(trig->y, m, trig->d);
|
return DSE(trig->y, m, trig->d);
|
||||||
|
|
||||||
case GOT_MON+GOT_YR:
|
case GOT_MON+GOT_YR:
|
||||||
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
||||||
if (y < trig->y) return Julian(trig->y, trig->m, 1);
|
if (y < trig->y) return DSE(trig->y, trig->m, 1);
|
||||||
if (m == trig->m) return startdate;
|
if (m == trig->m) return startdate;
|
||||||
return Julian(trig->y, trig->m, 1);
|
return DSE(trig->y, trig->m, 1);
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON+GOT_YR:
|
case GOT_DAY+GOT_MON+GOT_YR:
|
||||||
if (trig->d > DaysInMonth(trig->m, trig->y)) {
|
if (trig->d > DaysInMonth(trig->m, trig->y)) {
|
||||||
*err = E_BAD_DATE;
|
*err = E_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return Julian(trig->y, trig->m, trig->d);
|
return DSE(trig->y, trig->m, trig->d);
|
||||||
|
|
||||||
case GOT_YR+GOT_WD:
|
case GOT_YR+GOT_WD:
|
||||||
if (y > trig->y) return -1;
|
if (y > trig->y) return -1;
|
||||||
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
if (y < trig->y) j = DSE(trig->y, 0, 1);
|
||||||
else j = startdate;
|
else j = startdate;
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (DSEYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_MON+GOT_WD:
|
case GOT_MON+GOT_WD:
|
||||||
if (m == trig->m) {
|
if (m == trig->m) {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JMonth(j) == trig->m) return j;
|
if (DSEMonth(j) == trig->m) return j;
|
||||||
}
|
}
|
||||||
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
if (m >= trig->m) j = DSE(y+1, trig->m, 1);
|
||||||
else j = Julian(y, trig->m, 1);
|
else j = DSE(y, trig->m, 1);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j; /* Guaranteed to be within the month */
|
return j; /* Guaranteed to be within the month */
|
||||||
|
|
||||||
@@ -146,7 +150,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
/* If there are fewer days in previous month, no match */
|
/* If there are fewer days in previous month, no match */
|
||||||
if (trig->d <= DaysInMonth(m2, y2)) {
|
if (trig->d <= DaysInMonth(m2, y2)) {
|
||||||
j = Julian(y2, m2, trig->d);
|
j = DSE(y2, m2, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
@@ -155,7 +159,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, y)) {
|
if (trig->d <= DaysInMonth(m, y)) {
|
||||||
j = Julian(y, m, trig->d);
|
j = DSE(y, m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
@@ -164,18 +168,18 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m2 = m+1;
|
m2 = m+1;
|
||||||
if (m2 > 11) { m2 = 0; y++; }
|
if (m2 > 11) { m2 = 0; y++; }
|
||||||
while (trig->d > DaysInMonth(m2, y)) m2++;
|
while (trig->d > DaysInMonth(m2, y)) m2++;
|
||||||
j = Julian(y, m2, trig->d);
|
j = DSE(y, m2, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_YR+GOT_DAY:
|
case GOT_WD+GOT_YR+GOT_DAY:
|
||||||
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
||||||
if (y > trig->y) {
|
if (y > trig->y) {
|
||||||
j = Julian(trig->y, 11, trig->d);
|
j = DSE(trig->y, 11, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
} else if (y < trig->y) {
|
} else if (y < trig->y) {
|
||||||
j = Julian(trig->y, 0, trig->d);
|
j = DSE(trig->y, 0, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
@@ -183,17 +187,17 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
m2 = m-1;
|
m2 = m-1;
|
||||||
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
||||||
j = Julian(trig->y, m2, trig->d);
|
j = DSE(trig->y, m2, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (DSEYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, trig->y)) {
|
if (trig->d <= DaysInMonth(m, trig->y)) {
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = DSE(trig->y, m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (DSEYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,9 +205,9 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m == 11) return -1;
|
if (m == 11) return -1;
|
||||||
m++;
|
m++;
|
||||||
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = DSE(trig->y, m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (DSEYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON+GOT_WD:
|
case GOT_DAY+GOT_MON+GOT_WD:
|
||||||
@@ -220,34 +224,34 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
|
|
||||||
/* Try last year */
|
/* Try last year */
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = DSE(y, trig->m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Try this year */
|
/* Try this year */
|
||||||
y++;
|
y++;
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = DSE(y, trig->m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Must be next year */
|
/* Must be next year */
|
||||||
y++;
|
y++;
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = DSE(y, trig->m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_MON+GOT_YR:
|
case GOT_WD+GOT_MON+GOT_YR:
|
||||||
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
||||||
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
||||||
j = Julian(trig->y, trig->m, 1);
|
j = DSE(trig->y, trig->m, 1);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
FromJulian(j, &y2, &m2, &d2);
|
FromDSE(j, &y2, &m2, &d2);
|
||||||
if (m2 == trig->m) return j; else return -1;
|
if (m2 == trig->m) return j; else return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +260,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
*err = E_BAD_DATE;
|
*err = E_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
j = Julian(trig->y, trig->m, trig->d);
|
j = DSE(trig->y, trig->m, trig->d);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
@@ -269,25 +273,25 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* JMonth - Given a Julian date, what's the month? */
|
/* DSEMonth - Given a DSE date, what's the month? */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int JMonth(int jul)
|
static int DSEMonth(int dse)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* JYear - Given a Julian date, what's the year? */
|
/* DSEYear - Given a DSE date, what's the year? */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int JYear(int jul)
|
static int DSEYear(int dse)
|
||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
FromJulian(jul, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +301,7 @@ static int JYear(int jul)
|
|||||||
/* */
|
/* */
|
||||||
/* Given a trigger, compute the next trigger date. */
|
/* Given a trigger, compute the next trigger date. */
|
||||||
/* */
|
/* */
|
||||||
/* Returns the Julian date of next trigger, -1 if */
|
/* Returns the DSE date of next trigger, -1 if */
|
||||||
/* expired, -2 if can't compute trigger date. */
|
/* expired, -2 if can't compute trigger date. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -323,8 +327,11 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
start--;
|
start--;
|
||||||
|
if (start < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (iter > MaxSatIter) {
|
if (start < 0 || iter > MaxSatIter) {
|
||||||
/* omitfunc must have returned "true" too often */
|
/* omitfunc must have returned "true" too often */
|
||||||
*err = E_CANT_TRIG;
|
*err = E_CANT_TRIG;
|
||||||
return -2;
|
return -2;
|
||||||
@@ -387,6 +394,10 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
simple--;
|
simple--;
|
||||||
|
if (simple < 0) {
|
||||||
|
*err = E_CANT_TRIG;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (iter > MaxSatIter) {
|
if (iter > MaxSatIter) {
|
||||||
*err = E_CANT_TRIG;
|
*err = E_CANT_TRIG;
|
||||||
@@ -439,7 +450,7 @@ AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int sav
|
|||||||
/* Change trigger date to today */
|
/* Change trigger date to today */
|
||||||
r = today;
|
r = today;
|
||||||
if (DebugFlag & DB_PRTTRIG) {
|
if (DebugFlag & DB_PRTTRIG) {
|
||||||
FromJulian(r, &y, &m, &d);
|
FromDSE(r, &y, &m, &d);
|
||||||
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
||||||
FileName, LineNo,
|
FileName, LineNo,
|
||||||
get_day_name(r % 7),
|
get_day_name(r % 7),
|
||||||
@@ -530,7 +541,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|||||||
*err = OK;
|
*err = OK;
|
||||||
|
|
||||||
/* But check for obvious problems... */
|
/* But check for obvious problems... */
|
||||||
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
|
if ((WeekdayOmits | trig->localomit) == 0x7F) {
|
||||||
*err = E_2MANY_LOCALOMIT;
|
*err = E_2MANY_LOCALOMIT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -590,7 +601,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|||||||
LastTrigValid = 1;
|
LastTrigValid = 1;
|
||||||
}
|
}
|
||||||
if (DebugFlag & DB_PRTTRIG) {
|
if (DebugFlag & DB_PRTTRIG) {
|
||||||
FromJulian(result, &y, &m, &d);
|
FromDSE(result, &y, &m, &d);
|
||||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
||||||
FileName, LineNo,
|
FileName, LineNo,
|
||||||
get_day_name(result % 7),
|
get_day_name(result % 7),
|
||||||
@@ -621,12 +632,10 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|||||||
fprintf(ErrFp, "%s(%d): %s\n",
|
fprintf(ErrFp, "%s(%d): %s\n",
|
||||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||||
}
|
}
|
||||||
if (result != -1) {
|
if (save_in_globals) {
|
||||||
if (save_in_globals) {
|
LastTriggerDate = result;
|
||||||
LastTriggerDate = result;
|
LastTrigValid = 1;
|
||||||
LastTrigValid = 1;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,12 +648,10 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|||||||
|
|
||||||
/* Keep scanning... unless there's no point in doing it.*/
|
/* Keep scanning... unless there's no point in doing it.*/
|
||||||
if (nextstart <= start) {
|
if (nextstart <= start) {
|
||||||
if (result != -1) {
|
if (save_in_globals) {
|
||||||
if (save_in_globals) {
|
LastTriggerDate = result;
|
||||||
LastTriggerDate = result;
|
LastTrigValid = 1;
|
||||||
LastTrigValid = 1;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
trig->expired = 1;
|
trig->expired = 1;
|
||||||
if (DebugFlag & DB_PRTTRIG) {
|
if (DebugFlag & DB_PRTTRIG) {
|
||||||
fprintf(ErrFp, "%s(%d): %s\n",
|
fprintf(ErrFp, "%s(%d): %s\n",
|
||||||
@@ -661,40 +668,3 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* */
|
|
||||||
/* ComputeScanStart */
|
|
||||||
/* */
|
|
||||||
/* Figure out where to start scan from by examining SCANFROM */
|
|
||||||
/* and DURATION */
|
|
||||||
/* */
|
|
||||||
/***************************************************************/
|
|
||||||
int
|
|
||||||
ComputeScanStart(int today, Trigger *trig, TimeTrig *tt)
|
|
||||||
{
|
|
||||||
int minutes, days;
|
|
||||||
|
|
||||||
/* If we don't have a time/duration, just use scanfrom */
|
|
||||||
if (tt->ttime == NO_TIME ||
|
|
||||||
tt->duration == NO_TIME) {
|
|
||||||
if (trig->scanfrom == NO_DATE) {
|
|
||||||
return today;
|
|
||||||
}
|
|
||||||
return trig->scanfrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate time-based SCANFROM */
|
|
||||||
minutes = tt->ttime + tt->duration - 1;
|
|
||||||
|
|
||||||
/* Figure out how many days to scan backwards from */
|
|
||||||
days = minutes / MINUTES_PER_DAY;
|
|
||||||
|
|
||||||
if (trig->scanfrom != NO_DATE) {
|
|
||||||
if (trig->scanfrom <= today - days) {
|
|
||||||
return trig->scanfrom;
|
|
||||||
} else {
|
|
||||||
return today - days;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return today - days;
|
|
||||||
}
|
|
||||||
|
|||||||
14
src/types.h
14
src/types.h
@@ -5,7 +5,8 @@
|
|||||||
/* Type definitions all dumped here. */
|
/* Type definitions all dumped here. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ typedef struct {
|
|||||||
int eventduration; /* Original event duration (minutes) */
|
int eventduration; /* Original event duration (minutes) */
|
||||||
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
||||||
int addomit; /* Add trigger date to global OMITs */
|
int addomit; /* Add trigger date to global OMITs */
|
||||||
|
int noqueue; /* Don't queue even if timed */
|
||||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||||
@@ -155,8 +157,8 @@ enum TokTypes
|
|||||||
/* Commands first */
|
/* Commands first */
|
||||||
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeR, T_IncludeCmd, T_If, T_Else, T_EndIf,
|
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeR, T_IncludeCmd, T_If, T_Else, T_EndIf,
|
||||||
T_IfTrig, T_ErrMsg,
|
T_IfTrig, T_ErrMsg,
|
||||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
T_Set, T_UnSet, T_Fset, T_Funset, T_Omit, T_Banner, T_Exit,
|
||||||
T_AddOmit,
|
T_AddOmit, T_NoQueue,
|
||||||
T_WkDay,
|
T_WkDay,
|
||||||
T_Month, T_Time, T_Date, T_DateTime,
|
T_Month, T_Time, T_Date, T_DateTime,
|
||||||
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta,
|
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta,
|
||||||
@@ -238,6 +240,6 @@ typedef struct {
|
|||||||
/* Pure JSON */
|
/* Pure JSON */
|
||||||
#define PSCAL_LEVEL3 3
|
#define PSCAL_LEVEL3 3
|
||||||
|
|
||||||
#define TERMINAL_BACKGROUND_UNKNOWN 0
|
#define TERMINAL_BACKGROUND_UNKNOWN -1
|
||||||
#define TERMINAL_BACKGROUND_DARK 1
|
#define TERMINAL_BACKGROUND_DARK 0
|
||||||
#define TERMINAL_BACKGROUND_LIGHT 2
|
#define TERMINAL_BACKGROUND_LIGHT 1
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
/* functions. */
|
/* functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -53,6 +54,34 @@ static void FSet (UserFunc *f);
|
|||||||
static int SetUpLocalVars (UserFunc *f);
|
static int SetUpLocalVars (UserFunc *f);
|
||||||
static void DestroyLocalVals (UserFunc *f);
|
static void DestroyLocalVals (UserFunc *f);
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* DoFunset */
|
||||||
|
/* */
|
||||||
|
/* Undefine a user-defined function - the FUNSET command. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int DoFunset(ParsePtr p)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int seen_one = 0;
|
||||||
|
DynamicBuffer buf;
|
||||||
|
DBufInit(&buf);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
r = ParseIdentifier(p, &buf);
|
||||||
|
if (r == E_EOLN) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seen_one = 1;
|
||||||
|
FUnset(DBufValue(&buf));
|
||||||
|
DBufFree(&buf);
|
||||||
|
}
|
||||||
|
if (seen_one) return OK;
|
||||||
|
return E_PARSE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* DoFset */
|
/* DoFset */
|
||||||
@@ -95,8 +124,13 @@ int DoFset(ParsePtr p)
|
|||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
func->filename = StrDup(FileName);
|
if (FileName) {
|
||||||
|
func->filename = StrDup(FileName);
|
||||||
|
} else {
|
||||||
|
func->filename = StrDup("[cmdline]");
|
||||||
|
}
|
||||||
if (!func->filename) {
|
if (!func->filename) {
|
||||||
|
free(func);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
func->lineno = LineNo;
|
func->lineno = LineNo;
|
||||||
@@ -153,7 +187,7 @@ int DoFset(ParsePtr p)
|
|||||||
/* Allow an optional = sign: FSET f(x) = x*x */
|
/* Allow an optional = sign: FSET f(x) = x*x */
|
||||||
c = ParseNonSpaceChar(p, &r, 1);
|
c = ParseNonSpaceChar(p, &r, 1);
|
||||||
if (c == '=') {
|
if (c == '=') {
|
||||||
c = ParseNonSpaceChar(p, &r, 0);
|
(void) ParseNonSpaceChar(p, &r, 0);
|
||||||
}
|
}
|
||||||
/* Copy the text over */
|
/* Copy the text over */
|
||||||
if (p->isnested) {
|
if (p->isnested) {
|
||||||
@@ -315,7 +349,9 @@ int CallUserFunc(char const *name, int nargs, ParsePtr p)
|
|||||||
|
|
||||||
/* Skip the opening bracket, if there's one */
|
/* Skip the opening bracket, if there's one */
|
||||||
while (isempty(*s)) s++;
|
while (isempty(*s)) s++;
|
||||||
if (*s == BEG_OF_EXPR) s++;
|
if (*s == BEG_OF_EXPR) {
|
||||||
|
s++;
|
||||||
|
}
|
||||||
push_call(f->filename, f->name, f->lineno);
|
push_call(f->filename, f->name, f->lineno);
|
||||||
h = Evaluate(&s, f->locals, p);
|
h = Evaluate(&s, f->locals, p);
|
||||||
if (h == OK) {
|
if (h == OK) {
|
||||||
|
|||||||
43
src/utils.c
43
src/utils.c
@@ -5,7 +5,8 @@
|
|||||||
/* Useful utility functions. */
|
/* Useful utility functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -24,8 +25,6 @@ static char const DontEscapeMe[] =
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
|
|
||||||
#define UPPER(c) toupper(c)
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* StrnCpy */
|
/* StrnCpy */
|
||||||
@@ -37,27 +36,16 @@ char *StrnCpy(char *dest, char const *source, int n)
|
|||||||
{
|
{
|
||||||
char *odest = dest;
|
char *odest = dest;
|
||||||
|
|
||||||
|
if (n <= 0) {
|
||||||
|
*dest = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
while (n-- && (*dest++ = *source++)) ;
|
while (n-- && (*dest++ = *source++)) ;
|
||||||
if (*(dest-1)) *dest = 0;
|
if (*(dest-1)) *dest = 0;
|
||||||
return odest;
|
return odest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/* */
|
|
||||||
/* StrMatch */
|
|
||||||
/* */
|
|
||||||
/* Checks that two strings match (case-insensitive) to at */
|
|
||||||
/* least the specified number of characters, or the length */
|
|
||||||
/* of the first string, whichever is greater. */
|
|
||||||
/* */
|
|
||||||
/***************************************************************/
|
|
||||||
int StrMatch(char const *s1, char const *s2, int n)
|
|
||||||
{
|
|
||||||
int l;
|
|
||||||
if ((l = strlen(s1)) < n) return 0;
|
|
||||||
return !StrinCmp(s1, s2, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* StrinCmp - compare strings, case-insensitive */
|
/* StrinCmp - compare strings, case-insensitive */
|
||||||
@@ -68,12 +56,12 @@ int StrinCmp(char const *s1, char const *s2, int n)
|
|||||||
register int r;
|
register int r;
|
||||||
while (n && *s1 && *s2) {
|
while (n && *s1 && *s2) {
|
||||||
n--;
|
n--;
|
||||||
r = UPPER(*s1) - UPPER(*s2);
|
r = toupper(*s1) - toupper(*s2);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
s1++;
|
s1++;
|
||||||
s2++;
|
s2++;
|
||||||
}
|
}
|
||||||
if (n) return (UPPER(*s1) - UPPER(*s2)); else return 0;
|
if (n) return (toupper(*s1) - toupper(*s2)); else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -102,12 +90,12 @@ int StrCmpi(char const *s1, char const *s2)
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
while (*s1 && *s2) {
|
while (*s1 && *s2) {
|
||||||
r = UPPER(*s1) - UPPER(*s2);
|
r = toupper(*s1) - toupper(*s2);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
s1++;
|
s1++;
|
||||||
s2++;
|
s2++;
|
||||||
}
|
}
|
||||||
return UPPER(*s1) - UPPER(*s2);
|
return toupper(*s1) - toupper(*s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -125,7 +113,7 @@ int DateOK(int y, int m, int d)
|
|||||||
m > 11 ||
|
m > 11 ||
|
||||||
y > BASE + YR_RANGE ||
|
y > BASE + YR_RANGE ||
|
||||||
d > DaysInMonth(m, y) ) return 0;
|
d > DaysInMonth(m, y) ) return 0;
|
||||||
else return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions designed to defeat gcc optimizer */
|
/* Functions designed to defeat gcc optimizer */
|
||||||
@@ -224,13 +212,6 @@ clear_callstack(void)
|
|||||||
callstack = NULL;
|
callstack = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
have_callstack(void)
|
|
||||||
{
|
|
||||||
if (callstack) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_callstack_aux(FILE *fp, cs *entry)
|
print_callstack_aux(FILE *fp, cs *entry)
|
||||||
{
|
{
|
||||||
|
|||||||
299
src/var.c
299
src/var.c
@@ -6,7 +6,8 @@
|
|||||||
/* user- and system-defined variables. */
|
/* user- and system-defined variables. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2022 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -166,6 +167,13 @@ static int latitude_func(int do_set, Value *val)
|
|||||||
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int terminal_bg_func(int do_set, Value *val)
|
||||||
|
{
|
||||||
|
UNUSED(do_set);
|
||||||
|
val->type = INT_TYPE;
|
||||||
|
val->v.val = GetTerminalBackground();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int trig_date_func(int do_set, Value *val)
|
static int trig_date_func(int do_set, Value *val)
|
||||||
{
|
{
|
||||||
@@ -189,7 +197,7 @@ static int trig_day_func(int do_set, Value *val)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||||
val->v.val = d;
|
val->v.val = d;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -204,7 +212,7 @@ static int trig_mon_func(int do_set, Value *val)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||||
val->v.val = m+1;
|
val->v.val = m+1;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -219,7 +227,7 @@ static int trig_year_func(int do_set, Value *val)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
FromDSE(LastTriggerDate, &y, &m, &d);
|
||||||
val->v.val = y;
|
val->v.val = y;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -241,7 +249,7 @@ static int today_date_func(int do_set, Value *val)
|
|||||||
{
|
{
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
val->type = DATE_TYPE;
|
val->type = DATE_TYPE;
|
||||||
val->v.val = JulianToday;
|
val->v.val = DSEToday;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
static int today_day_func(int do_set, Value *val)
|
static int today_day_func(int do_set, Value *val)
|
||||||
@@ -249,7 +257,7 @@ static int today_day_func(int do_set, Value *val)
|
|||||||
int y, m, d;
|
int y, m, d;
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
val->type = INT_TYPE;
|
val->type = INT_TYPE;
|
||||||
FromJulian(JulianToday, &y, &m, &d);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
val->v.val = d;
|
val->v.val = d;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -259,7 +267,7 @@ static int today_mon_func(int do_set, Value *val)
|
|||||||
int y, m, d;
|
int y, m, d;
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
val->type = INT_TYPE;
|
val->type = INT_TYPE;
|
||||||
FromJulian(JulianToday, &y, &m, &d);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
val->v.val = m+1;
|
val->v.val = m+1;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -269,7 +277,7 @@ static int today_year_func(int do_set, Value *val)
|
|||||||
int y, m, d;
|
int y, m, d;
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
val->type = INT_TYPE;
|
val->type = INT_TYPE;
|
||||||
FromJulian(JulianToday, &y, &m, &d);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
val->v.val = y;
|
val->v.val = y;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -278,7 +286,7 @@ static int today_wday_func(int do_set, Value *val)
|
|||||||
{
|
{
|
||||||
UNUSED(do_set);
|
UNUSED(do_set);
|
||||||
val->type = INT_TYPE;
|
val->type = INT_TYPE;
|
||||||
val->v.val = (JulianToday + 1) % 7;
|
val->v.val = (DSEToday + 1) % 7;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,7 +532,9 @@ int DoSet (Parser *p)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
|
DynamicBuffer buf2;
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
|
DBufInit(&buf2);
|
||||||
|
|
||||||
r = ParseIdentifier(p, &buf);
|
r = ParseIdentifier(p, &buf);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
@@ -540,6 +550,13 @@ int DoSet (Parser *p)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = ParseToken(p, &buf2);
|
||||||
|
if (r) return r;
|
||||||
|
if (DBufLen(&buf2)) {
|
||||||
|
DBufFree(&buf2);
|
||||||
|
return E_EXPECTING_EOL;
|
||||||
|
}
|
||||||
|
DBufFree(&buf2);
|
||||||
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
||||||
else r = SetVar(DBufValue(&buf), &v);
|
else r = SetVar(DBufValue(&buf), &v);
|
||||||
if (buf.len > VAR_NAME_LEN) {
|
if (buf.len > VAR_NAME_LEN) {
|
||||||
@@ -761,11 +778,14 @@ typedef struct {
|
|||||||
char modifiable;
|
char modifiable;
|
||||||
int type;
|
int type;
|
||||||
void *value;
|
void *value;
|
||||||
int min;
|
int min; /* Or const-value */
|
||||||
int max;
|
int max;
|
||||||
int (*validate)(void const *newvalue);
|
|
||||||
} SysVar;
|
} SysVar;
|
||||||
|
|
||||||
|
/* Macro to access "min" but as a constval. Just to make source more
|
||||||
|
readable */
|
||||||
|
#define constval min
|
||||||
|
|
||||||
/* If the type of a sys variable is STR_TYPE, then min is redefined
|
/* If the type of a sys variable is STR_TYPE, then min is redefined
|
||||||
to be a flag indicating whether or not the value has been malloc'd. */
|
to be a flag indicating whether or not the value has been malloc'd. */
|
||||||
#define been_malloced min
|
#define been_malloced min
|
||||||
@@ -775,101 +795,113 @@ typedef struct {
|
|||||||
|
|
||||||
/* All of the system variables sorted alphabetically */
|
/* All of the system variables sorted alphabetically */
|
||||||
static SysVar SysVarArr[] = {
|
static SysVar SysVarArr[] = {
|
||||||
/* name mod type value min/mal max validate*/
|
/* name mod type value min/mal max */
|
||||||
{"Ago", 1, STR_TYPE, &DynamicAgo, 0, 0, NULL },
|
{"AddBlankLines", 1, INT_TYPE, &AddBlankLines, 0, 1 },
|
||||||
{"Am", 1, STR_TYPE, &DynamicAm, 0, 0, NULL },
|
{"Ago", 1, STR_TYPE, &DynamicAgo, 0, 0 },
|
||||||
{"And", 1, STR_TYPE, &DynamicAnd, 0, 0, NULL },
|
{"Am", 1, STR_TYPE, &DynamicAm, 0, 0 },
|
||||||
{"April", 1, STR_TYPE, &DynamicMonthName[3], 0, 0, NULL },
|
{"And", 1, STR_TYPE, &DynamicAnd, 0, 0 },
|
||||||
{"At", 1, STR_TYPE, &DynamicAt, 0, 0, NULL },
|
{"April", 1, STR_TYPE, &DynamicMonthName[3], 0, 0 },
|
||||||
{"August", 1, STR_TYPE, &DynamicMonthName[7], 0, 0, NULL },
|
{"At", 1, STR_TYPE, &DynamicAt, 0, 0 },
|
||||||
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1, NULL },
|
{"August", 1, STR_TYPE, &DynamicMonthName[7], 0, 0 },
|
||||||
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0, NULL },
|
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
|
||||||
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0, NULL },
|
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
|
||||||
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0, NULL },
|
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||||
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0, NULL },
|
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||||
{"December", 1, STR_TYPE, &DynamicMonthName[11],0, 0, NULL },
|
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
|
||||||
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0, NULL },
|
{"December", 1, STR_TYPE, &DynamicMonthName[11],0, 0 },
|
||||||
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999, NULL },
|
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
|
||||||
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, 1440, NULL },
|
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
|
||||||
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0, NULL },
|
{"DefaultTDelta", 1, INT_TYPE, &DefaultTDelta, 0, 1440 },
|
||||||
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0, NULL },
|
{"DeltaOverride", 0, INT_TYPE, &DeltaOverride, 0, 0 },
|
||||||
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0, NULL },
|
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
|
||||||
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0, NULL },
|
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
|
||||||
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0, NULL },
|
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
|
||||||
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0, NULL },
|
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
|
||||||
{"February", 1, STR_TYPE, &DynamicMonthName[1], 0, 0, NULL },
|
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
|
||||||
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132, NULL },
|
{"February", 1, STR_TYPE, &DynamicMonthName[1], 0, 0 },
|
||||||
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1, NULL },
|
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
|
||||||
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500, NULL },
|
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
|
||||||
{"Friday", 1, STR_TYPE, &DynamicDayName[4], 0, 0, NULL },
|
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 500 },
|
||||||
{"Fromnow", 1, STR_TYPE, &DynamicFromnow, 0, 0, NULL },
|
{"Friday", 1, STR_TYPE, &DynamicDayName[4], 0, 0 },
|
||||||
{"Hour", 1, STR_TYPE, &DynamicHour, 0, 0, NULL },
|
{"Fromnow", 1, STR_TYPE, &DynamicFromnow, 0, 0 },
|
||||||
{"Hplu", 1, STR_TYPE, &DynamicHplu, 0, 0, NULL },
|
{"Hour", 1, STR_TYPE, &DynamicHour, 0, 0 },
|
||||||
{"HushMode", 0, INT_TYPE, &Hush, 0, 0, NULL },
|
{"Hplu", 1, STR_TYPE, &DynamicHplu, 0, 0 },
|
||||||
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0, NULL },
|
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||||
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0, NULL },
|
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
||||||
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0, NULL },
|
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
||||||
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0, NULL },
|
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0 },
|
||||||
{"Is", 1, STR_TYPE, &DynamicIs, 0, 0, NULL },
|
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0 },
|
||||||
{"January", 1, STR_TYPE, &DynamicMonthName[0], 0, 0, NULL },
|
{"Is", 1, STR_TYPE, &DynamicIs, 0, 0 },
|
||||||
{"July", 1, STR_TYPE, &DynamicMonthName[6], 0, 0, NULL },
|
{"January", 1, STR_TYPE, &DynamicMonthName[0], 0, 0 },
|
||||||
{"June", 1, STR_TYPE, &DynamicMonthName[5], 0, 0, NULL },
|
{"July", 1, STR_TYPE, &DynamicMonthName[6], 0, 0 },
|
||||||
{"LatDeg", 1, SPECIAL_TYPE, latdeg_func, 0, 0, NULL },
|
{"June", 1, STR_TYPE, &DynamicMonthName[5], 0, 0 },
|
||||||
{"Latitude", 1, SPECIAL_TYPE, latitude_func, 0, 0, NULL },
|
{"LatDeg", 1, SPECIAL_TYPE, latdeg_func, 0, 0 },
|
||||||
{"LatMin", 1, SPECIAL_TYPE, latmin_func, 0, 0, NULL },
|
{"Latitude", 1, SPECIAL_TYPE, latitude_func, 0, 0 },
|
||||||
{"LatSec", 1, SPECIAL_TYPE, latsec_func, 0, 0, NULL },
|
{"LatMin", 1, SPECIAL_TYPE, latmin_func, 0, 0 },
|
||||||
{"Location", 1, STR_TYPE, &Location, 0, 0, NULL },
|
{"LatSec", 1, SPECIAL_TYPE, latsec_func, 0, 0 },
|
||||||
{"LongDeg", 1, SPECIAL_TYPE, longdeg_func, 0, 0, NULL },
|
{"Location", 1, STR_TYPE, &Location, 0, 0 },
|
||||||
{"Longitude", 1, SPECIAL_TYPE, longitude_func, 0, 0, NULL },
|
{"LongDeg", 1, SPECIAL_TYPE, longdeg_func, 0, 0 },
|
||||||
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0, NULL },
|
{"Longitude", 1, SPECIAL_TYPE, longitude_func, 0, 0 },
|
||||||
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0, NULL },
|
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0 },
|
||||||
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0, NULL },
|
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
|
||||||
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY, NULL },
|
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0 },
|
||||||
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY, NULL },
|
{"MaxFullOmits", 0, CONST_INT_TYPE, NULL, MAX_FULL_OMITS, 0},
|
||||||
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0, NULL },
|
{"MaxLateMinutes", 1, INT_TYPE, &MaxLateMinutes, 0, 1440 },
|
||||||
{"MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -780, 780, NULL },
|
{"MaxPartialOmits",0, CONST_INT_TYPE, NULL, MAX_PARTIAL_OMITS, 0},
|
||||||
{"Minute", 1, STR_TYPE, &DynamicMinute, 0, 0, NULL },
|
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||||
{"Monday", 1, STR_TYPE, &DynamicDayName[0], 0, 0, NULL },
|
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||||
{"Mplu", 1, STR_TYPE, &DynamicMplu, 0, 0, NULL },
|
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0 },
|
||||||
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0, NULL },
|
{"MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -780, 780 },
|
||||||
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0, NULL },
|
{"Minute", 1, STR_TYPE, &DynamicMinute, 0, 0 },
|
||||||
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0, NULL },
|
{"Monday", 1, STR_TYPE, &DynamicDayName[0], 0, 0 },
|
||||||
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0, NULL },
|
{"Mplu", 1, STR_TYPE, &DynamicMplu, 0, 0 },
|
||||||
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0, NULL },
|
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||||
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0, NULL },
|
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0 },
|
||||||
{"On", 1, STR_TYPE, &DynamicOn, 0, 0, NULL },
|
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0 },
|
||||||
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0, NULL },
|
{"NumFullOmits", 0, INT_TYPE, &NumFullOmits, 0, 0 },
|
||||||
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0, NULL },
|
{"NumPartialOmits",0, INT_TYPE, &NumPartialOmits, 0, 0 },
|
||||||
{"PSCal", 0, INT_TYPE, &PsCal, 0, 0, NULL },
|
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||||
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0, NULL },
|
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
||||||
{"Saturday", 1, STR_TYPE, &DynamicDayName[5], 0, 0, NULL },
|
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
|
||||||
{"September", 1, STR_TYPE, &DynamicMonthName[8], 0, 0, NULL },
|
{"On", 1, STR_TYPE, &DynamicOn, 0, 0 },
|
||||||
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0, NULL },
|
{"ParseUntriggered", 1, INT_TYPE, &ParseUntriggered, 0, 1 },
|
||||||
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0, NULL },
|
{"Pm", 1, STR_TYPE, &DynamicPm, 0, 0 },
|
||||||
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0, NULL },
|
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0 },
|
||||||
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0, NULL },
|
{"PSCal", 0, INT_TYPE, &PsCal, 0, 0 },
|
||||||
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132, NULL },
|
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
|
||||||
{"Sunday", 1, STR_TYPE, &DynamicDayName[6], 0, 0, NULL },
|
{"Saturday", 1, STR_TYPE, &DynamicDayName[5], 0, 0 },
|
||||||
{"SuppressLRM", 1, INT_TYPE, &SuppressLRM, 0, 1, NULL },
|
{"September", 1, STR_TYPE, &DynamicMonthName[8], 0, 0 },
|
||||||
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0, NULL },
|
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
|
||||||
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0, NULL },
|
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 },
|
||||||
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0, NULL },
|
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 },
|
||||||
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0, NULL },
|
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0 },
|
||||||
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0, NULL },
|
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132 },
|
||||||
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0, NULL },
|
{"Sunday", 1, STR_TYPE, &DynamicDayName[6], 0, 0 },
|
||||||
{"Today", 1, STR_TYPE, &DynamicToday, 0, 0, NULL },
|
{"SuppressLRM", 1, INT_TYPE, &SuppressLRM, 0, 1 },
|
||||||
{"Tomorrow", 1, STR_TYPE, &DynamicTomorrow, 0, 0, NULL },
|
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0 },
|
||||||
{"Tuesday", 1, STR_TYPE, &DynamicDayName[1], 0, 0, NULL },
|
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
|
||||||
{"Tw", 0, SPECIAL_TYPE, trig_wday_func, 0, 0, NULL },
|
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
|
||||||
{"Ty", 0, SPECIAL_TYPE, trig_year_func, 0, 0, NULL },
|
{"TerminalBackground", 0, SPECIAL_TYPE, terminal_bg_func, 0, 0 },
|
||||||
{"U", 0, SPECIAL_TYPE, today_date_func, 0, 0, NULL },
|
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0 },
|
||||||
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0, NULL },
|
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||||
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0, NULL },
|
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
|
||||||
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0, NULL },
|
{"Today", 1, STR_TYPE, &DynamicToday, 0, 0 },
|
||||||
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0, NULL },
|
{"Tomorrow", 1, STR_TYPE, &DynamicTomorrow, 0, 0 },
|
||||||
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0, NULL },
|
{"Tuesday", 1, STR_TYPE, &DynamicDayName[1], 0, 0 },
|
||||||
{"Was", 1, STR_TYPE, &DynamicWas, 0, 0, NULL },
|
{"Tw", 0, SPECIAL_TYPE, trig_wday_func, 0, 0 },
|
||||||
{"Wednesday", 1, STR_TYPE, &DynamicDayName[2], 0, 0, NULL }
|
{"Ty", 0, SPECIAL_TYPE, trig_year_func, 0, 0 },
|
||||||
|
{"U", 0, SPECIAL_TYPE, today_date_func, 0, 0 },
|
||||||
|
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0 },
|
||||||
|
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0 },
|
||||||
|
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 },
|
||||||
|
{"Use256Colors", 0, INT_TYPE, &Use256Colors, 0, 0 },
|
||||||
|
{"UseBGVTColors", 0, INT_TYPE, &UseBGVTColors, 0, 0 },
|
||||||
|
{"UseTrueColors", 0, INT_TYPE, &UseTrueColors, 0, 0 },
|
||||||
|
{"UseVTColors", 0, INT_TYPE, &UseVTColors, 0, 0 },
|
||||||
|
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0 },
|
||||||
|
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0 },
|
||||||
|
{"Was", 1, STR_TYPE, &DynamicWas, 0, 0 },
|
||||||
|
{"Wednesday", 1, STR_TYPE, &DynamicDayName[2], 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
||||||
@@ -887,29 +919,20 @@ int SetSysVar(char const *name, Value *value)
|
|||||||
int r;
|
int r;
|
||||||
SysVar *v = FindSysVar(name);
|
SysVar *v = FindSysVar(name);
|
||||||
if (!v) return E_NOSUCH_VAR;
|
if (!v) return E_NOSUCH_VAR;
|
||||||
if (v->type != SPECIAL_TYPE &&
|
|
||||||
v->type != value->type) return E_BAD_TYPE;
|
|
||||||
if (!v->modifiable) {
|
if (!v->modifiable) {
|
||||||
Eprint("%s: `$%s'", ErrMsg[E_CANT_MODIFY], name);
|
Eprint("%s: `$%s'", ErrMsg[E_CANT_MODIFY], name);
|
||||||
return E_CANT_MODIFY;
|
return E_CANT_MODIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v->type != SPECIAL_TYPE &&
|
||||||
|
v->type != value->type) return E_BAD_TYPE;
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
r = f(1, value);
|
r = f(1, value);
|
||||||
DestroyValue(*value);
|
DestroyValue(*value);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (v->validate) {
|
|
||||||
if (v->type == STR_TYPE) {
|
|
||||||
r = (v->validate)((void *) value->v.str);
|
|
||||||
} else {
|
|
||||||
r = (v->validate)((void *) &(value->v.val));
|
|
||||||
}
|
|
||||||
if (r != OK) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (v->type == STR_TYPE) {
|
if (v->type == STR_TYPE) {
|
||||||
/* If it's already the same, don't bother doing anything */
|
/* If it's already the same, don't bother doing anything */
|
||||||
if (!strcmp(value->v.str, (char const *) v->value)) {
|
if (!strcmp(value->v.str, (char const *) v->value)) {
|
||||||
@@ -943,6 +966,11 @@ int GetSysVar(char const *name, Value *val)
|
|||||||
|
|
||||||
val->type = ERR_TYPE;
|
val->type = ERR_TYPE;
|
||||||
if (!v) return E_NOSUCH_VAR;
|
if (!v) return E_NOSUCH_VAR;
|
||||||
|
if (v->type == CONST_INT_TYPE) {
|
||||||
|
val->v.val = v->constval;
|
||||||
|
val->type = INT_TYPE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
return f(0, val);
|
return f(0, val);
|
||||||
@@ -1023,6 +1051,7 @@ void DumpSysVarByName(char const *name)
|
|||||||
static void DumpSysVar(char const *name, const SysVar *v)
|
static void DumpSysVar(char const *name, const SysVar *v)
|
||||||
{
|
{
|
||||||
char buffer[VAR_NAME_LEN+10];
|
char buffer[VAR_NAME_LEN+10];
|
||||||
|
Value vtmp;
|
||||||
|
|
||||||
if (name && !*name) name=NULL;
|
if (name && !*name) name=NULL;
|
||||||
if (!v && !name) return; /* Shouldn't happen... */
|
if (!v && !name) return; /* Shouldn't happen... */
|
||||||
@@ -1035,33 +1064,23 @@ static void DumpSysVar(char const *name, const SysVar *v)
|
|||||||
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
||||||
fprintf(ErrFp, "%16s ", buffer);
|
fprintf(ErrFp, "%16s ", buffer);
|
||||||
if (v) {
|
if (v) {
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == CONST_INT_TYPE) {
|
||||||
Value val;
|
fprintf(ErrFp, "%d\n", v->constval);
|
||||||
|
} else if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
f(0, &val);
|
f(0, &vtmp);
|
||||||
PrintValue(&val, ErrFp);
|
PrintValue(&vtmp, ErrFp);
|
||||||
putc('\n', ErrFp);
|
putc('\n', ErrFp);
|
||||||
DestroyValue(val);
|
DestroyValue(vtmp);
|
||||||
} else if (v->type == STR_TYPE) {
|
} else if (v->type == STR_TYPE) {
|
||||||
char const *s = *((char **)v->value);
|
vtmp.type = STR_TYPE;
|
||||||
int y;
|
vtmp.v.str = * ((char **)v->value);
|
||||||
putc('"', ErrFp);
|
PrintValue(&vtmp, ErrFp);
|
||||||
for (y=0; y<MAX_PRT_LEN && *s; y++) {
|
|
||||||
if (*s == '"') {
|
|
||||||
fprintf(ErrFp, "\" + char(34) + \"");
|
|
||||||
s++;
|
|
||||||
} else {
|
|
||||||
putc(*s++, ErrFp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putc('"', ErrFp);
|
|
||||||
if (*s) fprintf(ErrFp, "...");
|
|
||||||
putc('\n', ErrFp);
|
putc('\n', ErrFp);
|
||||||
} else if (v->type == DATE_TYPE) {
|
} else if (v->type == DATE_TYPE) {
|
||||||
Value val;
|
vtmp.type = DATE_TYPE;
|
||||||
val.type = DATE_TYPE;
|
vtmp.v.val = * (int *) v->value;
|
||||||
val.v.val = * (int *) v->value;
|
PrintValue(&vtmp, ErrFp);
|
||||||
PrintValue(&val, ErrFp);
|
|
||||||
putc('\n', ErrFp);
|
putc('\n', ErrFp);
|
||||||
} else {
|
} else {
|
||||||
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));
|
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));
|
||||||
|
|||||||
49
tests/ansicolors.rem
Normal file
49
tests/ansicolors.rem
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
BANNER %
|
||||||
|
MSG TerminalBackground is: [$TerminalBackground]%
|
||||||
|
MSG UseVTColors is: [$UseVTColors]%
|
||||||
|
MSG Use256Colors is: [$Use256Colors]%
|
||||||
|
MSG UseTrueColors is: [$UseTrueColors]%
|
||||||
|
MSG UseBGVTColors is: [$UseBGVTColors]%
|
||||||
|
set n ansicolor("")
|
||||||
|
MSG This is [ansicolor(0,255,0)]green[n], [ansicolor("255 0 0")]red[n] and [ansicolor("0 0 255")]blue[n] text.%
|
||||||
|
MSG This is [ansicolor(0,0,0)][ansicolor(0,255,0,1)]black text on a green background[n]%
|
||||||
|
MSG This is [ansicolor(0,0,0,0,1)]clamped black text[n]%
|
||||||
|
MSG This is [ansicolor(255,255,255,0,1)]clamped white text[n]
|
||||||
|
|
||||||
|
FLUSH
|
||||||
|
|
||||||
|
# Test that MSF ignores ansi color sequences
|
||||||
|
set r ansicolor(255, 0, 0)
|
||||||
|
set g ansicolor(0, 255, 0)
|
||||||
|
set b ansicolor(0, 0, 255)
|
||||||
|
set n ansicolor("")
|
||||||
|
|
||||||
|
|
||||||
|
REM MSF Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.%_Here we have a formatted reminder. It should be word-wrapped nicely and neatly by Remind. Although it is very long and unwieldy, the MSF keyword will wrap it so it's pleasantly readable.
|
||||||
|
|
||||||
|
# Should have exactly the same word breaks
|
||||||
|
REM MSF [r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]%_[r]Here [g]we [b]have [r]a [g]formatted [b]reminder. [r]It [g]should[b] be [r]word-wrapped[g] nicely [b]and [r]neatly [g]by Remind. [b]Although [r]it [g]is [b]very [r]long [g]and [b]u[r]n[g]w[b]i[r]e[g]l[b]d[r]y[g], [r]the [g]MSF [b]keyword [r]will [r] [g] [b] [g]wrap [b]it [r]so [g]it's [b]pleasantly [r]readable.[n]
|
||||||
|
|
||||||
|
REM MSF Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_Εδώ έχουμε μια μορφοποιημένη υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
|
||||||
|
|
||||||
|
REM MSF [r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅%_[r]Εδώ [g]έχουμε [b]μια [r]μ[g]ο[b]ρ[r]φοποιημένη[n] υπενθύμιση. Θα πρέπει να είναι τυλιγμένο με λέξεις όμορφα και τακτοποιημένα από το Remind. Αν και είναι πολύ μακρύ και δυσκίνητο, η λέξη-κλειδί των ΓΧΣ θα το τυλίξει έτσι ώστε να είναι ευχάριστα ευανάγνωστο. 🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅🌅 🌅 🌅 🌅 🌅
|
||||||
|
FLUSH
|
||||||
|
|
||||||
|
# Some invalid combos
|
||||||
|
set a ansicolor(1)
|
||||||
|
set a ansicolor(-1, 0, 0)
|
||||||
|
set a ansicolor(42, 42, 256)
|
||||||
|
set a ansicolor("foo")
|
||||||
|
set a ansicolor("1 1")
|
||||||
|
set a ansicolor("-1 -1 0");
|
||||||
|
set a ansicolor("256 1 1");
|
||||||
|
set a ansicolor(128, 128, 128, 2)
|
||||||
|
set a ansicolor(128, 128, 128, -1)
|
||||||
|
set a ansicolor(128, 128, 128, 0, 2)
|
||||||
|
set a ansicolor(128, 128, 128, 0, -1)
|
||||||
|
|
||||||
|
set a ansicolor(128,0,0)
|
||||||
|
|
||||||
|
set str a + "foo: 🌅"
|
||||||
|
set w columns(str)
|
||||||
|
MSG Width of [str] is: [w]
|
||||||
5
tests/blanks.rem
Normal file
5
tests/blanks.rem
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
MSG $AddBlankLines=[$AddBlankLines]%_
|
||||||
|
MSG Hello
|
||||||
|
MSG Hi
|
||||||
|
MSF How are you?
|
||||||
|
MSG OK
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user