mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 22:38:37 +02:00
Compare commits
400 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7ab9b8bf8 | ||
|
|
4448271166 | ||
|
|
4861b535a2 | ||
|
|
167f0100c7 | ||
|
|
b0367c7a5c | ||
|
|
4ae8ad52f5 | ||
|
|
dbd64828ab | ||
|
|
158ca882ba | ||
|
|
623ed44608 | ||
|
|
f13b867626 | ||
|
|
ff85325886 | ||
|
|
aa830116ea | ||
|
|
1a4504ba28 | ||
|
|
20365c4627 | ||
|
|
fae8f89ed6 | ||
|
|
a0689999fe | ||
|
|
a42a0ab032 | ||
|
|
b66eb5d3ec | ||
|
|
8b4bc0f56e | ||
|
|
c9d984983f | ||
|
|
47125b051a | ||
|
|
e5e6ff6031 | ||
|
|
9f0aedb608 | ||
|
|
08af33ece5 | ||
|
|
9b421d0b94 | ||
|
|
7bd8d2dd25 | ||
|
|
a7c4879a0a | ||
|
|
8b3585a6b8 | ||
|
|
a223149aee | ||
|
|
9185341b0c | ||
|
|
bf2d707e13 | ||
|
|
f081e5c54d | ||
|
|
18a3db0f31 | ||
|
|
d2c115127d | ||
|
|
c12e7e1b8f | ||
|
|
d3495ab3aa | ||
|
|
b93a7a6195 | ||
|
|
e5519a8498 | ||
|
|
eb2256f873 | ||
|
|
637b137b1c | ||
|
|
e2d14e73bf | ||
|
|
fbbffb4672 | ||
|
|
422e098727 | ||
|
|
87347e30b2 | ||
|
|
3314ce9823 | ||
|
|
402c1fe614 | ||
|
|
1d57856aa8 | ||
|
|
c027c215d6 | ||
|
|
fa0428b9fe | ||
|
|
b01c499ce5 | ||
|
|
4e5033dd24 | ||
|
|
00863f3830 | ||
|
|
2d4b35e8b9 | ||
|
|
6e4f2b9466 | ||
|
|
9a6fc0253b | ||
|
|
3180c781ed | ||
|
|
632152e8b6 | ||
|
|
1048f7e98d | ||
|
|
3de265216e | ||
|
|
2bdcadc7ab | ||
|
|
421ddfc68e | ||
|
|
41594bc1ac | ||
|
|
e85199d464 | ||
|
|
a6ee3bc704 | ||
|
|
2909106f30 | ||
|
|
05b97aabb2 | ||
|
|
84af60d817 | ||
|
|
72403a2512 | ||
|
|
4ec619d646 | ||
|
|
6178a627a0 | ||
|
|
3095fd7e4a | ||
|
|
74a6041760 | ||
|
|
96127e37ff | ||
|
|
df5484ea35 | ||
|
|
0ae3dae030 | ||
|
|
e5979139ac | ||
|
|
f81f6deb20 | ||
|
|
f9951909d8 | ||
|
|
bbda972b05 | ||
|
|
4445e9c434 | ||
|
|
709adacac2 | ||
|
|
9841cdd355 | ||
|
|
4cabe5fd71 | ||
|
|
0db239f8a0 | ||
|
|
32fb1706c8 | ||
|
|
c9e6cd9796 | ||
|
|
81677528a5 | ||
|
|
7761baba10 | ||
|
|
52d252723f | ||
|
|
d476709b59 | ||
|
|
0910e3da74 | ||
|
|
2cc7b7c817 | ||
|
|
011a95ebbd | ||
|
|
bbdc086a1f | ||
|
|
7d6617d21e | ||
|
|
f684baeeb9 | ||
|
|
308104853b | ||
|
|
6953bcac35 | ||
|
|
69e9fa4721 | ||
|
|
72d154c5e0 | ||
|
|
84b0a96170 | ||
|
|
6d3b8f7a09 | ||
|
|
81749ac1c9 | ||
|
|
65989c29b7 | ||
|
|
ec4e58f25c | ||
|
|
0c699c2a19 | ||
|
|
739a938d32 | ||
|
|
61ad405b4a | ||
|
|
700e649e76 | ||
|
|
7bfdb1f0eb | ||
|
|
0c0280b2a9 | ||
|
|
57a1871077 | ||
|
|
ee972ad29f | ||
|
|
29c8475ea9 | ||
|
|
6dd0f6ed63 | ||
|
|
fc2d7ae446 | ||
|
|
d232ac0334 | ||
|
|
6e8dd68c8a | ||
|
|
495cc1b38d | ||
|
|
d90e74b1a3 | ||
|
|
bbd8a4b729 | ||
|
|
cae3e18717 | ||
|
|
0e989a7422 | ||
|
|
7b7ce5bb57 | ||
|
|
df95cdaad0 | ||
|
|
3026b6e5c2 | ||
|
|
b3306c5572 | ||
|
|
9ef3be33e5 | ||
|
|
292262c128 | ||
|
|
e54bfe9197 | ||
|
|
c56cfe9e1d | ||
|
|
f6b6a3285c | ||
|
|
6b031b0fdf | ||
|
|
2dab7025ba | ||
|
|
7403114897 | ||
|
|
82cbeec560 | ||
|
|
df6b4ac566 | ||
|
|
4ba21ab526 | ||
|
|
acac7a7b31 | ||
|
|
2290fd09f5 | ||
|
|
f02b6a1773 | ||
|
|
efffe05d42 | ||
|
|
950d67c522 | ||
|
|
a1aa61f54e | ||
|
|
3c2bd66460 | ||
|
|
245cebee56 | ||
|
|
c45364fdb3 | ||
|
|
e380308604 | ||
|
|
bd019524dd | ||
|
|
895536d7d3 | ||
|
|
3a0e41afd1 | ||
|
|
23dd28471e | ||
|
|
761217d403 | ||
|
|
77ed694111 | ||
|
|
61bcce3104 | ||
|
|
bf41b12ccd | ||
|
|
5eabd7d8d8 | ||
|
|
0c66f5f3af | ||
|
|
3190f784d9 | ||
|
|
394ff55879 | ||
|
|
9b846835bc | ||
|
|
01776af167 | ||
|
|
0db10424ad | ||
|
|
bafd7ea073 | ||
|
|
0ab27fcb4b | ||
|
|
95d016712e | ||
|
|
fcb55001bb | ||
|
|
7bc6961101 | ||
|
|
450e88fad8 | ||
|
|
3222b4c311 | ||
|
|
1e0cc3605d | ||
|
|
129b7bfeb7 | ||
|
|
388811b684 | ||
|
|
f83257407b | ||
|
|
e4ced77340 | ||
|
|
92e0bc316a | ||
|
|
a4a55f35b2 | ||
|
|
ed1150c189 | ||
|
|
08080f4e86 | ||
|
|
de4ebb8be6 | ||
|
|
11e2ce5093 | ||
|
|
2c560e6f2b | ||
|
|
643f394e6a | ||
|
|
6d047c2856 | ||
|
|
be86746685 | ||
|
|
da429b9629 | ||
|
|
b21a206c26 | ||
|
|
85bde8ba3a | ||
|
|
f84e658e6b | ||
|
|
8f0eba8bcd | ||
|
|
2faaaf78a8 | ||
|
|
7f659dace2 | ||
|
|
54cdd566c7 | ||
|
|
e212df87f9 | ||
|
|
4fb4db15e8 | ||
|
|
9a15a25a7b | ||
|
|
c02cfb9b17 | ||
|
|
3e726f21f7 | ||
|
|
21d4faa26f | ||
|
|
1d13d0ee07 | ||
|
|
329d13e480 | ||
|
|
2161c09b1d | ||
|
|
3f2e396c3c | ||
|
|
412e242109 | ||
|
|
e827516b72 | ||
|
|
7f953e98d7 | ||
|
|
821d3fe783 | ||
|
|
fdb4b302ac | ||
|
|
760d5d4a09 | ||
|
|
d561f98c42 | ||
|
|
ea74f276dc | ||
|
|
42cf82a5d5 | ||
|
|
825a6700da | ||
|
|
2f27645dac | ||
|
|
1e5b44d063 | ||
|
|
099ad9945d | ||
|
|
540ce3d946 | ||
|
|
ac2efcc993 | ||
|
|
b4bb1d9e37 | ||
|
|
9ec8b30934 | ||
|
|
fb38e5b35b | ||
|
|
5fa10e9d84 | ||
|
|
3bc1b5bd46 | ||
|
|
b266b399ba | ||
|
|
0e827a457d | ||
|
|
d05d85b243 | ||
|
|
a1faa8d804 | ||
|
|
70adbf90c2 | ||
|
|
501c04f4b6 | ||
|
|
d294e62be1 | ||
|
|
31f90b6c53 | ||
|
|
184d29c592 | ||
|
|
2d798bc4ec | ||
|
|
bd9a3761a6 | ||
|
|
b1063b0a9e | ||
|
|
cb2fffab92 | ||
|
|
55cca49428 | ||
|
|
5a0ab9ed8a | ||
|
|
1f2cfdfd84 | ||
|
|
dfd688caa6 | ||
|
|
830e3e339c | ||
|
|
bc9f560950 | ||
|
|
f91b748f50 | ||
|
|
3adbd7468c | ||
|
|
b66039ee24 | ||
|
|
27371f6475 | ||
|
|
19e7c34b47 | ||
|
|
3375aff3a7 | ||
|
|
41e9cb5ca3 | ||
|
|
6348860adf | ||
|
|
4e9d401002 | ||
|
|
3db2fc7d0f | ||
|
|
0101d76113 | ||
|
|
6fabab6d4b | ||
|
|
905f1b0aaf | ||
|
|
6a5ab8e70c | ||
|
|
943b037589 | ||
|
|
5624cd44de | ||
|
|
8529f8b843 | ||
|
|
08be7c43cf | ||
|
|
aae76207ec | ||
|
|
5434f8330e | ||
|
|
e18b4ed119 | ||
|
|
51f6ffc093 | ||
|
|
72de7c6b14 | ||
|
|
bd4785d631 | ||
|
|
cb08f12470 | ||
|
|
04146db69b | ||
|
|
d3fe045a39 | ||
|
|
2be1e16087 | ||
|
|
051e44ae3e | ||
|
|
6d5ae7a258 | ||
|
|
2e69e140eb | ||
|
|
516c4e2c39 | ||
|
|
b58ed62000 | ||
|
|
c685818783 | ||
|
|
3e20ce56c9 | ||
|
|
dd8d67f659 | ||
|
|
5ef4061819 | ||
|
|
a146a0c819 | ||
|
|
0f5a93cdf1 | ||
|
|
7db51e913e | ||
|
|
93ac1aebf7 | ||
|
|
56ebedb9de | ||
|
|
e87d33de50 | ||
|
|
a5774fd793 | ||
|
|
adb60f3400 | ||
|
|
47a0f63caa | ||
|
|
30a385a7bb | ||
|
|
9f2ae1773c | ||
|
|
f470297958 | ||
|
|
93dfc7995c | ||
|
|
c96869817f | ||
|
|
1bffa0e00b | ||
|
|
36035dda01 | ||
|
|
50a15cf089 | ||
|
|
b59d4ed4a4 | ||
|
|
4c53710279 | ||
|
|
2274e88485 | ||
|
|
984a4677f2 | ||
|
|
5e3dc54725 | ||
|
|
53a7bf9773 | ||
|
|
1dcc3897d6 | ||
|
|
fbc0375739 | ||
|
|
4a74c03fa4 | ||
|
|
d8833e6ce2 | ||
|
|
2b8b9a56aa | ||
|
|
85a8ebb357 | ||
|
|
a67d9e2524 | ||
|
|
6845e72fd5 | ||
|
|
0ab977fa05 | ||
|
|
ad64a12b2a | ||
|
|
cfde4b50bb | ||
|
|
f302c8eb95 | ||
|
|
7ecc355358 | ||
|
|
a52216d7e7 | ||
|
|
8d8d4b667d | ||
|
|
670369121e | ||
|
|
4365e580ee | ||
|
|
a8a09a905e | ||
|
|
dbb7381eb1 | ||
|
|
aa3531a6bf | ||
|
|
2848203d75 | ||
|
|
f0aef0703c | ||
|
|
7356a511e0 | ||
|
|
5be26a3cff | ||
|
|
36a80acb0c | ||
|
|
37ab03b49d | ||
|
|
75209cb40e | ||
|
|
4b2d274748 | ||
|
|
1423495b88 | ||
|
|
42e4ec8890 | ||
|
|
58fbd51ef4 | ||
|
|
7552dbb812 | ||
|
|
31e0ecb71d | ||
|
|
f6743a4f87 | ||
|
|
5f574949e6 | ||
|
|
724bce4fb9 | ||
|
|
8d59f025af | ||
|
|
aad44f4716 | ||
|
|
0a38d7d213 | ||
|
|
4fcd60fd95 | ||
|
|
38beeb8cb0 | ||
|
|
26f0acab35 | ||
|
|
3897973bc1 | ||
|
|
7b3da27461 | ||
|
|
a85ee5f31c | ||
|
|
b272863aa0 | ||
|
|
8249964380 | ||
|
|
af81bbb299 | ||
|
|
d818dd9c80 | ||
|
|
fe8e34dece | ||
|
|
ba928989f7 | ||
|
|
742f973028 | ||
|
|
043932fcbe | ||
|
|
ad5e096caa | ||
|
|
06c8fc8f78 | ||
|
|
487338d10c | ||
|
|
3d1c0e5667 | ||
|
|
ce3bb191c4 | ||
|
|
03e9dbf364 | ||
|
|
518aab3d02 | ||
|
|
f055664f77 | ||
|
|
ba3e01f2ce | ||
|
|
b6883c8a45 | ||
|
|
9e49ee3acb | ||
|
|
7481f68bb2 | ||
|
|
99792eec03 | ||
|
|
91458c7845 | ||
|
|
cad5849dc0 | ||
|
|
a38e120e99 | ||
|
|
0b31a78cf2 | ||
|
|
861858c1a6 | ||
|
|
d43a2277da | ||
|
|
f678dc96b8 | ||
|
|
c2e371904e | ||
|
|
2a1cbff22e | ||
|
|
a2d9f277c4 | ||
|
|
d939059417 | ||
|
|
740cd4cfed | ||
|
|
91a5306a67 | ||
|
|
b78ffcbffd | ||
|
|
4f72f557b7 | ||
|
|
e3b21d6d0d | ||
|
|
af28c49d8d | ||
|
|
67f4635573 | ||
|
|
5f8d10908d | ||
|
|
7307421812 | ||
|
|
5cd3b628c5 | ||
|
|
29e483ab64 | ||
|
|
66ddba45af | ||
|
|
9325b3f035 | ||
|
|
522c4c94e1 | ||
|
|
730505cff3 | ||
|
|
019783e1fa | ||
|
|
8612bb6480 | ||
|
|
7f1e6d21d9 | ||
|
|
e6c0371be1 | ||
|
|
58feaa7e0c | ||
|
|
a828378466 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.gitignore export-ignore
|
||||
.gitattributes export-ignore
|
||||
remind.php export-ignore
|
||||
sync-to-dianne-git export-ignore
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,7 @@ autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
src/Makefile
|
||||
www/Makefile
|
||||
*.o
|
||||
src/config.h
|
||||
src/remind
|
||||
@@ -11,3 +12,5 @@ tests/test.out
|
||||
.gitignore
|
||||
*~
|
||||
src/rem2ps
|
||||
src/version.h
|
||||
TAGS
|
||||
|
||||
10
COPYRIGHT
10
COPYRIGHT
@@ -3,8 +3,8 @@ THE REMIND COPYRIGHT
|
||||
1. REMIND refers to the entire set of files and documentation in the
|
||||
REMIND package.
|
||||
|
||||
2. REMIND is Copyright 1999-2005 Roaring Penguin Software Inc.,
|
||||
except where noted in individual files.
|
||||
2. REMIND is Copyright 1992-2018 Dianne Skoll, except where noted in
|
||||
individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
|
||||
@@ -293,8 +293,8 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
--
|
||||
David F. Skoll <dfs@roaringpenguin.com>
|
||||
Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
https://dianne.skoll.ca/projects/remind
|
||||
|
||||
Tel. (613) 231-6599
|
||||
http://www.roaringpenguin.com
|
||||
|
||||
|
||||
30
MICROSOFT-AND-APPLE
Normal file
30
MICROSOFT-AND-APPLE
Normal file
@@ -0,0 +1,30 @@
|
||||
MICROSOFT WINDOWS
|
||||
=================
|
||||
|
||||
I used to prohibit porting Remind to Microsoft Windows. However, this
|
||||
may cause problems with the GPL, so I have removed that restriction.
|
||||
|
||||
Although I cannot prevent you from porting Remind to Windows, I appeal
|
||||
to you not to do it. I am trying to encourage the growth of free
|
||||
software, not proprietary software.
|
||||
|
||||
If you port Remind to Windows, I will not provide support or answers to
|
||||
questions -- you're on your own. On the other hand, I will feel no guilt
|
||||
in taking enhancements and merging them into the UNIX stream.
|
||||
|
||||
APPLE
|
||||
=====
|
||||
|
||||
I can't prevent you from using Remind on Apple's products, but I hope
|
||||
you don't. Apple's corporate culture is the very antithesis of Free
|
||||
Software. Rather than using Mac OS X, I encourage you to switch to
|
||||
Linux or FreeBSD, two Free Software operating systems that are every
|
||||
bit as capable as Mac OS X and which are unencumbered by Apple's
|
||||
arbitrary restrictions.
|
||||
|
||||
And if you're looking to port Remind to other Apple products like the
|
||||
iPhone or iPad, please don't. Those products enforce Apple's rigorous
|
||||
controls much more stringently than Mac OS X on an Apple PC.
|
||||
|
||||
--
|
||||
Dianne Skoll
|
||||
10
Makefile
10
Makefile
@@ -8,7 +8,7 @@ all: src/Makefile
|
||||
@echo "* *"
|
||||
@echo "*******************"
|
||||
@echo ""
|
||||
@cd src; $(MAKE) all LANGDEF=$(LANGDEF)
|
||||
@cd src && $(MAKE) all LANGDEF=$(LANGDEF)
|
||||
|
||||
install:
|
||||
@echo ""
|
||||
@@ -18,17 +18,17 @@ install:
|
||||
@echo "* *"
|
||||
@echo "*********************"
|
||||
@echo ""
|
||||
cd src; $(MAKE) install
|
||||
@cd src && $(MAKE) install
|
||||
|
||||
clean:
|
||||
find . -name '*~' -exec rm {} \;
|
||||
cd src; $(MAKE) clean
|
||||
cd src && $(MAKE) clean
|
||||
|
||||
test:
|
||||
cd src && $(MAKE) test
|
||||
@cd src && $(MAKE) -s test
|
||||
|
||||
distclean: clean
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile
|
||||
|
||||
src/Makefile: src/Makefile.in
|
||||
./configure
|
||||
|
||||
4
README
4
README
@@ -34,5 +34,5 @@ If you do NOT have Tcl/Tk or are NOT running X Windows:
|
||||
|
||||
5) Type: "make install" -- you may need to be root to do this.
|
||||
|
||||
Contact info: mailto:dfs@roaringpenguin.com
|
||||
Home page: http://www.roaringpenguin.com/remind
|
||||
Contact info: mailto:dianne@skoll.ca
|
||||
Home page: https://dianne.skoll.ca/projects/remind/
|
||||
|
||||
15
WINDOWS
15
WINDOWS
@@ -1,15 +0,0 @@
|
||||
MICROSOFT WINDOWS
|
||||
|
||||
I used to prohibit porting Remind to Microsoft Windows. However, this
|
||||
may cause problems with the GPL, so I have removed that restriction.
|
||||
|
||||
Although I cannot prevent you from porting Remind to Windows, I appeal
|
||||
to you not to do it. I am trying to encourage the growth of free
|
||||
software, not proprietary software.
|
||||
|
||||
If you port Remind to Windows, I will not provide support or answers to
|
||||
questions -- you're on your own. On the other hand, I will feel no guilt
|
||||
in taking enhancements and merging them into the UNIX stream.
|
||||
|
||||
--
|
||||
David F. Skoll.
|
||||
126
build.tk
Executable file → Normal file
126
build.tk
Executable file → Normal file
@@ -7,8 +7,7 @@
|
||||
# A cheesy graphical front-end for building and installing REMIND.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1999 David F. Skoll
|
||||
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1992-2018 Dianne Skoll
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
@@ -95,10 +94,6 @@ proc CreateMainDialog {} {
|
||||
wm title . "Remind Configuration"
|
||||
wm iconname . "Remind Config"
|
||||
|
||||
doLogo
|
||||
destroy .c
|
||||
update idletasks
|
||||
|
||||
SetConfigFromRemind
|
||||
tabnotebook_create .tn
|
||||
|
||||
@@ -757,125 +752,6 @@ proc notebook_fix_size {win} {
|
||||
$win configure -width $maxw -height $maxh
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: drawLogo
|
||||
# %ARGUMENTS:
|
||||
# c -- canvas to draw logo in
|
||||
# bg -- background color of canvas
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Draws Roaring Penguin logo in a Tcl canvas
|
||||
#***********************************************************************
|
||||
proc drawLogo { c bg } {
|
||||
set logo_objs {
|
||||
{polygon 558 0 557 0 556 0 554 0 551 0 550 0 549 0 547 0 546 0 544 0 542 1 539 1 537 2 535 3 534 3 533 3 532 3 530 4 528 5 525 6 523 6 522 7 521 7 519 8 516 9 514 10 512 11 510 11 509 12 507 12 507 13 506 13 505 12 502 12 500 11 498 11 497 11 496 11 495 11 493 11 491 12 489 12 488 12 488 13 487 13 485 14 483 15 482 16 481 17 480 19 478 21 477 22 476 23 476 24 475 25 474 26 473 28 472 30 470 33 467 37 464 41 462 45 459 48 457 52 456 54 455 55 454 56 454 57 453 58 452 59 452 61 451 63 449 65 448 68 447 71 445 74 443 77 442 81 440 86 438 90 436 95 435 99 434 103 433 105 433 106 432 107 432 108 432 109 431 111 431 113 430 116 429 121 428 125 427 130 425 135 425 138 424 140 424 142 424 143 424 144 424 145 423 147 423 149 423 152 422 157 421 162 421 167 420 172 420 176 419 180 419 183 419 187 419 189 419 192 418 195 418 196 418 198 418 199 417 199 416 199 415 199 414 199 413 200 412 200 411 200 411 201 410 201 410 202 409 202 409 203 408 203 407 204 407 205 408 205 410 206 413 208 416 209 418 210 419 210 419 211 420 211 421 211 422 212 424 212 426 212 429 213 432 213 435 214 439 214 442 214 444 214 445 214 446 214 447 214 449 214 452 214 457 214 461 214 464 214 466 214 467 214 468 214 469 214 470 214 472 214 474 214 477 213 482 213 486 213 490 212 494 212 497 212 500 211 502 211 505 211 507 211 508 210 509 210 510 210 510 208 511 206 512 203 513 198 514 194 515 189 516 185 517 182 517 179 518 178 518 177 518 176 518 175 519 174 519 171 520 169 520 166 521 163 522 160 522 157 523 153 524 149 524 144 525 139 526 135 526 132 526 130 526 129 526 128 526 127 527 127 527 126 527 124 527 122 527 119 527 115 527 110 527 106 527 102 527 99 527 96 527 95 527 94 527 93 527 92 527 91 527 88 527 85 526 81 526 77 525 72 524 67 524 64 523 60 522 57 521 54 521 51 520 49 520 47 519 45 519 44 518 43 520 42 521 42 523 41 524 40 525 40 526 40 527 40 528 39 530 39 532 39 533 38 534 38 536 38 538 37 539 37 540 37 541 36 543 35 544 34 545 33 546 32 545 32 543 33 542 33 541 34 540 34 539 34 537 34 536 34 534 34 532 34 531 34 530 34 529 34 527 33 525 33 524 33 523 33 522 33 520 32 518 32 517 32 515 31 514 31 514 30 516 29 517 27 519 25 520 24 521 23 521 22 522 22 523 21 524 20 526 19 528 17 530 15 533 14 534 13 535 12 536 12 537 11 538 10 541 9 543 7 545 6 546 6 546 5 547 5 549 4 551 3 553 2 555 1 556 0 557 0 -outline {} -fill \#000000 -width 0}
|
||||
{line 558 0 557 0 556 0 554 0 551 0 550 0 549 0 547 0 546 0 544 0 542 1 539 1 537 2 535 3 534 3 533 3 532 3 530 4 528 5 525 6 523 6 522 7 521 7 519 8 516 9 514 10 512 11 510 11 509 12 507 12 507 13 506 13 505 12 502 12 500 11 498 11 497 11 496 11 495 11 493 11 491 12 489 12 488 12 488 13 487 13 485 14 483 15 482 16 481 17 480 19 478 21 477 22 476 23 476 24 475 25 474 26 473 28 472 30 470 33 467 37 464 41 462 45 459 48 457 52 456 54 455 55 454 56 454 57 453 58 452 59 452 61 451 63 449 65 448 68 447 71 445 74 443 77 442 81 440 86 438 90 436 95 435 99 434 103 433 105 433 106 432 107 432 108 432 109 431 111 431 113 430 116 429 121 428 125 427 130 425 135 425 138 424 140 424 142 424 143 424 144 424 145 423 147 423 149 423 152 422 157 421 162 421 167 420 172 420 176 419 180 419 183 419 187 419 189 419 192 418 195 418 196 418 198 418 199 417 199 416 199 415 199 414 199 413 200 412 200 411 200 411 201 410 201 410 202 409 202 409 203 408 203 407 204 407 205 408 205 410 206 413 208 416 209 418 210 419 210 419 211 420 211 421 211 422 212 424 212 426 212 429 213 432 213 435 214 439 214 442 214 444 214 445 214 446 214 447 214 449 214 452 214 457 214 461 214 464 214 466 214 467 214 468 214 469 214 470 214 472 214 474 214 477 213 482 213 486 213 490 212 494 212 497 212 500 211 502 211 505 211 507 211 508 210 509 210 510 210 510 208 511 206 512 203 513 198 514 194 515 189 516 185 517 182 517 179 518 178 518 177 518 176 518 175 519 174 519 171 520 169 520 166 521 163 522 160 522 157 523 153 524 149 524 144 525 139 526 135 526 132 526 130 526 129 526 128 526 127 527 127 527 126 527 124 527 122 527 119 527 115 527 110 527 106 527 102 527 99 527 96 527 95 527 94 527 93 527 92 527 91 527 88 527 85 526 81 526 77 525 72 524 67 524 64 523 60 522 57 521 54 521 51 520 49 520 47 519 45 519 44 518 43 520 42 521 42 523 41 524 40 525 40 526 40 527 40 528 39 530 39 532 39 533 38 534 38 536 38 538 37 539 37 540 37 541 36 543 35 544 34 545 33 546 32 545 32 543 33 542 33 541 34 540 34 539 34 537 34 536 34 534 34 532 34 531 34 530 34 529 34 527 33 525 33 524 33 523 33 522 33 520 32 518 32 517 32 515 31 514 31 514 30 516 29 517 27 519 25 520 24 521 23 521 22 522 22 523 21 524 20 526 19 528 17 530 15 533 14 534 13 535 12 536 12 537 11 538 10 541 9 543 7 545 6 546 6 546 5 547 5 549 4 551 3 553 2 555 1 556 0 557 0 558 0 -joinstyle bevel}
|
||||
{polygon 490 94 490 95 490 96 489 99 489 103 489 106 488 109 488 111 488 112 488 113 488 115 487 117 487 119 487 121 486 123 485 126 485 130 484 133 483 136 483 137 483 138 483 139 482 139 482 140 482 141 481 144 480 147 479 150 478 153 477 154 477 155 477 156 476 157 476 159 475 161 473 164 472 167 471 170 470 172 468 175 467 176 467 178 466 179 466 180 465 180 465 179 464 177 463 174 462 171 461 169 461 168 461 167 460 166 460 165 460 163 459 161 458 158 458 155 457 152 457 151 457 150 457 149 457 148 456 146 456 143 456 141 456 139 456 138 456 137 456 136 456 134 456 132 456 129 457 126 457 124 457 123 457 121 458 121 458 120 458 121 458 123 458 125 458 127 457 129 457 130 457 131 457 132 458 134 458 136 458 139 458 141 458 143 458 144 459 145 459 148 460 150 460 151 460 152 460 153 461 154 461 155 462 158 462 160 463 162 464 164 464 166 465 167 465 168 465 169 466 169 466 168 467 166 468 163 470 160 470 158 471 157 471 156 472 155 472 154 473 152 474 150 475 147 476 144 477 141 478 139 478 138 479 137 479 136 480 134 480 132 481 129 482 126 483 124 483 122 483 121 484 121 484 120 484 118 485 116 486 112 487 109 487 106 488 103 488 101 489 99 489 97 490 95 490 94 -outline {} -fill $bg -width 0}
|
||||
{line 490 94 490 95 490 96 489 99 489 103 489 106 488 109 488 111 488 112 488 113 488 115 487 117 487 119 487 121 486 123 485 126 485 130 484 133 483 136 483 137 483 138 483 139 482 139 482 140 482 141 481 144 480 147 479 150 478 153 477 154 477 155 477 156 476 157 476 159 475 161 473 164 472 167 471 170 470 172 468 175 467 176 467 178 466 179 466 180 465 180 465 179 464 177 463 174 462 171 461 169 461 168 461 167 460 166 460 165 460 163 459 161 458 158 458 155 457 152 457 151 457 150 457 149 457 148 456 146 456 143 456 141 456 139 456 138 456 137 456 136 456 134 456 132 456 129 457 126 457 124 457 123 457 121 458 121 458 120 458 121 458 123 458 125 458 127 457 129 457 130 457 131 457 132 458 134 458 136 458 139 458 141 458 143 458 144 459 145 459 148 460 150 460 151 460 152 460 153 461 154 461 155 462 158 462 160 463 162 464 164 464 166 465 167 465 168 465 169 466 169 466 168 467 166 468 163 470 160 470 158 471 157 471 156 472 155 472 154 473 152 474 150 475 147 476 144 477 141 478 139 478 138 479 137 479 136 480 134 480 132 481 129 482 126 483 124 483 122 483 121 484 121 484 120 484 118 485 116 486 112 487 109 487 106 488 103 488 101 489 99 489 97 490 95 490 94 -joinstyle bevel}
|
||||
{polygon 503 22 503 23 504 23 504 24 505 24 505 25 505 26 505 27 505 28 505 29 504 29 504 30 503 30 502 30 502 31 501 31 501 30 500 30 499 30 499 29 499 28 499 27 499 26 499 25 499 24 500 24 500 23 501 23 502 22 503 22 -outline {} -fill $bg -width 0}
|
||||
{line 503 22 503 23 504 23 504 24 505 24 505 25 505 26 505 27 505 28 505 29 504 29 504 30 503 30 502 30 502 31 501 31 501 30 500 30 499 30 499 29 499 28 499 27 499 26 499 25 499 24 500 24 500 23 501 23 502 22 503 22 -joinstyle bevel}
|
||||
{polygon 517 44 516 45 515 46 513 47 513 48 512 48 511 48 510 49 508 49 506 50 505 50 504 50 503 50 501 50 498 50 497 51 496 51 495 50 492 50 490 50 487 50 486 49 484 49 483 49 482 48 481 48 481 49 480 51 479 53 479 54 478 55 478 56 477 58 477 59 477 61 477 62 477 63 477 65 477 67 476 68 476 69 477 71 477 72 477 74 477 75 477 76 478 76 479 77 481 77 484 78 485 79 486 79 487 79 488 80 490 81 491 82 493 83 494 84 495 85 496 87 498 88 498 89 499 90 500 92 500 94 500 96 501 98 501 99 501 100 501 101 500 102 500 103 500 104 500 105 499 106 499 107 498 108 498 109 498 110 497 111 497 112 497 113 497 114 497 115 498 115 498 116 499 117 499 118 500 118 500 119 501 120 502 121 502 122 503 122 503 123 502 125 502 128 501 132 501 136 500 139 500 141 500 142 499 143 499 144 499 146 498 148 497 151 496 153 495 156 494 160 493 163 492 165 491 167 491 168 491 169 490 169 490 171 489 174 487 177 486 180 485 182 484 184 484 185 483 185 483 186 482 188 481 190 479 193 478 197 477 199 476 202 475 204 474 206 473 208 472 209 472 210 474 210 476 209 479 209 483 209 488 208 492 207 496 207 499 206 502 206 503 206 504 205 504 204 505 201 506 198 507 193 509 188 510 183 512 179 513 176 514 173 514 172 514 171 514 170 515 169 515 167 516 165 516 162 517 160 518 157 518 154 519 150 520 146 521 142 521 137 522 133 523 129 523 126 523 124 523 122 524 122 524 121 524 120 524 118 524 116 524 113 524 109 524 105 525 101 525 97 525 94 525 92 525 91 525 90 525 89 525 88 525 87 524 85 524 82 524 78 523 74 523 70 522 66 522 62 521 59 521 56 520 54 519 51 519 49 518 47 518 46 518 45 518 44 -outline {} -fill $bg -width 0}
|
||||
{line 517 44 516 45 515 46 513 47 513 48 512 48 511 48 510 49 508 49 506 50 505 50 504 50 503 50 501 50 498 50 497 51 496 51 495 50 492 50 490 50 487 50 486 49 484 49 483 49 482 48 481 48 481 49 480 51 479 53 479 54 478 55 478 56 477 58 477 59 477 61 477 62 477 63 477 65 477 67 476 68 476 69 477 71 477 72 477 74 477 75 477 76 478 76 479 77 481 77 484 78 485 79 486 79 487 79 488 80 490 81 491 82 493 83 494 84 495 85 496 87 498 88 498 89 499 90 500 92 500 94 500 96 501 98 501 99 501 100 501 101 500 102 500 103 500 104 500 105 499 106 499 107 498 108 498 109 498 110 497 111 497 112 497 113 497 114 497 115 498 115 498 116 499 117 499 118 500 118 500 119 501 120 502 121 502 122 503 122 503 123 502 125 502 128 501 132 501 136 500 139 500 141 500 142 499 143 499 144 499 146 498 148 497 151 496 153 495 156 494 160 493 163 492 165 491 167 491 168 491 169 490 169 490 171 489 174 487 177 486 180 485 182 484 184 484 185 483 185 483 186 482 188 481 190 479 193 478 197 477 199 476 202 475 204 474 206 473 208 472 209 472 210 474 210 476 209 479 209 483 209 488 208 492 207 496 207 499 206 502 206 503 206 504 205 504 204 505 201 506 198 507 193 509 188 510 183 512 179 513 176 514 173 514 172 514 171 514 170 515 169 515 167 516 165 516 162 517 160 518 157 518 154 519 150 520 146 521 142 521 137 522 133 523 129 523 126 523 124 523 122 524 122 524 121 524 120 524 118 524 116 524 113 524 109 524 105 525 101 525 97 525 94 525 92 525 91 525 90 525 89 525 88 525 87 524 85 524 82 524 78 523 74 523 70 522 66 522 62 521 59 521 56 520 54 519 51 519 49 518 47 518 46 518 45 518 44 517 44 -joinstyle bevel}
|
||||
{polygon 11 126 12 126 13 126 16 126 19 126 23 126 27 126 32 126 36 126 39 126 41 126 43 126 45 126 47 126 50 127 51 127 52 127 53 128 54 128 56 129 57 130 58 132 59 132 59 133 60 134 61 135 61 137 62 138 62 139 62 140 62 142 62 144 62 145 62 147 62 148 62 149 62 150 61 152 61 154 61 155 61 156 60 157 60 158 59 159 58 161 57 162 57 163 56 164 55 165 54 166 53 167 51 168 49 169 48 169 47 170 46 170 47 171 49 171 51 172 52 172 53 173 54 174 55 175 56 177 56 178 57 180 57 181 57 182 57 183 57 184 57 185 57 187 57 189 57 190 57 191 56 192 56 194 56 196 56 199 56 200 56 201 56 202 55 203 55 205 55 206 55 207 55 208 55 209 56 209 56 210 56 211 57 212 58 212 58 213 57 213 56 213 55 213 51 213 47 213 43 213 40 213 38 213 37 213 37 212 37 211 36 210 36 209 36 208 36 207 36 206 36 205 37 204 37 203 37 202 37 201 37 199 37 198 37 197 37 196 37 195 37 194 38 192 38 189 38 188 38 187 38 186 38 185 38 184 38 182 37 181 37 180 37 179 36 179 36 178 35 178 34 177 33 177 32 177 31 177 30 177 28 177 26 177 24 177 24 178 24 179 24 182 23 186 23 190 22 195 22 200 21 205 21 208 20 211 20 213 19 213 17 213 14 213 10 213 7 213 4 213 2 213 1 213 1 212 1 211 2 208 2 205 2 201 3 196 4 190 4 184 5 177 6 169 7 162 8 155 9 149 9 143 10 138 10 134 11 131 11 129 11 127 11 126 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 26 163 27 163 29 163 31 163 32 163 33 162 35 162 36 162 37 161 38 161 39 160 40 159 40 158 41 157 42 156 42 154 43 153 43 152 43 151 43 150 43 149 43 148 43 147 43 146 42 145 42 144 42 143 41 143 41 142 40 142 40 141 39 141 38 141 37 141 36 140 35 140 34 140 33 140 31 140 30 140 29 140 28 141 28 142 28 145 28 148 27 151 27 155 26 158 26 161 26 162 26 163 -outline {} -fill \#000000 -width 0}
|
||||
{line 11 126 12 126 13 126 16 126 19 126 23 126 27 126 32 126 36 126 39 126 41 126 43 126 45 126 47 126 50 127 51 127 52 127 53 128 54 128 56 129 57 130 58 132 59 132 59 133 60 134 61 135 61 137 62 138 62 139 62 140 62 142 62 144 62 145 62 147 62 148 62 149 62 150 61 152 61 154 61 155 61 156 60 157 60 158 59 159 58 161 57 162 57 163 56 164 55 165 54 166 53 167 51 168 49 169 48 169 47 170 46 170 47 171 49 171 51 172 52 172 53 173 54 174 55 175 56 177 56 178 57 180 57 181 57 182 57 183 57 184 57 185 57 187 57 189 57 190 57 191 56 192 56 194 56 196 56 199 56 200 56 201 56 202 55 203 55 205 55 206 55 207 55 208 55 209 56 209 56 210 56 211 57 212 58 212 58 213 57 213 56 213 55 213 51 213 47 213 43 213 40 213 38 213 37 213 37 212 37 211 36 210 36 209 36 208 36 207 36 206 36 205 37 204 37 203 37 202 37 201 37 199 37 198 37 197 37 196 37 195 37 194 38 192 38 189 38 188 38 187 38 186 38 185 38 184 38 182 37 181 37 180 37 179 36 179 36 178 35 178 34 177 33 177 32 177 31 177 30 177 28 177 26 177 24 177 24 178 24 179 24 182 23 186 23 190 22 195 22 200 21 205 21 208 20 211 20 213 19 213 17 213 14 213 10 213 7 213 4 213 2 213 1 213 1 212 1 211 2 208 2 205 2 201 3 196 4 190 4 184 5 177 6 169 7 162 8 155 9 149 9 143 10 138 10 134 11 131 11 129 11 127 11 126 -joinstyle bevel}
|
||||
{polygon 26 163 27 163 29 163 31 163 32 163 33 162 35 162 36 162 37 161 38 161 39 160 40 159 40 158 41 157 42 156 42 154 43 153 43 152 43 151 43 150 43 149 43 148 43 147 43 146 42 145 42 144 42 143 41 143 41 142 40 142 40 141 39 141 38 141 37 141 36 140 35 140 34 140 33 140 31 140 30 140 29 140 28 141 28 142 28 145 28 148 27 151 27 155 26 158 26 161 26 162 26 163 -outline {} -fill $bg -width 0}
|
||||
{polygon 90 215 89 215 86 214 84 214 81 213 79 213 78 213 77 213 77 212 75 212 74 211 72 209 70 207 69 205 68 204 68 203 68 202 67 202 67 200 66 198 66 195 66 193 66 192 66 191 66 190 66 188 66 185 66 182 66 180 66 177 66 175 66 174 67 172 67 171 67 170 67 169 67 167 68 165 68 162 68 159 69 156 69 155 69 154 70 152 70 151 70 149 71 147 72 144 73 142 74 139 75 138 75 137 76 136 76 135 77 134 79 132 81 130 82 129 83 129 83 128 84 128 85 127 88 126 91 125 93 125 95 124 97 124 99 124 100 124 101 124 102 124 104 125 107 125 110 126 112 126 113 126 114 127 115 127 116 128 117 129 118 130 120 131 121 133 122 135 123 136 123 137 123 138 123 139 124 141 124 143 125 146 125 148 125 149 125 150 125 152 125 156 125 159 124 162 124 164 124 166 124 168 124 169 123 169 123 170 123 171 123 173 122 177 122 180 122 182 121 183 121 184 121 185 121 187 120 189 120 191 119 193 118 196 117 199 116 200 116 201 116 202 115 203 114 204 112 206 111 208 109 209 109 210 108 210 107 211 106 211 103 213 100 213 98 214 96 214 94 215 92 215 91 215 90 215 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 91 201 92 201 94 200 95 200 96 200 96 199 97 198 98 197 99 196 99 195 100 194 100 193 100 191 101 189 101 188 101 187 102 185 102 182 103 179 103 177 103 175 103 173 104 171 104 170 104 169 104 168 104 166 104 163 105 160 105 158 105 157 105 156 105 154 105 153 106 150 106 148 105 146 105 145 105 144 105 143 105 142 104 141 104 140 103 139 101 138 100 138 99 138 98 138 96 138 95 139 94 139 94 140 93 141 92 142 91 143 91 144 91 145 91 146 90 148 89 150 89 151 89 152 89 154 88 157 88 160 87 162 87 164 87 166 87 168 86 169 86 170 86 171 86 173 86 176 85 179 85 181 85 182 85 183 85 185 85 186 85 189 85 191 85 193 85 194 85 195 85 196 86 197 86 198 86 199 87 199 88 200 89 201 90 201 91 201 -outline {} -fill $bg -width 0}
|
||||
{line 90 215 89 215 86 214 84 214 81 213 79 213 78 213 77 213 77 212 75 212 74 211 72 209 70 207 69 205 68 204 68 203 68 202 67 202 67 200 66 198 66 195 66 193 66 192 66 191 66 190 66 188 66 185 66 182 66 180 66 177 66 175 66 174 67 172 67 171 67 170 67 169 67 167 68 165 68 162 68 159 69 156 69 155 69 154 70 152 70 151 70 149 71 147 72 144 73 142 74 139 75 138 75 137 76 136 76 135 77 134 79 132 81 130 82 129 83 129 83 128 84 128 85 127 88 126 91 125 93 125 95 124 97 124 99 124 100 124 101 124 102 124 104 125 107 125 110 126 112 126 113 126 114 127 115 127 116 128 117 129 118 130 120 131 121 133 122 135 123 136 123 137 123 138 123 139 124 141 124 143 125 146 125 148 125 149 125 150 125 152 125 156 125 159 124 162 124 164 124 166 124 168 124 169 123 169 123 170 123 171 123 173 122 177 122 180 122 182 121 183 121 184 121 185 121 187 120 189 120 191 119 193 118 196 117 199 116 200 116 201 116 202 115 203 114 204 112 206 111 208 109 209 109 210 108 210 107 211 106 211 103 213 100 213 98 214 96 214 94 215 92 215 91 215 90 215 -joinstyle bevel}
|
||||
{polygon 149 126 173 126 182 213 163 213 162 197 142 197 138 213 118 213 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 158 142 147 181 161 181 -outline {} -fill \#000000 -width 0}
|
||||
{line 149 126 173 126 182 213 163 213 162 197 142 197 138 213 118 213 149 126}
|
||||
{polygon 158 142 147 181 161 181 -outline {} -fill $bg -width 0}
|
||||
{polygon 196 126 197 126 198 126 201 126 204 126 208 126 212 126 217 126 221 126 224 126 226 126 228 126 230 126 232 126 235 127 236 127 237 127 238 128 239 128 241 129 242 130 244 132 244 133 245 133 245 134 246 135 246 137 247 138 247 139 247 140 247 142 247 144 247 145 247 147 247 148 247 149 247 150 246 152 246 154 246 155 246 156 245 157 245 158 244 159 244 161 242 162 242 163 241 164 240 165 239 166 238 167 236 168 235 169 233 169 232 169 232 170 231 170 232 171 234 171 236 172 237 172 238 172 238 173 239 174 240 175 241 177 241 178 242 180 242 181 242 182 242 183 242 184 242 185 242 187 242 189 242 190 242 191 241 192 241 194 241 196 241 199 241 200 241 201 241 202 241 203 240 205 240 206 240 207 240 208 241 208 241 209 241 210 241 211 242 212 243 212 243 213 242 213 240 213 236 213 232 213 228 213 225 213 223 213 222 213 222 212 222 211 221 210 221 209 221 208 221 207 221 206 221 205 221 204 221 203 221 202 222 201 222 199 222 198 222 197 222 196 222 195 222 194 223 192 223 189 223 188 223 187 223 186 223 185 223 184 223 182 222 181 222 180 222 179 221 178 220 178 218 177 217 177 216 177 215 177 213 177 211 177 209 177 209 178 209 179 209 182 208 186 208 190 207 195 206 200 206 205 206 208 205 211 205 213 204 213 202 213 199 213 196 213 192 213 189 213 187 213 186 213 186 212 186 211 187 208 187 205 188 201 188 196 189 190 190 184 190 177 191 169 192 162 193 155 194 149 194 143 195 138 196 134 196 131 196 129 196 127 196 126 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 211 163 212 163 214 163 216 163 217 163 218 162 220 162 221 162 222 161 223 161 224 160 225 159 225 158 226 157 227 157 227 156 227 154 228 153 228 152 228 151 228 150 228 149 228 148 228 147 228 146 227 145 227 144 227 143 226 142 225 142 225 141 224 141 223 141 222 141 221 140 220 140 219 140 218 140 217 140 215 140 214 140 214 141 213 142 213 145 213 148 212 151 212 155 212 158 211 161 211 162 211 163 -outline {} -fill \#000000 -width 0}
|
||||
{line 196 126 197 126 198 126 201 126 204 126 208 126 212 126 217 126 221 126 224 126 226 126 228 126 230 126 232 126 235 127 236 127 237 127 238 128 239 128 241 129 242 130 244 132 244 133 245 133 245 134 246 135 246 137 247 138 247 139 247 140 247 142 247 144 247 145 247 147 247 148 247 149 247 150 246 152 246 154 246 155 246 156 245 157 245 158 244 159 244 161 242 162 242 163 241 164 240 165 239 166 238 167 236 168 235 169 233 169 232 169 232 170 231 170 232 171 234 171 236 172 237 172 238 172 238 173 239 174 240 175 241 177 241 178 242 180 242 181 242 182 242 183 242 184 242 185 242 187 242 189 242 190 242 191 241 192 241 194 241 196 241 199 241 200 241 201 241 202 241 203 240 205 240 206 240 207 240 208 241 208 241 209 241 210 241 211 242 212 243 212 243 213 242 213 240 213 236 213 232 213 228 213 225 213 223 213 222 213 222 212 222 211 221 210 221 209 221 208 221 207 221 206 221 205 221 204 221 203 221 202 222 201 222 199 222 198 222 197 222 196 222 195 222 194 223 192 223 189 223 188 223 187 223 186 223 185 223 184 223 182 222 181 222 180 222 179 221 178 220 178 218 177 217 177 216 177 215 177 213 177 211 177 209 177 209 178 209 179 209 182 208 186 208 190 207 195 206 200 206 205 206 208 205 211 205 213 204 213 202 213 199 213 196 213 192 213 189 213 187 213 186 213 186 212 186 211 187 208 187 205 188 201 188 196 189 190 190 184 190 177 191 169 192 162 193 155 194 149 194 143 195 138 196 134 196 131 196 129 196 127 196 126 -joinstyle bevel}
|
||||
{polygon 211 163 212 163 214 163 216 163 217 163 218 162 220 162 221 162 222 161 223 161 224 160 225 159 225 158 226 157 227 157 227 156 227 154 228 153 228 152 228 151 228 150 228 149 228 148 228 147 228 146 227 145 227 144 227 143 226 142 225 142 225 141 224 141 223 141 222 141 221 140 220 140 219 140 218 140 217 140 215 140 214 140 214 141 213 142 213 145 213 148 212 151 212 155 212 158 211 161 211 162 211 163 -outline {} -fill $bg -width 0}
|
||||
{polygon 259 126 278 126 268 213 249 213 -outline {} -fill \#000000 -width 0}
|
||||
{line 259 126 278 126 268 213 249 213 259 126}
|
||||
{polygon 288 126 310 126 319 183 326 126 343 126 333 213 311 213 302 153 295 213 278 213 -outline {} -fill \#000000 -width 0}
|
||||
{line 288 126 310 126 319 183 326 126 343 126 333 213 311 213 302 153 295 213 278 213 288 126}
|
||||
{polygon 383 152 384 151 384 150 384 149 384 148 384 147 384 146 384 145 384 144 383 143 383 142 383 141 382 140 382 139 381 139 380 138 379 138 378 138 377 138 376 138 375 139 374 139 373 139 373 140 372 141 371 142 370 144 370 145 369 145 369 146 368 148 368 151 368 152 368 153 367 154 367 157 366 160 366 162 366 164 366 166 365 168 365 169 365 170 365 171 365 173 365 176 364 179 364 181 364 182 364 183 364 185 364 186 364 189 364 191 364 193 364 194 364 195 364 196 364 197 365 198 365 199 366 199 366 200 368 201 369 201 370 201 371 201 373 201 373 200 374 200 375 200 375 199 376 198 377 197 377 196 378 196 378 195 379 193 379 192 379 191 380 189 380 187 380 186 381 185 381 184 381 183 381 182 381 181 381 180 380 180 377 180 374 180 373 180 372 180 373 179 373 176 373 173 374 170 374 168 374 166 375 166 376 166 379 166 383 166 387 166 392 166 395 166 398 166 400 166 401 166 401 167 400 168 400 171 400 174 399 179 398 184 398 190 397 196 397 201 396 205 395 209 395 211 395 213 394 213 392 213 389 213 385 213 383 213 382 213 382 212 382 209 382 207 383 205 382 205 381 206 380 208 380 209 379 209 378 210 377 211 376 212 375 213 374 213 372 214 371 214 370 214 368 215 367 215 365 215 364 215 363 215 361 214 359 214 356 213 355 213 354 213 353 213 352 212 351 211 349 209 348 207 346 205 346 204 346 203 345 201 345 198 344 196 344 194 344 193 344 192 344 190 344 186 344 184 344 181 345 179 345 177 345 175 345 174 345 172 345 171 346 171 346 169 346 166 347 163 347 160 347 158 347 156 348 156 348 155 348 153 348 152 349 150 349 148 350 145 351 142 352 140 353 138 353 137 354 137 354 136 355 134 357 132 359 131 360 130 361 129 362 128 364 127 366 126 369 125 371 125 374 124 376 124 378 124 379 124 380 124 381 124 383 125 386 125 388 125 390 126 391 126 392 126 392 127 394 127 395 128 397 129 398 131 400 133 400 134 400 135 401 136 401 138 402 140 402 141 402 142 402 143 402 146 402 148 402 150 402 151 402 152 401 152 399 152 396 152 393 152 389 152 386 152 384 152 -outline {} -fill \#000000 -width 0}
|
||||
{line 383 152 384 151 384 150 384 149 384 148 384 147 384 146 384 145 384 144 383 143 383 142 383 141 382 140 382 139 381 139 380 138 379 138 378 138 377 138 376 138 375 139 374 139 373 139 373 140 372 141 371 142 370 144 370 145 369 145 369 146 368 148 368 151 368 152 368 153 367 154 367 157 366 160 366 162 366 164 366 166 365 168 365 169 365 170 365 171 365 173 365 176 364 179 364 181 364 182 364 183 364 185 364 186 364 189 364 191 364 193 364 194 364 195 364 196 364 197 365 198 365 199 366 199 366 200 368 201 369 201 370 201 371 201 373 201 373 200 374 200 375 200 375 199 376 198 377 197 377 196 378 196 378 195 379 193 379 192 379 191 380 189 380 187 380 186 381 185 381 184 381 183 381 182 381 181 381 180 380 180 377 180 374 180 373 180 372 180 373 179 373 176 373 173 374 170 374 168 374 166 375 166 376 166 379 166 383 166 387 166 392 166 395 166 398 166 400 166 401 166 401 167 400 168 400 171 400 174 399 179 398 184 398 190 397 196 397 201 396 205 395 209 395 211 395 213 394 213 392 213 389 213 385 213 383 213 382 213 382 212 382 209 382 207 383 205 382 205 381 206 380 208 380 209 379 209 378 210 377 211 376 212 375 213 374 213 372 214 371 214 370 214 368 215 367 215 365 215 364 215 363 215 361 214 359 214 356 213 355 213 354 213 353 213 352 212 351 211 349 209 348 207 346 205 346 204 346 203 345 201 345 198 344 196 344 194 344 193 344 192 344 190 344 186 344 184 344 181 345 179 345 177 345 175 345 174 345 172 345 171 346 171 346 169 346 166 347 163 347 160 347 158 347 156 348 156 348 155 348 153 348 152 349 150 349 148 350 145 351 142 352 140 353 138 353 137 354 137 354 136 355 134 357 132 359 131 360 130 361 129 362 128 364 127 366 126 369 125 371 125 374 124 376 124 378 124 379 124 380 124 381 124 383 125 386 125 388 125 390 126 391 126 392 126 392 127 394 127 395 128 397 129 398 131 400 133 400 134 400 135 401 136 401 138 402 140 402 141 402 142 402 143 402 146 402 148 402 150 402 151 402 152 401 152 399 152 396 152 393 152 389 152 386 152 384 152 383 152 -joinstyle bevel}
|
||||
{polygon 118 229 119 229 121 229 124 229 128 229 133 229 137 229 142 229 145 229 146 229 147 229 148 229 150 229 152 230 155 230 156 230 157 231 158 231 159 231 160 232 162 233 163 235 165 236 165 237 166 237 166 238 166 239 167 241 167 243 168 243 168 244 168 245 168 247 168 249 168 251 168 252 168 253 168 254 167 255 167 258 166 261 166 262 166 263 165 264 165 265 164 267 162 269 161 271 160 272 159 273 157 274 155 275 154 276 153 276 153 277 152 277 149 278 147 278 145 279 143 279 142 279 140 279 139 279 137 279 135 279 132 279 131 279 130 280 130 281 130 283 130 286 129 291 128 295 128 300 127 304 127 307 127 309 127 310 127 311 126 311 124 311 121 311 117 311 113 311 110 311 109 311 108 311 108 310 108 308 108 305 109 301 109 297 110 291 111 284 112 277 113 270 114 263 115 255 115 249 116 243 117 238 117 235 118 232 118 230 118 229 -outline {} -fill \#1892ff -width 0}
|
||||
{polygon 132 265 133 265 134 265 136 265 137 265 138 265 139 265 140 264 141 264 142 264 143 264 143 263 144 263 145 262 146 262 146 261 146 260 147 259 148 258 148 256 148 255 148 254 148 253 148 252 148 251 148 250 148 249 148 248 147 247 147 246 146 245 145 244 144 244 143 243 142 243 141 243 140 243 138 243 137 243 135 243 135 244 135 245 134 247 134 250 134 254 133 257 133 261 133 263 133 264 132 265 -outline {} -fill \#1892ff -width 0}
|
||||
{line 118 229 119 229 121 229 124 229 128 229 133 229 137 229 142 229 145 229 146 229 147 229 148 229 150 229 152 230 155 230 156 230 157 231 158 231 159 231 160 232 162 233 163 235 165 236 165 237 166 237 166 238 166 239 167 241 167 243 168 243 168 244 168 245 168 247 168 249 168 251 168 252 168 253 168 254 167 255 167 258 166 261 166 262 166 263 165 264 165 265 164 267 162 269 161 271 160 272 159 273 157 274 155 275 154 276 153 276 153 277 152 277 149 278 147 278 145 279 143 279 142 279 140 279 139 279 137 279 135 279 132 279 131 279 130 280 130 281 130 283 130 286 129 291 128 295 128 300 127 304 127 307 127 309 127 310 127 311 126 311 124 311 121 311 117 311 113 311 110 311 109 311 108 311 108 310 108 308 108 305 109 301 109 297 110 291 111 284 112 277 113 270 114 263 115 255 115 249 116 243 117 238 117 235 118 232 118 230 118 229 -joinstyle bevel -fill \#1892ff}
|
||||
{polygon 176 229 223 229 221 244 193 244 191 261 217 261 215 277 189 277 187 295 215 295 214 311 166 311 -outline {} -fill \#1892ff -width 0}
|
||||
{line 176 229 223 229 221 244 193 244 191 261 217 261 215 277 189 277 187 295 215 295 214 311 166 311 176 229 -fill \#1892ff}
|
||||
{polygon 232 229 254 229 263 282 270 229 288 229 277 311 256 311 246 254 239 311 222 311 -outline {} -fill \#1892ff -width 0}
|
||||
{line 232 229 254 229 263 282 270 229 288 229 277 311 256 311 246 254 239 311 222 311 232 229 -fill \#1892ff}
|
||||
{polygon 328 254 328 253 328 251 328 250 328 249 328 248 328 247 328 246 328 245 328 244 327 243 327 242 326 242 325 241 324 241 323 240 322 240 321 240 319 241 318 241 317 242 316 243 315 244 314 246 314 247 314 248 313 250 312 252 312 253 312 254 312 256 311 259 311 261 311 263 310 265 310 267 310 268 310 270 310 271 309 273 309 276 309 279 308 281 308 282 308 283 308 284 308 286 308 288 308 290 308 292 308 293 308 294 309 296 309 297 310 298 311 299 312 300 313 300 314 300 315 300 316 300 317 299 318 299 319 299 319 298 320 298 321 297 322 296 322 295 323 293 323 292 324 291 324 289 325 287 325 285 325 284 325 283 325 282 326 282 326 281 326 280 325 280 324 280 321 280 319 280 317 280 317 279 317 276 318 273 318 270 318 268 319 267 321 267 324 267 327 267 332 267 336 267 340 267 343 267 344 267 345 267 345 268 345 269 344 271 344 274 343 279 343 284 342 289 341 294 341 300 340 304 340 307 340 309 339 310 339 311 338 311 336 311 333 311 330 311 328 311 327 311 326 311 327 310 327 307 327 305 327 304 327 303 326 304 325 306 324 307 324 308 323 308 322 309 321 310 320 311 319 311 318 311 317 312 316 312 315 312 314 312 313 312 311 313 310 313 309 313 308 313 307 313 306 312 303 312 301 311 299 311 298 311 298 310 296 310 295 309 294 308 292 306 291 304 290 302 290 301 290 300 289 297 289 295 289 293 289 292 289 291 289 289 289 286 289 283 289 280 289 278 289 275 290 274 290 273 290 272 290 271 290 270 291 267 291 264 291 261 292 259 292 258 292 257 292 256 292 255 293 253 293 252 294 249 295 247 296 244 297 242 298 240 298 239 299 238 300 237 301 235 303 234 304 232 305 232 306 231 308 230 311 229 313 228 316 228 318 227 320 227 322 227 323 227 324 227 325 227 327 228 330 228 333 229 335 229 336 229 337 229 338 230 340 231 341 232 343 234 344 236 345 237 345 238 346 240 346 242 347 244 347 246 347 247 347 250 347 251 346 252 346 253 346 254 345 254 343 254 341 254 337 254 334 254 331 254 329 254 328 254 -outline {} -fill \#1892ff -width 0}
|
||||
{line 328 254 328 253 328 251 328 250 328 249 328 248 328 247 328 246 328 245 328 244 327 243 327 242 326 242 325 241 324 241 323 240 322 240 321 240 319 241 318 241 317 242 316 243 315 244 314 246 314 247 314 248 313 250 312 252 312 253 312 254 312 256 311 259 311 261 311 263 310 265 310 267 310 268 310 270 310 271 309 273 309 276 309 279 308 281 308 282 308 283 308 284 308 286 308 288 308 290 308 292 308 293 308 294 309 296 309 297 310 298 311 299 312 300 313 300 314 300 315 300 316 300 317 299 318 299 319 299 319 298 320 298 321 297 322 296 322 295 323 293 323 292 324 291 324 289 325 287 325 285 325 284 325 283 325 282 326 282 326 281 326 280 325 280 324 280 321 280 319 280 317 280 317 279 317 276 318 273 318 270 318 268 319 267 321 267 324 267 327 267 332 267 336 267 340 267 343 267 344 267 345 267 345 268 345 269 344 271 344 274 343 279 343 284 342 289 341 294 341 300 340 304 340 307 340 309 339 310 339 311 338 311 336 311 333 311 330 311 328 311 327 311 326 311 327 310 327 307 327 305 327 304 327 303 326 304 325 306 324 307 324 308 323 308 322 309 321 310 320 311 319 311 318 311 317 312 316 312 315 312 314 312 313 312 311 313 310 313 309 313 308 313 307 313 306 312 303 312 301 311 299 311 298 311 298 310 296 310 295 309 294 308 292 306 291 304 290 302 290 301 290 300 289 297 289 295 289 293 289 292 289 291 289 289 289 286 289 283 289 280 289 278 289 275 290 274 290 273 290 272 290 271 290 270 291 267 291 264 291 261 292 259 292 258 292 257 292 256 292 255 293 253 293 252 294 249 295 247 296 244 297 242 298 240 298 239 299 238 300 237 301 235 303 234 304 232 305 232 306 231 308 230 311 229 313 228 316 228 318 227 320 227 322 227 323 227 324 227 325 227 327 228 330 228 333 229 335 229 336 229 337 229 338 230 340 231 341 232 343 234 344 236 345 237 345 238 346 240 346 242 347 244 347 246 347 247 347 250 347 251 346 252 346 253 346 254 345 254 343 254 341 254 337 254 334 254 331 254 329 254 328 254 -joinstyle bevel -fill \#1892ff}
|
||||
{polygon 405 284 404 286 404 289 403 291 403 293 403 294 402 295 402 297 401 299 400 301 398 303 397 304 397 305 396 306 394 307 392 309 391 309 391 310 390 310 389 310 386 311 384 312 381 312 380 312 378 313 376 313 375 313 374 313 372 312 369 312 367 312 365 311 364 311 363 311 362 310 360 310 358 309 356 307 355 306 354 305 354 304 353 303 353 301 352 299 352 298 352 297 351 295 351 293 351 290 351 288 352 286 352 285 352 284 352 283 352 282 352 280 353 277 353 273 354 268 355 262 355 256 356 250 357 245 357 240 358 236 358 233 359 231 359 229 360 229 362 229 365 229 368 229 372 229 375 229 377 229 378 229 377 230 377 232 377 234 376 238 376 242 375 247 375 253 374 259 373 265 372 271 372 276 371 280 371 284 370 287 370 288 370 289 370 290 370 291 370 292 370 293 370 294 370 295 370 296 371 297 372 298 372 299 373 299 374 299 374 300 375 300 376 300 377 300 378 300 379 299 380 299 381 299 381 298 382 297 383 297 383 296 383 295 384 295 384 294 384 293 385 292 385 291 385 290 385 289 385 288 386 287 386 284 386 280 387 276 388 271 388 265 389 259 390 253 390 247 391 242 392 238 392 234 392 232 393 230 393 229 394 229 396 229 399 229 402 229 406 229 409 229 411 229 412 229 412 231 411 233 411 236 410 240 410 245 409 250 408 256 407 262 407 268 406 273 406 277 405 280 405 282 405 283 -outline {} -fill \#1892ff -width 0}
|
||||
{line 405 284 404 286 404 289 403 291 403 293 403 294 402 295 402 297 401 299 400 301 398 303 397 304 397 305 396 306 394 307 392 309 391 309 391 310 390 310 389 310 386 311 384 312 381 312 380 312 378 313 376 313 375 313 374 313 372 312 369 312 367 312 365 311 364 311 363 311 362 310 360 310 358 309 356 307 355 306 354 305 354 304 353 303 353 301 352 299 352 298 352 297 351 295 351 293 351 290 351 288 352 286 352 285 352 284 352 283 352 282 352 280 353 277 353 273 354 268 355 262 355 256 356 250 357 245 357 240 358 236 358 233 359 231 359 229 360 229 362 229 365 229 368 229 372 229 375 229 377 229 378 229 377 230 377 232 377 234 376 238 376 242 375 247 375 253 374 259 373 265 372 271 372 276 371 280 371 284 370 287 370 288 370 289 370 290 370 291 370 292 370 293 370 294 370 295 370 296 371 297 372 298 372 299 373 299 374 299 374 300 375 300 376 300 377 300 378 300 379 299 380 299 381 299 381 298 382 297 383 297 383 296 383 295 384 295 384 294 384 293 385 292 385 291 385 290 385 289 385 288 386 287 386 284 386 280 387 276 388 271 388 265 389 259 390 253 390 247 391 242 392 238 392 234 392 232 393 230 393 229 394 229 396 229 399 229 402 229 406 229 409 229 411 229 412 229 412 231 411 233 411 236 410 240 410 245 409 250 408 256 407 262 407 268 406 273 406 277 405 280 405 282 405 283 405 284 -joinstyle bevel -fill \#1892ff}
|
||||
{polygon 421 229 439 229 429 311 410 311 -outline {} -fill \#1892ff -width 0}
|
||||
{line 421 229 439 229 429 311 410 311 421 229 -fill \#1892ff}
|
||||
{polygon 449 229 471 229 480 282 487 229 504 229 494 311 473 311 463 254 456 311 439 311 -outline {} -fill \#1892ff -width 0}
|
||||
{line 449 229 471 229 480 282 487 229 504 229 494 311 473 311 463 254 456 311 439 311 449 229 -fill \#1892ff}
|
||||
{polygon 114 354 114 355 114 356 114 357 114 358 114 359 115 359 115 360 116 360 117 360 118 360 119 359 119 358 120 358 120 357 120 356 119 355 119 354 118 353 117 352 116 352 115 351 114 350 113 350 112 349 110 348 109 347 109 346 108 345 108 343 107 342 107 341 107 340 107 339 107 338 108 337 108 336 108 335 109 334 109 333 110 333 110 332 111 331 112 331 113 331 114 330 115 330 116 330 117 330 118 330 119 330 120 330 121 331 122 331 123 332 124 332 124 333 125 334 125 335 125 336 126 336 126 337 126 338 126 339 126 340 125 340 123 340 121 340 119 340 119 339 119 338 119 337 119 336 118 336 118 335 117 335 116 335 116 336 115 336 115 337 114 337 114 338 114 339 115 340 115 341 115 342 116 343 117 343 118 344 120 345 121 345 122 346 123 347 124 347 124 348 125 349 126 351 126 352 126 353 126 354 126 355 126 356 126 358 126 359 126 360 125 361 125 362 124 363 123 364 122 364 122 365 121 365 120 365 119 366 118 366 117 366 116 366 115 366 114 365 113 365 112 365 111 364 110 364 109 363 108 362 108 361 108 360 107 359 107 358 107 357 107 356 107 355 107 354 108 354 110 354 112 354 113 354 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 152 366 151 365 149 365 148 365 147 364 146 364 145 363 144 361 143 360 143 359 143 357 142 357 142 356 142 354 142 352 142 351 142 349 142 348 142 347 142 345 142 343 142 342 142 341 142 340 143 339 143 337 143 336 144 335 144 334 145 333 146 332 146 331 148 331 149 330 150 330 151 330 152 330 154 330 155 331 157 331 158 332 159 333 160 334 161 335 161 336 161 337 162 339 162 340 162 341 162 342 162 344 162 345 162 346 162 347 162 348 162 349 162 351 162 352 162 353 162 354 162 355 162 357 161 358 161 360 161 361 160 362 159 363 159 364 158 364 157 365 155 365 154 366 153 366 152 366 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 152 360 153 360 154 360 154 359 155 358 155 357 155 356 155 355 155 354 155 353 155 351 155 350 155 349 155 348 155 346 155 344 155 343 155 342 155 341 155 339 155 338 154 337 154 336 153 336 153 335 152 335 152 336 151 336 150 336 150 337 150 338 149 338 149 339 149 340 149 341 149 342 149 343 149 345 149 346 149 347 149 348 149 349 149 351 149 352 149 353 149 354 149 355 149 356 149 357 149 358 150 358 150 359 151 360 152 360 -outline {} -fill $bg -width 0}
|
||||
{polygon 179 331 195 331 195 337 185 337 185 344 195 344 195 351 185 351 185 365 179 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 215 337 209 337 209 331 228 331 228 337 222 337 222 365 215 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 241 331 248 331 251 355 254 331 260 331 263 355 266 331 272 331 267 365 260 365 257 341 254 365 247 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 293 331 301 331 308 365 302 365 301 358 294 358 293 365 286 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 297 337 295 352 299 352 -outline {} -fill $bg -width 0}
|
||||
{polygon 324 331 325 331 327 331 329 331 332 331 334 331 335 331 336 331 337 331 338 331 339 332 340 332 340 333 341 333 341 334 342 334 342 335 342 336 343 337 343 338 343 339 343 340 343 341 343 342 343 343 342 343 342 344 342 345 341 345 341 346 340 347 339 348 338 348 339 349 340 349 341 349 341 350 342 351 342 352 342 353 342 354 342 355 343 356 343 357 343 358 343 359 343 360 343 361 343 362 343 363 343 364 344 364 344 365 342 365 340 365 338 365 337 365 336 365 336 364 336 363 336 362 336 361 336 360 336 359 336 358 336 357 336 356 336 355 336 354 335 353 335 352 335 351 334 351 333 351 332 351 331 351 330 351 330 352 330 355 330 358 330 361 330 364 330 365 329 365 327 365 325 365 324 365 324 364 324 363 324 360 324 357 324 353 324 348 324 343 324 339 324 335 324 333 324 331 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 330 345 331 345 332 345 333 345 334 345 335 345 335 344 335 343 336 343 336 342 336 341 336 340 336 339 335 338 335 337 334 337 333 336 332 336 331 336 330 336 330 337 330 338 330 341 330 343 330 345 -outline {} -fill $bg -width 0}
|
||||
{polygon 360 331 376 331 376 337 367 337 367 344 376 344 376 351 367 351 367 358 377 358 377 365 360 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 416 331 423 331 423 365 416 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 440 331 448 331 454 353 454 331 460 331 460 365 452 365 446 341 446 365 440 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 485 343 485 342 485 341 485 340 485 339 485 338 485 337 484 337 484 336 483 336 483 335 482 335 482 336 481 336 480 337 480 338 480 339 480 340 480 341 479 341 479 343 479 344 479 346 479 347 479 348 479 349 479 351 479 352 479 353 480 354 480 355 480 356 480 357 480 358 480 359 481 359 481 360 482 360 483 360 484 360 484 359 485 359 485 358 485 357 485 356 485 355 485 354 485 353 485 352 487 352 489 352 491 352 492 352 492 353 492 354 492 356 492 357 491 357 491 358 491 359 491 360 490 361 490 362 490 363 489 363 488 364 487 364 486 365 485 365 484 366 482 366 480 365 479 365 478 365 477 365 477 364 476 364 476 363 475 362 474 361 474 360 473 358 473 357 473 356 473 355 473 353 472 352 472 350 472 349 472 348 472 347 472 346 473 344 473 343 473 342 473 341 473 339 473 338 474 336 474 335 475 334 476 333 476 332 478 331 479 330 481 330 482 330 483 330 485 330 486 330 486 331 487 331 488 332 489 332 489 333 490 333 490 334 491 335 491 336 491 337 491 338 492 340 492 341 492 342 492 343 491 343 490 343 488 343 486 343 485 343 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 500 356 506 356 506 365 500 365 -outline {} -fill \#000000 -width 0}
|
||||
{polygon 132 265 133 265 134 265 136 265 137 265 138 265 139 265 140 264 141 264 142 264 143 264 143 263 144 263 145 262 146 262 146 261 146 260 147 259 148 258 148 256 148 255 148 254 148 253 148 252 148 251 148 250 148 249 148 248 147 247 147 246 146 245 145 244 144 244 143 243 142 243 141 243 140 243 138 243 137 243 135 243 135 244 135 245 134 247 134 250 134 254 133 257 133 261 133 263 133 264 132 265 -outline {} -fill $bg -width 0}
|
||||
}
|
||||
foreach obj $logo_objs {
|
||||
eval $c create $obj -tags logo
|
||||
}
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: doLogo
|
||||
# %ARGUMENTS:
|
||||
# None
|
||||
# %RETURNS:
|
||||
# Nothing
|
||||
# %DESCRIPTION:
|
||||
# Does the logo thing
|
||||
#***********************************************************************
|
||||
proc doLogo {} {
|
||||
canvas .c -width 600 -height 400 -bg #FFFFFF
|
||||
pack .c
|
||||
drawLogo .c #FFFFFF
|
||||
|
||||
# Funky effect
|
||||
.c create text 4 4 -anchor nw -text "Welcome to Remind" \
|
||||
-fill red -font {-family times -size -24 -weight bold} -tags remind
|
||||
.c lower remind
|
||||
|
||||
.c move logo -300 20
|
||||
|
||||
update idletasks
|
||||
|
||||
for {set i 0} {$i < 16} {incr i} {
|
||||
.c move logo 20 0
|
||||
update idletasks
|
||||
after 30
|
||||
}
|
||||
|
||||
.c create text 4 28 -anchor nw -text "http://www.roaringpenguin.com" \
|
||||
-fill red -font {-family courier -size -14 -weight bold}
|
||||
|
||||
set rem [FindRemind]
|
||||
if {$rem != ""} {
|
||||
.c create text 4 52 -anchor nw -text "Found existing Remind... reusing settings" -fill red -font {-family courier -size -14 -weight bold}
|
||||
.c create text 4 66 -anchor nw -text "from $rem" -fill red -font {-family courier -size -14 -weight bold}
|
||||
}
|
||||
update idletasks
|
||||
after 2500
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
# %PROCEDURE: FindRemind
|
||||
# %ARGUMENTS:
|
||||
|
||||
40
configure.in
40
configure.in
@@ -14,6 +14,36 @@ EOF
|
||||
|
||||
AC_CONFIG_HEADER(src/config.h)
|
||||
|
||||
if test "`uname -s`" = "Darwin" ; then
|
||||
trap 'echo Be patient...' INT TERM
|
||||
cat <<'EOF'
|
||||
|
||||
Please don't use Apple products. This script will continue in 30 seconds
|
||||
if you insist on compiling Remind on Mac OS X.
|
||||
|
||||
EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
if uname -s | grep -i -q 'cygwin' ; then
|
||||
trap 'echo Be patient...' INT TERM
|
||||
cat <<'EOF'
|
||||
|
||||
Please don't use Microsoft products. This script will continue in 30
|
||||
seconds if you insist on compiling Remind on Cygwin.
|
||||
|
||||
EOF
|
||||
for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
|
||||
sleep 1
|
||||
done
|
||||
trap - INT
|
||||
trap - TERM
|
||||
fi
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
@@ -31,7 +61,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/file.h)
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h wctype.h locale.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
@@ -41,8 +71,10 @@ AC_FUNC_UTIME_NULL
|
||||
AC_HEADER_TIME
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv)
|
||||
AC_OUTPUT(src/Makefile)
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||
VERSION=03.02.00
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
9
contrib/README
Normal file
9
contrib/README
Normal file
@@ -0,0 +1,9 @@
|
||||
This directory contains contributed scripts. They are provided
|
||||
"as-is" with no warranty. Please do not contact Dianne Skoll for help
|
||||
with these scripts; instead, contact the script authors.
|
||||
|
||||
You should check the upstream sources; there may be newer versions
|
||||
of these scripts available.
|
||||
|
||||
--
|
||||
Dianne Skoll
|
||||
279
contrib/ical2rem.pl
Executable file
279
contrib/ical2rem.pl
Executable file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# ical2rem.pl -
|
||||
# Reads iCal files and outputs remind-compatible files. Tested ONLY with
|
||||
# calendar files created by Mozilla Calendar/Sunbird. Use at your own risk.
|
||||
# Copyright (c) 2005, 2007, Justin B. Alcorn
|
||||
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
# version 0.5.2 2007-03-23
|
||||
# - BUG: leadtime for recurring events had a max of 4 instead of DEFAULT_LEAD_TIME
|
||||
# - remove project-lead-time, since Category was a non-standard attribute
|
||||
# - NOTE: There is a bug in iCal::Parser v1.14 that causes multiple calendars to
|
||||
# fail if a calendar with recurring events is followed by a calendar with no
|
||||
# recurring events. This has been reported to the iCal::Parser author.
|
||||
# version 0.5.1 2007-03-21
|
||||
# - BUG: Handle multiple calendars on STDIN
|
||||
# - add --heading option for priority on section headers
|
||||
# version 0.5 2007-03-21
|
||||
# - Add more help options
|
||||
# - --project-lead-time option
|
||||
# - Supress printing of heading if there are no todos to print
|
||||
# version 0.4
|
||||
# - Version 0.4 changes all written or inspired by, and thanks to Mark Stosberg
|
||||
# - Change to GetOptions
|
||||
# - Change to pipe
|
||||
# - Add --label, --help options
|
||||
# - Add Help Text
|
||||
# - Change to subroutines
|
||||
# - Efficiency and Cleanup
|
||||
# version 0.3
|
||||
# - Convert to GPL (Thanks to Mark Stosberg)
|
||||
# - Add usage
|
||||
# version 0.2
|
||||
# - add command line switches
|
||||
# - add debug code
|
||||
# - add SCHED _sfun keyword
|
||||
# - fix typos
|
||||
# version 0.1 - ALPHA CODE.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cat /path/to/file*.ics | ical2rem.pl > ~/.ical2rem
|
||||
|
||||
All options have reasonable defaults:
|
||||
--label Calendar name (Default: Calendar)
|
||||
--lead-time Advance days to start reminders (Default: 3)
|
||||
--todos, --no-todos Process Todos? (Default: Yes)
|
||||
--heading Define a priority for static entries
|
||||
--help Usage
|
||||
--man Complete man page
|
||||
|
||||
Expects an ICAL stream on STDIN. Converts it to the format
|
||||
used by the C<remind> script and prints it to STDOUT.
|
||||
|
||||
=head2 --label
|
||||
|
||||
ical2rem.pl --label "Bob's Calendar"
|
||||
|
||||
The syntax generated includes a label for the calendar parsed.
|
||||
By default this is "Calendar". You can customize this with
|
||||
the "--label" option.
|
||||
|
||||
=head2 --lead-time
|
||||
|
||||
ical2rem.pl --lead-time 3
|
||||
|
||||
How may days in advance to start getting reminders about the events. Defaults to 3.
|
||||
|
||||
=head2 --no-todos
|
||||
|
||||
ical2rem.pl --no-todos
|
||||
|
||||
If you don't care about the ToDos the calendar, this will surpress
|
||||
printing of the ToDo heading, as well as skipping ToDo processing.
|
||||
|
||||
=head2 --heading
|
||||
|
||||
ical2rem.pl --heading "PRIORITY 9999"
|
||||
|
||||
Set an option on static messages output. Using priorities can made the static messages look different from
|
||||
the calendar entries. See the file defs.rem from the remind distribution for more information.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use iCal::Parser;
|
||||
use DateTime;
|
||||
use Getopt::Long 2.24 qw':config auto_help';
|
||||
use Pod::Usage;
|
||||
use Data::Dumper;
|
||||
use vars '$VERSION';
|
||||
$VERSION = "0.5.2";
|
||||
|
||||
# Declare how many days in advance to remind
|
||||
my $DEFAULT_LEAD_TIME = 3;
|
||||
my $PROCESS_TODOS = 1;
|
||||
my $HEADING = "";
|
||||
my $help;
|
||||
my $man;
|
||||
|
||||
my $label = 'Calendar';
|
||||
GetOptions (
|
||||
"label=s" => \$label,
|
||||
"lead-time=i" => \$DEFAULT_LEAD_TIME,
|
||||
"todos!" => \$PROCESS_TODOS,
|
||||
"heading=s" => \$HEADING,
|
||||
"help|?" => \$help,
|
||||
"man" => \$man
|
||||
);
|
||||
pod2usage(1) if $help;
|
||||
pod2usage(-verbose => 2) if $man;
|
||||
|
||||
my $month = ['None','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
|
||||
my @calendars;
|
||||
my $in;
|
||||
|
||||
while (<>) {
|
||||
$in .= $_;
|
||||
if (/END:VCALENDAR/) {
|
||||
push(@calendars,$in);
|
||||
$in = "";
|
||||
}
|
||||
}
|
||||
my $parser = iCal::Parser->new();
|
||||
my $hash = $parser->parse_strings(@calendars);
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# Subroutines
|
||||
#
|
||||
#############################################################
|
||||
#
|
||||
# _process_todos()
|
||||
# expects 'todos' hashref from iCal::Parser is input
|
||||
# returns String to output
|
||||
sub _process_todos {
|
||||
my $todos = shift;
|
||||
|
||||
my ($todo, @newtodos, $leadtime);
|
||||
my $output = "";
|
||||
|
||||
$output .= 'REM '.$HEADING.' MSG '.$label.' ToDos:%"%"%'."\n";
|
||||
|
||||
# For sorting, make sure everything's got something
|
||||
# To sort on.
|
||||
my $now = DateTime->now;
|
||||
for $todo (@{$todos}) {
|
||||
# remove completed items
|
||||
if ($todo->{'STATUS'} && $todo->{'STATUS'} eq 'COMPLETED') {
|
||||
next;
|
||||
} elsif ($todo->{'DUE'}) {
|
||||
# All we need is a due date, everything else is sugar
|
||||
$todo->{'SORT'} = $todo->{'DUE'}->clone;
|
||||
} elsif ($todo->{'DTSTART'}) {
|
||||
# for sorting, sort on start date if there's no due date
|
||||
$todo->{'SORT'} = $todo->{'DTSTART'}->clone;
|
||||
} else {
|
||||
# if there's no due or start date, just make it now.
|
||||
$todo->{'SORT'} = $now;
|
||||
}
|
||||
push(@newtodos,$todo);
|
||||
}
|
||||
if (! (scalar @newtodos)) {
|
||||
return "";
|
||||
}
|
||||
# Now sort on the new Due dates and print them out.
|
||||
for $todo (sort { DateTime->compare($a->{'SORT'}, $b->{'SORT'}) } @newtodos) {
|
||||
my $due = $todo->{'SORT'}->clone();
|
||||
my $priority = "";
|
||||
if (defined($todo->{'PRIORITY'})) {
|
||||
if ($todo->{'PRIORITY'} == 1) {
|
||||
$priority = "PRIORITY 1000";
|
||||
} elsif ($todo->{'PRIORITY'} == 3) {
|
||||
$priority = "PRIORITY 7500";
|
||||
}
|
||||
}
|
||||
if (defined($todo->{'DTSTART'}) && defined($todo->{'DUE'})) {
|
||||
# Lead time is duration of task + lead time
|
||||
my $diff = ($todo->{'DUE'}->delta_days($todo->{'DTSTART'})->days())+$DEFAULT_LEAD_TIME;
|
||||
$leadtime = "+".$diff;
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
$output .= "REM ".$due->month_abbr." ".$due->day." ".$due->year." $leadtime $priority MSG \%a $todo->{'SUMMARY'}\%\"\%\"\%\n";
|
||||
}
|
||||
$output .= 'REM '.$HEADING.' MSG %"%"%'."\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Main Program
|
||||
#
|
||||
######################################################################
|
||||
|
||||
print _process_todos($hash->{'todos'}) if $PROCESS_TODOS;
|
||||
|
||||
my ($leadtime, $yearkey, $monkey, $daykey,$uid,%eventsbyuid);
|
||||
print 'REM '.$HEADING.' MSG '.$label.' Events:%"%"%'."\n";
|
||||
my $events = $hash->{'events'};
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if ($eventsbyuid{$uid}) {
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
for (my $i = 0;$i < $DEFAULT_LEAD_TIME && !defined($event->{'LEADTIME'});$i++) {
|
||||
if ($eventsbyuid{$uid}{$curreventday->subtract( days => $i+1 )->epoch() }) {
|
||||
$event->{'LEADTIME'} = $i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$eventsbyuid{$uid} = $event;
|
||||
my $curreventday = $event->{'DTSTART'}->clone;
|
||||
$curreventday->truncate( to => 'day' );
|
||||
$eventsbyuid{$uid}{$curreventday->epoch()} =1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach $yearkey (sort keys %{$events} ) {
|
||||
my $yearevents = $events->{$yearkey};
|
||||
foreach $monkey (sort {$a <=> $b} keys %{$yearevents}){
|
||||
my $monevents = $yearevents->{$monkey};
|
||||
foreach $daykey (sort {$a <=> $b} keys %{$monevents} ) {
|
||||
my $dayevents = $monevents->{$daykey};
|
||||
foreach $uid (sort {
|
||||
DateTime->compare($dayevents->{$a}->{'DTSTART'}, $dayevents->{$b}->{'DTSTART'})
|
||||
} keys %{$dayevents}) {
|
||||
my $event = $dayevents->{$uid};
|
||||
if (exists($event->{'LEADTIME'})) {
|
||||
$leadtime = "+".$event->{'LEADTIME'};
|
||||
} else {
|
||||
$leadtime = "+".$DEFAULT_LEAD_TIME;
|
||||
}
|
||||
my $start = $event->{'DTSTART'};
|
||||
print "REM ".$start->month_abbr." ".$start->day." ".$start->year." $leadtime ";
|
||||
if ($start->hour > 0) {
|
||||
print " AT ";
|
||||
print $start->strftime("%H:%M");
|
||||
print " SCHED _sfun MSG %a %2 ";
|
||||
} else {
|
||||
print " MSG %a ";
|
||||
}
|
||||
print "%\"$event->{'SUMMARY'}";
|
||||
print " at $event->{'LOCATION'}" if $event->{'LOCATION'};
|
||||
print "\%\"%\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
#:vim set ft=perl ts=4 sts=4 expandtab :
|
||||
13
contrib/rem2ics-0.93/Makefile
Normal file
13
contrib/rem2ics-0.93/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
DESTDIR?=
|
||||
PREFIX?=/usr
|
||||
BINDIR?=$(PREFIX)/bin
|
||||
MANDIR?=$(PREFIX)/share/man
|
||||
|
||||
default: rem2ics.1
|
||||
|
||||
rem2ics.1:
|
||||
pod2man -c "" rem2ics > rem2ics.1
|
||||
|
||||
install: rem2ics.1
|
||||
install -p -D rem2ics $(DESTDIR)$(BINDIR)/rem2ics
|
||||
install -p -D -m 0644 rem2ics.1 $(DESTDIR)$(MANDIR)/man1/rem2ics.1
|
||||
847
contrib/rem2ics-0.93/rem2ics
Executable file
847
contrib/rem2ics-0.93/rem2ics
Executable file
@@ -0,0 +1,847 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# rem2ics -- convert the output of "remind -s" into RFC2445 iCalendar format.
|
||||
|
||||
# Copyright 2007,2008,2009
|
||||
# Mark Atwood <me@mark.atwood.name>
|
||||
# Paul Hinze <paul dot t dot hinze at gmail dot com>
|
||||
# Michael Schultz <mjschultz at gmail dot com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the
|
||||
# Free Software Foundation, Inc.
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston MA 02110-1301 USA
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rem2ics - convert the output of "remind -s" into RFC2445 iCalendar format.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
TZ=I<timezone> B<rem2ics> [B<-man>] [B<-do>] [B<-norecur>] [B<-usetag>] E<lt>input E<gt>output
|
||||
|
||||
=head1 OPTIONS AND ARGUMENTS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<-man>
|
||||
|
||||
Print the manual page and exit.
|
||||
|
||||
=item B<-do>
|
||||
|
||||
Actually do the conversion. Otherwise just print a brief help message
|
||||
and usage example, and then exit.
|
||||
|
||||
=item B<-norecur>
|
||||
|
||||
Do not attempt to detect and fold together recurring events.
|
||||
|
||||
=item B<-usetag>
|
||||
|
||||
Generate UIDs using remind TAG clauses.
|
||||
|
||||
=back
|
||||
|
||||
Input is from standard input
|
||||
|
||||
Output is to standard output.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
remind -s360 -irem2ics=1 ~/.reminders 1 Jan 1991 | TZ=PST8PDT rem2ics -do >reminders.ics
|
||||
|
||||
This tells B<remind> to use ~/.reminders, and to process the entire
|
||||
range of dates it can handle (from Jan 1 1991 to Dec 31 2020), and to
|
||||
define a variable named C<rem2ics>, which can be used in
|
||||
C<IF !defined("rem2ics")> / C<ENDIF> pairs.
|
||||
B<rem2ics> will use a timezone of PST8PDT, and will fold events that
|
||||
have the same name and duration into a single iCalendar VEVENT object.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
=head2 Timezones and the TZ environment variable.
|
||||
|
||||
B<rem2ics> uses the TZ environment variable to determine the value of
|
||||
the RFC2445 TZID property. If you are running on a Linux or other GNU
|
||||
libc based system, you probably don't (and probably shouldn't)
|
||||
normally have TZ set. You can confirm this by running C<printenv TZ>
|
||||
at a shell prompt. If your remind data is in your "local time", and
|
||||
it probably is, you should probably set TZ to a good name for your
|
||||
local timezone just for the run of this script. You probably should
|
||||
NOT set TZ in your login scripts.
|
||||
|
||||
You can use TZ like this:
|
||||
|
||||
remind -s ~/.reminders | TZ=PST8PDT rem2ics -do >reminders.ics
|
||||
|
||||
or
|
||||
|
||||
remind -s ~/.reminders | TZ=US/Pacific rem2ics -do >reminders.ics
|
||||
|
||||
|
||||
If, for some reason, your remind files are all in GMT instead of
|
||||
localtime (you smart person you!), you can do this:
|
||||
|
||||
remind -s ~/.reminders | TZ=GMT rem2ics -do >reminders.ics
|
||||
|
||||
or
|
||||
|
||||
remind -s ~/.reminders | TZ=0 rem2ics -do >reminders.ics
|
||||
|
||||
and B<rem2ics> will use the ISO8601 "Z" notation for GMT time in the ics
|
||||
file. (Other synonyms for GMT are the empty string (not the same as
|
||||
the TZ not set), "I<0>", "I<Z>", "I<Zulu>", "I<Greenwitch>", "I<GMT>",
|
||||
"I<GMT+0>, and "I<GMT-0>".)
|
||||
|
||||
If you leave TZ undefined and unset, B<rem2ics> will use the ISO8601
|
||||
"T" notation date strings with no TZID property, which RFC2445 calls a
|
||||
"floating time". Who knows, it might work for you!
|
||||
|
||||
The TZ string value is literally incorporated into the iCalendar
|
||||
stream, so whatever your iCalendar-using application needs is what you
|
||||
should use. You may have to experiment a bit.
|
||||
|
||||
You can look around in C</usr/share/zoneinfo> to get the names of
|
||||
every timezone anywhere. This is the "Olson database" that RFC2445
|
||||
refers to. Read the man page for L<tzfile(5)> for more than you ever
|
||||
wanted to know about the format of these files, and about GNU libc's
|
||||
handling of timezones. As complex as it is, it's certainly better
|
||||
than what POSIX defines or what most legacy UNIX systems do, and most
|
||||
certainly better than Microsoft, who in their "cutting edge" "state of
|
||||
the art" "server" OS, still hasn't figured out that daylight time
|
||||
rules might be different in different years.
|
||||
|
||||
If you just ran B<rem2ics> without reading all this stuff, or if you
|
||||
don't want to worry about it at all, and somehow your iCalendar
|
||||
application manager is able to guess the proper timezone for you, just
|
||||
leave TZ undefined, and B<rem2ics> will use the ISO8601 "T" notation
|
||||
date strings with no TZID property, which RFC2445 calls a "floating
|
||||
time". Who knows, it might work for you!
|
||||
|
||||
=head2 Detecting recurring events
|
||||
|
||||
B<rem2ics> tries to detect recurring events. If any multiple events
|
||||
appear with exactly the text and exactly the same duration (including
|
||||
"no duration"), instead of multiple VEVENT objects, there will be just
|
||||
one VEVENT object, that will have a RFC2445 C<RDATE> property.
|
||||
|
||||
B<rem2ics> is not yet smart enough to derive an C<RRULE> based
|
||||
recurrance. If you really want that feature, either implement it and
|
||||
send in a patch, or contact the author and convince him to do it.
|
||||
|
||||
=head2 Other iCalendar Properties
|
||||
|
||||
B<rem2ics> does not generate C<DESCRIPTION> or C<LOCATION>. One
|
||||
would have to heuristically parse them out of the text, and everyone
|
||||
uses a idiosyncratic way of putting things in B<remind>.
|
||||
|
||||
If the B<-usetag> option is not used or no C<TAG> is set for a
|
||||
reminder, B<rem2ics> will synthesize C<UID> properties for each
|
||||
VEVENT, but the UIDs will be different (and unique) for each run of
|
||||
B<rem2ics>. If you run rem2ics twice and import the two resulting ICS
|
||||
streams into your new scheduling program, your appointments will
|
||||
appear twice. If, however, you have set C<TAG> clauses in your
|
||||
reminders and activated B<-usetag>, these will be used. The same
|
||||
applies for tags synthesized by B<remind>'s B<-y> option. Hence, it
|
||||
is more useful to use the B<-y> option than to let B<rem2ics>
|
||||
synthesize UIDs, because the UIDs will stay the same across multiple
|
||||
runs.
|
||||
|
||||
=head2 Other iCalendar Perl objects
|
||||
|
||||
Why does't B<rem2ics> use any of the iCalendar Perl stuff in CPAN?
|
||||
Because I don't trust them, and they are too big for this app. One
|
||||
links to a binary library. Another hasn't been maintained since 1991,
|
||||
and is full of notes as to how buggy and incomplete it is. And so
|
||||
forth. I am not at this moment interested in groveling around in
|
||||
L<Net::iCal>, L<DateTime::Format::iCal>, L<Tie::iCal>,
|
||||
L<iCal::Parser>, or C<libical>.
|
||||
|
||||
=head2 Previous implementation
|
||||
|
||||
There is a working quick & dirty rem2ics written in awk
|
||||
by Anthony J. Chivetta E<lt>achivetta@gmail.comE<gt>.
|
||||
|
||||
But it has the following problems: it doesn't escape the text, it
|
||||
doesn't handle events that cross over midnight, it doesn't do
|
||||
timezones, it doesn't enforce the correct EOL sequence, and it doesn't
|
||||
fold long lines. This is a replacement for that script.
|
||||
|
||||
=head1 TODO
|
||||
|
||||
If TZ not set, grab out of system config somewhere
|
||||
Detect recurring events.
|
||||
If I'm REALLY smart, derive RRULE
|
||||
Handle characters not in US-ASCII. Latin1? UTF8?
|
||||
|
||||
=head1 VERSION HISTORY
|
||||
|
||||
=over 8
|
||||
|
||||
=item version 0.1 2007-02-08
|
||||
|
||||
First cut.
|
||||
|
||||
=item version 0.2 2007-02-09
|
||||
|
||||
Reorg into multipass over a data structure.
|
||||
|
||||
=item version 0.3 2007-02-10
|
||||
|
||||
Collapse repeating events. Fold output lines.
|
||||
|
||||
=item version 0.9 2007-02-11
|
||||
|
||||
POD. Command line options. First public release.
|
||||
|
||||
=item version 0.91 2007-02-14
|
||||
|
||||
Bug fix, error message for non-recurring events
|
||||
|
||||
=item version 0.92 2008-01-28
|
||||
|
||||
Bug fix,
|
||||
rem2ics 0.91 chokes on timed reminders with
|
||||
duration using `remind -s` as it functions in remind-03.01.03.
|
||||
Remind 3.01 changed how the -s data is formated for events that have a duration
|
||||
Patch by Paul Hinze E<lt>paul dot t dot hinze at gmail dot comE<gt>
|
||||
and Michael Schultz E<lt>mjschultz at gmail dot comE<gt>
|
||||
|
||||
=item version 0.93 2009-06-25
|
||||
|
||||
Add B<-usetag> option to allow for UIDs to stay the same across multiple runs
|
||||
by using the remind TAG clause.
|
||||
Patch by Tim Weber E<lt>scy at scytale dot nameE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<http://mark.atwood.name/code/rem2ics>
|
||||
|
||||
L<http://en.wikipedia.org/wiki/ICalendar>
|
||||
|
||||
L<http://tools.ietf.org/html/rfc2445>
|
||||
|
||||
L<https://dianne.skoll.ca/projects/remind/>
|
||||
|
||||
L<remind(1)>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright 2007,2008,2009 by Mark Atwood E<lt>me+rem2ics@mark.atwood.nameE<gt>. L<http://mark.atwood.name/>.
|
||||
|
||||
Please report bugs (with patches, if possible).
|
||||
|
||||
Inspired by Anthony J. Chivetta E<lt>achivetta@gmail.comE<gt>'s
|
||||
rem2ics in awk.
|
||||
|
||||
Thank you to Dianne Skoll E<lt>dianne@skoll.ca<gt> for Remind,
|
||||
and to the IETF calsch wg for the iCalendar specification.
|
||||
|
||||
=cut
|
||||
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
my $app_name = "rem2ics";
|
||||
my $app_version = "0.93";
|
||||
|
||||
# process the command line
|
||||
my %options;
|
||||
GetOptions(\%options, qw(man do norecurr usetag)) || pod2usage(2);
|
||||
pod2usage(-verbose => 2) if ($options{man});
|
||||
|
||||
unless ($options{do}) {
|
||||
print STDERR "Run \"$0 -man\" for information and usage examples.\n"
|
||||
. "Pay special attention to information about timezone.\n";
|
||||
exit(99);
|
||||
}
|
||||
|
||||
# grab the hostname
|
||||
# this is used as part of the UID property of each VEVENT
|
||||
my $ical_uid_hostname = $ENV{'HOSTNAME'};
|
||||
unless ($ical_uid_hostname) {
|
||||
print STDERR "Warning! "
|
||||
. "The environment variable HOSTNAME was not properly set.\n"
|
||||
. "Will use \"localhost\" in the RFC2445 UID property\n";
|
||||
$ical_uid_hostname = "localhost";
|
||||
}
|
||||
|
||||
# look for the TZ
|
||||
my $ical_tzid = undef;
|
||||
if (exists $ENV{'TZ'}) {
|
||||
$ical_tzid = $ENV{'TZ'};
|
||||
my %synonyms_for_gmt = (
|
||||
'' => 1, '0' => 1, 'z' => 1, 'zulu' => 1, 'greenwitch' => 1,
|
||||
'gmt' => 1, 'gmt+0' => 1, 'gmt-0' => 1, );
|
||||
if (exists $synonyms_for_gmt{lc($ical_tzid)}) {
|
||||
$ical_tzid = ''; # empty means GMT, below
|
||||
}
|
||||
} else {
|
||||
# leave it undefined, that has a meaning below
|
||||
}
|
||||
|
||||
# RFC2445 DTSTAMP property will be the time we started running ($^T)
|
||||
my ($ical_dtstamp);
|
||||
{
|
||||
my @gt = gmtime($^T);
|
||||
$ical_dtstamp = sprintf("%04d%02d%02dZ%02d%02d%02dZ",
|
||||
1900+$gt[5], $gt[4]+1, $gt[3],
|
||||
$gt[2], $gt[1], $gt[0]);
|
||||
}
|
||||
|
||||
my ($cnt, $v, @events);
|
||||
|
||||
$cnt = 0;
|
||||
foreach (<STDIN>) {
|
||||
$cnt++;
|
||||
|
||||
s/#.*//; # toss comments
|
||||
next if /^\s*$/; # skip blank lines
|
||||
chomp;
|
||||
|
||||
$v = undef;
|
||||
|
||||
# store the raw line
|
||||
$v->{src} = $_;
|
||||
$v->{cnt} = $cnt;
|
||||
|
||||
# split and parse the line
|
||||
# if we don't like it, skip it and go around again
|
||||
|
||||
# sf[0] = date, in yyyy/mm/dd format
|
||||
# sf[1] = special, usually "*"
|
||||
# sf[2] = tag, usually "*"
|
||||
# sf[3] = duration, in minutes
|
||||
# sf[4] = time, since midnight, in minutes
|
||||
# sf[5] = text
|
||||
|
||||
my @sf = split(' ', $_, 6);
|
||||
next unless ($sf[1] eq '*'); # ignore SPECIAL lines
|
||||
next unless (($sf[3] eq '*') or ($sf[3] =~ m/\d+/));
|
||||
next unless (($sf[4] eq '*') or ($sf[4] =~ m/\d+/));
|
||||
next unless (length($sf[5]) > 0);
|
||||
|
||||
my @dt = split('/', $sf[0], 3);
|
||||
next unless ($dt[0] =~ m/^\d{4}$/); # year
|
||||
next unless ($dt[1] =~ m/^\d{2}$/); # month
|
||||
next unless ($dt[2] =~ m/^\d{2}$/); # day
|
||||
|
||||
if ($sf[4] ne "*") { # a time was given
|
||||
# When an event has a time, remind -s "helpfully" also
|
||||
# puts it as text at the start of the text portion.
|
||||
# This takes the following form:
|
||||
# ##:##[a|p]m <rest of MSG>
|
||||
# or, if the event has a duration:
|
||||
# ##:##[a|p]m-##:##[a|p]m <rest of MSG>
|
||||
# Rather than a nasty regex, just splitting at the
|
||||
# first space does the trick.
|
||||
my($extra_time, $textmsg) = split(' ', $sf[5], 2);
|
||||
$sf[5] = $textmsg;
|
||||
}
|
||||
|
||||
$v->{sf} = \@sf;
|
||||
$v->{dt} = \@dt;
|
||||
|
||||
push @events, $v;
|
||||
}
|
||||
|
||||
# generate the "date time string" for each event
|
||||
foreach $v (@events) {
|
||||
if (${$v->{sf}}[4] eq "*") { # no time was given
|
||||
$v->{dts} = sprintf("%04d%02d%02d", @{$v->{dt}});
|
||||
} else { # a time was given
|
||||
my ($t_hr, $t_mn) = &idiv(${$v->{sf}}[4], 60);
|
||||
$v->{dts} = sprintf("%04d%02d%02dT%02d%02d00",
|
||||
@{$v->{dt}}, $t_hr, $t_mn);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
my(%grovel);
|
||||
|
||||
# if the user doesnt want recurrance detection
|
||||
unless ($options{norecurr}) {
|
||||
|
||||
# then dont put events in the grovel hash
|
||||
|
||||
foreach $v (@events) {
|
||||
# key is duration followed by text
|
||||
# \036 is "ASCII RS Record Separator"
|
||||
my $k = ${$v->{sf}}[3] . "\036" . ${$v->{sf}}[5];
|
||||
push @{$grovel{$k}}, $v;
|
||||
}
|
||||
|
||||
foreach my $k (keys %grovel) {
|
||||
if ((scalar @{$grovel{$k}}) > 1) {
|
||||
$v = ${$grovel{$k}}[0];
|
||||
$v->{recurlist} = \@{$grovel{$k}};
|
||||
foreach my $v0 (@{$grovel{$k}}) {
|
||||
$v0->{is_recurrance} = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# All of the individual events are in the @events array. All of the
|
||||
# unique combinations of duration/event name are the keys in the
|
||||
# %grovel hash, the elements of which are references to an arrays of
|
||||
# references to the events, in the same ordering as they we read by
|
||||
# us, which *ought* to be in datewise order. I don't know if "remind
|
||||
# -s" actually sorts into true chronological order. If it doesn't, we
|
||||
# might have a problem if a recurring event has two instances both on
|
||||
# the first day.
|
||||
|
||||
# Every event that is recurring has a "is_recurrance" property.
|
||||
# Additionally, (hopefully) the first/earliest event in a set of
|
||||
# recurrances has a "recurlist" property. The "recurlist" is a
|
||||
# reference to a list of references to each of the events. The first
|
||||
# one on that list will be the same event that has the "recurlist"
|
||||
# property. The "is_recurrance" property is a reference back to the
|
||||
# event that has the "recurlist" property.
|
||||
|
||||
foreach my $k (keys %grovel) {
|
||||
next if ((scalar @{$grovel{$k}}) <= 1);
|
||||
|
||||
my $recur_str = "";
|
||||
foreach $v (@{$grovel{$k}}) {
|
||||
if (${$v->{sf}}[4] eq "*") { # no time was given
|
||||
$recur_str .= ($v->{dts} . ",");
|
||||
} else {
|
||||
if (defined($ical_tzid)) {
|
||||
if ($ical_tzid eq '') { # tz is defined but empty, so in GMT
|
||||
$recur_str .= $v->{dts} . "Z,";
|
||||
} else { # tz is non-zero, so output the tz as well
|
||||
$recur_str .= $v->{dts} . ",";
|
||||
}
|
||||
} else { # undefined tz, just floating time
|
||||
$recur_str .= $v->{dts} . ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# the recur_str now has an extra comma at the end. chop it off
|
||||
chop($recur_str);
|
||||
${$grovel{$k}}[0]->{recur_str} = $recur_str;
|
||||
}
|
||||
|
||||
foreach my $k (keys %grovel) {
|
||||
next if ((scalar @{$grovel{$k}}) <= 1);
|
||||
my $v = ${$grovel{$k}}[0]; # grab the head of each list
|
||||
if (${$v->{sf}}[4] eq "*") { # no time was given
|
||||
# the default value type for an RDATE is DATE-TIME,
|
||||
# we much change the type to DATE
|
||||
$v->{i_rdate} = sprintf("RDATE;VALUE=DATE:");
|
||||
} else {
|
||||
if (defined($ical_tzid)) {
|
||||
if ($ical_tzid eq '') { # tz is defined but empty, so in GMT
|
||||
$v->{i_rdate} = sprintf("RDATE:");
|
||||
} else { # tz is non-zero, so output the tz as well
|
||||
$v->{i_rdate} = sprintf("RDATE;TZID=%s:", $ical_tzid);
|
||||
}
|
||||
} else { # undefined tz, just floating time
|
||||
$v->{i_rdate} = sprintf("RDATE:");
|
||||
}
|
||||
}
|
||||
# now stick the recur_str onto the end
|
||||
$v->{i_rdate} .= $v->{recur_str};
|
||||
# if we ever get memory tight, we can probably undef($v->{recur_str})
|
||||
}
|
||||
|
||||
foreach $v (@events) {
|
||||
# for recurrant events, skip those that arnt the "head"
|
||||
next if ($v->{is_recurrance} and (not $v->{recurlist}));
|
||||
|
||||
if (${$v->{sf}}[4] eq "*") { # no time was given
|
||||
$v->{i_dtstart} = sprintf("DTSTART:%s", $v->{dts});
|
||||
} else {
|
||||
if (defined($ical_tzid)) {
|
||||
if ($ical_tzid eq '') { # tz is defined but empty, so in GMT
|
||||
$v->{i_dtstart} = sprintf("DTSTART:%sZ", $v->{dts});
|
||||
} else { # tz is non-zero, so output the tz as well
|
||||
$v->{i_dtstart} = sprintf("DTSTART;TZID=%s:%s",
|
||||
$ical_tzid, $v->{dts});
|
||||
}
|
||||
} else { # undefined tz, just floating time
|
||||
$v->{i_dtstart} = sprintf("DTSTART:%s", $v->{dts});
|
||||
}
|
||||
}
|
||||
|
||||
if (${$v->{sf}}[3] ne "*") { # a duration was given
|
||||
# It's convienient that RFC2445 defines DURATION, thus we
|
||||
# don't need to calculate DTEND, with awkward figuring out
|
||||
# crossing hours, days, months, year, etc. Instead we
|
||||
# will let the iCalendar consuming application worry about it.
|
||||
$v->{i_duration} = sprintf("PT%dM", ${$v->{sf}}[3]);
|
||||
}
|
||||
}
|
||||
|
||||
# output header
|
||||
print "BEGIN:VCALENDAR\015\012"
|
||||
. "VERSION:2.0\015\012"
|
||||
. "PRODID:http://mark.atwood.name/code/rem2ics"
|
||||
. " $app_name $app_version\015\012";
|
||||
|
||||
# output each vevent
|
||||
foreach $v (@events) {
|
||||
# for recurrant events, only output the "head", skip the others
|
||||
next if ($v->{is_recurrance} and (not $v->{recurlist}));
|
||||
|
||||
print "BEGIN:VEVENT\015\012";
|
||||
my $tag = ${$v->{sf}}[2];
|
||||
# if $tag is not set, fake up a UID from start time, process id & input line count
|
||||
if ($tag eq "*" || !$options{usetag}) {
|
||||
$tag = sprintf("%x.%x.%x", $^T, $$, $v->{cnt});
|
||||
}
|
||||
# add rem2ics and hostname to UID
|
||||
print &lineify(sprintf("UID:rem2ics.%s@%s",
|
||||
$tag, $ical_uid_hostname));
|
||||
print &lineify("SUMMARY:" . "ify(${$v->{sf}}[5]));
|
||||
print &lineify($v->{i_dtstart});
|
||||
print &lineify("DURATION:" . $v->{i_duration})
|
||||
if ($v->{i_duration});
|
||||
print &lineify($v->{i_rdate})
|
||||
if ($v->{i_rdate});
|
||||
print &lineify("DTSTAMP:" . $ical_dtstamp);
|
||||
print &lineify("COMMENT: generated by $app_name $app_version\\n"
|
||||
. " http://mark.atwood.name/code/rem2ics\\n"
|
||||
. " data[" . $v->{cnt} . "]=|" . "ify($v->{src}) . "|");
|
||||
print "END:VEVENT\015\012";
|
||||
}
|
||||
|
||||
# output trailer
|
||||
print "END:VCALENDAR\015\012";
|
||||
|
||||
|
||||
# integer division, return both quotient and remainder
|
||||
sub idiv {
|
||||
my $n = shift; my $d = shift;
|
||||
my $r = $n; my $q = 0;
|
||||
while ($r >= $d) {
|
||||
$r = $r - $d;
|
||||
$q = $q + 1;
|
||||
}
|
||||
return ($q, $r);
|
||||
}
|
||||
|
||||
# todo, perl5 version that defines ()*, need to specify a requires up top
|
||||
sub lineify {
|
||||
return join("\015\012 ", unpack('(A72)*', shift)) . "\015\012";
|
||||
}
|
||||
|
||||
sub quotify {
|
||||
my $s = shift;
|
||||
return $s if $s =~ m/^(\w| )*$/;
|
||||
|
||||
$s =~ s/\\/\\\\/gso;
|
||||
$s =~ s/\n/\\n/gso;
|
||||
$s =~ s/\s/ /gso;
|
||||
$s =~ s/\"/\\"/gso;
|
||||
$s =~ s/\,/\\,/gso;
|
||||
$s =~ s/\:/\\:/gso;
|
||||
$s =~ s/\;/\\;/gso;
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
EOF
|
||||
50
contrib/rem2ics-0.93/rem2ics.spec
Normal file
50
contrib/rem2ics-0.93/rem2ics.spec
Normal file
@@ -0,0 +1,50 @@
|
||||
Name: rem2ics
|
||||
Version: 0.93
|
||||
Release: 1%{?dist}
|
||||
Summary: Converts the output of "remind -s" into RFC2445 iCalendar format
|
||||
|
||||
Group: Applications/Productivity
|
||||
License: GPLv2+
|
||||
URL: http://mark.atwood.name/code/rem2ics/
|
||||
Source0: http://mark.atwood.name/code/rem2ics/rem2ics-%{version}.tar.gz
|
||||
Source1: rem2ics-Makefile
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
BuildArch: noarch
|
||||
BuildRequires: perl
|
||||
|
||||
|
||||
%description
|
||||
rem2ics converts the output of "remind -s" into RFC2445 iCalendar format.
|
||||
You may want to install remind if you install this package.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q -c
|
||||
cp -a %SOURCE1 Makefile
|
||||
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags}
|
||||
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir $RPM_BUILD_ROOT
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc
|
||||
%{_bindir}/rem2ics
|
||||
%{_mandir}/man1/rem2ics.1*
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Mar 25 2008 Till Maas <opensource till name> - 0.92-1
|
||||
- initial spec for Fedora
|
||||
56
contrib/remind-conf-mode.06/ac-remind.el
Normal file
56
contrib/remind-conf-mode.06/ac-remind.el
Normal file
@@ -0,0 +1,56 @@
|
||||
;;; setup for remind autocompletion (totally optional)
|
||||
|
||||
;; put something like
|
||||
;; (add-hook 'remind-conf-mode '(load-library "ac-remind")) in your .emacs file.
|
||||
(require 'auto-complete)
|
||||
|
||||
(define-key ac-complete-mode-map "\r" nil)
|
||||
|
||||
(defvar ac-remind-keywords
|
||||
'((candidates
|
||||
. (lambda ()
|
||||
(all-completions ac-target remind-keywords ))))
|
||||
"Source for remind-conf completion keywords.")
|
||||
|
||||
(defvar ac-remind-time-words
|
||||
'((candidates
|
||||
. (lambda ()
|
||||
(all-completions ac-target remind-time-words))))
|
||||
"Source for remind-conf time words completions.")
|
||||
|
||||
(defvar ac-remind-builtin-variables
|
||||
'((candidates
|
||||
. (lambda ()
|
||||
(all-completions ac-target remind-builtin-variables))))
|
||||
"Source for remind-conf builtin variables.")
|
||||
|
||||
(defvar ac-remind-type-keywords
|
||||
'((candidates
|
||||
. (lambda ()
|
||||
(all-completions ac-target remind-type-keywords))))
|
||||
"Source for remind-conf type keywords.")
|
||||
|
||||
(defvar ac-remind-builtin-functions
|
||||
'((candidates
|
||||
. (lambda ()
|
||||
(all-completions ac-target remind-builtin-functions))))
|
||||
"Source for remind-conf completion builtin functions.")
|
||||
|
||||
(add-hook 'remind-conf-mode-hook
|
||||
(lambda () "Makes auto-completion work in remind-conf-mode"
|
||||
(make-local-variable 'ac-sources)
|
||||
(setq ac-sources '(ac-remind-keywords
|
||||
ac-remind-builtin-variables
|
||||
ac-remind-builtin-functions
|
||||
ac-remind-type-keywords
|
||||
ac-remind-time-words
|
||||
ac-source-abbrev))
|
||||
(auto-complete-mode 1)))
|
||||
|
||||
(provide 'ac-remind)
|
||||
;; (define-skeleton ac-look
|
||||
;; ""
|
||||
;; (skeleton-read "well? ")
|
||||
;; "(when (looking-at (regexp-opt remind-" str " 'words))" \n
|
||||
;; >"(setq ac-sources '(ac-remind-" str ")))"
|
||||
;; )
|
||||
444
contrib/remind-conf-mode.06/remind-conf-mode.el
Normal file
444
contrib/remind-conf-mode.06/remind-conf-mode.el
Normal file
@@ -0,0 +1,444 @@
|
||||
;;; remind-conf-mode.el --- A mode to help configure remind.
|
||||
|
||||
;; Copyright (C) 2008 Shelagh Manton <shelagh.manton@gmail.com>
|
||||
|
||||
;; Author: Shelagh Manton <shelagh.manton@gmail.com> with help from
|
||||
;; Dianne Skoll
|
||||
;; Keywords: remind configure mode
|
||||
;; Version: .04
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 2
|
||||
;; of the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software
|
||||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
;; 02111-1307, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Use this mode to help with the configuration of remind configuration files.
|
||||
;; Put (require 'remind-conf-mode) in your .emacs file
|
||||
;; or (autoload 'remind-conf-mode "remind-conf-mode" "Mode to help with remind files" t)
|
||||
;; also put (add-to-list 'auto-mode-alist '("\\.rem\\'" . remind-conf-mode)) and
|
||||
;; (setq auto-mode-alist
|
||||
;; (cons '(".reminders$" . remind-conf-mode) auto-mode-alist))
|
||||
;; if you want to have the mode work automatically when you open a remind configuration file.
|
||||
|
||||
;; If you want to use the auto-complete stuff, you will need to download and install the
|
||||
;; auto-complete library from http://www.cx4a.org/pub/auto-complete.el and put
|
||||
;; (require 'auto-complete) in your emacs with
|
||||
;; (add-hook 'remind-conf-mode-hook
|
||||
;; (lambda ()
|
||||
;; (make-local-variable 'ac-sources)
|
||||
;; (setq ac-sources '(ac-remind-conf ac-remind-builtin-variables ac-remind-builtin-functions))
|
||||
;; (auto-complete t)))
|
||||
;; in your .emacs file
|
||||
|
||||
;; PS. you could add ac-source-abbrev ac-source-words-in-buffer to have abbrevs and
|
||||
;; other words in buffer auto-complete too
|
||||
|
||||
;;; History:
|
||||
;; Thu, Feb 14, 2008
|
||||
;; Based mode on wpld-mode tutorial and sample-mode on emacs wiki.
|
||||
;; Ideas from mupad.el for font-lock styles.
|
||||
;; Mon, Jan 26, 2008
|
||||
;; Added rem-setup-colors to make it easy for colourised remind output.
|
||||
;; Added a demo skeleton for people to copy for easy entry of coloured remind entries.
|
||||
;; tried to hook in the auto-complete library so that all known functions and keywords can be easily entered.
|
||||
;; EXPERIMENTAL, but seems to work well here (emacs cvs).
|
||||
;; Seems to work without case folding which is nice. wonder why it didn't yesterday?
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
||||
(require 'font-lock); this goes in the define-derived-mode part.
|
||||
(when (featurep 'xemacs)
|
||||
(require 'overlay)) ;I wonder if this will help with font-lock and xemacs?
|
||||
|
||||
|
||||
(defgroup remind-conf nil
|
||||
"Options for remind-conf-mode."
|
||||
:group 'remind-conf
|
||||
:prefix "remind-conf-")
|
||||
|
||||
|
||||
(defvar remind-conf-mode-hook nil
|
||||
"Hook to run in `remind-conf-mode'.")
|
||||
|
||||
;; keymap
|
||||
|
||||
(defvar remind-conf-mode-map
|
||||
(let ((remind-conf-mode-map (make-sparse-keymap)))
|
||||
remind-conf-mode-map)
|
||||
"Keymap for `remind-conf-mode'.")
|
||||
|
||||
(define-key remind-conf-mode-map "\C-cr" 'rem-skel)
|
||||
(define-key remind-conf-mode-map "\C-ct" 'rem-today)
|
||||
(define-key remind-conf-mode-map "\C-cd" 'rem-today-skel)
|
||||
(define-key remind-conf-mode-map "\C-cw" 'rem-week-away)
|
||||
(define-key remind-conf-mode-map "\C-cx" 'rem-tomorrow)
|
||||
(define-key remind-conf-mode-map "\C-ca" 'rem-days-away)
|
||||
(define-key remind-conf-mode-map "\M-j" 'remind-indent-line)
|
||||
(define-key remind-conf-mode-map (kbd "RET") 'remind-indent-line)
|
||||
(define-key remind-conf-mode-map "\C-c\C-c" 'rem-save-file)
|
||||
|
||||
;; syntax-table
|
||||
|
||||
(defvar remind-conf-syntax-table
|
||||
(let ((remind-conf-syntax-table (make-syntax-table text-mode-syntax-table)))
|
||||
(modify-syntax-entry ?\; ". 1b" remind-conf-syntax-table)
|
||||
(modify-syntax-entry ?\# ". 1b" remind-conf-syntax-table)
|
||||
(modify-syntax-entry ?\n "> b" remind-conf-syntax-table)
|
||||
;Names with _ are still one word.
|
||||
(modify-syntax-entry ?_ "w" remind-conf-syntax-table)
|
||||
(modify-syntax-entry ?. "w" remind-conf-syntax-table)
|
||||
remind-conf-syntax-table)
|
||||
"Syntax table for `remind-conf-mode'.")
|
||||
|
||||
;;; keyword sets
|
||||
|
||||
(defconst remind-keywords
|
||||
(sort
|
||||
(list "RUN" "REM" "ONCE" "SATISFY" "BEFORE" "UNSET" "OMIT"
|
||||
"OMIT" "DATE" "SKIP" "ONCE" "AFTER" "WARN" "PRIORITY" "AT" "SCHED" "IF" "ELSE" "ENDIF"
|
||||
"WARN" "UNTIL" "THROUGH" "SCANFROM" "DURATION" "TAG" "MSG" "MSF" "CAL" "SPECIAL" "IFTRIG"
|
||||
"PS" "PSFILE" "BANNER" "INCLUDE" "PUSH-OMIT-CONTEXT" "DEBUG" "DUMPVARS"
|
||||
"CLEAR-OMIT-CONTEXT" "POP-OMIT-CONTEXT" "SET" "ERRMSG" "FSET"
|
||||
"EXIT" "FLUSH" "PRESERVE" "MOON" "COLOR" "COLOUR")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
(defconst remind-type-keywords
|
||||
(sort
|
||||
(list "INT" "STRING" "TIME" "DATE" "SHADE")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
(defconst remind-builtin-variables
|
||||
(sort
|
||||
(list "$CalcUTC" "$CalMode" "$DefaultPrio" "$EndSent" "$EndSentIg" "$NumTrig"
|
||||
"$FirstIndent" "$FoldYear" "$FormWidth" "$MinsFromUTC" "$LatDeg" "$LatMin" "$LatSec"
|
||||
"$Location" "$LongDeg" "$LongMin" "$LongSec" "$MaxSatIter" "$SubsIndent")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
(defconst remind-time-words
|
||||
(sort
|
||||
(list "Jan" "January" "Feb" "Mar" "Apr" "Jun" "Jul" "Aug" "Sept" "Sep" "Oct" "Nov" "Dec" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December" "Mon" "Monday" "Tue" "Tues" "Tuesday" "Wed" "Wednesday" "Thu" "Thursday" "Fri" "Friday" "Saturday" "Sat" "Sun" "Sunday")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "abs" "access" "shell" "args" "asc" "baseyr" "char" "choose" "coerce" "date"
|
||||
"dawn" "today" "day" "daysinmon" "defined" "dosubst" "dusk" "easterdate" "easter"
|
||||
"filedir" "filename" "getenv" "hour" "iif" "trigger" "index" "isdst" "isleap"
|
||||
"isomitted" "hebdate" "hebday" "hebmon" "hebyear" "language" "ord" "thisyear"
|
||||
"sunrise" "sunset" "lower" "max" "min" "minute" "mon" "moondate" "moontime"
|
||||
"moonphase" "now" "ostype" "plural" "realnow" "realtoday" "sgn" "strlen" "psshade"
|
||||
"substr" "trigdate" "trigger" "trigtime" "trigvalid" "typeof" "upper" "psmoon"
|
||||
"value" "version" "wkday" "wkdaynum" "msgprefix" "msgsuffix" "year")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
;;; faces
|
||||
;;example of setting up special faces for a mode.
|
||||
|
||||
(defvar remind-conf-command-face 'remind-conf-command-face
|
||||
"Remind commands.")
|
||||
(defface remind-conf-command-face
|
||||
'((t :foreground "SeaGreen4" :bold t))
|
||||
"Font Lock mode face used to highlight commands."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-keyword-face 'remind-conf-keyword-face
|
||||
"Remind keywords.")
|
||||
(defface remind-conf-keyword-face
|
||||
'((t :foreground "blue violet"))
|
||||
"Font Lock mode face used to highlight keywords."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-substitutes-face 'remind-conf-substitutes-face
|
||||
"Remind substitutes.")
|
||||
(defface remind-conf-substitutes-face
|
||||
'((t :foreground "blue2"))
|
||||
"Font Lock mode face used to highlight substitutes."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-endline-face 'remind-conf-endline-face
|
||||
"Remind endline.")
|
||||
(defface remind-conf-endline-face
|
||||
'((t :foreground "goldenrod2" :bold t))
|
||||
"Font Lock mode face used to highlight commands."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-variable-face 'remind-conf-variable-face
|
||||
"Remind variable.")
|
||||
(defface remind-conf-variable-face
|
||||
'((t :foreground "DeepPink2" :bold t))
|
||||
"Font Lock mode face used to highlight commands."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-color-face 'remind-conf-color-face
|
||||
"Remind color variables.")
|
||||
(defface remind-conf-color-face
|
||||
'((t :foreground "gold" :bold t))
|
||||
"Font Lock mode face used to highlight color changes."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-delta-face 'remind-conf-delta-face
|
||||
"Remind deltas.")
|
||||
(defface remind-conf-delta-face
|
||||
'((t :foreground "sandy brown" :bold t))
|
||||
"Font Lock mode face used to highlight deltas."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-comment-face 'remind-comment-face
|
||||
"Remind comments.")
|
||||
(defface remind-comment-face
|
||||
'((t :foreground "brown"))
|
||||
"Font-lock face for highlighting comments."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-string-face 'remind-string-face
|
||||
"Remind strings.")
|
||||
(defface remind-string-face
|
||||
'((t :foreground "tomato"))
|
||||
"Font lock mode face used to highlight strings."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-time-face 'remind-time-face
|
||||
"Remind time words.")
|
||||
(defface remind-time-face
|
||||
'((t :foreground "LightSeaGreen" :bold t))
|
||||
"Font lock mode face to highlight time phrases."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defvar remind-conf-type-face 'remind-conf-type-face
|
||||
"Remind type keywords.")
|
||||
(defface remind-conf-type-face
|
||||
'((t :foreground "orange" :bold t))
|
||||
"Font lock mode face to highlight type keywords."
|
||||
:group 'remind-conf)
|
||||
|
||||
(defcustom rem-post-save-function ""
|
||||
"Name of shell function that can be run when you save and close a remind file.
|
||||
|
||||
If you put a & after the name of the function, it will run asyncronously. This might
|
||||
be useful if the process takes a long time."
|
||||
:type 'string
|
||||
:group 'remind-conf
|
||||
)
|
||||
|
||||
;; keywords
|
||||
|
||||
(defconst remind-conf-font-lock-keywords-1
|
||||
(list
|
||||
'("^[\;\#]\\s-+.*$" . remind-comment-face)
|
||||
(cons (regexp-opt remind-keywords 'words) remind-conf-keyword-face)
|
||||
'("%[\"_]" . font-lock-warning-face)
|
||||
'("\\(%[a-mops-w]\\)" . remind-conf-substitutes-face)
|
||||
'("\"[^\"]*\"" . remind-string-face))
|
||||
"Minimal font-locking for `remind-conf-mode'.")
|
||||
|
||||
(defconst remind-conf-font-lock-keywords-2
|
||||
(append remind-conf-font-lock-keywords-1
|
||||
(list
|
||||
(cons (regexp-opt remind-time-words 'words) remind-time-face)
|
||||
(cons (regexp-opt remind-builtin-functions 'words) remind-conf-command-face)
|
||||
'("%$" . remind-conf-endline-face)))
|
||||
"Additional commands to highlight in `remind-conf-mode'.")
|
||||
|
||||
(defconst remind-conf-font-lock-keywords-3
|
||||
(append remind-conf-font-lock-keywords-2
|
||||
(list
|
||||
(cons (regexp-opt remind-type-keywords 'words) remind-conf-type-face)
|
||||
'("\[[a-zA-Z]\\{3,6\\}\]" . remind-conf-color-face)
|
||||
'("\\s-+\\([12][0-9]\\|3[01]\\|0?[0-9]\\)\\s-+" . remind-conf-substitutes-face);better date regexp
|
||||
'("\\s-+\\(\\(?:20\\|19\\)[0-9][0-9]\\)\\s-+" . remind-conf-substitutes-face);years
|
||||
'("\\s-+\\(2[0-4]\\|[01]?[0-9][.:][0-5][0-9]\\)\\s-+" . remind-conf-substitutes-face);24hour clock, more precise
|
||||
'("\\s-+\\([+-][+-]?[1-9][0-9]*\\)\\s-+" 1 remind-conf-delta-face prepend)
|
||||
(cons (regexp-opt remind-builtin-variables 'words) remind-conf-variable-face)))
|
||||
"The ultimate in highlighting experiences for `remind-conf-mode'.")
|
||||
|
||||
(defcustom remind-conf-font-lock-keywords 'remind-conf-font-lock-keywords-3
|
||||
"Font-lock highlighting level for `remind-conf-mode'."
|
||||
:group 'remind-conf
|
||||
:type '(choice (const :tag "Barest minimum of highlighting." remind-conf-font-lock-keywords-1)
|
||||
(const :tag "Medium highlighting." remind-conf-font-lock-keywords-2)
|
||||
(const :tag "Highlighting deluxe." remind-conf-font-lock-keywords-3)))
|
||||
|
||||
;;; Indentation (I'm sure this could be made more simple. But at least it works.)
|
||||
|
||||
(defcustom remind-indent-level 4
|
||||
"User definable indentation."
|
||||
:group 'remind-conf
|
||||
:type '(integer)
|
||||
)
|
||||
|
||||
(defun remind-indent-line ()
|
||||
"Indent current line for remind configuration files."
|
||||
(interactive)
|
||||
(forward-line 0) ;remember this happens on every line as it is done per line basis
|
||||
(if (bobp)
|
||||
(indent-line-to 0)
|
||||
(let ((not-indented t) cur-indent)
|
||||
(if (looking-at "^[ \t]*\\<\\(ENDIF\\|POP\\(?:-OMIT-CONTEXT\\)?\\)\\>")
|
||||
(progn
|
||||
(save-excursion
|
||||
(forward-line -1)
|
||||
(setq cur-indent (- (current-indentation) remind-indent-level))) ;note that not-indented is still t
|
||||
(if (< cur-indent 0) (setq cur-indent 0)))
|
||||
(save-excursion
|
||||
(while not-indented
|
||||
(forward-line -1)
|
||||
(if (looking-at "^[ \t]*\\<\\(ENDIF\\|POP\\(?:-OMIT-CONTEXT\\)?\\)\\>")
|
||||
(progn
|
||||
(setq cur-indent 0)
|
||||
(delete-horizontal-space) ;don't know why I need this when other similar indent functions don't.
|
||||
(setq not-indented nil))
|
||||
(if (looking-at "\\<\\(IF\\(?:TRIG\\)?\\|PUSH\\(?:-OMIT-CONTEXT\\)?\\)\\>")
|
||||
(progn
|
||||
(setq cur-indent remind-indent-level)
|
||||
(setq not-indented nil))
|
||||
(if (bobp)
|
||||
(setq not-indented nil))))))
|
||||
(if cur-indent
|
||||
(indent-line-to cur-indent)
|
||||
(indent-line-to 0))))))
|
||||
|
||||
;;; Convenience functions
|
||||
|
||||
(define-skeleton rem-skel
|
||||
"Skeleton to insert a rem line in a remind configuration file."
|
||||
nil
|
||||
"REM "(skeleton-read "Date? " )
|
||||
("Optional: How many days ahead? " " +" str )
|
||||
resume:
|
||||
("Optional: At what time? Format eg 13:00. " " AT " str)
|
||||
resume:
|
||||
("Optional: How many minutes ahead? " " +" str )
|
||||
resume:
|
||||
("Optional: At what priority? eg 0-9999" " PRIORITY " str )
|
||||
resume:
|
||||
" MSG %\"" (skeleton-read "Your message? " )"%b%\"%" \n
|
||||
)
|
||||
|
||||
(define-skeleton rem-today-skel
|
||||
"Skeleton to insert a line for today's date."
|
||||
nil
|
||||
"REM " (format-time-string "%d %b %Y")
|
||||
("Optional: At what time? Format eg 13:20. " " AT " str)
|
||||
resume:
|
||||
("Optional: How many minutes ahead? " " +" str )
|
||||
resume:
|
||||
("Optional: At what priority? eg 0-9999" " PRIORITY " str )
|
||||
resume:
|
||||
" MSG " (skeleton-read "Your message? " )"%b.%" \n
|
||||
)
|
||||
|
||||
(defun rem-today ()
|
||||
"Insert the date for today in a remind friendly style."
|
||||
(interactive)
|
||||
(insert (format-time-string "%e %b %Y")))
|
||||
|
||||
(defun rem-tomorrow ()
|
||||
"Insert tomorrow's date in a remind friendly style."
|
||||
(interactive)
|
||||
(insert (format-time-string "%e %b %Y" (time-add (current-time) (days-to-time 1)))))
|
||||
|
||||
(defun rem-days-away (arg)
|
||||
"Insert a day N number of days in the future.
|
||||
|
||||
Takes a prefix argument, but defaults to 4."
|
||||
(interactive "nHow many Days?: ")
|
||||
(insert (format-time-string "%e %b %Y" (time-add (current-time) (days-to-time arg)))))
|
||||
|
||||
(defun rem-week-away ()
|
||||
"Insert a day 7 days in the future."
|
||||
(interactive)
|
||||
(insert (format-time-string "%e %b %Y" (time-add (current-time) (days-to-time 7)))))
|
||||
|
||||
(setq skeleton-end-hook nil) ; so the skeletons will not automatically go to a new line.
|
||||
|
||||
;;; private function
|
||||
;; could make it useful for others. Put somethin like the following in your .emacs
|
||||
;(setq rem-post-save-function "~/bin/dailypic &")
|
||||
|
||||
(defun rem-save-file ()
|
||||
"Save the file and start the shell function in one go.
|
||||
|
||||
This function will close the window after running. It needs the
|
||||
variable `rem-post-save-function' to be set. It will be most
|
||||
useful to people who have some sort of function they run to use
|
||||
remind data ie procucing calendars."
|
||||
(interactive)
|
||||
(if (boundp 'rem-post-save-function)
|
||||
(progn (save-buffer)
|
||||
(shell-command rem-post-save-function)
|
||||
(kill-buffer-and-window))
|
||||
(error "`rem-post-save-function' variable is not set")))
|
||||
|
||||
(defun rem-setup-colors ()
|
||||
"Insert set of variables for coloured output in remind messages."
|
||||
(interactive)
|
||||
(find-file (expand-file-name "~/.reminders"))
|
||||
(goto-char 0) ;we do want it somewhere near the top of the file.
|
||||
(save-excursion
|
||||
(re-search-forward "\n\n"); squeeze it in where you have a free line.
|
||||
(insert "\nSET Esc CHAR(27)
|
||||
SET Nrm Esc + \"[0m\"
|
||||
SET Blk Esc + \"[0;30m\"
|
||||
SET Red Esc + \"[0;31m\"
|
||||
SET Grn Esc + \"[0;32m\"
|
||||
SET Ylw Esc + \"[0;33m\"
|
||||
SET Blu Esc + \"[0;34m\"
|
||||
SET Mag Esc + \"[0;35m\"
|
||||
SET Cyn Esc + \"[0;36m\"
|
||||
SET Wht Esc + \"[0;37m\"
|
||||
SET Gry Esc + \"[30;1m\"
|
||||
SET BrRed Esc + \"[31;1m\"
|
||||
SET BrGrn Esc + \"[32;1m\"
|
||||
SET BrYlw Esc + \"[33;1m\"
|
||||
SET BrBlu Esc + \"[34;1m\"
|
||||
SET BrMag Esc + \"[35;1m\"
|
||||
SET BrCyn Esc + \"[36;1m\"
|
||||
SET BrWht Esc + \"[37;1m\" \n \n")))
|
||||
|
||||
;; So now you can do things like:
|
||||
|
||||
(define-skeleton birthcol
|
||||
"Make birthdays magenta.
|
||||
Acts on the region or places point where it needs to be."
|
||||
nil
|
||||
"[Mag]" _ " [Nrm]")
|
||||
|
||||
;; finally the derived mode.
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode remind-conf-mode text-mode "REM"
|
||||
"Major mode for editing remind calendar configuration files.
|
||||
|
||||
\\{remind-conf-mode-map}"
|
||||
:syntax-table remind-conf-syntax-table
|
||||
(set (make-local-variable 'font-lock-keywords-case-fold-search) t) ;this is not working atm 2009-04-13
|
||||
(set (make-local-variable 'font-lock-defaults) '(remind-conf-font-lock-keywords))
|
||||
(set (make-local-variable 'comment-start) ";")
|
||||
(set (make-local-variable 'comment-start) "#")
|
||||
(set (make-local-variable 'comment-end) "\n")
|
||||
(set (make-local-variable 'fill-column) '100);cause I was having problems with autofill.
|
||||
(set (make-local-variable 'indent-line-function) 'remind-indent-line)
|
||||
(use-local-map remind-conf-mode-map)
|
||||
)
|
||||
|
||||
|
||||
(provide 'remind-conf-mode)
|
||||
;;; remind-conf-mode.el ends here
|
||||
|
||||
;;; Indentation code
|
||||
;;; work out how to make the syntax highlighting work only before the (MSG|MSF)
|
||||
;;; keywords and not after.
|
||||
;;; for my own use. keymap to save file and do dailypic C-c C-c in time honoured tradition?
|
||||
@@ -1,4 +1,4 @@
|
||||
REMIND version 3.1 for UNIX
|
||||
REMIND version 3.2 for UNIX
|
||||
|
||||
REMIND is a sophisticated alarm/calendar program. Details are given
|
||||
in the man page, "remind.1".
|
||||
@@ -6,16 +6,16 @@ in the man page, "remind.1".
|
||||
INSTALLING REMIND:
|
||||
-----------------
|
||||
|
||||
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X Windows:
|
||||
--------------------------------------------------------------
|
||||
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X11:
|
||||
----------------------------------------------------------------------
|
||||
|
||||
1) Type: wish ./build.tk from the top-level Remind directory.
|
||||
Fill in the various options and hit "Build Remind"
|
||||
|
||||
2) Type: "make install" -- you may need to be root to do this.
|
||||
|
||||
If you do NOT have Tcl/Tk or are NOT running X Windows:
|
||||
-------------------------------------------------------
|
||||
If you do NOT have Tcl/Tk or are NOT running X11:
|
||||
-------------------------------------------------
|
||||
|
||||
1) Edit the file "src/custom.h" according to your preferences.
|
||||
|
||||
@@ -73,12 +73,12 @@ RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
|
||||
|
||||
1. POPUP REMINDERS
|
||||
|
||||
If you're running under X-Windows and you have the TCL tools,
|
||||
you can create simple pop-up reminders by creating the following
|
||||
TCL script called 'popup'. It pops a message on to the screen and
|
||||
waits for you to press the 'OK' button. If you don't press the OK button
|
||||
within 15 seconds, it exits anyway. To use it, you can use the '-k' option
|
||||
for Remind as follows:
|
||||
If you're running under X11 and you have the Tcl tools, you can create
|
||||
simple pop-up reminders by creating the following Tcl script called
|
||||
'popup'. It pops a message on to the screen and waits for you to
|
||||
press the 'OK' button. If you don't press the OK button within 15
|
||||
seconds, it exits anyway. To use it, you can use the '-k' option for
|
||||
Remind as follows:
|
||||
|
||||
remind "-kpopup '%s'&" .reminders
|
||||
|
||||
@@ -93,12 +93,12 @@ Norman Walsh.
|
||||
#!/usr/local/bin/wish
|
||||
wm withdraw .
|
||||
after 15000 { destroy . ; exit }
|
||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
||||
destroy .
|
||||
exit
|
||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
||||
|
||||
|
||||
--
|
||||
David F. Skoll <dfs@roaringpenguin.com>
|
||||
http://www.roaringpenguin.com/remind/
|
||||
Dianne Skoll <dianne@skoll.ca>
|
||||
https://dianne.skoll.ca/projects/remind/
|
||||
|
||||
340
docs/WHATSNEW
340
docs/WHATSNEW
@@ -1,5 +1,332 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.2 Patch 0 - 2020-01-03
|
||||
|
||||
- IMPROVEMENT: Add support for events spanning multiple days (with AT
|
||||
and DURATION). Add trigeventstart() and trigeventduration()
|
||||
introspection functions; see "MULTI-DAY EVENTS" in the man page.
|
||||
|
||||
- IMPROVEMENT: Add introspection functions trigback(), trigdelta(),
|
||||
trigduration(), trigfrom(), trigpriority(), trigrep(),
|
||||
trigscanfrom(), trigtimedelta(), trigtimerep(), and triguntil(). See
|
||||
man page for details; thanks to Tim Chase for the suggestion.
|
||||
|
||||
- IMPROVEMENT: TkRemind: Use PNG images for the next month / previous
|
||||
month buttons rather than -> and <-. Also use nice anti-aliased
|
||||
moon phase images instead of ugly blocky bitmaps.
|
||||
|
||||
- CHANGE: Modify addition so that previously-illegal combinations
|
||||
TIME + TIME, TIME + DATETIME and DATETIME + TIME are now allowed.
|
||||
Also allow DATETIME - TIME. If t1 and t2 are expressions of type TIME
|
||||
and dt is an expression of type DATETIME, then the following are now
|
||||
equivalent (before, the expressions on the left-hand side would fail
|
||||
with a "Type mismatch" error.)
|
||||
|
||||
t1 + t2 == t1 + coerce("INT", t2)
|
||||
dt + t2 == dt + coerce("INT", t2)
|
||||
t1 + dt == coerce("INT", t1) + dt
|
||||
dt - t2 == dt - coerce("INT", t2)
|
||||
|
||||
- DOC FIX: Document previously-undocumented $MaxStringLen system variable
|
||||
|
||||
- DOC FIX: Various minor documentation fixes.
|
||||
|
||||
- BUG FIX: Specifying a DURATION without an AT clause results in an error.
|
||||
Before, it would be accepted but not do anything useful.
|
||||
|
||||
- BUG FIX: Catch potential date overflow in slide() function
|
||||
|
||||
- BUG FIX: Fix compile error when compiling Romanian version; eliminate
|
||||
compiler warning when compiling non-English versions.
|
||||
|
||||
- BUG FIX: TkRemind: Fix startup failure of TkRemind if options are at
|
||||
default. :(
|
||||
|
||||
* Version 3.1 Patch 17 - 2019-11-15
|
||||
|
||||
- IMPROVEMENT: Add "Extra Remind Options" setting to TkRemind.
|
||||
|
||||
- IMPROVEMENT: Enable warning-free compilation even with gcc -Wextra flag.
|
||||
|
||||
- IMPROVEMENT: Warn if "OMIT a THROUGH b" has a > b.
|
||||
|
||||
- SYNTACTIC SUGAR: Make "SCANFROM -n" the same as "SCANFROM [today() - n]"
|
||||
|
||||
- BUG FIX: Don't dump expired reminders when dumping queue.
|
||||
|
||||
- BUG FIX: Fix failure when specifying a Jahrzeit in Adar. Fix
|
||||
courtesy of Dov Feldstern
|
||||
|
||||
- BUG FIX: Fix various documentation errors and update man page.
|
||||
|
||||
* Version 3.1 Patch 16 - 2018-11-09
|
||||
|
||||
- IMPROVEMENT: Add patch from Stephen Morgan to calculate astronomical and
|
||||
nautical twilight in addition to civil twilight.
|
||||
|
||||
- BUG FIX: The rem2html script correctly handles a SHADE special with only
|
||||
one number (a grey level).
|
||||
|
||||
- IMPROVEMENT: Remind accepts DATETIME constants in ISO-8601 format and can
|
||||
optionally be configured to output them that way too.
|
||||
|
||||
- MINOR IMPROVEMENT: TkRemind puts its hostname in the window title bar.
|
||||
|
||||
- MINOR IMPROVEMENT: TkRemind restarts the background remind daemon if
|
||||
the .reminders file changes
|
||||
|
||||
- MINOR IMPROVEMENT: TkRemind has a "Queue" button that lets you see details
|
||||
of upcoming queued reminders. This is mostly for debugging and the output
|
||||
is not particularly readable.
|
||||
|
||||
- BUG FIX: The definitions form Yom Hazikaron and Yom Ha'atzmaut were not
|
||||
quite right; they have been fixed.
|
||||
|
||||
- MINOR IMPROVEMENT: TkRemind centers popups over the main calendar
|
||||
window rather than over the desktop background. This is better
|
||||
behavior in multi-monitor setups.
|
||||
|
||||
- BUG FIX: In "remind -z0" mode, remind wakes up exactly on the minute instead
|
||||
of sleeping for 60 seconds each time, which could cause it to fall behind.
|
||||
|
||||
* Version 3.1 Patch 15 - 2015-07-27
|
||||
|
||||
- BUG FIX: Fix a buffer overflow found by Alexander Keller
|
||||
|
||||
- BUG FIX: Fix a typo in this file: was 2014 instead of 2015.
|
||||
|
||||
- BUG FIX: Make parser reject an AT followed by more than one time.
|
||||
|
||||
- BUG FIX: Make parser reject epeated delta or *repeat values.
|
||||
|
||||
* Version 3.1 Patch 14 - 2015-04-24
|
||||
|
||||
- NEW FEATURE: Putting the line __EOF__ in a .rem file causes Remind
|
||||
to treat it as end-of-file.
|
||||
|
||||
- IMPROVEMENT: Use better PNG images for moons in the HTML display
|
||||
|
||||
- CHANGE: Author name updated from "David" to "Dianne"
|
||||
|
||||
- BUG FIX: The "-n" command-line option should really run in "ADVANCE_MODE"
|
||||
rather than "CAL_MODE" internally; otherwise, the substitution sequences
|
||||
may be misinterpreted.
|
||||
|
||||
- BUG FIX: A typo in clearing out MD5 sum context has been fixed.
|
||||
|
||||
- BUG FIX: Typo in Spanish translation was fixed.
|
||||
|
||||
* Version 3.1 Patch 13 - 2013-03-22
|
||||
|
||||
- BUG FIX: Sunrise/Sunset calculations greatly improved thanks to John
|
||||
McGowan. Accuracy should now be within a couple of minutes in most
|
||||
places.
|
||||
|
||||
- BUG FIX: Allow specification of margins as low as 0 points in rem2ps,
|
||||
courtesy of Jonathan Kamens.
|
||||
|
||||
- BUG FIX: Permit compilation with gcc 2.95 (which doesn't allow variable
|
||||
declarations after non-declaration statements in a block.)
|
||||
|
||||
- BUG FIX: Several minor documentation errors corrected courtesy of
|
||||
Simon Ruderich.
|
||||
|
||||
- BUG FIX: Spurious test harness failure was fixed.
|
||||
|
||||
* Version 3.1 Patch 12 - 2012-01-23
|
||||
|
||||
- NEW FEATURE: Many substitution sequences "%x" have an alternate mode
|
||||
denoted by "%*x". This alternate mode leaves out prepositions. For
|
||||
example, in English "%i" might yield "on 01-25" while "%*i" yields only
|
||||
"01-25".
|
||||
|
||||
- BUG FIX: The "dusk" and "dawn" calculations were completely wrong. They
|
||||
have been fixed. Also, sunrise/sunset calculations have been tweaked,
|
||||
so the results may be off by a minute or two compared to previous versions
|
||||
of Remind.
|
||||
|
||||
* Version 3.1 Patch 11 - 2011-12-16
|
||||
|
||||
- BUG FIX: For some inexplicable reason, dawn was considered to happen when
|
||||
the sun was 14 degrees below the horizon instead of the standard 6
|
||||
degrees for Civil Dawn. This has been fixed.
|
||||
|
||||
- BUG FIXES: Clarified the man pages and fixed some typos.
|
||||
|
||||
- BUG FIX: Add THROUGH to the remind.vim syntax highlighting file.
|
||||
|
||||
- ENHANCEMENT (?): Allow SPECIAL COLOR to be spelled SPECIAL COLOUR.
|
||||
|
||||
- BUG FIX: Apply minor Debian cleanups reported by Kurt B. Kaiser.
|
||||
|
||||
* Version 3.1 Patch 10 - 2010-11-01
|
||||
|
||||
- NOTE: This is the 20th anniversary of Remind's first public release.
|
||||
|
||||
- ENHANCEMENT: Add the THROUGH keyword. You can omit blocks of dates with:
|
||||
|
||||
OMIT start THROUGH end
|
||||
|
||||
and the syntax REM start THROUGH end is equivalent to REM start *1 UNTIL end
|
||||
|
||||
- ENHANCEMENT: Add support for multibyte characters (eg, UTF-8) in calendar
|
||||
output. Note that UTF-8 strings are still not supported in PostScript
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: Add support for UTF-8 line-drawing characters in calendar
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: You can have multiple TAG clauses in a REM statement.
|
||||
|
||||
- BUG FIX: Avoid spawning long-running background processes in "make test".
|
||||
|
||||
- BUG FIX: Don't declare variables in the middle of statements (old C
|
||||
compilers choke.)
|
||||
|
||||
* Version 3.1 Patch 9 - 2010-06-20
|
||||
|
||||
- MAJOR ENHANCEMENT: New "purge mode" to delete expired reminders. See
|
||||
the PURGE MODE section of the remind man page.
|
||||
|
||||
- ENHANCEMENT: Support DURATION in TkRemind. Thanks to Marek Marczykowski.
|
||||
|
||||
- BUG FIX: Don't change the order of PS and PSFILE reminders. Bug found
|
||||
by John McGowan.
|
||||
|
||||
- BUG FIX: "REM 1990-01-01 SATISFY 1" would yield a spurious parse error
|
||||
in earlier versions of Remind.
|
||||
|
||||
- BUG FIX: Yom HaShoah is moved to Thursday if it would normally fall on
|
||||
a Friday. Thanks to Jonathan Kamens for pointing this out.
|
||||
|
||||
* Version 3.1 Patch 8 - 2010-03-09
|
||||
|
||||
- ENHANCEMENT: Include some useful scripts in contrib/
|
||||
|
||||
- ENHANCEMENT: Add the $T, $Td, $Tm, $Tw, $Ty, $U, $Ud, $Um, $Uw, $Uy
|
||||
special variables to make reminder files less wordy. See man page
|
||||
for details.
|
||||
|
||||
- MINOR ENHANCEMENT: Set an icon photo window manager resource on TkRemind.
|
||||
|
||||
- POLICY CHANGE: Discourage use of Remind on MS Windows or Apple Mac OS X.
|
||||
|
||||
- BUG FIX: Ignore msgprefix() and msgsuffix() on RUN-type reminders.
|
||||
|
||||
- BUG FIX: Adjust Remind and Rem2PS so that SHADE specials don't obliterate
|
||||
earlier MOON specials.
|
||||
|
||||
- BUG FIX: Fix bug in SCHED calculations if Remind is started in the middle
|
||||
of a SCHED interval.
|
||||
|
||||
* Version 3.1 Patch 7 - 2009-05-31
|
||||
|
||||
- ENHANCEMENT: Wherever you could write "day Mon year", the parser now
|
||||
accepts "YYYY-MM-DD". This applies on the command-line and to the
|
||||
REM and OMIT keywords. You can avoid wrapping date calculations in
|
||||
the trigger() function in many cases.
|
||||
|
||||
- ENHANCEMENT: New slide() built-in function eases some complicated reminders.
|
||||
|
||||
* Version 3.1 Patch 6 - 2008-11-16
|
||||
|
||||
- MAJOR ENHANCEMENT: A new OMITFUNC clause gives you additional
|
||||
control and flexibility over "omitted days" calculations. This is
|
||||
useful when holidays influence the timing of events several days
|
||||
later. See "COMPUTED LOCAL OMITS" in the man page.
|
||||
|
||||
- ENHANCEMENT: The new evaltrig() built-in function lets you evaluate triggers
|
||||
from within an expression.
|
||||
|
||||
- ENHANCEMENT: The new weekno() built-in function returns the ISO 8601
|
||||
week number of a date.
|
||||
|
||||
- ENHANCEMENT: The "WEEK" special lets you annotate calendar output with the
|
||||
week number. The TkRemind, rem2ps and rem2html back-ends support WEEK.
|
||||
|
||||
- MINOR ENHANCEMENT: You can control whether timed reminders come before or
|
||||
after non-timed reminders with the "-g" flag.
|
||||
|
||||
- BUG FIX: TkRemind did not work correctly if ~/.reminders was a directory.
|
||||
|
||||
- BUG FIX: TkRemind incorrectly invoked Remind with the "-a" flag when
|
||||
showing today's reminders.
|
||||
|
||||
- BUG FIX: In certain cases, a trigger containing a day, month and
|
||||
weekday would fail if it needed to cross a year boundary. This has
|
||||
been fixed.
|
||||
|
||||
* Version 3.1 Patch 5 - 2008-04-15
|
||||
|
||||
- MAJOR ENHANCEMENT: If you supply a directory name on the command line
|
||||
or for an INCLUDE command, then Remind reads all *.rem file in that
|
||||
directory (in the order returned by "glob")
|
||||
|
||||
- ENHANCEMENT: The plain-text calendar ("-c") can draw lines using VT-100
|
||||
line-drawing characters if invoked as "-cl"
|
||||
|
||||
- ENHANCEMENT: The plain-text calendar can approximate SPECIAL COLOR reminders
|
||||
using VT-100 color escape sequences if invoked as "-cc". (You can combine
|
||||
the colors and line-drawing characters with -clc or -ccl.)
|
||||
|
||||
- ENHANCEMENT: The "-t" option can take a numeric argument n. In this case,
|
||||
all reminders are assumed to have a delta of +n. (Without the argument,
|
||||
an infinite delta is assumed, as before.) If a numeric argument is given,
|
||||
the new system variable $DeltaOffset is set to the argument.
|
||||
|
||||
- MINOR ENHANCEMENT: The "-i" command-line option can be used to define
|
||||
a function as well as set a variable.
|
||||
|
||||
- MINOR ENHANCEMENT: String constants can have embedded quotes "Like \"this"
|
||||
|
||||
- MINOR ENHANCEMENT: tkremind works better on small screens like that of
|
||||
the Eee-PC.
|
||||
|
||||
- BUG FIX: Minor fix to HTML output courtesy of Ian! Allen.
|
||||
|
||||
- BUG FIX: Parse error in calendar mode was fixed.
|
||||
|
||||
* Version 3.1 Patch 4 - 2008-02-03
|
||||
|
||||
- ENHANCMENT: tkremind respects the "-b1" option and operates in 24-hour
|
||||
clock mode if the option is supplied.
|
||||
|
||||
- ENHANCEMENT: tkremind has been tweaked to look better with Tcl/Tk 8.5.
|
||||
|
||||
- CLEANUP: Version is kept only in configure.in instead of two different
|
||||
places.
|
||||
|
||||
- CLEANUP: Added "const" qualifier to many places in the code that previously
|
||||
lacked it.
|
||||
|
||||
- BUG FIX: A rare parsing error involving interaction between SATISFY and
|
||||
SKIP has been fixed.
|
||||
|
||||
- BUG FIX: rem2html would output a horribly-wrong calendar for a 28-day
|
||||
February starting on Sunday (such as February 2009.) This has been fixed.
|
||||
|
||||
- BUG FIX: The "-ivar=value" command-line option failed if Remind re-execed
|
||||
itself because we overwrote argv[]. This has been fixed.
|
||||
|
||||
* Version 3.1 Patch 3 - 2007-10-15
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
|
||||
- rem2html now uses CSS for a much better-looking calendar.
|
||||
NOTE: rem2html was completely rewritten and some of the command-line
|
||||
options have changed!
|
||||
|
||||
- If a reminder has a DURATION clause, then the starting and ending times
|
||||
are output in calendar mode.
|
||||
|
||||
+ BUG FIXES
|
||||
|
||||
- DST rules in "defs.rem" were updated to reflect new US/Canadian DST rules.
|
||||
|
||||
- If a REM command cannot compute a trigger date, the SATISFY expression
|
||||
is not evaluated. This helps avoid spurious error messages in some
|
||||
reminders.
|
||||
|
||||
* Version 3.1 Patch 2 - 2007-09-12
|
||||
|
||||
+ MINOR ENHANCEMENTS
|
||||
@@ -28,7 +355,7 @@ CHANGES TO REMIND
|
||||
|
||||
*** THIS MAY AFFECT BACKENDS ***
|
||||
|
||||
Backends supplied by Roaring Penguin (rem2ps, rem2html and tkremind)
|
||||
Backends supplied with Remind (rem2ps, rem2html and tkremind)
|
||||
are known to work properly.
|
||||
|
||||
- "remind -p" no longer suppresses any AT-time associated with SPECIAL
|
||||
@@ -36,7 +363,7 @@ CHANGES TO REMIND
|
||||
|
||||
*** THIS MAY AFFECT BACKENDS ***
|
||||
|
||||
Backends supplied by Roaring Penguin (rem2ps, rem2html and tkremind)
|
||||
Backends supplied with Remind (rem2ps, rem2html and tkremind)
|
||||
are known to work properly.
|
||||
|
||||
+ BUG FIXES
|
||||
@@ -249,11 +576,6 @@ CHANGES TO REMIND
|
||||
|
||||
* Version 3.0 Patch 20 - 1999-04-12
|
||||
|
||||
+ NEWS
|
||||
|
||||
- I have started a company, Roaring Penguin Software
|
||||
Inc. (http://www.roaringpenguin.com) and it now holds the Remind copyright.
|
||||
|
||||
+ LICENSE CHANGE
|
||||
|
||||
- Remind is now distributed under the pure GPL. See the file WINDOWS for my
|
||||
@@ -269,8 +591,6 @@ CHANGES TO REMIND
|
||||
|
||||
+ BUG FIXES
|
||||
|
||||
- Changed copyright notices to Roaring Penguin Software Inc.
|
||||
|
||||
- Rem2PS was passing specials like HTML, etc. in PostScript output.
|
||||
YECH! Fix courtesty of Derek J. Decker.
|
||||
|
||||
@@ -368,7 +688,7 @@ CHANGES TO REMIND
|
||||
+ BUG FIXES
|
||||
|
||||
- Fixed sunset(), sunrise() and minsfromutc() functions which were broken
|
||||
by 3.0.17. (In 3.0.17, they did not account for daylight savings time.)
|
||||
by 3.0.17. (In 3.0.17, they did not account for daylight saving time.)
|
||||
|
||||
- Updated "finnish.h" to include proper URL and translation of all
|
||||
error messages.
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
# "#COLORS" for examples of ANSI color escape sequences. #
|
||||
# #
|
||||
# This file is part of REMIND. #
|
||||
# Copyright (C) 1992-1997 David F. Skoll #
|
||||
# Copyright (C) 1999-2000 Roaring Penguin Software Inc. #
|
||||
# Copyright (C) 1992-2018 Dianne Skoll #
|
||||
# #
|
||||
#############################################################################
|
||||
|
||||
@@ -27,8 +26,8 @@ RUN OFF
|
||||
################################################
|
||||
# Ensure required version of remind is used... #
|
||||
################################################
|
||||
IF version() < "03.00.19"
|
||||
ERRMSG This file requires at least version 03.00.19 of Remind.%
|
||||
IF version() < "03.01.08"
|
||||
ERRMSG This file requires at least version 03.01.08 of Remind.%
|
||||
ERRMSG This version is version [version()].
|
||||
EXIT
|
||||
ENDIF
|
||||
@@ -93,53 +92,10 @@ SET Week_1 1
|
||||
SET Week_2 8
|
||||
SET Week_3 15
|
||||
SET Week_4 22
|
||||
FSET _last(mo) "1 " + MON((mo%12)+1)+" --7"
|
||||
|
||||
# Shorthand for commonly used expression...
|
||||
FSET _trig() TRIGGER(TRIGDATE())
|
||||
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
|
||||
|
||||
# Handy function to provide SCANFROM dates...
|
||||
FSET _back(days) TRIGGER(TODAY()-days)
|
||||
|
||||
###########################################################
|
||||
# On MS-DOS systems, the standard C library functions are #
|
||||
# not reliable for computing offsets from local time to #
|
||||
# UTC. The following provides a work-around for the #
|
||||
# sunrise() and sunset() functions. Note, however, that #
|
||||
# if Daylight Savings Time is in effect for today(), the #
|
||||
# sun functions return times in DST even for dates on #
|
||||
# which DST is not in effect; the converse can also occur.#
|
||||
# #
|
||||
# Change the timezone to your timezone - the default is #
|
||||
# for EST which is 5 hours (300 minutes) behind UTC. #
|
||||
# The code is correct for places in which Daylight Savings#
|
||||
# Time begins on the last Sunday in April and ends on the #
|
||||
# last Sunday in October. #
|
||||
###########################################################
|
||||
|
||||
IF OSTYPE() == "MSDOS"
|
||||
# Eastern Standard Time
|
||||
SET TimeZone -300
|
||||
|
||||
# Use --8 rather than --7 because we want the last day BEFORE
|
||||
# the time switch occurs.
|
||||
REM Sun 1 May --8 SATISFY 1
|
||||
SET BegDst TRIGDATE()
|
||||
|
||||
REM Sun 1 Nov --8 SATISFY 1
|
||||
SET EndDst TRIGDATE()
|
||||
|
||||
SET $CalcUTC 0
|
||||
|
||||
# Check out the following IF statement and figure out why it works!
|
||||
IF EndDst < BegDst
|
||||
# Daylight Savings Time
|
||||
SET $MinsFromUTC TimeZone+60
|
||||
ELSE
|
||||
# Standard Time
|
||||
SET $MinsFromUTC TimeZone
|
||||
ENDIF
|
||||
ENDIF
|
||||
FSET _back(days) TODAY()-days
|
||||
|
||||
###########################################################
|
||||
# Function which returns a string in "am/pm" format based #
|
||||
@@ -209,14 +165,14 @@ FSET _mail(from, subj) "fastmail -f " + \
|
||||
REM 4 July SCANFROM [_back(7)] SATISFY 1
|
||||
|
||||
IF WKDAYNUM(TRIGDATE()) == Sat
|
||||
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
|
||||
OMIT [TRIGGER(TRIGDATE()-1)] MSG Independence day (observed)
|
||||
REM [TRIGDATE()] MSG Independence day (actual)
|
||||
OMIT [TRIGDATE()-1] MSG Independence day (observed)
|
||||
ELSE
|
||||
IF WKDAYNUM(TRIGDATE()) == Sun
|
||||
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
|
||||
OMIT [TRIGGER(TRIGDATE()+1)] MSG Independence day (observed)
|
||||
REM [TRIGDATE()] MSG Independence day (actual)
|
||||
OMIT [TRIGDATE()+1] MSG Independence day (observed)
|
||||
ELSE
|
||||
OMIT [TRIGGER(TRIGDATE())] MSG Independence day
|
||||
OMIT [TRIGDATE()] MSG Independence day
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
@@ -237,7 +193,7 @@ REM Mon 8 SATISFY 1
|
||||
# But only actually trigger the delayed meeting if the previous
|
||||
# Monday was a holiday
|
||||
IF ISOMITTED(TRIGDATE()-7)
|
||||
REM [TRIGGER(TRIGDATE())] MSG Delayed meeting
|
||||
REM [TRIGDATE()] MSG Delayed meeting
|
||||
ENDIF
|
||||
|
||||
############################################################################
|
||||
@@ -328,12 +284,12 @@ REM Sat Sun SPECIAL SHADE 220
|
||||
|
||||
SET SaveTrig $NumTrig
|
||||
SET easter EASTERDATE(YEAR(TODAY()))
|
||||
REM [TRIGGER(easter-46)] MSG %"Ash Wednesday%"
|
||||
REM [TRIGGER(easter-7)] MSG %"Palm Sunday%"
|
||||
OMIT [TRIGGER(easter-2)] MSG %"Good Friday%"
|
||||
OMIT [TRIGGER(easter)] MSG %"Easter%" Sunday
|
||||
REM [TRIGGER(easter+39)] MSG %"Ascension Day%"
|
||||
REM [TRIGGER(easter+49)] MSG %"Pentecost%"
|
||||
REM [easter-46] MSG %"Ash Wednesday%"
|
||||
REM [easter-7] MSG %"Palm Sunday%"
|
||||
OMIT [easter-2] MSG %"Good Friday%"
|
||||
OMIT [easter] MSG %"Easter%" Sunday
|
||||
REM [easter+39] MSG %"Ascension Day%"
|
||||
REM [easter+49] MSG %"Pentecost%"
|
||||
|
||||
# Some holidays are omitted, some are not. You may want to change
|
||||
# which ones are omitted - use the general forms shown below.
|
||||
@@ -345,9 +301,17 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
|
||||
REM Feb 2 MSG %"Ground Hog Day%"
|
||||
REM Feb 14 MSG %"Valentine's%" Day
|
||||
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"President's Day%"
|
||||
OMIT [trigdate()] MSG %"President's Day%"
|
||||
REM Mar 17 MSG %"St. Patrick's%" Day
|
||||
REM Sun Apr 1 ++2 MSG Daylight Savings Time - %"DST starts%" %b
|
||||
|
||||
# The DST rules are accurate for most locations in
|
||||
# North America
|
||||
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
|
||||
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
|
||||
|
||||
REM Sun [_last(Oct)] ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
||||
REM Sun 1 Nov ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
|
||||
|
||||
REM Apr 1 MSG %"April Fool's%" Day
|
||||
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
|
||||
REM May 5 MSG %"Cinco de Mayo%"
|
||||
@@ -355,23 +319,23 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
|
||||
REM Sun May [Week_2] MSG %"Mother's Day%"
|
||||
REM Sat May [Week_3] MSG %"Armed Forces Day%"
|
||||
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Memorial Day%"
|
||||
OMIT [trigdate()] MSG %"Memorial Day%"
|
||||
REM Jun 14 MSG %"Flag Day%"
|
||||
REM Sun Jun [Week_3] MSG %"Father's Day%"
|
||||
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Labor Day%"
|
||||
OMIT [trigdate()] MSG %"Labor Day%"
|
||||
REM Mon Oct [Week_2] MSG %"Columbus Day%"
|
||||
REM Nov 11 MSG %"Veterans Day%"
|
||||
REM Sun [_last(Oct)] MSG Daylight Savings Time - %"DST over%"
|
||||
|
||||
REM Oct 30 MSG %"Mischief Night%"
|
||||
REM Oct 31 MSG %"Halloween%"
|
||||
REM Tue Nov 2 SCANFROM [_back(7)] \
|
||||
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \
|
||||
MSG %"Election%" Day
|
||||
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Thanksgiving%" Day
|
||||
OMIT [trigdate()] MSG %"Thanksgiving%" Day
|
||||
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
|
||||
OMIT [_trig()] MSG %"Thanksgiving%" (cont.)
|
||||
OMIT [trigdate()] MSG %"Thanksgiving%" (cont.)
|
||||
OMIT Dec 24 MSG %"Christmas Eve%"
|
||||
OMIT Dec 25 MSG %"Christmas%" Day
|
||||
|
||||
@@ -409,10 +373,10 @@ REM PS Border Border moveto \
|
||||
([hebday(today())] [hebmon(today())]) show
|
||||
|
||||
# Fill in the phases of the moon on the PostScript calendar
|
||||
[trigger(moondate(0))] SPECIAL MOON 0
|
||||
[trigger(moondate(1))] SPECIAL MOON 1
|
||||
[trigger(moondate(2))] SPECIAL MOON 2
|
||||
[trigger(moondate(3))] SPECIAL MOON 3
|
||||
[moondate(0)] SPECIAL MOON 0
|
||||
[moondate(1)] SPECIAL MOON 1
|
||||
[moondate(2)] SPECIAL MOON 2
|
||||
[moondate(3)] SPECIAL MOON 3
|
||||
|
||||
# The following example puts sunrise and sunset times in PostScript in the
|
||||
# calendar - the sizes are hard-coded, however, and work best in landscape.
|
||||
@@ -435,7 +399,7 @@ REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
|
||||
# dates were obtained from "The First Jewish Catalog" by Richard Siegel #
|
||||
# and Michael and Sharon Strassfeld, published by the Jewish Publication #
|
||||
# Society of America. The Reform version of the calendar was guessed #
|
||||
# at by David Skoll based on experience. There is probably no standard #
|
||||
# at by Dianne Skoll based on experience. There is probably no standard #
|
||||
# Reform position on many of the holidays, so you may have to adjust #
|
||||
# the file as required. #
|
||||
# #
|
||||
@@ -465,11 +429,11 @@ SET InIsrael 0
|
||||
SET Reform 0
|
||||
|
||||
# Convenient function definition to save typing
|
||||
FSET _h(x, y) TRIGGER(HEBDATE(x,y))
|
||||
FSET _h(x, y) HEBDATE(x,y)
|
||||
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7)
|
||||
FSET _PastSat(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastSun(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastMon(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1))
|
||||
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _PastSun(x, y) IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1)
|
||||
FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
|
||||
|
||||
# Default values in case InIsrael and Reform are not set
|
||||
SET InIsrael VALUE("InIsrael", 0)
|
||||
@@ -500,7 +464,7 @@ ELSE
|
||||
ENDIF
|
||||
|
||||
# Because Kislev can change length, we must be more careful about Chanukah
|
||||
FSET _chan(x) TRIGGER(HEBDATE(24, "Kislev", today()-9)+x)
|
||||
FSET _chan(x) HEBDATE(24, "Kislev", today()-9)+x
|
||||
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
|
||||
[_chan(2)] MSG %"Chanukah 2%"
|
||||
[_chan(3)] MSG %"Chanukah 3%"
|
||||
@@ -523,9 +487,9 @@ ENDIF
|
||||
|
||||
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
|
||||
IF WKDAYNUM(_h2(13, "Adar")) != 6
|
||||
REM [TRIGGER(_h2(13, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
|
||||
REM [_h2(13, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||
ELSE
|
||||
REM [TRIGGER(_h2(11, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
|
||||
REM [_h2(11, "Adar")] ++4 MSG %"Fast of Esther%" is %b.
|
||||
ENDIF
|
||||
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
|
||||
[_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
|
||||
@@ -541,17 +505,23 @@ IF !InIsrael && !Reform
|
||||
[_h(22, "Nisan")] MSG %"Pesach 8%"
|
||||
ENDIF
|
||||
|
||||
[_PastSun(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
REM [_PastSun(27, "Nisan")] SATISFY 1
|
||||
|
||||
# If 4 Iyar is a Friday, then Yom Hazikaron is
|
||||
IF $Tw == 5
|
||||
REM [_PastSun(26, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
ELSE
|
||||
REM [_PastSun(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
|
||||
ENDIF
|
||||
|
||||
# If 4 Iyar is a Thursday or Friday, then Yom Hazikaron is
|
||||
# the Wednesday before and Yom Ha'atzmaut is on
|
||||
# Thursday. If 4 Iyar is a Sunday, then Yom Hazikaron
|
||||
# moves to 5 Iyar and Yom Ha'atzmaut to 6 Iyar.
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 5
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 4 || WKDAYNUM(_h2(4, "Iyar")) == 5
|
||||
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
IF WKDAYNUM(_h2, 4, "Iyar") == 0
|
||||
IF WKDAYNUM(_h2(4, "Iyar")) == 0
|
||||
[_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
|
||||
[_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
|
||||
ELSE
|
||||
|
||||
@@ -1,53 +1,79 @@
|
||||
" Vim syntax file
|
||||
" Language: Remind
|
||||
" Maintainer: Davide Alberani <alberanid@bigfoot.com>
|
||||
" Last change: 03 Dec 1999
|
||||
" Version: 0.1
|
||||
" URL: http://members.xoom.com/alberanid/vim/syntax/remind.vim
|
||||
" Maintainer: Davide Alberani <alberanid@libero.it>
|
||||
" Last Change: 18 Sep 2009
|
||||
" Version: 0.5
|
||||
" URL: http://erlug.linux.it/~da/vim/syntax/remind.vim
|
||||
"
|
||||
" remind is a sophisticated reminder service
|
||||
" you can download remind from ftp://ftp.doe.carleton.ca/pub/remind-3.0/
|
||||
" you can download remind from:
|
||||
" https://dianne.skoll.ca/projects/remind/
|
||||
|
||||
" clear any unwanted syntax defs
|
||||
syn clear
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" shut case off
|
||||
" shut case off.
|
||||
syn case ignore
|
||||
|
||||
syn keyword remindCommands REM OMIT SET FSET UNSET
|
||||
syn keyword remindExpiry UNTIL SCANFROM SCAN WARN SCHED
|
||||
syn keyword remindExpiry UNTIL FROM SCANFROM SCAN WARN SCHED THROUGH
|
||||
syn keyword remindTag PRIORITY TAG
|
||||
syn keyword remindTimed AT DURATION
|
||||
syn keyword remindMove ONCE SKIP BEFORE AFTER
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP COLOR COLOUR
|
||||
syn keyword remindRun MSG MSF RUN CAL SATISFY SPECIAL PS PSFILE SHADE MOON
|
||||
syn keyword remindConditional IF ELSE ENDIF IFTRIG
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindComment "#.*$"
|
||||
syn region remindString start=+'+ end=+'+ skip=+\\\\\|\\'+ oneline
|
||||
syn region remindString start=+"+ end=+"+ skip=+\\\\\|\\"+ oneline
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindVar "\$[_a-zA-Z][_a-zA-Z0-9]*"
|
||||
syn match remindSubst "%[^ ]"
|
||||
syn match remindAdvanceNumber "\(\*\|+\|-\|++\|--\)[0-9]\+"
|
||||
" XXX: use different separators for dates and times?
|
||||
syn match remindDateSeparators "[/:@\.-]" contained
|
||||
syn match remindTimes "[0-9]\{1,2}[:\.][0-9]\{1,2}" contains=remindDateSeparators
|
||||
" XXX: why not match only valid dates? Ok, checking for 'Feb the 30' would
|
||||
" be impossible, but at least check for valid months and times.
|
||||
syn match remindDates "'[0-9]\{4}[/-][0-9]\{1,2}[/-][0-9]\{1,2}\(@[0-9]\{1,2}[:\.][0-9]\{1,2}\)\?'" contains=remindDateSeparators
|
||||
" This will match trailing whitespaces that seem to break rem2ps.
|
||||
" Courtesy of Michael Dunn.
|
||||
syn match remindWarning display excludenl "\S\s\+$"ms=s+1
|
||||
|
||||
if !exists("did_remind_syntax_inits")
|
||||
let did_remind_syntax_inits = 1
|
||||
hi link remindCommands Function
|
||||
hi link remindExpiry Repeat
|
||||
hi link remindTag Label
|
||||
hi link remindTimed Statement
|
||||
hi link remindMove Statement
|
||||
hi link remindSpecial Include
|
||||
hi link remindRun Function
|
||||
hi link remindConditional Conditional
|
||||
hi link remindComment Comment
|
||||
hi link remindString String
|
||||
hi link remindDebug Debug
|
||||
hi link remindVar Identifier
|
||||
hi link remindSubst Constant
|
||||
hi link remindAdvanceNumber Number
|
||||
|
||||
if version >= 508 || !exists("did_remind_syn_inits")
|
||||
if version < 508
|
||||
let did_remind_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
|
||||
HiLink remindCommands Function
|
||||
HiLink remindExpiry Repeat
|
||||
HiLink remindTag Label
|
||||
HiLink remindTimed Statement
|
||||
HiLink remindMove Statement
|
||||
HiLink remindSpecial Include
|
||||
HiLink remindRun Function
|
||||
HiLink remindConditional Conditional
|
||||
HiLink remindComment Comment
|
||||
HiLink remindTimes String
|
||||
HiLink remindString String
|
||||
HiLink remindDebug Debug
|
||||
HiLink remindVar Identifier
|
||||
HiLink remindSubst Constant
|
||||
HiLink remindAdvanceNumber Number
|
||||
HiLink remindDateSeparators Comment
|
||||
HiLink remindDates String
|
||||
HiLink remindWarning Error
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
let b:current_syntax = "remind"
|
||||
|
||||
"EOF vim: ts=8 noet tw=100 sw=8 sts=0
|
||||
" vim: ts=8 sw=2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.TH CM2REM 1 "18 October 1999"
|
||||
.UC4
|
||||
.UC 4
|
||||
.SH NAME
|
||||
cm2rem.tcl \- Convert Sun's "cm" input file to Remind format
|
||||
.SH SYNOPSIS
|
||||
@@ -10,10 +10,7 @@ it into a \fBRemind\fR script. Note that \fBcm2rem.tcl\fR can convert
|
||||
\fIonly\fR version 3 calendar manager files. If you are using version 4
|
||||
files, there should be a system utility to convert them to version 3 files.
|
||||
.SH AUTHOR
|
||||
\fBcm2rem.tcl\fR is supported by Roaring Penguin Software
|
||||
Inc. (http://www.roaringpenguin.com)
|
||||
.PP
|
||||
\fBcm2rem.tcl\fR was written by David F. Skoll <dfs@roaringpenguin.com>.
|
||||
\fBcm2rem.tcl\fR was written by Dianne Skoll <dianne@skoll.ca>.
|
||||
.SH BUGS
|
||||
Not all of the Sun calendar manager options are respected. In particular,
|
||||
nothing is done for e-mail actions. Also, the resulting Remind script
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.TH REM 1 "30 August 2007"
|
||||
.UC4
|
||||
.TH REM 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rem \- Invoke Remind with a default filename
|
||||
.SH SYNOPSIS
|
||||
@@ -15,6 +15,6 @@ value of DOTREMINDERS as the filename. Otherwise, \fBremind\fR uses
|
||||
the filename $HOME/.reminders
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
Remind was written by David F. Skoll <dfs@roaringpenguin.com>
|
||||
Remind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
.SH SEE ALSO
|
||||
\fBremind\fR
|
||||
|
||||
14
man/rem2ps.1
14
man/rem2ps.1
@@ -1,5 +1,5 @@
|
||||
.TH REM2PS 1 "11 April 2005"
|
||||
.UC4
|
||||
.TH REM2PS 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rem2ps \- draw a PostScript calendar from Remind output
|
||||
.SH SYNOPSIS
|
||||
@@ -362,7 +362,10 @@ Other back-ends may understand other specials. A back end should
|
||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
||||
.PP
|
||||
\fItag\fR is whatever tag the user provided with the \fBTAG\fR clause,
|
||||
or "*" if no tag was provided.
|
||||
or "*" if no tag was provided. If there is more than one \fBTAG\fR clause,
|
||||
the tags appear in a comma-separated list. For example, the command
|
||||
\fBREM TAG foo TAG bar TAG quux\fR would result in \fBfoo,bar,quux\fR
|
||||
in the \fItag\fR field.
|
||||
.PP
|
||||
\fIdur\fR is the \fBDURATION\fR value in minutes, or "*" if no duration
|
||||
was provided.
|
||||
@@ -391,10 +394,7 @@ that don't care about this information should ignore lines starting with
|
||||
"#" (except, of course, for the # rem2ps lines.)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
Rem2PS is now supported by Roaring Penguin Software
|
||||
Inc. (http://www.roaringpenguin.com)
|
||||
.PP
|
||||
Rem2PS was written by David F. Skoll <dfs@roaringpenguin.com>.
|
||||
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
|
||||
.SH BUGS
|
||||
All \fBRem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
|
||||
Any time you supply
|
||||
|
||||
1052
man/remind.1
1052
man/remind.1
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
.TH TKREMIND 1 "15 February 1998"
|
||||
.TH TKREMIND 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
tkremind \- graphical front-end to Remind calendar program
|
||||
@@ -21,6 +21,8 @@ extra features as you become a more sophisticated \fBRemind\fR programmer.
|
||||
on to \fBRemind\fR. The options it passes are
|
||||
\fB\-b\fR, \fB\-g\fR, \fB\-x\fR, \fB\-i\fR and \fB\-m\fR.
|
||||
See the \fBRemind\fR man page for details about the options.
|
||||
Note that \fBTkRemind\fR will respect the \fB\-m\fR and
|
||||
\fB\-b1\fR options and adjust its appearance accordingly.
|
||||
|
||||
\fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders.
|
||||
It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file
|
||||
@@ -72,7 +74,7 @@ The next control specifies an expiry date for the reminder. Select
|
||||
the check button to enable an expiry date, and fill in the values
|
||||
using pull-down menus.
|
||||
|
||||
The third control specifes how much advance notice you want (if any),
|
||||
The third control specifies how much advance notice you want (if any),
|
||||
and whether or not weekends and holidays are counted when computing advance
|
||||
notice.
|
||||
|
||||
@@ -102,7 +104,7 @@ edit the reminder, thereby gaining access to advanced features of
|
||||
\fBRemind\fR's idioms for expressing different types of reminders.
|
||||
|
||||
.SH PRINTING
|
||||
To print the current month's calender, click \fBPrint...\fR on the
|
||||
To print the current month's calendar, click \fBPrint...\fR on the
|
||||
main calendar window. This brings up the print dialog. Printing
|
||||
either produces a PostScript file or sends PostScript to a UNIX command.
|
||||
|
||||
@@ -177,7 +179,7 @@ it starts up in a normal window.
|
||||
.TP
|
||||
.B Show Today's Reminders on Startup
|
||||
If this is selected, \fBTkRemind\fR shows a text window containing reminders
|
||||
which would be issued by "remind -q -a -r" on startup, and when the date
|
||||
which would be issued by "remind \-q \-a \-r" on startup, and when the date
|
||||
changes at midnight.
|
||||
|
||||
.TP
|
||||
@@ -266,7 +268,7 @@ the body. Furthermore, if you use expression-pasting in the body,
|
||||
When \fBTkRemind\fR invokes \fBRemind\fR, it supplies the option:
|
||||
.PP
|
||||
.nf
|
||||
-itkremind=1
|
||||
\-itkremind=1
|
||||
.fi
|
||||
.PP
|
||||
on the command line. So, in your \fBRemind\fR file, you can include:
|
||||
@@ -287,7 +289,9 @@ file to store additional state. You can certainly mix
|
||||
if you are aware of the following rules and limitations:
|
||||
.TP
|
||||
o
|
||||
Do not use the \fBTAG\fR keyword in hand-crafted reminders.
|
||||
\fBTkRemind\fR uses \fBTAG\fRs of the form \fBTKTAG\fR\fInnn\fR
|
||||
where \fInnn\fR is a number. You should not use such \fBTAG\fRs
|
||||
in hand-crafted reminders.
|
||||
.TP
|
||||
o
|
||||
Do not edit lines starting with "# TKTAGnnn", "# TKEND", or any
|
||||
@@ -354,13 +358,9 @@ This line is emitted in response to a \fBSTATUS\fR command. The number
|
||||
\fIn\fR is the number of reminders in the queue.
|
||||
|
||||
.SH AUTHOR
|
||||
TkRemind is now supported by Roaring Penguin Software
|
||||
Inc. (http://www.roaringpenguin.com)
|
||||
.PP
|
||||
TkRemind was written by David F. Skoll <dfs@roaringpenguin.com>.
|
||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
\fBTkRemind\fR is Copyright 1996-1998 by David F. Skoll, Copyright
|
||||
1999 by Roaring Penguin Software Inc.
|
||||
\fBTkRemind\fR is Copyright 1996-2020 by Dianne Skoll.
|
||||
|
||||
.SH FILES
|
||||
|
||||
|
||||
3
scripts/cm2rem.tcl
Executable file → Normal file
3
scripts/cm2rem.tcl
Executable file → Normal file
@@ -8,8 +8,7 @@
|
||||
# files (version 3 only) to Remind format.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1998 by David F. Skoll
|
||||
# Copyright (C) 1999-2000 by Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
|
||||
463
scripts/tkremind
463
scripts/tkremind
@@ -7,8 +7,7 @@
|
||||
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1998 David F. Skoll
|
||||
# Copyright (C) 1999-2005 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1992-2020 Dianne Skoll
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
@@ -17,6 +16,80 @@ exec wish "$0" "$@"
|
||||
|
||||
wm withdraw .
|
||||
|
||||
set Hostname [exec hostname]
|
||||
|
||||
# Our icon photo
|
||||
catch {
|
||||
image create photo rpicon -data {
|
||||
R0lGODlhFwAgAOecABUTERYTERYUERcVEhgWExkXFBkXFRoXFRsZFhwZFxwa
|
||||
GB0bGR4cGR4cGh8dGiAeHCEfHCEfHSIgHSIgHiQiHyYkISknJCooJispJywq
|
||||
Jy4sKTIwLjUzMDUzMTo4Njs5Nzs5ODw7ODw7OT07OT48OkE/PUJAPkNBP0RC
|
||||
QEVDQUVEQkdFQ0lIRkpJR01LSU5MSlBPTVFQTlNSUFRSUFRSUVVTUlVUUllY
|
||||
VltZV1xaWF1cWmBfXmJgX2RiYGZlY2dmZGppZ2tqaG1ram9tbHFwb3Jwb3Rz
|
||||
cXV0c3Z0c3Z1c3Z1dHd1dHh2dXh3dnt5eHx7eXx7en18en59e4B/foGAf4KB
|
||||
f4SDgYWEgoWEg4eGhIiHhouKiI2Mio6Ni46NjJCQj5KRkJSTkZeWlpiXlpmY
|
||||
l5qZmJybmp6dnKCfnqGgoKKhoKOioaSjoqinp6qpqKurqq+urbCvrrCwr7Gw
|
||||
r7OysbW1tLi3tri3t7u6ur28vMTDw8TEw8XFxMbFxcfGxsfHxsrJycrKyczM
|
||||
y83My83MzM3NzdDQz9LR0dPS0tPT09fX19jY19ra2dvb29zc29zc3Ojn5+jo
|
||||
6Orq6uzs7O/v7/T09PX19fb29vf39/r6+vv7+/7+/v//////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////
|
||||
/////////////////////yH5BAEKAP8ALAAAAAAXACAAAAj+AP8JHEiwoMGD
|
||||
CAcusRAAQEKDBQIcEBAAwUODAQJAsBGAwsWCBzJuUBLgI0ENGVM2dACg5UWV
|
||||
KU+Y/JfRQBknPoq8ATQz4wxOQIFa6vMx5ZSgQetczJDSClKgcF6mFDEnE9I2
|
||||
D0fADOChUdA1D7dmTBEUTditDQRQAnomIQaxICpoAmomoUoAGS2YIBIUDEIu
|
||||
YndI8FAJaBaEMlIuSEkloxugUBBOSLkh44AvGfkAPYJQpYqMLIQEILB205DO
|
||||
KW9kJHMhQAmgkaKgzsgjggM5GbEAxaNmdoAPOoz8CCAgEVAtg3wPEPMnQQAU
|
||||
QWsg5AAzDZSMbIBeaoHwAUwSDAI2XMAENA8ThAPEBvAStEkc3yonrOW0aUMk
|
||||
+BkBVAlaKATC8Fsp8Igid5ABgxMHtaTgggy6ZFBAADs= }
|
||||
|
||||
wm iconphoto . -default rpicon
|
||||
}
|
||||
|
||||
# Left and right arrows
|
||||
image create photo leftarrow -data {
|
||||
iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAC3XpUWHRSYXcgcHJvZmlsZSB0eXBl
|
||||
IGV4aWYAAHja7ZdRkuMoDIbfOcUeAUkIieNgA1Vzgz3+/mDa6aR7pmpn52EfYioGK+IX6BNOd+h/
|
||||
/xjhL1xUJIak5rnkHHGlkgpXDDxe19VTTOt+Xefu6dke7i8YJkEv12Pu27/Cro8Jlrb9eLYH20Ls
|
||||
W+gj8haUGZkfK/EtJHzZaT+HsufV9Gk7+3O0bdOre31OhmQ0hZ5w4C4kEXefUQQrkCIVd8ZdZDnB
|
||||
WiUtC4l+n7twD1+Sd49echfrtstzKkLM2yG/5GjbSb/P3crQ5xXRI/LTFyZ3iC+5G6P5GP3aXU0Z
|
||||
mcphb+pjK2sExwOplDUtoxk+irGtVtAcWzxBrIHmgXYGKsTI9qBEjSoN6qs/6cQSE3c29Mwny7K5
|
||||
GBc+F5Q0Gw024GlBHDROUJPJ5V4LrbhlxTvJEbkRPJkgNol+aeE74++0W2iMWbpE0e9cYV08axrL
|
||||
mOTmHV4AQmPnVFd+Vwuf6iZ+AisgqCvNjg3WeFwSh9KjtmRxFvhpTCFeR4OsbQGkCLEViyEBgZhR
|
||||
zJQpGrMRIY8OPhUrZ0l8gACpcqMwwEYkA47zjI05RsuXlS8zXi0AoZLFgAYHCLBSUtSPJUcNVRVN
|
||||
QVWzmroWrVlyyppztjzfUdXEkqllM3MrVl08uXp2c/fitXARvMK05GKheCmlVgStkK6YXeFR68GH
|
||||
HOnQIx92+FGOeqJ8znTqmU87/Sxnbdyk4fi33Cw0b6XVTh2l1FPXnrt176XXgVobMtLQkYcNH2XU
|
||||
m9qm+kyNXsj9mhptapNYWn72oAaz2YcEzdeJTmYgxolA3CYBFDRPZtEpJZ7kJrNYGIdCGdRIJ5xG
|
||||
kxgIpk6sg252D3K/5BY0/Stu/DNyYaL7E+TCRLfJfeX2DbVW1y+KLEDzFM6cRhl4scGhe2Wv8zfp
|
||||
t/vwXwXeQm+ht9Bb6C30FnoL/X+EBv54wL+a4R9jg5HlHbplXQAAAAZiS0dEAP8A/wD/oL2nkwAA
|
||||
AAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB+MMHwEqD2+Y0soAAABKSURBVCjPY2DADuoZSAC1
|
||||
DAwM/0lVjFMDI5riJiR+Gz71yCYTwgx1JCj+z8TAwPCRgQyQT6wNjGiaJqDx8QUShk0kO48kUIhL
|
||||
AgCfBSz4satMtQAAAABJRU5ErkJggg==
|
||||
}
|
||||
|
||||
image create photo rightarrow -data {
|
||||
iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAC3HpUWHRSYXcgcHJvZmlsZSB0eXBl
|
||||
IGV4aWYAAHja7ZdRkuMoDIbfOcUeAUkIieNgA1Vzgz3+/mDa6aR7pmpn52EfYipgK7IE/ydId+h/
|
||||
/xjhL1xUJIak5rnkHHGlkgpX3Hi8rmukmFZ/Xece6dke7i8YJsEo12Pu27/Cro8XLG378WwPtgOx
|
||||
70AfmXdAmZn5MRPfgYQvO+3nUPZ7NX1azv4cbdv0Gl6fk0GMpognHLgLSUTvM4tgBlKkomf0IssJ
|
||||
1ippW+R77cJ9+yLeffeiXazbLs9ShJi3Q37RaNtJv9duKfR5RvTI/PSFyZ3ii3ZjNB+jX6urKUOp
|
||||
HPaiPpay7uB4QMpLjYxm+CjubbWC5ljiCWINNA+0M1AhhtqDEjWqNKiv8aQTU0zc2TAynyzL5mJc
|
||||
+FxQ0mw02ICnBXHQOEFNJpd7LrTylpXvJEfmRvBkQrBJ9EsL3xl/p92BxpilSxT91grz4lnTmMYk
|
||||
N3t4AQiNrakufVcLn+omfgIrIKhLZscCazyuEIfSo7ZkcRb4aUwhXluDrO0AkAi5FZMhAYGYSZQy
|
||||
RWM2Iujo4FMxc5bEBwiQKjcKA2xEMuA4z9x4x2j5svJlxtECECpZDGiwgQArJUX9WHLUUFXRFFQ1
|
||||
q6lr0Zolp6w5Z8vzjKomlkwtm5lbseriydWzm7sXr4WL4AjTkouF4qWUWpG0InTF2xUetR58yJEO
|
||||
PfJhhx/lqCfK50ynnvm0089y1sZNGrZ/y81C81Za7dRRSj117blb9156Hai1ISMNHXnY8FFGvalt
|
||||
qs/U6IXcr6nRpjaJpeVnD2owm32EoHmc6GQGYpwIxG0SQEHzZBadUuJJbjKLhbEplEGNdMJpNImB
|
||||
YOrEOuhm9yD3S25B07/ixj8jFya6P0EuTHSb3Fdu31Brdf2iyAI0d+HUNMrAwQaH7pW9zt+k3x7D
|
||||
fw3wDvQO9A70DvQO9A70DvT/CTTwxwP+1Qz/AGOHkeWpKJljAAAABmJLR0QA/wD/AP+gvaeTAAAA
|
||||
CXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH4wwfASohs07fBQAAAFhJREFUKM9jYMAN6hlIBP8Z
|
||||
GBhqSdWAoYmFgYGhDSqBCzRB6WZ0kwjhWpgNxIImBgYGRiYSA+IjKU7KZ2BgYGCEMrB5eiISuwCN
|
||||
jzdY80mJh3xSPFiITRAA3qskpC7RIkIAAAAASUVORK5CYII=
|
||||
}
|
||||
proc missing_tcllib { pkg } {
|
||||
catch { puts stderr "Could not find the '$pkg' package -- you must install tcllib.\nPlease see http://tcllib.sourceforge.net/" }
|
||||
tk_dialog .err "Error: tcllib not installed" "Could not find the '$pkg' package -- you must install tcllib. Please see http://tcllib.sourceforge.net/" error 0 OK
|
||||
@@ -76,6 +149,9 @@ set OptDescr(MailAddr) "(String) Specify an e-mail address to which reminders sh
|
||||
set Option(SMTPServer) "127.0.0.1"
|
||||
set OptDescr(SMTPServer) "(String) IP address or host name of SMTP server to use for sending e-mail"
|
||||
|
||||
set Option(ExtraRemindArgs) ""
|
||||
set OptDescr(ExtraRemindArgs) "(String) Extra arguments when invoking remind"
|
||||
|
||||
# Remind program to execute -- supply full path if you want
|
||||
set Remind "remind"
|
||||
#set Remind "/home/dfs/Remind/src/remind"
|
||||
@@ -93,8 +169,12 @@ set EditorPid -1
|
||||
set AppendFile {NOSUCHFILE}
|
||||
catch {set AppendFile $ReminderFile}
|
||||
|
||||
set SetFontsWorked 0
|
||||
#---------------- DON'T CHANGE STUFF BELOW HERE ------------------
|
||||
|
||||
# 24-hour clock mode
|
||||
set TwentyFourHourMode 0
|
||||
|
||||
# Is Monday in first column?
|
||||
set MondayFirst 0
|
||||
|
||||
@@ -153,10 +233,10 @@ set HighestTagSoFar 0
|
||||
proc Initialize {} {
|
||||
|
||||
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
|
||||
global MondayFirst
|
||||
|
||||
set CommandLine "|$Remind -itkremind=1 -p -y -l"
|
||||
set PSCmd "$Remind -p -l"
|
||||
global MondayFirst TwentyFourHourMode ReminderFileModTime
|
||||
global Option
|
||||
set CommandLine "|$Remind -itkremind=1 -p -y -l EXTRA"
|
||||
set PSCmd "$Remind -p -l EXTRA"
|
||||
set i 0
|
||||
while {$i < $argc} {
|
||||
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
|
||||
@@ -165,6 +245,9 @@ proc Initialize {} {
|
||||
if {[regexp -- {m} [lindex $argv $i]]} {
|
||||
set MondayFirst 1
|
||||
}
|
||||
if {"[lindex $argv $i]" == "-b1"} {
|
||||
set TwentyFourHourMode 1
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
@@ -180,6 +263,14 @@ proc Initialize {} {
|
||||
}
|
||||
}
|
||||
|
||||
# If reminder file is a directory and appendfile is the same as
|
||||
# reminder file, choose append file to be $ReminderFile/100-tkremind.rem
|
||||
if {[file isdirectory $ReminderFile]} {
|
||||
if {"$ReminderFile" == "$AppendFile"} {
|
||||
set AppendFile [file join $ReminderFile "100-tkremind.rem"]
|
||||
}
|
||||
}
|
||||
|
||||
# Check system sanity
|
||||
if {! [file readable $ReminderFile]} {
|
||||
set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"]
|
||||
@@ -193,6 +284,12 @@ proc Initialize {} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {[file isdirectory $ReminderFile] && ! [file exists $AppendFile]} {
|
||||
if {![catch {close [open "$AppendFile" "a"]}]} {
|
||||
tk_dialog .error "Created File" "Created blank file `$AppendFile'" info 0 "OK"
|
||||
}
|
||||
}
|
||||
|
||||
if {! [file writable $AppendFile]} {
|
||||
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
|
||||
exit 1
|
||||
@@ -201,9 +298,49 @@ proc Initialize {} {
|
||||
append CommandLine " $ReminderFile"
|
||||
append PSCmd " $ReminderFile"
|
||||
set DayNames [GetWeekdayNames]
|
||||
|
||||
# Get modification time of ReminderFile
|
||||
set ReminderFileModTime -1
|
||||
catch {
|
||||
set ReminderFileModTime [file mtime $ReminderFile]
|
||||
}
|
||||
|
||||
MonitorReminderFile
|
||||
|
||||
# puts "CommandLine: $CommandLine"
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# MonitorReminderFile
|
||||
# If Reminder File modtime changes, restart daemon
|
||||
#---------------------------------------------------------------------------
|
||||
proc MonitorReminderFile {} {
|
||||
global ReminderFileModTime ReminderFile
|
||||
|
||||
if {$ReminderFileModTime < 0} {
|
||||
# Could not stat file
|
||||
return
|
||||
}
|
||||
|
||||
set mtime -1
|
||||
catch {
|
||||
set mtime [file mtime $ReminderFile]
|
||||
}
|
||||
if {$mtime < 0} {
|
||||
# Doh!
|
||||
return
|
||||
}
|
||||
|
||||
# Run ourselves again
|
||||
after 60000 MonitorReminderFile
|
||||
|
||||
# Redraw calendar and restart daemon if needed
|
||||
if {$ReminderFileModTime < $mtime} {
|
||||
set ReminderFileModTime $mtime
|
||||
FillCalWindow
|
||||
RestartBackgroundRemindDaemon
|
||||
}
|
||||
}
|
||||
#---------------------------------------------------------------------------
|
||||
# GetWeekdayNames - Spawn a remind process and get the names of the weekdays
|
||||
# Also sets CurMonth and CurYear.
|
||||
@@ -271,9 +408,14 @@ proc CalEntryOffset { firstDay } {
|
||||
#***********************************************************************
|
||||
proc CreateCalFrame { w dayNames } {
|
||||
# Figure out reasonable height for text frames
|
||||
global SetFontsWorked
|
||||
set h [winfo screenheight .]
|
||||
if {$h <= 480} {
|
||||
set h 2
|
||||
if {$SetFontsWorked} {
|
||||
set h 3
|
||||
} else {
|
||||
set h 2
|
||||
}
|
||||
} elseif {$h <= 600} {
|
||||
set h 4
|
||||
} else {
|
||||
@@ -329,10 +471,13 @@ proc CreateCalFrame { w dayNames } {
|
||||
#***********************************************************************
|
||||
proc ConfigureCalFrame { w firstDay numDays } {
|
||||
global CurMonth CurYear TodayMonth TodayYear TodayDay
|
||||
global tk_version
|
||||
set offset [CalEntryOffset $firstDay]
|
||||
set first [expr $offset+1]
|
||||
set last [expr $offset+$numDays]
|
||||
|
||||
set bg [lindex [. configure -background] 3]
|
||||
|
||||
for {set i 0} {$i < $first} {incr i} {
|
||||
grid $w.l$i $w.t$i
|
||||
$w.l$i configure -text "" -command "" -state disabled -relief flat
|
||||
@@ -344,8 +489,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
|
||||
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
|
||||
$w.t$i configure -state disabled
|
||||
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
||||
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
||||
$w.t$i configure -background $bg
|
||||
$w.l$i configure -background $bg
|
||||
}
|
||||
for {set i $first} {$i <= $last} {incr i} {
|
||||
grid $w.l$i $w.t$i
|
||||
@@ -360,8 +505,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
|
||||
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
|
||||
$w.t$i configure -state disabled
|
||||
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
||||
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
||||
$w.t$i configure -background $bg
|
||||
$w.l$i configure -background $bg
|
||||
}
|
||||
set forgetIt 0
|
||||
for {set i [expr $last+1]} {$i < 42} {incr i} {
|
||||
@@ -385,8 +530,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
|
||||
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
|
||||
$w.t$i configure -state disabled
|
||||
$w.t$i configure -background [lindex [$w.t$i configure -background] 3]
|
||||
$w.l$i configure -background [lindex [$w.l$i configure -background] 3]
|
||||
$w.t$i configure -background $bg
|
||||
$w.l$i configure -background $bg
|
||||
}
|
||||
if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
|
||||
set n [expr $TodayDay + $offset]
|
||||
@@ -394,6 +539,12 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
}
|
||||
}
|
||||
|
||||
proc DoQueue {} {
|
||||
global DaemonFile
|
||||
puts $DaemonFile "QUEUE"
|
||||
flush $DaemonFile
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# CreateCalWindow -- create the calendar window.
|
||||
# Arguments:
|
||||
@@ -409,16 +560,17 @@ proc CreateCalWindow { dayNames } {
|
||||
CreateCalFrame .cal $dayNames
|
||||
|
||||
frame .b
|
||||
button .b.prev -text {<-} -command {MoveMonth -1} -border 1
|
||||
button .b.prev -image leftarrow -width 24 -command {MoveMonth -1} -border 1
|
||||
button .b.this -text {Today} -command {ThisMonth} -border 1
|
||||
button .b.next -text {->} -command {MoveMonth 1} -border 1
|
||||
button .b.next -image rightarrow -width 24 -command {MoveMonth 1} -border 1
|
||||
button .b.goto -text {Go To Date...} -command {GotoDialog} -border 1
|
||||
button .b.print -text {Print...} -command {DoPrint} -border 1
|
||||
button .b.queue -text {Queue...} -command {DoQueue} -border 1
|
||||
button .b.quit -text {Quit} -command {Quit} -border 1
|
||||
button .b.options -text {Options...} -command EditOptions -border 1
|
||||
label .b.status -text "" -width 25 -relief sunken -border 1
|
||||
label .b.nqueued -text "" -width 20 -relief sunken -border 1
|
||||
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.quit -side left -fill x
|
||||
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.queue .b.quit -side left -fill both
|
||||
pack .b.status -side left -fill x -expand 1
|
||||
pack .b.nqueued -side left -fill x
|
||||
pack .b -side bottom -fill x -expand 0
|
||||
@@ -527,6 +679,14 @@ proc EditOptions {} {
|
||||
pack $w.editor -in $w.ef -side left -expand 1 -fill x
|
||||
$w.editor insert 0 $tmpOpt(Editor)
|
||||
|
||||
# extra args
|
||||
frame $w.eaf
|
||||
label $w.eal -text "Extra Arguments for Remind:" -anchor w -justify left
|
||||
entry $w.extraargs -width 30
|
||||
pack $w.eal -in $w.eaf -side left -expand 0 -fill none
|
||||
pack $w.extraargs -in $w.eaf -side left -expand 1 -fill x
|
||||
$w.extraargs insert 0 $tmpOpt(ExtraRemindArgs)
|
||||
|
||||
frame $w.sep1 -border 1 -relief sunken
|
||||
frame $w.sep2 -border 1 -relief sunken
|
||||
|
||||
@@ -547,6 +707,7 @@ proc EditOptions {} {
|
||||
pack $w.eml -in $w.f -side top -expand 0 -fill x
|
||||
pack $w.fsmtp -in $w.f -side top -expand 0 -fill x
|
||||
pack $w.ef -in $w.f -side top -expand 0 -fill x
|
||||
pack $w.eaf -in $w.f -side top -expand 0 -fill x
|
||||
pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1
|
||||
|
||||
button $w.apply -text "Apply Options" -command "ApplyOptions $w; destroy $w"
|
||||
@@ -554,7 +715,7 @@ proc EditOptions {} {
|
||||
button $w.cancel -text "Cancel" -command "destroy $w"
|
||||
|
||||
pack $w.apply $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
|
||||
CenterWindow $w
|
||||
CenterWindow $w .
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -568,15 +729,26 @@ proc EditOptions {} {
|
||||
#***********************************************************************
|
||||
proc ApplyOptions { w } {
|
||||
global Option tmpOpt
|
||||
|
||||
set tmpOpt(RunCmd) [$w.cmd get]
|
||||
set tmpOpt(Editor) [$w.editor get]
|
||||
set tmpOpt(ExtraRemindArgs) [$w.extraargs get]
|
||||
set tmpOpt(MailAddr) [$w.email_address get]
|
||||
set tmpOpt(SMTPServer) [$w.smtp get]
|
||||
|
||||
set need_restart 0
|
||||
if {"$tmpOpt(ExtraRemindArgs)" != "$Option(ExtraRemindArgs)"} {
|
||||
set need_restart 1
|
||||
}
|
||||
# Copy working copy to real option set
|
||||
foreach name [array names tmpOpt] {
|
||||
set Option($name) $tmpOpt($name)
|
||||
}
|
||||
if {$need_restart != 0} {
|
||||
FillCalWindow
|
||||
StopBackgroundRemindDaemon
|
||||
StartBackgroundRemindDaemon
|
||||
}
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -661,8 +833,9 @@ proc LoadOptions {} {
|
||||
# Any side effects
|
||||
#***********************************************************************
|
||||
proc ConfigureCalWindow { month year firstDay numDays } {
|
||||
global Hostname
|
||||
.h.title configure -text "$month $year"
|
||||
wm title . "$month $year - TkRemind"
|
||||
wm title . "$month $year - TkRemind on $Hostname"
|
||||
wm iconname . "$month $year"
|
||||
ConfigureCalFrame .cal $firstDay $numDays
|
||||
}
|
||||
@@ -673,12 +846,13 @@ proc ConfigureCalWindow { month year firstDay numDays } {
|
||||
proc FillCalWindow {} {
|
||||
set FileName ""
|
||||
set LineNo 0
|
||||
global DayNames CurYear CurMonth MonthNames CommandLine
|
||||
global DayNames CurYear CurMonth MonthNames CommandLine Option
|
||||
|
||||
Status "Firing off Remind..."
|
||||
set month [lindex $MonthNames $CurMonth]
|
||||
|
||||
set file [open "$CommandLine $month $CurYear" r]
|
||||
set cmd [regsub EXTRA $CommandLine $Option(ExtraRemindArgs)]
|
||||
set file [open "$cmd $month $CurYear" r]
|
||||
# Look for # rem2ps begin line
|
||||
while { [gets $file line] >= 0 } {
|
||||
if { [string compare "$line" "# rem2ps begin"] == 0 } { break }
|
||||
@@ -720,6 +894,13 @@ proc FillCalWindow {} {
|
||||
set month [string trimleft $month 0]
|
||||
set extratags ""
|
||||
switch -exact -- $type {
|
||||
"WEEK" {
|
||||
set stuff [string trimleft $stuff]
|
||||
set stuff [string trimright $stuff]
|
||||
set label [expr $firstWkday + $day - 1]
|
||||
.cal.l$label configure -text "$day $stuff"
|
||||
continue
|
||||
}
|
||||
"SHADE" {
|
||||
DoShadeSpecial $n $stuff
|
||||
continue
|
||||
@@ -728,6 +909,7 @@ proc FillCalWindow {} {
|
||||
DoMoonSpecial $n $stuff
|
||||
continue
|
||||
}
|
||||
"COLOUR" -
|
||||
"COLOR" {
|
||||
if {[regexp {^ *([0-9]+) +([0-9]+) +([0-9]+) +(.*)$} $stuff all r g b rest]} {
|
||||
if {$r > 255} {
|
||||
@@ -754,7 +936,7 @@ proc FillCalWindow {} {
|
||||
}
|
||||
}
|
||||
}
|
||||
if { $type != "*" && $type != "COLOR"} {
|
||||
if { $type != "*" && $type != "COLOR" && $type != "COLOUR"} {
|
||||
continue
|
||||
}
|
||||
.cal.t$n configure -state normal
|
||||
@@ -828,7 +1010,7 @@ proc Status { stuff } {
|
||||
# None
|
||||
#---------------------------------------------------------------------------
|
||||
proc DoPrint {} {
|
||||
global PrintDest PrintSize PrintMargins PrintOrient PrintFill PrintEncoding PrintSmallCalendars PrintStatus Rem2PS PSCmd
|
||||
global PrintDest PrintSize PrintMargins PrintOrient PrintFill PrintEncoding PrintSmallCalendars PrintStatus Rem2PS PSCmd Option
|
||||
global CurMonth CurYear MonthNames
|
||||
catch {destroy .p}
|
||||
toplevel .p
|
||||
@@ -886,7 +1068,7 @@ proc DoPrint {} {
|
||||
bind .p <KeyPress-Escape> ".p.cancel flash; .p.cancel invoke"
|
||||
bind .p <KeyPress-Return> ".p.print flash; .p.print invoke"
|
||||
set PrintStatus 2
|
||||
CenterWindow .p
|
||||
CenterWindow .p .
|
||||
tkwait visibility .p
|
||||
set oldFocus [focus]
|
||||
focus .p.filename
|
||||
@@ -920,7 +1102,8 @@ proc DoPrint {} {
|
||||
}
|
||||
|
||||
# Build the command line
|
||||
set cmd "$PSCmd 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS"
|
||||
set p [regsub EXTRA $PSCmd $Option(ExtraRemindArgs)]
|
||||
set cmd "$p 1 [lindex $MonthNames $CurMonth] $CurYear | $Rem2PS"
|
||||
if {$PrintSize == "letter"} {
|
||||
append cmd " -m Letter"
|
||||
} else {
|
||||
@@ -1008,7 +1191,7 @@ proc GotoDialog {} {
|
||||
pack .g.y -expand 1 -fill x
|
||||
pack .g.b -expand 1 -fill x
|
||||
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
||||
CenterWindow .g
|
||||
CenterWindow .g .
|
||||
set oldFocus [focus]
|
||||
grab .g
|
||||
focus .g.y.e
|
||||
@@ -1067,7 +1250,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
|
||||
# Set up: Year, Month, Day, WeekdayName
|
||||
global CurYear CurMonth EnglishDayNames MonthNames OptionType SkipType
|
||||
global ModifyDialogResult
|
||||
global ModifyDialogResult TwentyFourHourMode
|
||||
|
||||
set OptionType 1
|
||||
set SkipType 1
|
||||
@@ -1083,12 +1266,13 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
frame $w.exp -border 4
|
||||
frame $w.adv -border 4
|
||||
frame $w.weekend -border 4
|
||||
frame $w.durationbox -border 4
|
||||
frame $w.time -border 4
|
||||
frame $w.hol -border 4
|
||||
frame $w.msg
|
||||
frame $w.buttons
|
||||
pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.hol $w.msg -side top -anchor w -pady 4 -expand 1 -fill both
|
||||
pack $w.o $w.exp $w.adv $w.weekend $w.time $w.durationbox $w.hol $w.msg -side top -anchor w -pady 4 -expand 1 -fill both
|
||||
pack $w.buttons -side top -anchor w -pady 4 -expand 1 -fill x
|
||||
|
||||
# TYPE 1 REMINDER
|
||||
@@ -1187,7 +1371,11 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
checkbutton $w.timebut -text "Timed reminder at"
|
||||
$w.timebut deselect
|
||||
menubutton $w.timehour -text "12" -menu $w.timehour.menu -relief raised
|
||||
CreateDayMenu $w.timehour 1 12 0
|
||||
if {$TwentyFourHourMode} {
|
||||
CreateDayMenu $w.timehour 0 23 0
|
||||
} else {
|
||||
CreateDayMenu $w.timehour 1 12 0
|
||||
}
|
||||
menubutton $w.timemin -text "00" -menu $w.timemin.menu -relief raised
|
||||
menu $w.timemin.menu -tearoff 0
|
||||
foreach i {00 05 10 15 20 25 30 35 40 45 50 55} {
|
||||
@@ -1195,10 +1383,12 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
-command "$w.timemin configure -text $i"
|
||||
}
|
||||
|
||||
menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised
|
||||
menu $w.ampm.menu -tearoff 0
|
||||
$w.ampm.menu add command -label "AM" -command "$w.ampm configure -text {AM}"
|
||||
$w.ampm.menu add command -label "PM" -command "$w.ampm configure -text {PM}"
|
||||
if {!$TwentyFourHourMode} {
|
||||
menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised
|
||||
menu $w.ampm.menu -tearoff 0
|
||||
$w.ampm.menu add command -label "AM" -command "$w.ampm configure -text {AM}"
|
||||
$w.ampm.menu add command -label "PM" -command "$w.ampm configure -text {PM}"
|
||||
}
|
||||
|
||||
checkbutton $w.timeadvbut -text "with"
|
||||
$w.timeadvbut deselect
|
||||
@@ -1217,7 +1407,27 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
$w.timerep.menu add command -label $i -command "$w.timerep configure -text $i"
|
||||
}
|
||||
label $w.timelab2 -text "minutes"
|
||||
pack $w.timebut $w.timehour $w.timemin $w.ampm $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
|
||||
if {$TwentyFourHourMode} {
|
||||
pack $w.timebut $w.timehour $w.timemin $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
|
||||
} else {
|
||||
pack $w.timebut $w.timehour $w.timemin $w.ampm $w.timeadvbut $w.timeadv $w.timelab1 $w.timerepbut $w.timerep $w.timelab2 -side left -anchor w -in $w.time
|
||||
}
|
||||
|
||||
# DURATION
|
||||
checkbutton $w.durationbut -text "Duration"
|
||||
$w.durationbut deselect
|
||||
menubutton $w.durationh -text "1" -menu $w.durationh.menu -relief raised
|
||||
menu $w.durationh.menu -tearoff 0
|
||||
foreach i {0 1 2 3 4 5 6 7 8 9 10 11 12} {
|
||||
$w.durationh.menu add command -label $i -command "$w.durationh configure -text $i"
|
||||
}
|
||||
label $w.durationcolon -text ":"
|
||||
menubutton $w.durationm -text "00" -menu $w.durationm.menu -relief raised
|
||||
menu $w.durationm.menu -tearoff 0
|
||||
foreach i {00 15 30 45} {
|
||||
$w.durationm.menu add command -label $i -command "$w.durationm configure -text $i"
|
||||
}
|
||||
pack $w.durationbut $w.durationh $w.durationcolon $w.durationm -side left -anchor w -in $w.durationbox
|
||||
|
||||
# SKIP TYPE
|
||||
label $w.labhol -text "On holidays or weekends:"
|
||||
@@ -1248,7 +1458,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
set ModifyDialogResult 0
|
||||
|
||||
# Center the window on the root
|
||||
CenterWindow $w
|
||||
CenterWindow $w .
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -1261,7 +1471,7 @@ proc CreateModifyDialog {w day firstDay args} {
|
||||
#***********************************************************************
|
||||
proc RemindDialogToOptions { w } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
set ans {}
|
||||
lappend ans "-global-OptionType" $OptionType
|
||||
@@ -1295,13 +1505,20 @@ proc RemindDialogToOptions { w } {
|
||||
#***********************************************************************
|
||||
proc OptionsToRemindDialog { w opts } {
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut
|
||||
global timebut timeadvbut timerepbut TwentyFourHourMode durationbut
|
||||
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
|
||||
set hour ""
|
||||
set ampm ""
|
||||
foreach {flag value} $opts {
|
||||
switch -glob -- $flag {
|
||||
"-text-*" {
|
||||
set win [string range $flag 6 end]
|
||||
$w.$win configure -text $value
|
||||
catch { $w.$win configure -text $value }
|
||||
if {"$flag" == "-text-ampm"} {
|
||||
set ampm $value
|
||||
} elseif {"$flag" == "-text-timehour"} {
|
||||
set hour $value
|
||||
}
|
||||
}
|
||||
"-global-*" {
|
||||
set win [string range $flag 8 end]
|
||||
@@ -1314,6 +1531,26 @@ proc OptionsToRemindDialog { w opts } {
|
||||
}
|
||||
}
|
||||
}
|
||||
if {"$hour" != ""} {
|
||||
if {$TwentyFourHourMode} {
|
||||
if {"$ampm" != ""} {
|
||||
if {"$ampm" == "PM" && $hour < 12} {
|
||||
incr hour 12;
|
||||
$w.timehour configure -text $hour
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if {$hour > 12} {
|
||||
incr hour -12
|
||||
$w.timehour configure -text $hour
|
||||
$w.ampm configure -text "PM"
|
||||
} else {
|
||||
if {"$ampm" == ""} {
|
||||
$w.ampm configure -text "AM"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
@@ -1444,17 +1681,24 @@ proc ModifyDay {d firstDay} {
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# CenterWindow -- center a window on the screen. Stolen from tk_dialog code
|
||||
# CenterWindow -- center a window on the screen or over a parent.
|
||||
# Stolen from tk_dialog code
|
||||
# Arguments:
|
||||
# w -- window to center
|
||||
# parent -- window over which to center. Defaults to screen if not supplied.
|
||||
#---------------------------------------------------------------------------
|
||||
proc CenterWindow {w} {
|
||||
proc CenterWindow {w {parent {}}} {
|
||||
wm withdraw $w
|
||||
update idletasks
|
||||
set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
|
||||
- [winfo vrootx [winfo parent $w]]]
|
||||
set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
|
||||
- [winfo vrooty [winfo parent $w]]]
|
||||
if {"$parent" == ""} {
|
||||
set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
|
||||
- [winfo vrootx [winfo parent $w]]]
|
||||
set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
|
||||
- [winfo vrooty [winfo parent $w]]]
|
||||
} else {
|
||||
set x [expr [winfo rootx $parent] + [winfo width $parent]/2 - [winfo reqwidth $w]/2]
|
||||
set y [expr [winfo rooty $parent] + [winfo height $parent]/2 - [winfo reqheight $w]/2]
|
||||
}
|
||||
wm geom $w +$x+$y
|
||||
wm deiconify $w
|
||||
}
|
||||
@@ -1467,7 +1711,7 @@ proc CenterWindow {w} {
|
||||
# The reminder as a string.
|
||||
#---------------------------------------------------------------------------
|
||||
proc CreateReminder {w} {
|
||||
global DidOmit
|
||||
global DidOmit TwentyFourHourMode
|
||||
|
||||
set body [string trim [$w.entry get]]
|
||||
|
||||
@@ -1480,7 +1724,7 @@ proc CreateReminder {w} {
|
||||
# Delegate the first part to CreateReminder1, CreateReminder2, or
|
||||
# CreateReminder3
|
||||
global OptionType SkipType repbut expbut advbut advcount
|
||||
global timebut timeadvbut timerepbut
|
||||
global timebut timeadvbut timerepbut durationbut
|
||||
|
||||
set rem [CreateReminder$OptionType $w]
|
||||
|
||||
@@ -1504,13 +1748,15 @@ proc CreateReminder {w} {
|
||||
if {$timebut} {
|
||||
set hour [$w.timehour cget -text]
|
||||
set min [$w.timemin cget -text]
|
||||
if {[$w.ampm cget -text] == "PM"} {
|
||||
if {$hour < 12} {
|
||||
incr hour 12
|
||||
}
|
||||
} else {
|
||||
if {$hour == 12} {
|
||||
set hour 0
|
||||
if {!$TwentyFourHourMode} {
|
||||
if {[$w.ampm cget -text] == "PM"} {
|
||||
if {$hour < 12} {
|
||||
incr hour 12
|
||||
}
|
||||
} else {
|
||||
if {$hour == 12} {
|
||||
set hour 0
|
||||
}
|
||||
}
|
||||
}
|
||||
append rem " AT $hour:$min"
|
||||
@@ -1520,6 +1766,9 @@ proc CreateReminder {w} {
|
||||
if {$timerepbut} {
|
||||
append rem " *[$w.timerep cget -text]"
|
||||
}
|
||||
if {$durationbut} {
|
||||
append rem " DURATION [$w.durationh cget -text]:[$w.durationm cget -text]"
|
||||
}
|
||||
}
|
||||
|
||||
global SkipType
|
||||
@@ -1732,7 +1981,7 @@ proc EditReminder {rem args} {
|
||||
pack .edit.f -side top -fill x -expand 1
|
||||
bind .edit <KeyPress-Escape> ".edit.but1 flash; .edit.but1 invoke"
|
||||
set ModifyDialogResult 0
|
||||
CenterWindow .edit
|
||||
CenterWindow .edit .
|
||||
tkwait visibility .edit
|
||||
set oldFocus [focus]
|
||||
focus .edit.t
|
||||
@@ -1842,7 +2091,7 @@ proc BrowseForFile {w title {oktext "OK"} {showdots 0} {filter "*"}} {
|
||||
bindtags $w.entry "Entry $w.entry $w all"
|
||||
|
||||
bindtags $w.list "Listbox $w.list $w all"
|
||||
CenterWindow $w
|
||||
CenterWindow $w .
|
||||
set oldFocus [focus]
|
||||
tkwait visibility $w
|
||||
focus $w.entry
|
||||
@@ -1965,8 +2214,8 @@ proc BrowseForFileRead {w {dir ""}} {
|
||||
# Starts a background Remind daemon to handle timed reminders
|
||||
#---------------------------------------------------------------------------
|
||||
proc StartBackgroundRemindDaemon {} {
|
||||
global Remind DaemonFile ReminderFile
|
||||
set problem [catch { set DaemonFile [open "|$Remind -z0 $ReminderFile" "r+"] } err]
|
||||
global Remind DaemonFile ReminderFile Option
|
||||
set problem [catch { set DaemonFile [open "|$Remind -z0 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||
if {$problem} {
|
||||
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
||||
} else {
|
||||
@@ -2004,13 +2253,61 @@ proc StopBackgroundRemindDaemon {} {
|
||||
# Restarts the background Remind daemon
|
||||
#---------------------------------------------------------------------------
|
||||
proc RestartBackgroundRemindDaemon {} {
|
||||
global DaemonFile
|
||||
global DaemonFile ReminderFile ReminderFileModTime
|
||||
|
||||
# Don't let the background handler trigger another reread
|
||||
catch {
|
||||
set mtime [file mtime $ReminderFile]
|
||||
set ReminderFileModTime $mtime
|
||||
}
|
||||
|
||||
catch {
|
||||
puts $DaemonFile "REREAD"
|
||||
flush $DaemonFile
|
||||
}
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ShowQueue
|
||||
# Arguments:
|
||||
# file -- file channel that is readable
|
||||
# Returns:
|
||||
# nothing
|
||||
# Description:
|
||||
# Dumps the debugging queue listing
|
||||
#---------------------------------------------------------------------------
|
||||
proc ShowQueue { file } {
|
||||
set w .queuedbg
|
||||
catch { destroy $w }
|
||||
toplevel $w
|
||||
wm title $w "Queue (Debugging Output)"
|
||||
wm iconname $w "Queue Dbg"
|
||||
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
||||
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
||||
button $w.ok -text "OK" -command "destroy $w"
|
||||
grid $w.t -row 0 -column 0 -sticky nsew
|
||||
grid $w.sb -row 0 -column 1 -sticky ns
|
||||
grid $w.ok -row 1 -column 0 -sticky w
|
||||
grid columnconfigure $w 0 -weight 1
|
||||
grid columnconfigure $w 1 -weight 0
|
||||
grid rowconfigure $w 0 -weight 1
|
||||
grid rowconfigure $w 1 -weight 0
|
||||
set did 0
|
||||
CenterWindow $w .
|
||||
while (1) {
|
||||
gets $file line
|
||||
if {$line == "NOTE endqueue"} {
|
||||
break
|
||||
}
|
||||
set did 1
|
||||
$w.t insert end "$line\n"
|
||||
}
|
||||
if {!$did} {
|
||||
$w.t insert end "*** Queue is empty ***\n"
|
||||
}
|
||||
$w.t configure -state disabled
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# DaemonReadable
|
||||
# Arguments:
|
||||
@@ -2033,6 +2330,9 @@ proc DaemonReadable { file } {
|
||||
scan $line "NOTE reminder %s %s %s" time now tag
|
||||
IssueBackgroundReminder $file $time $now $tag
|
||||
}
|
||||
"NOTE queue" {
|
||||
ShowQueue $file
|
||||
}
|
||||
"NOTE newdate" {
|
||||
# Date has rolled over -- clear "ignore" list
|
||||
catch { unset Ignore}
|
||||
@@ -2124,7 +2424,7 @@ proc IssueBackgroundReminder { file time now tag } {
|
||||
pack $w.nomore $w.kill -in $w.b -side left
|
||||
}
|
||||
|
||||
CenterWindow $w
|
||||
CenterWindow $w .
|
||||
|
||||
update
|
||||
if {$Option(RingBell)} {
|
||||
@@ -2191,9 +2491,9 @@ proc main {} {
|
||||
|
||||
global AppendFile HighestTagSoFar DayNames
|
||||
catch {
|
||||
puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll"
|
||||
puts "Copyright (C) 1999-2007 Roaring Penguin Software Inc."
|
||||
puts "\nTkRemind Copyright (C) 1996-2020 Dianne Skoll"
|
||||
}
|
||||
catch { SetFonts }
|
||||
LoadOptions
|
||||
CreateMoonImages
|
||||
Initialize
|
||||
@@ -2647,7 +2947,12 @@ proc DoMoonSpecial { n stuff } {
|
||||
# Displays current date and time in status window
|
||||
#***********************************************************************
|
||||
proc DisplayTime {} {
|
||||
set msg [clock format [clock seconds] -format "%e %b %Y %I:%M%p"]
|
||||
global TwentyFourHourMode
|
||||
if {$TwentyFourHourMode} {
|
||||
set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
|
||||
} else {
|
||||
set msg [clock format [clock seconds] -format "%e %b %Y %I:%M%p"]
|
||||
}
|
||||
Status $msg
|
||||
}
|
||||
|
||||
@@ -2661,14 +2966,10 @@ proc DisplayTime {} {
|
||||
# Creates the moon images "new", "first", "full" and "last"
|
||||
#***********************************************************************
|
||||
proc CreateMoonImages {} {
|
||||
image create bitmap full -foreground black \
|
||||
-data "#define newmoon_width 16\n#define newmoon_height 16\nstatic unsigned char newmoon_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0x30, 0x06, 0x0c, 0x18, 0x04, 0x10, 0x02, 0x20,\n0x02, 0x20, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x02, 0x20, 0x02, 0x20,\n0x04, 0x10, 0x0c, 0x18, 0x30, 0x06, 0xc0, 0x01};"
|
||||
image create bitmap first -foreground black \
|
||||
-data "#define firstquarter_width 16\n#define firstquarter_height 16\nstatic unsigned char firstquarter_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xf0, 0x06, 0xfc, 0x18, 0xfc, 0x10, 0xfe, 0x20,\n0xfe, 0x20, 0xff, 0x40, 0xff, 0x40, 0xff, 0x40, 0xfe, 0x20, 0xfe, 0x20,\n0xfc, 0x10, 0xfc, 0x18, 0xf0, 0x06, 0xc0, 0x01};"
|
||||
image create bitmap new -foreground black \
|
||||
-data "#define fullmoon_width 16\n#define fullmoon_height 16\nstatic unsigned char fullmoon_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xf0, 0x07, 0xfc, 0x1f, 0xfc, 0x1f, 0xfe, 0x3f,\n0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xfe, 0x3f, 0xfe, 0x3f,\n0xfc, 0x1f, 0xfc, 0x1f, 0xf0, 0x07, 0xc0, 0x01};"
|
||||
image create bitmap last -foreground black \
|
||||
-data "#define lastquarter_width 16\n#define lastquarter_height 16\nstatic unsigned char lastquarter_bits[] = {\n0x00, 0x00, 0xc0, 0x01, 0xb0, 0x07, 0x8c, 0x1f, 0x84, 0x1f, 0x82, 0x3f,\n0x82, 0x3f, 0x81, 0x7f, 0x81, 0x7f, 0x81, 0x7f, 0x82, 0x3f, 0x82, 0x3f,\n0x84, 0x1f, 0x8c, 0x1f, 0xb0, 0x07, 0xc0, 0x01};"
|
||||
image create photo full -data "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC"
|
||||
image create photo first -data "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC"
|
||||
image create photo new -data "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII="
|
||||
image create photo last -data "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg=="
|
||||
}
|
||||
|
||||
#***********************************************************************
|
||||
@@ -2721,10 +3022,18 @@ proc ShowTodaysReminders {} {
|
||||
grid $w.sb -row 0 -column 1 -sticky ns
|
||||
grid $w.ok -row 1 -column 0 -sticky w
|
||||
|
||||
CenterWindow $w
|
||||
CenterWindow $w .
|
||||
|
||||
# Grab the reminders
|
||||
set stuff [exec -keepnewline $Remind -g -q -a -r $ReminderFile 2>/dev/null]
|
||||
set stuff ""
|
||||
set cmdline "|$Remind -g -q -r "
|
||||
append cmdline $Option(ExtraRemindArgs);
|
||||
append cmdline " $ReminderFile 2>/dev/null"
|
||||
set f [open $cmdline r]
|
||||
while {[gets $f line] >= 0} {
|
||||
append stuff "$line\n"
|
||||
}
|
||||
close $f
|
||||
$w.text insert end $stuff
|
||||
$w.text configure -state disabled
|
||||
}
|
||||
@@ -2784,4 +3093,16 @@ proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder
|
||||
}
|
||||
}
|
||||
|
||||
# Adjust font defaults for screen size
|
||||
proc SetFonts {} {
|
||||
global SetFontsWorked
|
||||
set h [winfo screenheight .]
|
||||
if {$h <= 480} {
|
||||
# Small screen (maybe eeepc?)
|
||||
font configure TkDefaultFont -size 6
|
||||
font configure TkFixedFont -size 6
|
||||
}
|
||||
set SetFontsWorked 1
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Makefile.in for REMIND
|
||||
#
|
||||
|
||||
VERSION=03.01.02
|
||||
SHELL= /bin/sh
|
||||
BETA = 1
|
||||
srcdir=@srcdir@
|
||||
@@ -12,6 +11,7 @@ bindir=@bindir@
|
||||
datadir=@datadir@
|
||||
datarootdir=@datarootdir@
|
||||
VPATH=$(srcdir)
|
||||
VERSION=@VERSION@
|
||||
|
||||
INSTALL=@INSTALL@
|
||||
INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||
@@ -38,10 +38,12 @@ REMINDOBJS= $(REMINDSRCS:.c=.o)
|
||||
all: remind rem2ps
|
||||
|
||||
test: remind
|
||||
sh ../tests/test-rem
|
||||
@sh ../tests/test-rem
|
||||
|
||||
.c.o:
|
||||
@CC@ -c @CFLAGS@ @DEFS@ $(CEXTRA) $(LANGDEF) -I. -I$(srcdir) $<
|
||||
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) $(LANGDEF) -I. -I$(srcdir) $<
|
||||
|
||||
$(REMINDOBJS): $(REMINDHDRS)
|
||||
|
||||
rem2ps: rem2ps.o dynbuf.o
|
||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o
|
||||
@@ -79,16 +81,14 @@ depend:
|
||||
|
||||
# Build a tar file based on all files checked into git.
|
||||
distro:
|
||||
ln -s . ../remind-$(VERSION)
|
||||
(cd ..; git-ls-files -x .gitignore) | sed -e 's/^/remind-$(VERSION)\//' | xargs tar -C .. -cvf remind-$(VERSION).tar
|
||||
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION).tar
|
||||
gzip -f -v -9 remind-$(VERSION).tar
|
||||
rm -f ../remind-$(VERSION)
|
||||
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION).tar.gz
|
||||
|
||||
beta-tgz:
|
||||
ln -s . ../remind-$(VERSION)-BETA-$(BETA)
|
||||
(cd ..; git-ls-files -x .gitignore) | sed -e 's/^/remind-$(VERSION)-BETA-$(BETA)\//' | xargs tar -C .. -cvf remind-$(VERSION)-BETA-$(BETA).tar
|
||||
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar
|
||||
gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar
|
||||
rm -f ../remind-$(VERSION)-BETA-$(BETA)
|
||||
|
||||
#---------------- Stuff after this added by "make depend" -----------------
|
||||
|
||||
|
||||
|
||||
890
src/calendar.c
890
src/calendar.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,3 @@
|
||||
/* src/config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define if utime(file, NULL) sets file's timestamp to the present. */
|
||||
#undef HAVE_UTIME_NULL
|
||||
|
||||
@@ -12,10 +10,23 @@
|
||||
/* Define if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
#undef HAVE_GLOB
|
||||
|
||||
#undef HAVE_SETENV
|
||||
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
#undef HAVE_MBSTOWCS
|
||||
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* The number of bytes in a unsigned int. */
|
||||
#undef SIZEOF_UNSIGNED_INT
|
||||
|
||||
|
||||
32
src/custom.h
32
src/custom.h
@@ -6,8 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -37,7 +36,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DEFAULT_PAGE {"Letter", 612, 792}
|
||||
/* #define DEFAULT_PAGE {"A4", 595, 842} */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* DATESEP: The default date separator. Standard usage is '-'; */
|
||||
/* others may prefer '/'. */
|
||||
@@ -52,6 +51,13 @@
|
||||
#define TIMESEP ':'
|
||||
/* #define TIMESEP '.' */
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* DATETIMESEP: The default datetime separator. Default is '@'; */
|
||||
/* others may prefer 'T'. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DATETIMESEP '@'
|
||||
/* #define DATETIMESEP '/' */
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* ISOLATIN1: define it to 1 if you use the */
|
||||
/* ISO 8859-1 character set instead of ASCII. */
|
||||
@@ -148,6 +154,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -161,7 +173,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define INCLUDE_NEST 8
|
||||
#define INCLUDE_NEST 9
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* IF_NEST: How many nested IFs do we handle? Maximum is the number */
|
||||
@@ -172,17 +184,17 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many attempts to resolve a weird date spec? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define TRIG_ATTEMPTS 50
|
||||
#define TRIG_ATTEMPTS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -215,3 +227,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -37,7 +36,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DEFAULT_PAGE {"Letter", 612, 792}
|
||||
/* #define DEFAULT_PAGE {"A4", 595, 842} */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* DATESEP: The default date separator. Standard usage is '-'; */
|
||||
/* others may prefer '/'. */
|
||||
@@ -52,6 +51,13 @@
|
||||
#define TIMESEP ':'
|
||||
/* #define TIMESEP '.' */
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* DATETIMESEP: The default datetime separator. Default is '@'; */
|
||||
/* others may prefer 'T'. */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define DATETIMESEP '@'
|
||||
/* #define DATETIMESEP '/' */
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* ISOLATIN1: define it to 1 if you use the */
|
||||
/* ISO 8859-1 character set instead of ASCII. */
|
||||
@@ -148,6 +154,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PRT_LEN 40
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* MAX_STR_LEN: If non-zero, Remind will limit the maximum length */
|
||||
/* of string values to avoid eating up all of memory... */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_STR_LEN 65535
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
|
||||
/*---------------------------------------------------------------------*/
|
||||
@@ -161,7 +173,7 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define INCLUDE_NEST 8
|
||||
#define INCLUDE_NEST 9
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* IF_NEST: How many nested IFs do we handle? Maximum is the number */
|
||||
@@ -172,17 +184,17 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many attempts to resolve a weird date spec? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define TRIG_ATTEMPTS 50
|
||||
#define TRIG_ATTEMPTS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -215,3 +227,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
491
src/dorem.c
491
src/dorem.c
@@ -7,8 +7,7 @@
|
||||
/* commands. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -19,9 +18,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
@@ -29,12 +28,23 @@
|
||||
static char const DontEscapeMe[] =
|
||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
||||
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim);
|
||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
||||
static int ParseLocalOmit (ParsePtr s, Trigger *t);
|
||||
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||
static int ParseUntil (ParsePtr s, Trigger *t);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
|
||||
static int ComputeTrigDuration(TimeTrig *t);
|
||||
|
||||
static int
|
||||
ComputeTrigDuration(TimeTrig *t)
|
||||
{
|
||||
if (t->ttime == NO_TIME ||
|
||||
t->duration == NO_TIME) {
|
||||
return 0;
|
||||
}
|
||||
return (t->ttime + t->duration - 1) / 1440;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -48,7 +58,7 @@ int DoRem(ParsePtr p)
|
||||
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
int r;
|
||||
int r, err;
|
||||
int jul;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
@@ -56,28 +66,54 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (trig.typ == NO_TYPE) {
|
||||
PurgeEchoLine("%s\n%s\n", "#!P! Cannot parse next line", CurLine);
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
PurgeEchoLine("%s\n", "#!P: Cannot purge SATISFY-type reminders");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
return r;
|
||||
}
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (tok.val == PASSTHRU_TYPE) {
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (!DBufLen(&buf)) {
|
||||
FreeTrig(&trig);
|
||||
DBufFree(&buf);
|
||||
return E_EOLN;
|
||||
}
|
||||
@@ -86,13 +122,42 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
trig.typ = tok.val;
|
||||
jul = LastTriggerDate;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid || PurgeMode) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
if (r) return r;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (PurgeMode) {
|
||||
if (trig.expired || jul < JulianToday) {
|
||||
if (p->expr_happened) {
|
||||
if (p->nonconst_expr) {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line has expired, but contains expression... please verify");
|
||||
PurgeEchoLine("#!P: Expired: %s\n", CurLine);
|
||||
}
|
||||
} else {
|
||||
PurgeEchoLine("#!P: Expired: %s\n", CurLine);
|
||||
}
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
/* Queue the reminder, if necessary */
|
||||
if (jul == JulianToday &&
|
||||
!(!IgnoreOnce &&
|
||||
@@ -100,17 +165,21 @@ int DoRem(ParsePtr p)
|
||||
FileAccessDate == JulianToday))
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) return OK;
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
if (Daemon) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -120,11 +189,12 @@ int DoRem(ParsePtr p)
|
||||
/* trigger structure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
int y, m, d;
|
||||
|
||||
DBufInit(&buf);
|
||||
|
||||
@@ -141,16 +211,23 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->once = NO_ONCE;
|
||||
trig->typ = NO_TYPE;
|
||||
trig->scanfrom = NO_DATE;
|
||||
trig->from = NO_DATE;
|
||||
trig->priority = DefaultPrio;
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->tag[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->duration_days = 0;
|
||||
trig->eventstart = NO_TIME;
|
||||
trig->eventduration = NO_TIME;
|
||||
DBufInit(&(trig->tags));
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
tim->delta = NO_DELTA;
|
||||
tim->rep = NO_REP;
|
||||
tim->duration = NO_TIME;
|
||||
LastTriggerTime = NO_TIME;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = NO_TIME;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
/* Read space-delimited string */
|
||||
@@ -160,6 +237,33 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* Figure out what we've got */
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch(tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
trig->d = d;
|
||||
break;
|
||||
|
||||
case T_DateTime:
|
||||
DBufFree(&buf);
|
||||
if (trig->d != NO_DAY) return E_DAY_TWICE;
|
||||
if (trig->m != NO_MON) return E_MON_TWICE;
|
||||
if (trig->y != NO_YR) return E_YR_TWICE;
|
||||
FromJulian(tok.val / MINUTES_PER_DAY, &y, &m, &d);
|
||||
trig->y = y;
|
||||
trig->m = m;
|
||||
trig->d = d;
|
||||
tim->ttime = (tok.val % MINUTES_PER_DAY);
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_WkDay:
|
||||
DBufFree(&buf);
|
||||
if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
|
||||
@@ -186,8 +290,9 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_At:
|
||||
DBufFree(&buf);
|
||||
r=ParseTimeTrig(s, tim);
|
||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||
if (r) return r;
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
|
||||
case T_Scanfrom:
|
||||
@@ -212,6 +317,14 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
}
|
||||
return OK;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (trig->rep != NO_REP) return E_REP_TWICE;
|
||||
trig->rep = 1;
|
||||
r = ParseUntil(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_Until:
|
||||
DBufFree(&buf);
|
||||
r=ParseUntil(s, trig);
|
||||
@@ -256,6 +369,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
case T_Omit:
|
||||
DBufFree(&buf);
|
||||
if (trig->omitfunc[0]) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
|
||||
r = ParseLocalOmit(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
@@ -265,6 +382,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
|
||||
return OK;
|
||||
|
||||
case T_OmitFunc:
|
||||
if (trig->localomit) {
|
||||
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
|
||||
}
|
||||
r=ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Warn:
|
||||
r=ParseToken(s, &buf);
|
||||
if(r) return r;
|
||||
@@ -275,7 +402,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
case T_Tag:
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->tag, DBufValue(&buf), TAG_LEN);
|
||||
AppendTag(&(trig->tags), DBufValue(&buf));
|
||||
break;
|
||||
|
||||
case T_Duration:
|
||||
@@ -286,7 +413,15 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
switch(tok.type) {
|
||||
case T_Time:
|
||||
case T_LongTime:
|
||||
tim->duration = tok.val;
|
||||
if (tok.val != 0) {
|
||||
tim->duration = tok.val;
|
||||
} else {
|
||||
tim->duration = NO_TIME;
|
||||
}
|
||||
if (save_in_globals) {
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
default:
|
||||
return E_BAD_TIME;
|
||||
@@ -321,7 +456,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
/* ParseTimeTrig - parse the AT part of a timed reminder */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
Token tok;
|
||||
int r;
|
||||
@@ -336,16 +471,19 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
switch(tok.type) {
|
||||
case T_Time:
|
||||
DBufFree(&buf);
|
||||
if (tim->ttime != NO_TIME) return E_TIME_TWICE;
|
||||
tim->ttime = tok.val;
|
||||
break;
|
||||
|
||||
case T_Delta:
|
||||
DBufFree(&buf);
|
||||
if (tim->delta != NO_DELTA) return E_DELTA_TWICE;
|
||||
tim->delta = (tok.val > 0) ? tok.val : -tok.val;
|
||||
break;
|
||||
|
||||
case T_Rep:
|
||||
DBufFree(&buf);
|
||||
if (tim->rep != NO_REP) return E_REP_TWICE;
|
||||
tim->rep = tok.val;
|
||||
break;
|
||||
|
||||
@@ -353,7 +491,10 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
|
||||
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
|
||||
|
||||
/* Save trigger time in global variable */
|
||||
LastTriggerTime = tim->ttime;
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -442,6 +583,23 @@ static int ParseUntil(ParsePtr s, Trigger *t)
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]);
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]);
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]);
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]);
|
||||
@@ -517,6 +675,47 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_YR_TWICE]);
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_MON_TWICE]);
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
case T_Back:
|
||||
DBufFree(&buf);
|
||||
if (type != SCANFROM_TYPE) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
|
||||
return E_INCOMPLETE;
|
||||
}
|
||||
if (y != NO_YR) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_YR_TWICE]);
|
||||
return E_YR_TWICE;
|
||||
}
|
||||
if (m != NO_MON) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_MON_TWICE]);
|
||||
return E_MON_TWICE;
|
||||
}
|
||||
if (d != NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_DAY_TWICE]);
|
||||
return E_DAY_TWICE;
|
||||
}
|
||||
if (tok.val < 0) {
|
||||
tok.val = -tok.val;
|
||||
}
|
||||
FromJulian(JulianToday - tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
|
||||
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
|
||||
@@ -529,9 +728,12 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
}
|
||||
t->scanfrom = Julian(y, m, d);
|
||||
if (type == FROM_TYPE) {
|
||||
t->from = t->scanfrom;
|
||||
if (t->scanfrom < JulianToday) {
|
||||
t->scanfrom = JulianToday;
|
||||
}
|
||||
} else {
|
||||
t->from = NO_DATE;
|
||||
}
|
||||
|
||||
PushToken(DBufValue(&buf), s);
|
||||
@@ -550,39 +752,45 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
{
|
||||
int r, y, m, d;
|
||||
char PrioExpr[25];
|
||||
char PrioExpr[VAR_NAME_LEN+25];
|
||||
char tmpBuf[64];
|
||||
DynamicBuffer buf, calRow;
|
||||
DynamicBuffer pre_buf;
|
||||
char *s;
|
||||
char const *s;
|
||||
Value v;
|
||||
|
||||
DBufInit(&buf);
|
||||
DBufInit(&calRow);
|
||||
DBufInit(&pre_buf);
|
||||
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
|
||||
if ((t->typ == PASSTHRU_TYPE && strcmp(t->passthru, "COLOR")) ||
|
||||
if ((t->typ == PASSTHRU_TYPE && strcmp(t->passthru, "COLOR") && strcmp(t->passthru, "COLOUR")) ||
|
||||
t->typ == CAL_TYPE ||
|
||||
t->typ == PS_TYPE ||
|
||||
t->typ == PSF_TYPE)
|
||||
return OK;
|
||||
|
||||
/* Handle COLOR types */
|
||||
if (t->typ == PASSTHRU_TYPE && !strcmp(t->passthru, "COLOR")) {
|
||||
if (t->typ == PASSTHRU_TYPE && (!strcmp(t->passthru, "COLOR") || !strcmp(t->passthru, "COLOUR"))) {
|
||||
/* Strip off three tokens */
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
}
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
t->typ = MSG_TYPE;
|
||||
@@ -598,10 +806,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
}
|
||||
|
||||
/* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
|
||||
format. */
|
||||
/* If it's NextMode, process as a ADVANCE_MODE-type entry, and issue
|
||||
simple-calendar format. */
|
||||
if (NextMode) {
|
||||
if ( (r=DoSubst(p, &buf, t, tim, jul, CAL_MODE)) ) return r;
|
||||
if ( (r=DoSubst(p, &buf, t, tim, jul, ADVANCE_MODE)) ) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&pre_buf);
|
||||
@@ -622,16 +830,12 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (t->tag[0]) {
|
||||
sprintf(tmpBuf, "%s ", t->tag);
|
||||
} else {
|
||||
sprintf(tmpBuf, "* ");
|
||||
}
|
||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||
DBufFree(&calRow);
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (*DBufValue(&(t->tags))) {
|
||||
DBufPuts(&calRow, DBufValue(&(t->tags)));
|
||||
DBufPutc(&calRow, ' ');
|
||||
} else {
|
||||
DBufPuts(&calRow, "* ");
|
||||
}
|
||||
if (tim->duration != NO_TIME) {
|
||||
sprintf(tmpBuf, "%d ", tim->duration);
|
||||
} else {
|
||||
@@ -666,38 +870,46 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Put the substituted string into the substitution buffer */
|
||||
if (UserFuncExists("msgprefix") == 1) {
|
||||
sprintf(PrioExpr, "msgprefix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
return E_NO_MEM;
|
||||
/* Put the substituted string into the substitution buffer */
|
||||
|
||||
/* Don't use msgprefix() on RUN-type reminders */
|
||||
if (t->typ != RUN_TYPE) {
|
||||
if (UserFuncExists("msgprefix") == 1) {
|
||||
sprintf(PrioExpr, "msgprefix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
DestroyValue(v);
|
||||
}
|
||||
DestroyValue(v);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
|
||||
if (UserFuncExists("msgsuffix") == 1) {
|
||||
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
return E_NO_MEM;
|
||||
if (t->typ != RUN_TYPE) {
|
||||
if (UserFuncExists("msgsuffix") == 1) {
|
||||
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
|
||||
s = PrioExpr;
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
DestroyValue(v);
|
||||
}
|
||||
DestroyValue(v);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
|
||||
if (DBufPutc(&buf, '\n') != OK) {
|
||||
DBufFree(&buf);
|
||||
@@ -743,7 +955,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
NumTriggered++;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -751,12 +963,13 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
/* */
|
||||
/* Return 1 if we should trigger a reminder, based on today's */
|
||||
/* date and the trigger. Return 0 if reminder should not be */
|
||||
/* triggered. */
|
||||
/* triggered. Sets *err non-zero in event of an error. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
{
|
||||
int r;
|
||||
int r, omit;
|
||||
*err = 0;
|
||||
|
||||
/* Handle the ONCE modifier in the reminder. */
|
||||
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
|
||||
@@ -766,7 +979,17 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
|
||||
/* Don't trigger timed reminders if DontIssueAts is true, and if the
|
||||
reminder is for today */
|
||||
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
|
||||
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) {
|
||||
if (DontIssueAts > 1) {
|
||||
/* If two or more -a options, then *DO* issue ats that are in the
|
||||
future */
|
||||
if (tim->ttime < SystemTime(0) / 60) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't trigger "old" timed reminders */
|
||||
/*** REMOVED...
|
||||
@@ -780,7 +1003,12 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
|
||||
/* If there's a "warn" function, it overrides any deltas */
|
||||
if (t->warn[0] != 0) {
|
||||
return ShouldTriggerBasedOnWarn(t, jul);
|
||||
if (DeltaOffset) {
|
||||
if (jul <= JulianToday + DeltaOffset) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return ShouldTriggerBasedOnWarn(t, jul, err);
|
||||
}
|
||||
|
||||
/* Move back by delta days, if any */
|
||||
@@ -788,16 +1016,29 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
if (t->delta < 0)
|
||||
jul = jul + t->delta;
|
||||
else {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
r = t->delta;
|
||||
while(r && jul > JulianToday) {
|
||||
if (max < r*2) max = r*2;
|
||||
while(iter++ < max) {
|
||||
if (!r || (jul <= JulianToday)) {
|
||||
break;
|
||||
}
|
||||
jul--;
|
||||
if (!IsOmitted(jul, t->localomit)) r--;
|
||||
*err = IsOmitted(jul, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) r--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Should we trigger the reminder? */
|
||||
return (jul <= JulianToday);
|
||||
return (jul <= JulianToday + DeltaOffset);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -807,33 +1048,65 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
|
||||
/* Do the "satisfying..." remind calculation. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
|
||||
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
{
|
||||
int iter, jul, r;
|
||||
int iter, jul, r, start;
|
||||
Value v;
|
||||
char *s, *t;
|
||||
char const *s;
|
||||
char const *t;
|
||||
|
||||
t = p->pos;
|
||||
iter = 0;
|
||||
jul = trig->scanfrom;
|
||||
start = trig->scanfrom;
|
||||
while (iter++ < MaxSatIter) {
|
||||
jul = ComputeTrigger(jul, trig, &r);
|
||||
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1);
|
||||
if (r) {
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
if (jul == -1) {
|
||||
return E_EXPIRED;
|
||||
}
|
||||
s = p->pos;
|
||||
r = EvaluateExpr(p, &v);
|
||||
t = p->pos;
|
||||
if (r) return r;
|
||||
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (v.type == INT_TYPE && v.v.val) return OK;
|
||||
if (v.type == STR_TYPE && *v.v.str) return OK;
|
||||
if ((v.type == INT_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && *v.v.str)) {
|
||||
AdjustTriggerForDuration(trig->scanfrom, jul, trig, tt, 1);
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
int y, m, d;
|
||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[LastTriggerDate % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tt->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tt->ttime / 60),
|
||||
(tt->ttime % 60));
|
||||
if (tt->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tt->duration / 60),
|
||||
(tt->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
p->pos = s;
|
||||
jul++;
|
||||
if (jul+trig->duration_days < start) {
|
||||
start++;
|
||||
} else {
|
||||
start = jul+trig->duration_days+1;
|
||||
}
|
||||
}
|
||||
p->pos = t;
|
||||
LastTrigValid = 0;
|
||||
return OK;
|
||||
return E_CANT_TRIG;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -844,7 +1117,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
|
||||
static int ParsePriority(ParsePtr s, Trigger *t)
|
||||
{
|
||||
int p, r;
|
||||
char *u;
|
||||
char const *u;
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
@@ -882,14 +1155,14 @@ static int ParsePriority(ParsePtr s, Trigger *t)
|
||||
/* Execute the '-k' command, escaping shell chars in message. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoMsgCommand(char *cmd, char *msg)
|
||||
int DoMsgCommand(char const *cmd, char const *msg)
|
||||
{
|
||||
int r;
|
||||
int i, l;
|
||||
DynamicBuffer execBuffer;
|
||||
|
||||
DynamicBuffer buf;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
DBufInit(&buf);
|
||||
DBufInit(&execBuffer);
|
||||
@@ -943,12 +1216,12 @@ finished:
|
||||
/* function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
|
||||
{
|
||||
char buffer[VAR_NAME_LEN+32];
|
||||
int i;
|
||||
char *s;
|
||||
int r;
|
||||
char const *s;
|
||||
int r, omit;
|
||||
Value v;
|
||||
int lastReturnVal = 0; /* Silence compiler warning */
|
||||
|
||||
@@ -960,7 +1233,7 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
for (i=1; ; i++) {
|
||||
sprintf(buffer, "%s(%d)", t->warn, i);
|
||||
s = buffer;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) {
|
||||
Eprint("%s: `%s': %s", ErrMsg[M_BAD_WARN_FUNC],
|
||||
t->warn, ErrMsg[r]);
|
||||
@@ -986,9 +1259,21 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
|
||||
if (JulianToday + v.v.val == jul) return 1;
|
||||
} else {
|
||||
int j = jul;
|
||||
while (v.v.val) {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < v.v.val * 2) max = v.v.val*2;
|
||||
while(iter++ <= max) {
|
||||
j--;
|
||||
if (!IsOmitted(j, t->localomit)) v.v.val++;
|
||||
*err = IsOmitted(j, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (!omit) v.v.val++;
|
||||
if (!v.v.val) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter > max) {
|
||||
Eprint("Delta: Bad OMITFUNC? %s", ErrMsg[E_CANT_TRIG]);
|
||||
return 0;
|
||||
}
|
||||
if (j == JulianToday) return 1;
|
||||
}
|
||||
|
||||
136
src/dosubst.c
136
src/dosubst.c
@@ -6,8 +6,7 @@
|
||||
/* reminders are triggered. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -19,9 +18,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
|
||||
#define UPPER(c) (islower(c) ? toupper(c) : (c))
|
||||
@@ -54,13 +53,15 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
int d, m, y;
|
||||
int tim = tt->ttime;
|
||||
int h, min, hh, ch, cmin, chh;
|
||||
char *pm, *cpm;
|
||||
char const *pm, *cpm;
|
||||
int tdiff, adiff, mdiff, hdiff;
|
||||
char *mplu, *hplu, *when, *plu;
|
||||
char const *mplu, *hplu, *when, *plu;
|
||||
int has_quote = 0;
|
||||
char *ss, *os;
|
||||
char *ss;
|
||||
char *os;
|
||||
char s[256];
|
||||
int origLen = DBufLen(dbuf);
|
||||
int altmode;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
|
||||
@@ -140,6 +141,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
|
||||
continue;
|
||||
}
|
||||
altmode = 0;
|
||||
s[0] = 0;
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) {
|
||||
@@ -149,6 +151,17 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
if (c == '*') {
|
||||
altmode = c;
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) {
|
||||
DBufFree(dbuf);
|
||||
return err;
|
||||
}
|
||||
if (!c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
done = 0;
|
||||
if (diff <= 1) {
|
||||
switch(UPPER(c)) {
|
||||
@@ -205,8 +218,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_A_OVER
|
||||
L_A_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %d %s, %d", L_ON, DayName[jul%7], d,
|
||||
MonthName[m], y);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -224,7 +242,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_C_OVER
|
||||
L_C_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s", L_ON, DayName[jul%7]);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%s", DayName[jul%7]);
|
||||
} else {
|
||||
sprintf(s, "%s %s", L_ON, DayName[jul%7]);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -242,8 +264,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_E_OVER
|
||||
L_E_OVER
|
||||
#else
|
||||
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, d, DateSep,
|
||||
m+1, DateSep, y);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%02d%c%02d%c%04d", d, DateSep,
|
||||
m+1, DateSep, y);
|
||||
} else {
|
||||
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, d, DateSep,
|
||||
m+1, DateSep, y);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -252,7 +279,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_F_OVER
|
||||
L_F_OVER
|
||||
#else
|
||||
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, m+1, DateSep, d, DateSep, y);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||
} else {
|
||||
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, m+1, DateSep, d, DateSep, y);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -261,7 +292,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_G_OVER
|
||||
L_G_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %d %s", L_ON, DayName[jul%7], d, MonthName[m]);
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -270,7 +305,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_H_OVER
|
||||
L_H_OVER
|
||||
#else
|
||||
sprintf(s, "%s %02d%c%02d", L_ON, d, DateSep, m+1);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
||||
} else {
|
||||
sprintf(s, "%s %02d%c%02d", L_ON, d, DateSep, m+1);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -279,7 +318,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_I_OVER
|
||||
L_I_OVER
|
||||
#else
|
||||
sprintf(s, "%s %02d%c%02d", L_ON, m+1, DateSep, d);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
||||
} else {
|
||||
sprintf(s, "%s %02d%c%02d", L_ON, m+1, DateSep, d);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -288,8 +331,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_J_OVER
|
||||
L_J_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %s %d%s, %d", L_ON, DayName[jul%7],
|
||||
MonthName[m], d, plu, y);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%s, %s %d%s, %d", DayName[jul%7],
|
||||
MonthName[m], d, plu, y);
|
||||
} else {
|
||||
sprintf(s, "%s %s, %s %d%s, %d", L_ON, DayName[jul%7],
|
||||
MonthName[m], d, plu, y);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -298,8 +346,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_K_OVER
|
||||
L_K_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %s %d%s", L_ON, DayName[jul%7],
|
||||
MonthName[m], d, plu);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%s, %s %d%s", DayName[jul%7],
|
||||
MonthName[m], d, plu);
|
||||
} else {
|
||||
sprintf(s, "%s %s, %s %d%s", L_ON, DayName[jul%7],
|
||||
MonthName[m], d, plu);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -308,7 +361,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_L_OVER
|
||||
L_L_OVER
|
||||
#else
|
||||
sprintf(s, "%s %04d%c%02d%c%02d", L_ON, y, DateSep, m+1, DateSep, d);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
||||
} else {
|
||||
sprintf(s, "%s %04d%c%02d%c%02d", L_ON, y, DateSep, m+1, DateSep, d);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -390,8 +447,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_U_OVER
|
||||
L_U_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d,
|
||||
plu, MonthName[m], y);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -400,8 +462,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_V_OVER
|
||||
L_V_OVER
|
||||
#else
|
||||
sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu,
|
||||
MonthName[m]);
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -463,7 +530,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
#ifdef L_2_OVER
|
||||
L_2_OVER
|
||||
#else
|
||||
sprintf(s, "%s %d%c%02d%s", L_AT, hh, TimeSep, min, pm);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%d%c%02d%s", hh, TimeSep, min, pm);
|
||||
} else {
|
||||
sprintf(s, "%s %d%c%02d%s", L_AT, hh, TimeSep, min, pm);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -473,7 +544,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
L_3_OVER
|
||||
#else
|
||||
|
||||
sprintf(s, "%s %02d%c%02d", L_AT, h, TimeSep, min);
|
||||
if (altmode == '*') {
|
||||
sprintf(s, "%02d%c%02d", h, TimeSep, min);
|
||||
} else {
|
||||
sprintf(s, "%s %02d%c%02d", L_AT, h, TimeSep, min);
|
||||
}
|
||||
#endif
|
||||
SHIP_OUT(s);
|
||||
break;
|
||||
@@ -589,8 +664,11 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
|
||||
}
|
||||
if (isupper(c)) {
|
||||
os = DBufValue(dbuf) - strlen(s);
|
||||
*os = UPPER(*os);
|
||||
os = DBufValue(dbuf);
|
||||
os += strlen(os) - strlen(s);
|
||||
if (os >= DBufValue(dbuf)) {
|
||||
*os = UPPER(*os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +727,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
/* default triggers and a mode of NORMAL_MODE. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoSubstFromString(char *source, DynamicBuffer *dbuf,
|
||||
int DoSubstFromString(char const *source, DynamicBuffer *dbuf,
|
||||
int jul, int tim)
|
||||
{
|
||||
Trigger tempTrig;
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
/* buffers. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -42,7 +41,7 @@ static int DBufMakeRoom(DynamicBuffer *dbuf, int n)
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
buf = (char *) malloc(size);
|
||||
buf = malloc(size);
|
||||
if (!buf) return E_NO_MEM;
|
||||
|
||||
/* Copy contents */
|
||||
@@ -102,7 +101,7 @@ int DBufPutcFN(DynamicBuffer *dbuf, char c)
|
||||
%DESCRIPTION:
|
||||
Appends a string to the buffer.
|
||||
**********************************************************************/
|
||||
int DBufPuts(DynamicBuffer *dbuf, char *str)
|
||||
int DBufPuts(DynamicBuffer *dbuf, char const *str)
|
||||
{
|
||||
int l = strlen(str);
|
||||
if (!l) return OK;
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
/* Declaration of functions for manipulating dynamic buffers */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -25,7 +24,7 @@ typedef struct {
|
||||
|
||||
void DBufInit(DynamicBuffer *dbuf);
|
||||
int DBufPutcFN(DynamicBuffer *dbuf, char c);
|
||||
int DBufPuts(DynamicBuffer *dbuf, char *str);
|
||||
int DBufPuts(DynamicBuffer *dbuf, char const *str);
|
||||
void DBufFree(DynamicBuffer *dbuf);
|
||||
int DBufGets(DynamicBuffer *dbuf, FILE *fp);
|
||||
|
||||
|
||||
18
src/err.h
18
src/err.h
@@ -5,8 +5,7 @@
|
||||
/* Error definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -117,7 +116,10 @@
|
||||
#define E_EXPECTING_NUMBER 97
|
||||
#define M_BAD_WARN_FUNC 98
|
||||
#define E_CANT_CONVERT_TZ 99
|
||||
|
||||
#define E_NO_MATCHING_REMS 100
|
||||
#define E_STRING_TOO_LONG 101
|
||||
#define E_TIME_TWICE 102
|
||||
#define E_DURATION_NO_AT 103
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
@@ -189,7 +191,7 @@ EXTERN char *ErrMsg[]
|
||||
"Too many partial OMITs",
|
||||
"Too many full OMITs",
|
||||
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||
"Error reading file",
|
||||
"Error reading",
|
||||
"Expecting end-of-line",
|
||||
"Invalid Hebrew date",
|
||||
"IIF needs odd number of arguments",
|
||||
@@ -203,7 +205,7 @@ EXTERN char *ErrMsg[]
|
||||
"Back value specified twice",
|
||||
"ONCE keyword used twice. (Hah.)",
|
||||
"Expecting time after AT",
|
||||
"UNTIL keyword used twice",
|
||||
"THROUGH/UNTIL keyword used twice",
|
||||
"Incomplete date specification",
|
||||
"FROM/SCANFROM keyword used twice",
|
||||
"Variable",
|
||||
@@ -230,7 +232,11 @@ EXTERN char *ErrMsg[]
|
||||
"%d reminder(s) queued for later today.\n",
|
||||
"Expecting number",
|
||||
"Bad function in WARN clause",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
204
src/expr.c
204
src/expr.c
@@ -5,8 +5,7 @@
|
||||
/* This file contains routines to parse and evaluate */
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* Copyright 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -31,7 +30,6 @@
|
||||
#define LE 4
|
||||
#define NE 5
|
||||
|
||||
static char CoerceBuf[512];
|
||||
extern int NumFuncs;
|
||||
|
||||
static int Multiply(void), Divide(void), Mod(void), Add(void),
|
||||
@@ -41,8 +39,7 @@ static int Multiply(void), Divide(void), Mod(void), Add(void),
|
||||
UnMinus(void), LogNot(void),
|
||||
Compare(int);
|
||||
|
||||
static int MakeValue (char *s, Value *v, Var *locals);
|
||||
static int ParseLiteralDate (char **s, int *jul, int *tim);
|
||||
static int MakeValue (char const *s, Value *v, Var *locals, ParsePtr p);
|
||||
|
||||
/* Binary operators - all left-associative */
|
||||
|
||||
@@ -73,9 +70,7 @@ Operator UnOp[] = {
|
||||
};
|
||||
#define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator))
|
||||
|
||||
/* Functions have the same definitions as operators, except the prec field
|
||||
is used to indicate how many arguments are needed. */
|
||||
extern Operator Func[];
|
||||
extern BuiltinFunc Func[];
|
||||
|
||||
Operator OpStack[OP_STACK_SIZE];
|
||||
Value ValStack[VAL_STACK_SIZE];
|
||||
@@ -132,10 +127,10 @@ static void CleanStack(void)
|
||||
/* PeekChar - peek ahead to next char. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static char PeekChar(char **s)
|
||||
static char PeekChar(char const **s)
|
||||
{
|
||||
char *t = *s;
|
||||
while (*t && isspace(*t)) t++;
|
||||
char const *t = *s;
|
||||
while (*t && isempty(*t)) t++;
|
||||
return *t;
|
||||
}
|
||||
|
||||
@@ -146,14 +141,14 @@ static char PeekChar(char **s)
|
||||
/* Read a token. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseExprToken(DynamicBuffer *buf, char **in)
|
||||
static int ParseExprToken(DynamicBuffer *buf, char const **in)
|
||||
{
|
||||
|
||||
char c;
|
||||
|
||||
DBufFree(buf);
|
||||
/* Skip white space */
|
||||
while (**in && isspace(**in)) (*in)++;
|
||||
while (**in && isempty(**in)) (*in)++;
|
||||
|
||||
if (!**in) return OK;
|
||||
|
||||
@@ -204,6 +199,46 @@ static int ParseExprToken(DynamicBuffer *buf, char **in)
|
||||
if (c == '\"') {
|
||||
if (!**in) return E_MISS_QUOTE;
|
||||
while (**in) {
|
||||
/* Allow backslash-escapes */
|
||||
if (**in == '\\') {
|
||||
int r;
|
||||
(*in)++;
|
||||
if (!**in) {
|
||||
DBufFree(buf);
|
||||
return E_MISS_QUOTE;
|
||||
}
|
||||
switch(**in) {
|
||||
case 'a':
|
||||
r = DBufPutc(buf, '\a');
|
||||
break;
|
||||
case 'b':
|
||||
r = DBufPutc(buf, '\b');
|
||||
break;
|
||||
case 'f':
|
||||
r = DBufPutc(buf, '\f');
|
||||
break;
|
||||
case 'n':
|
||||
r = DBufPutc(buf, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
r = DBufPutc(buf, '\r');
|
||||
break;
|
||||
case 't':
|
||||
r = DBufPutc(buf, '\t');
|
||||
break;
|
||||
case 'v':
|
||||
r = DBufPutc(buf, '\v');
|
||||
break;
|
||||
default:
|
||||
r = DBufPutc(buf, **in);
|
||||
}
|
||||
(*in)++;
|
||||
if (r != OK) {
|
||||
DBufFree(buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = *(*in)++;
|
||||
if (DBufPutc(buf, c) != OK) {
|
||||
DBufFree(buf);
|
||||
@@ -246,7 +281,7 @@ static int ParseExprToken(DynamicBuffer *buf, char **in)
|
||||
(*in)++;
|
||||
}
|
||||
/* Chew up any remaining white space */
|
||||
while (**in && isspace(**in)) (*in)++;
|
||||
while (**in && isempty(**in)) (*in)++;
|
||||
|
||||
/* Peek ahead - is it '('? Then we have a function call */
|
||||
if (**in == '(') {
|
||||
@@ -266,14 +301,14 @@ static int ParseExprToken(DynamicBuffer *buf, char **in)
|
||||
/* Put the result into value pointed to by v. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int EvalExpr(char **e, Value *v)
|
||||
int EvalExpr(char const **e, Value *v, ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
|
||||
OpStackPtr = 0;
|
||||
ValStackPtr = 0;
|
||||
|
||||
r = Evaluate(e, NULL);
|
||||
r = Evaluate(e, NULL, p);
|
||||
|
||||
/* Put last character parsed back onto input stream */
|
||||
if (DBufLen(&ExprBuf)) (*e)--;
|
||||
@@ -289,15 +324,16 @@ int EvalExpr(char **e, Value *v)
|
||||
}
|
||||
|
||||
/* Evaluate - do the actual work of evaluation. */
|
||||
int Evaluate(char **s, Var *locals)
|
||||
int Evaluate(char const **s, Var *locals, ParsePtr p)
|
||||
{
|
||||
int OpBase, ValBase;
|
||||
int r;
|
||||
Operator *f;
|
||||
Operator *o;
|
||||
BuiltinFunc *f;
|
||||
int args; /* Number of function arguments */
|
||||
Operator op, op2;
|
||||
Value va;
|
||||
char *ufname = NULL; /* Stop GCC from complaining about use of uninit var */
|
||||
char const *ufname = NULL; /* Stop GCC from complaining about use of uninit var */
|
||||
|
||||
OpBase = OpStackPtr;
|
||||
ValBase = ValStackPtr;
|
||||
@@ -313,7 +349,7 @@ int Evaluate(char **s, Var *locals)
|
||||
|
||||
if (*DBufValue(&ExprBuf) == '(') { /* Parenthesized expression */
|
||||
DBufFree(&ExprBuf);
|
||||
r = Evaluate(s, locals); /* Leaves the last parsed token in ExprBuf */
|
||||
r = Evaluate(s, locals, p); /* Leaves the last parsed token in ExprBuf */
|
||||
if (r) return r;
|
||||
r = OK;
|
||||
if (*DBufValue(&ExprBuf) != ')') {
|
||||
@@ -336,10 +372,12 @@ int Evaluate(char **s, Var *locals)
|
||||
}
|
||||
args = 0;
|
||||
if (PeekChar(s) == ')') { /* Function has no arguments */
|
||||
if (f) r = CallFunc(f, 0);
|
||||
else {
|
||||
r = CallUserFunc(ufname, 0);
|
||||
free(ufname);
|
||||
if (f) {
|
||||
if (!f->is_constant && (p != NULL)) p->nonconst_expr = 1;
|
||||
r = CallFunc(f, 0);
|
||||
} else {
|
||||
r = CallUserFunc(ufname, 0, p);
|
||||
free((char *) ufname);
|
||||
}
|
||||
if (r) return r;
|
||||
r = ParseExprToken(&ExprBuf, s); /* Guaranteed to be right paren. */
|
||||
@@ -347,33 +385,35 @@ int Evaluate(char **s, Var *locals)
|
||||
} else { /* Function has some arguments */
|
||||
while(1) {
|
||||
args++;
|
||||
r = Evaluate(s, locals);
|
||||
r = Evaluate(s, locals, p);
|
||||
if (r) {
|
||||
if (!f) free(ufname);
|
||||
if (!f) free((char *) ufname);
|
||||
return r;
|
||||
}
|
||||
if (*DBufValue(&ExprBuf) == ')') break;
|
||||
else if (*DBufValue(&ExprBuf) != ',') {
|
||||
if (!f) free(ufname);
|
||||
if (!f) free((char *) ufname);
|
||||
Eprint("%s: `%c'", ErrMsg[E_EXPECT_COMMA],
|
||||
*DBufValue(&ExprBuf));
|
||||
DBufFree(&ExprBuf);
|
||||
return E_EXPECT_COMMA;
|
||||
}
|
||||
}
|
||||
if (f) r = CallFunc(f, args);
|
||||
else {
|
||||
r = CallUserFunc(ufname, args);
|
||||
free(ufname);
|
||||
if (f) {
|
||||
if (!f->is_constant && (p != NULL)) p->nonconst_expr = 1;
|
||||
r = CallFunc(f, args);
|
||||
} else {
|
||||
r = CallUserFunc(ufname, args, p);
|
||||
free((char *) ufname);
|
||||
}
|
||||
DBufFree(&ExprBuf);
|
||||
if (r) return r;
|
||||
}
|
||||
} else { /* Unary operator */
|
||||
f = FindFunc(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS);
|
||||
if (f) {
|
||||
o = FindOperator(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS);
|
||||
if (o) {
|
||||
DBufFree(&ExprBuf);
|
||||
PushOpStack(*f);
|
||||
PushOpStack(*o);
|
||||
continue; /* Still looking for an atomic vlue */
|
||||
} else if (!ISID(*DBufValue(&ExprBuf)) &&
|
||||
*DBufValue(&ExprBuf) != '$' &&
|
||||
@@ -384,7 +424,7 @@ int Evaluate(char **s, Var *locals)
|
||||
DBufFree(&ExprBuf);
|
||||
return E_ILLEGAL_CHAR;
|
||||
} else { /* Must be a literal value */
|
||||
r = MakeValue(DBufValue(&ExprBuf), &va, locals);
|
||||
r = MakeValue(DBufValue(&ExprBuf), &va, locals, p);
|
||||
DBufFree(&ExprBuf);
|
||||
if (r) return r;
|
||||
PushValStack(va);
|
||||
@@ -419,13 +459,13 @@ int Evaluate(char **s, Var *locals)
|
||||
return OK;
|
||||
}
|
||||
/* Must be a binary operator */
|
||||
f = FindFunc(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS);
|
||||
o = FindOperator(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS);
|
||||
DBufFree(&ExprBuf);
|
||||
if (!f) return E_EXPECTING_BINOP;
|
||||
if (!o) return E_EXPECTING_BINOP;
|
||||
|
||||
/* While operators of higher or equal precedence are on the stack,
|
||||
pop them off and evaluate */
|
||||
while (OpStackPtr > OpBase && OpStack[OpStackPtr-1].prec >= f->prec) {
|
||||
while (OpStackPtr > OpBase && OpStack[OpStackPtr-1].prec >= o->prec) {
|
||||
PopOpStack(op2);
|
||||
if (r) return r;
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
@@ -437,7 +477,7 @@ int Evaluate(char **s, Var *locals)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
PushOpStack(*f);
|
||||
PushOpStack(*o);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +488,7 @@ int Evaluate(char **s, Var *locals)
|
||||
/* a date or the value of a symbol. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int MakeValue(char *s, Value *v, Var *locals)
|
||||
static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
||||
{
|
||||
int len;
|
||||
int h, m, r;
|
||||
@@ -456,7 +496,7 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
||||
if (*s == '\"') { /* It's a literal string "*/
|
||||
len = strlen(s)-1;
|
||||
v->type = STR_TYPE;
|
||||
v->v.str = (char *) malloc(len);
|
||||
v->v.str = malloc(len);
|
||||
if (! v->v.str) {
|
||||
v->type = ERR_TYPE;
|
||||
return E_NO_MEM;
|
||||
@@ -503,6 +543,7 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
||||
v->v.val = len;
|
||||
return OK;
|
||||
} else if (*s == '$') { /* A system variable */
|
||||
if (p) p->nonconst_expr = 1;
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
fprintf(ErrFp, "%s => ", s);
|
||||
r = GetSysVar(s+1, v);
|
||||
@@ -513,10 +554,11 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
||||
Putc('\n', ErrFp);
|
||||
}
|
||||
return r;
|
||||
} else /* Must be a symbol */
|
||||
} else { /* Must be a symbol */
|
||||
if (DebugFlag & DB_PRTEXPR)
|
||||
fprintf(ErrFp, "%s => ", s);
|
||||
r = GetVarValue(s, v, locals);
|
||||
}
|
||||
r = GetVarValue(s, v, locals, p);
|
||||
if (! (DebugFlag & DB_PRTEXPR)) return r;
|
||||
if (r == OK) {
|
||||
PrintValue(v, ErrFp);
|
||||
@@ -533,7 +575,9 @@ static int MakeValue(char *s, Value *v, Var *locals)
|
||||
int DoCoerce(char type, Value *v)
|
||||
{
|
||||
int h, d, m, y, i, k;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
char coerce_buf[128];
|
||||
|
||||
/* Do nothing if value is already the right type */
|
||||
if (type == v->type) return OK;
|
||||
@@ -562,12 +606,12 @@ int DoCoerce(char type, Value *v)
|
||||
}
|
||||
case STR_TYPE:
|
||||
switch(v->type) {
|
||||
case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
|
||||
case TIME_TYPE: sprintf(CoerceBuf, "%02d%c%02d", v->v.val / 60,
|
||||
case INT_TYPE: sprintf(coerce_buf, "%d", v->v.val); break;
|
||||
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
|
||||
TimeSep, v->v.val % 60);
|
||||
break;
|
||||
case DATE_TYPE: FromJulian(v->v.val, &y, &m, &d);
|
||||
sprintf(CoerceBuf, "%04d%c%02d%c%02d",
|
||||
sprintf(coerce_buf, "%04d%c%02d%c%02d",
|
||||
y, DateSep, m+1, DateSep, d);
|
||||
break;
|
||||
case DATETIME_TYPE:
|
||||
@@ -576,13 +620,13 @@ int DoCoerce(char type, Value *v)
|
||||
k = v->v.val % MINUTES_PER_DAY;
|
||||
h = k / 60;
|
||||
i = k % 60;
|
||||
sprintf(CoerceBuf, "%04d%c%02d%c%02d@%02d%c%02d",
|
||||
y, DateSep, m+1, DateSep, d, h, TimeSep, i);
|
||||
sprintf(coerce_buf, "%04d%c%02d%c%02d%c%02d%c%02d",
|
||||
y, DateSep, m+1, DateSep, d, DateTimeSep, h, TimeSep, i);
|
||||
break;
|
||||
default: return E_CANT_COERCE;
|
||||
}
|
||||
v->type = STR_TYPE;
|
||||
v->v.str = StrDup(CoerceBuf);
|
||||
v->v.str = StrDup(coerce_buf);
|
||||
if (!v->v.str) {
|
||||
v->type = ERR_TYPE;
|
||||
return E_NO_MEM;
|
||||
@@ -697,6 +741,8 @@ static int Add(void)
|
||||
Value v1, v2, v3;
|
||||
int r;
|
||||
|
||||
size_t l1, l2;
|
||||
|
||||
PopValStack(v2);
|
||||
if ( (r = FnPopValStack(&v1)) ) {
|
||||
DestroyValue(v2);
|
||||
@@ -720,9 +766,9 @@ static int Add(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a datetime plus an int, add 'em */
|
||||
if ((v1.type == DATETIME_TYPE && v2.type == INT_TYPE) ||
|
||||
(v1.type == INT_TYPE && v2.type == DATETIME_TYPE)) {
|
||||
/* If it's a datetime plus an int or a time, add 'em */
|
||||
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
||||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
||||
v1.v.val += v2.v.val;
|
||||
if (v1.v.val < 0) return E_DATE_OVER;
|
||||
v1.type = DATETIME_TYPE;
|
||||
@@ -730,9 +776,11 @@ static int Add(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a time plus an int, add 'em mod MINUTES_PER_DAY */
|
||||
/* If it's a time plus an int or a time plus a time,
|
||||
add 'em mod MINUTES_PER_DAY */
|
||||
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE)) {
|
||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
||||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
||||
v1.v.val = (v1.v.val + v2.v.val) % MINUTES_PER_DAY;
|
||||
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
||||
v1.type = TIME_TYPE;
|
||||
@@ -751,13 +799,19 @@ static int Add(void)
|
||||
return r;
|
||||
}
|
||||
v3.type = STR_TYPE;
|
||||
v3.v.str = (char *) malloc(strlen(v1.v.str) + strlen(v2.v.str) + 1);
|
||||
l1 = strlen(v1.v.str);
|
||||
l2 = strlen(v2.v.str);
|
||||
if (MaxStringLen && (l1 + l2 > (size_t) MaxStringLen)) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_STRING_TOO_LONG;
|
||||
}
|
||||
v3.v.str = malloc(l1 + l2 + 1);
|
||||
if (!v3.v.str) {
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
strcpy(v3.v.str, v1.v.str);
|
||||
strcat(v3.v.str, v2.v.str);
|
||||
strcpy(v3.v.str+l1, v2.v.str);
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
PushValStack(v3);
|
||||
return OK;
|
||||
@@ -800,8 +854,9 @@ static int Subtract(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a datetime minus an int, do subtraction, checking for underflow */
|
||||
if (v1.type == DATETIME_TYPE && v2.type == INT_TYPE) {
|
||||
/* If it's a datetime minus an int or a time, do subtraction,
|
||||
* checking for underflow */
|
||||
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
||||
v1.v.val -= v2.v.val;
|
||||
if (v1.v.val < 0) return E_DATE_OVER;
|
||||
PushValStack(v1);
|
||||
@@ -1078,7 +1133,28 @@ static int LogNot(void)
|
||||
/* Find a function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
Operator *FindFunc(char *name, Operator where[], int num)
|
||||
Operator *FindOperator(char const *name, Operator where[], int num)
|
||||
{
|
||||
int top=num-1, bot=0;
|
||||
int mid, r;
|
||||
while (top >= bot) {
|
||||
mid = (top + bot) / 2;
|
||||
r = StrCmpi(name, where[mid].name);
|
||||
if (!r) return &where[mid];
|
||||
else if (r > 0) bot = mid+1;
|
||||
else top = mid-1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FindFunc */
|
||||
/* */
|
||||
/* Find a function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
BuiltinFunc *FindFunc(char const *name, BuiltinFunc where[], int num)
|
||||
{
|
||||
int top=num-1, bot=0;
|
||||
int mid, r;
|
||||
@@ -1102,7 +1178,7 @@ Operator *FindFunc(char *name, Operator where[], int num)
|
||||
void PrintValue (Value *v, FILE *fp)
|
||||
{
|
||||
int y, m, d;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
if (v->type == STR_TYPE) {
|
||||
s=v->v.str;
|
||||
@@ -1120,7 +1196,7 @@ void PrintValue (Value *v, FILE *fp)
|
||||
}
|
||||
else if (v->type == DATETIME_TYPE) {
|
||||
FromJulian(v->v.val / MINUTES_PER_DAY, &y, &m, &d);
|
||||
fprintf(fp, "%04d%c%02d%c%02d@%02d%c%02d", y, DateSep, m+1, DateSep, d,
|
||||
fprintf(fp, "%04d%c%02d%c%02d%c%02d%c%02d", y, DateSep, m+1, DateSep, d, DateTimeSep,
|
||||
(v->v.val % MINUTES_PER_DAY) / 60, TimeSep, (v->v.val % MINUTES_PER_DAY) % 60);
|
||||
}
|
||||
else fprintf(fp, "ERR");
|
||||
@@ -1154,7 +1230,7 @@ int CopyValue(Value *dest, const Value *src)
|
||||
/* and tim; update s. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int ParseLiteralDate(char **s, int *jul, int *tim)
|
||||
int ParseLiteralDate(char const **s, int *jul, int *tim)
|
||||
{
|
||||
int y, m, d;
|
||||
int hour, min;
|
||||
@@ -1188,7 +1264,7 @@ static int ParseLiteralDate(char **s, int *jul, int *tim)
|
||||
*jul = Julian(y, m, d);
|
||||
|
||||
/* Do we have a time part as well? */
|
||||
if (**s == ' ' || **s == '@') {
|
||||
if (**s == ' ' || **s == '@' || **s == 'T' || **s == 't') {
|
||||
(*s)++;
|
||||
while(isdigit(**s)) {
|
||||
hour *= 10;
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
/* Contains a few definitions used by expression evaluator. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
392
src/files.c
392
src/files.c
@@ -7,8 +7,7 @@
|
||||
/* files. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -17,6 +16,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
@@ -42,20 +46,34 @@
|
||||
/* Define the structures needed by the file caching system */
|
||||
typedef struct cache {
|
||||
struct cache *next;
|
||||
char *text;
|
||||
char const *text;
|
||||
int LineNo;
|
||||
} CachedLine;
|
||||
|
||||
typedef struct cheader {
|
||||
struct cheader *next;
|
||||
char *filename;
|
||||
char const *filename;
|
||||
CachedLine *cache;
|
||||
int ownedByMe;
|
||||
} CachedFile;
|
||||
|
||||
/* A linked list of filenames if we INCLUDE /some/directory/ */
|
||||
typedef struct fname_chain {
|
||||
struct fname_chain *next;
|
||||
char const *filename;
|
||||
} FilenameChain;
|
||||
|
||||
/* Cache filename chains for directories */
|
||||
typedef struct directory_fname_chain {
|
||||
struct directory_fname_chain *next;
|
||||
FilenameChain *chain;
|
||||
char const *dirname;
|
||||
} DirectoryFilenameChain;
|
||||
|
||||
/* Define the structures needed by the INCLUDE file system */
|
||||
typedef struct {
|
||||
char *filename;
|
||||
char const *filename;
|
||||
FilenameChain *chain;
|
||||
int LineNo;
|
||||
unsigned int IfFlags;
|
||||
int NumIfs;
|
||||
@@ -66,6 +84,7 @@ typedef struct {
|
||||
|
||||
static CachedFile *CachedFiles = (CachedFile *) NULL;
|
||||
static CachedLine *CLine = (CachedLine *) NULL;
|
||||
static DirectoryFilenameChain *CachedDirectoryChains = NULL;
|
||||
|
||||
static FILE *fp;
|
||||
|
||||
@@ -73,9 +92,52 @@ static IncludeStruct IStack[INCLUDE_NEST];
|
||||
static int IStackPtr = 0;
|
||||
|
||||
static int ReadLineFromFile (void);
|
||||
static int CacheFile (const char *fname);
|
||||
static int CacheFile (char const *fname);
|
||||
static void DestroyCache (CachedFile *cf);
|
||||
static int CheckSafety (void);
|
||||
static int PopFile (void);
|
||||
|
||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
{
|
||||
DynamicBuffer fname_buf;
|
||||
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) {
|
||||
fclose(PurgeFP);
|
||||
}
|
||||
PurgeFP = NULL;
|
||||
|
||||
/* Do not open a purge file if we're below purge
|
||||
include depth */
|
||||
if (IStackPtr-2 >= PurgeIncludeDepth) {
|
||||
PurgeFP = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
DBufInit(&fname_buf);
|
||||
if (DBufPuts(&fname_buf, fname) != OK) return;
|
||||
if (DBufPuts(&fname_buf, ".purged") != OK) return;
|
||||
PurgeFP = fopen(DBufValue(&fname_buf), mode);
|
||||
if (!PurgeFP) {
|
||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
||||
}
|
||||
DBufFree(&fname_buf);
|
||||
}
|
||||
|
||||
static void FreeChainItem(FilenameChain *chain)
|
||||
{
|
||||
if (chain->filename) free((void *) chain->filename);
|
||||
free(chain);
|
||||
}
|
||||
|
||||
static void FreeChain(FilenameChain *chain)
|
||||
{
|
||||
FilenameChain *next;
|
||||
while(chain) {
|
||||
next = chain->next;
|
||||
FreeChainItem(chain);
|
||||
chain = next;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -118,6 +180,8 @@ int ReadLine(void)
|
||||
static int ReadLineFromFile(void)
|
||||
{
|
||||
int l;
|
||||
char copy_buffer[4096];
|
||||
size_t n;
|
||||
|
||||
DynamicBuffer buf;
|
||||
|
||||
@@ -137,14 +201,32 @@ static int ReadLineFromFile(void)
|
||||
}
|
||||
if (feof(fp)) {
|
||||
FCLOSE(fp);
|
||||
if ((DBufLen(&buf) == 0) &&
|
||||
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
}
|
||||
l = DBufLen(&buf);
|
||||
if (l && (DBufValue(&buf)[l-1] == '\\')) {
|
||||
DBufValue(&buf)[l-1] = 0;
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
if (PurgeMode) {
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (DBufPutc(&LineBuffer, '\n') != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
DBufValue(&buf)[l-1] = '\n';
|
||||
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
|
||||
DBufFree(&buf);
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -153,8 +235,25 @@ static int ReadLineFromFile(void)
|
||||
DBufFree(&LineBuffer);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
FreshLine = 1;
|
||||
DBufFree(&buf);
|
||||
|
||||
/* If the line is: __EOF__ treat it as end-of-file */
|
||||
CurLine = DBufValue(&LineBuffer);
|
||||
if (!strcmp(CurLine, "__EOF__")) {
|
||||
if (PurgeMode && PurgeFP) {
|
||||
PurgeEchoLine("%s\n", "__EOF__");
|
||||
while ((n = fread(copy_buffer, 1, sizeof(copy_buffer), fp)) != 0) {
|
||||
fwrite(copy_buffer, 1, n, PurgeFP);
|
||||
}
|
||||
if (PurgeFP != stdout) fclose(PurgeFP);
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
FCLOSE(fp);
|
||||
DBufFree(&LineBuffer);
|
||||
CurLine = DBufValue(&LineBuffer);
|
||||
}
|
||||
|
||||
FreshLine = 1;
|
||||
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
|
||||
return OK;
|
||||
}
|
||||
@@ -171,11 +270,18 @@ static int ReadLineFromFile(void)
|
||||
/* ShouldCache is 1, cache the file */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int OpenFile(const char *fname)
|
||||
int OpenFile(char const *fname)
|
||||
{
|
||||
CachedFile *h = CachedFiles;
|
||||
int r;
|
||||
|
||||
if (PurgeMode) {
|
||||
if (PurgeFP != NULL && PurgeFP != stdout) {
|
||||
fclose(PurgeFP);
|
||||
}
|
||||
PurgeFP = NULL;
|
||||
}
|
||||
|
||||
/* Assume we own the file for now */
|
||||
RunDisabled &= ~RUN_NOTOWNER;
|
||||
|
||||
@@ -183,6 +289,9 @@ int OpenFile(const char *fname)
|
||||
|
||||
while (h) {
|
||||
if (!strcmp(fname, h->filename)) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Found in cache\n", fname);
|
||||
}
|
||||
CLine = h->cache;
|
||||
STRSET(FileName, fname);
|
||||
LineNo = 0;
|
||||
@@ -197,8 +306,20 @@ int OpenFile(const char *fname)
|
||||
/* If it's a dash, then it's stdin */
|
||||
if (!strcmp(fname, "-")) {
|
||||
fp = stdin;
|
||||
if (PurgeMode) {
|
||||
PurgeFP = stdout;
|
||||
}
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `-': Reading stdin\n");
|
||||
}
|
||||
} else {
|
||||
fp = fopen(fname, "r");
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||
}
|
||||
if (PurgeMode) {
|
||||
OpenPurgeFile(fname, "w");
|
||||
}
|
||||
}
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
CLine = NULL;
|
||||
@@ -212,8 +333,10 @@ int OpenFile(const char *fname)
|
||||
if (strcmp(fname, "-")) {
|
||||
fp = fopen(fname, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||
} else {
|
||||
fp = stdin;
|
||||
if (PurgeMode) PurgeFP = stdout;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,18 +353,25 @@ int OpenFile(const char *fname)
|
||||
/* Returns an indication of success or failure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int CacheFile(const char *fname)
|
||||
static int CacheFile(char const *fname)
|
||||
{
|
||||
int r;
|
||||
CachedFile *cf;
|
||||
CachedLine *cl;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Caching file `%s' in memory\n", fname);
|
||||
}
|
||||
cl = NULL;
|
||||
/* Create a file header */
|
||||
cf = NEW(CachedFile);
|
||||
cf->cache = NULL;
|
||||
if (!cf) { ShouldCache = 0; FCLOSE(fp); return E_NO_MEM; }
|
||||
if (!cf) {
|
||||
ShouldCache = 0;
|
||||
FCLOSE(fp);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cf->filename = StrDup(fname);
|
||||
if (!cf->filename) {
|
||||
ShouldCache = 0;
|
||||
@@ -267,7 +397,7 @@ static int CacheFile(const char *fname)
|
||||
}
|
||||
/* Skip blank chars */
|
||||
s = DBufValue(&LineBuffer);
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
if (*s && *s!=';' && *s!='#') {
|
||||
/* Add the line to the cache */
|
||||
if (!cl) {
|
||||
@@ -311,13 +441,33 @@ static int CacheFile(const char *fname)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* NextChainedFile - move to the next chained file in a glob */
|
||||
/* list. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int NextChainedFile(IncludeStruct *i)
|
||||
{
|
||||
while(i->chain) {
|
||||
FilenameChain *cur = i->chain;
|
||||
i->chain = i->chain->next;
|
||||
if (OpenFile(cur->filename) == OK) {
|
||||
return OK;
|
||||
} else {
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], cur->filename);
|
||||
}
|
||||
}
|
||||
return E_EOF;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* PopFile - we've reached the end. Pop up to the previous */
|
||||
/* file, or return E_EOF */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int PopFile(void)
|
||||
static int PopFile(void)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
|
||||
@@ -326,8 +476,21 @@ int PopFile(void)
|
||||
|
||||
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
|
||||
if (!IStackPtr) return E_EOF;
|
||||
i = &IStack[IStackPtr-1];
|
||||
|
||||
if (i->chain) {
|
||||
int oldRunDisabled = RunDisabled;
|
||||
if (NextChainedFile(i) == OK) {
|
||||
return OK;
|
||||
}
|
||||
RunDisabled = oldRunDisabled;
|
||||
}
|
||||
|
||||
if (IStackPtr <= 1) {
|
||||
return E_EOF;
|
||||
}
|
||||
|
||||
IStackPtr--;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
LineNo = i->LineNo;
|
||||
IfFlags = i->IfFlags;
|
||||
@@ -343,13 +506,15 @@ int PopFile(void)
|
||||
if (strcmp(i->filename, "-")) {
|
||||
fp = fopen(i->filename, "r");
|
||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||
} else {
|
||||
fp = stdin;
|
||||
if (PurgeMode) PurgeFP = stdout;
|
||||
}
|
||||
if (fp != stdin)
|
||||
(void) fseek(fp, i->offset, 0); /* Trust that it works... */
|
||||
}
|
||||
free(i->filename);
|
||||
free((char *) i->filename);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -361,13 +526,13 @@ int PopFile(void)
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoInclude(ParsePtr p)
|
||||
{
|
||||
{
|
||||
DynamicBuffer buf;
|
||||
int r, e;
|
||||
|
||||
DBufInit(&buf);
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
e = VerifyEoln(p);
|
||||
e = VerifyEoln(p);
|
||||
if (e) Eprint("%s", ErrMsg[e]);
|
||||
if ( (r=IncludeFile(DBufValue(&buf))) ) {
|
||||
DBufFree(&buf);
|
||||
@@ -379,6 +544,126 @@ int DoInclude(ParsePtr p)
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
{
|
||||
DynamicBuffer pattern;
|
||||
char *dir;
|
||||
size_t l;
|
||||
int r;
|
||||
glob_t glob_buf;
|
||||
DirectoryFilenameChain *dc = CachedDirectoryChains;
|
||||
|
||||
i->chain = NULL;
|
||||
if (!*dirname) return E_CANT_OPEN;
|
||||
|
||||
dir = StrDup(dirname);
|
||||
if (!dir) return E_NO_MEM;
|
||||
|
||||
/* Strip trailing slashes off directory */
|
||||
l = strlen(dir);
|
||||
while(l) {
|
||||
if (*(dir+l-1) == '/') {
|
||||
l--;
|
||||
*(dir+l) = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Repair root directory :-) */
|
||||
if (!l) {
|
||||
*dir = '/';
|
||||
}
|
||||
|
||||
/* Check the cache */
|
||||
while(dc) {
|
||||
if (!strcmp(dc->dirname, dir)) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Found cached directory listing for `%s'\n",
|
||||
dir);
|
||||
}
|
||||
free(dir);
|
||||
i->chain = dc->chain;
|
||||
return OK;
|
||||
}
|
||||
dc = dc->next;
|
||||
}
|
||||
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Scanning directory `%s' for *.rem files\n", dir);
|
||||
}
|
||||
|
||||
if (ShouldCache) {
|
||||
dc = malloc(sizeof(DirectoryFilenameChain));
|
||||
if (dc) {
|
||||
dc->dirname = StrDup(dir);
|
||||
if (!dc->dirname) {
|
||||
free(dc);
|
||||
dc = NULL;
|
||||
}
|
||||
}
|
||||
if (dc) {
|
||||
if (DebugFlag & DB_TRACE_FILES) {
|
||||
fprintf(ErrFp, "Caching directory `%s' listing\n", dir);
|
||||
}
|
||||
|
||||
dc->chain = NULL;
|
||||
dc->next = CachedDirectoryChains;
|
||||
CachedDirectoryChains = dc;
|
||||
}
|
||||
}
|
||||
|
||||
DBufInit(&pattern);
|
||||
DBufPuts(&pattern, dir);
|
||||
DBufPuts(&pattern, "/*.rem");
|
||||
free(dir);
|
||||
|
||||
r = glob(DBufValue(&pattern), 0, NULL, &glob_buf);
|
||||
DBufFree(&pattern);
|
||||
|
||||
if (r == GLOB_NOMATCH) {
|
||||
globfree(&glob_buf);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (r != 0) {
|
||||
globfree(&glob_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add the files to the chain backwards to preserve sort order */
|
||||
for (r=glob_buf.gl_pathc-1; r>=0; r--) {
|
||||
FilenameChain *ch = malloc(sizeof(FilenameChain));
|
||||
if (!ch) {
|
||||
globfree(&glob_buf);
|
||||
FreeChain(i->chain);
|
||||
i->chain = NULL;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
/* TODO: stat the file and only add if it's a plain file and
|
||||
readable by us */
|
||||
ch->filename = StrDup(glob_buf.gl_pathv[r]);
|
||||
if (!ch->filename) {
|
||||
globfree(&glob_buf);
|
||||
FreeChain(i->chain);
|
||||
i->chain = NULL;
|
||||
free(ch);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
ch->next = i->chain;
|
||||
i->chain = ch;
|
||||
}
|
||||
if (dc) {
|
||||
dc->chain = i->chain;
|
||||
}
|
||||
|
||||
globfree(&glob_buf);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IncludeFile */
|
||||
@@ -387,22 +672,28 @@ int DoInclude(ParsePtr p)
|
||||
/* inclusion. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int IncludeFile(const char *fname)
|
||||
int IncludeFile(char const *fname)
|
||||
{
|
||||
IncludeStruct *i;
|
||||
int r;
|
||||
int oldRunDisabled;
|
||||
struct stat statbuf;
|
||||
|
||||
FreshLine = 1;
|
||||
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||
i = &IStack[IStackPtr];
|
||||
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) return E_NO_MEM;
|
||||
if (FileName) {
|
||||
i->filename = StrDup(FileName);
|
||||
if (!i->filename) return E_NO_MEM;
|
||||
} else {
|
||||
i->filename = NULL;
|
||||
}
|
||||
i->LineNo = LineNo;
|
||||
i->NumIfs = NumIfs;
|
||||
i->IfFlags = IfFlags;
|
||||
i->CLine = CLine;
|
||||
i->offset = -1L;
|
||||
i->chain = NULL;
|
||||
if (RunDisabled & RUN_NOTOWNER) {
|
||||
i->ownedByMe = 0;
|
||||
} else {
|
||||
@@ -415,15 +706,52 @@ int IncludeFile(const char *fname)
|
||||
|
||||
IStackPtr++;
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
/* If it's a directory, set up the glob chain here. */
|
||||
if (stat(fname, &statbuf) == 0) {
|
||||
FilenameChain *fc;
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
if (SetupGlobChain(fname, i) == OK) { /* Glob succeeded */
|
||||
if (!i->chain) { /* Oops... no matching files */
|
||||
if (!Hush) {
|
||||
Eprint("%s: %s", fname, ErrMsg[E_NO_MATCHING_REMS]);
|
||||
}
|
||||
PopFile();
|
||||
return E_NO_MATCHING_REMS;
|
||||
}
|
||||
while(i->chain) {
|
||||
fc = i->chain;
|
||||
i->chain = i->chain->next;
|
||||
|
||||
/* Munch first file */
|
||||
oldRunDisabled = RunDisabled;
|
||||
if (!OpenFile(fc->filename)) {
|
||||
return OK;
|
||||
}
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fc->filename);
|
||||
RunDisabled = oldRunDisabled;
|
||||
}
|
||||
/* Couldn't open anything... bail */
|
||||
return PopFile();
|
||||
} else {
|
||||
if (!Hush) {
|
||||
Eprint("%s: %s", fname, ErrMsg[E_NO_MATCHING_REMS]);
|
||||
}
|
||||
}
|
||||
return E_NO_MATCHING_REMS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
oldRunDisabled = RunDisabled;
|
||||
/* Try to open the new file */
|
||||
if (!OpenFile(fname)) {
|
||||
return OK;
|
||||
}
|
||||
RunDisabled = oldRunDisabled;
|
||||
/* Ugh! We failed! */
|
||||
if ( (r=PopFile()) ) return r;
|
||||
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fname);
|
||||
/* Ugh! We failed! */
|
||||
PopFile();
|
||||
return E_CANT_OPEN;
|
||||
}
|
||||
|
||||
@@ -432,7 +760,7 @@ int IncludeFile(const char *fname)
|
||||
/* GetAccessDate - get the access date of a file. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int GetAccessDate(char *file)
|
||||
int GetAccessDate(char const *file)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct tm *t1;
|
||||
@@ -457,10 +785,10 @@ static void DestroyCache(CachedFile *cf)
|
||||
{
|
||||
CachedLine *cl, *cnext;
|
||||
CachedFile *temp;
|
||||
if (cf->filename) free(cf->filename);
|
||||
if (cf->filename) free((char *) cf->filename);
|
||||
cl = cf->cache;
|
||||
while (cl) {
|
||||
if (cl->text) free (cl->text);
|
||||
if (cl->text) free ((char *) cl->text);
|
||||
cnext = cl->next;
|
||||
free(cl);
|
||||
cl = cnext;
|
||||
@@ -488,7 +816,7 @@ static void DestroyCache(CachedFile *cf)
|
||||
/***************************************************************/
|
||||
int TopLevel(void)
|
||||
{
|
||||
return !IStackPtr;
|
||||
return IStackPtr <= 1;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
1520
src/funcs.c
1520
src/funcs.c
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,7 @@
|
||||
/* globals.h and err.h */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -37,7 +36,7 @@ EXTERN int CurMon;
|
||||
EXTERN int CurYear;
|
||||
EXTERN int LineNo;
|
||||
EXTERN int FreshLine;
|
||||
EXTERN INIT( char *MsgCommand, NULL);
|
||||
EXTERN INIT( char const *MsgCommand, NULL);
|
||||
EXTERN INIT( int ShowAllErrors, 0);
|
||||
EXTERN INIT( int DebugFlag, 0);
|
||||
EXTERN INIT( int DoCalendar, 0);
|
||||
@@ -53,15 +52,17 @@ EXTERN INIT( int CalMonths, 0);
|
||||
EXTERN INIT( int Hush, 0);
|
||||
EXTERN INIT( int NextMode, 0);
|
||||
EXTERN INIT( int InfiniteDelta, 0);
|
||||
EXTERN INIT( int DeltaOffset, 0);
|
||||
EXTERN INIT( int RunDisabled, 0);
|
||||
EXTERN INIT( int IgnoreOnce, 0);
|
||||
EXTERN INIT( int SortByTime, 0);
|
||||
EXTERN INIT( int SortByDate, 0);
|
||||
EXTERN INIT( int SortByPrio, 0);
|
||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||
EXTERN INIT( long SysTime, -1L);
|
||||
|
||||
EXTERN char *InitialFile;
|
||||
EXTERN char const *InitialFile;
|
||||
EXTERN int FileAccessDate;
|
||||
|
||||
EXTERN INIT( int DontFork, 0);
|
||||
@@ -71,24 +72,34 @@ EXTERN INIT( int DontIssueAts, 0);
|
||||
EXTERN INIT( int Daemon, 0);
|
||||
EXTERN INIT( char DateSep, DATESEP);
|
||||
EXTERN INIT( char TimeSep, TIMESEP);
|
||||
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
||||
EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 150);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( char *FileName, NULL);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN INIT( int PurgeMode, 0);
|
||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||
EXTERN FILE *ErrFp;
|
||||
EXTERN INIT( FILE *PurgeFP, NULL);
|
||||
EXTERN INIT( int NumIfs, 0);
|
||||
EXTERN INIT( unsigned int IfFlags, 0);
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
EXTERN INIT( int LastTrigValid, 0);
|
||||
EXTERN Trigger LastTrigger;
|
||||
EXTERN TimeTrig LastTimeTrig;
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
EXTERN INIT( int LastTriggerTime, 0);
|
||||
EXTERN INIT( int ShouldCache, 0);
|
||||
EXTERN char *CurLine;
|
||||
EXTERN char const *CurLine;
|
||||
EXTERN INIT( int NumTriggered, 0);
|
||||
EXTERN int ArgC;
|
||||
EXTERN char **ArgV;
|
||||
EXTERN char const **ArgV;
|
||||
EXTERN INIT( int CalLines, CAL_LINES);
|
||||
EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseUTF8Chars, 0);
|
||||
EXTERN INIT( int UseVTColors, 0);
|
||||
|
||||
/* Latitude and longitude */
|
||||
EXTERN INIT( int LatDeg, LAT_DEG);
|
||||
|
||||
23
src/hbcal.c
23
src/hbcal.c
@@ -5,8 +5,7 @@
|
||||
/* Support for the Hebrew calendar */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||
/* 1985. */
|
||||
@@ -55,7 +54,7 @@
|
||||
#define ADAR2ADARA 1
|
||||
#define ADAR2BOTH 2
|
||||
|
||||
static char *HebMonthNames[] = {
|
||||
static char const *HebMonthNames[] = {
|
||||
"Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B",
|
||||
"Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"};
|
||||
|
||||
@@ -137,10 +136,10 @@ int DaysInHebYear(int y)
|
||||
/* given the LENGTH of the Hebrew year. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *DaysInHebMonths(int ylen)
|
||||
char const *DaysInHebMonths(int ylen)
|
||||
{
|
||||
static char monlen[13] =
|
||||
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29};
|
||||
static char monlen[14] =
|
||||
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29, 29};
|
||||
|
||||
|
||||
if (ylen > 355) {
|
||||
@@ -166,7 +165,7 @@ char *DaysInHebMonths(int ylen)
|
||||
int HebToJul(int hy, int hm, int hd)
|
||||
{
|
||||
int ylen;
|
||||
char *monlens;
|
||||
char const *monlens;
|
||||
int rh;
|
||||
int m;
|
||||
|
||||
@@ -201,7 +200,7 @@ void JulToHeb(int jul, int *hy, int *hm, int *hd)
|
||||
int y, m, d;
|
||||
int rh;
|
||||
int ylen;
|
||||
char *monlen;
|
||||
char const *monlen;
|
||||
/* Get the common year */
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
y += 3763; /* Over-estimate a bit to be on the safe side below... */
|
||||
@@ -232,7 +231,7 @@ void JulToHeb(int jul, int *hy, int *hm, int *hd)
|
||||
/* year. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int HebNameToNum(const char *mname)
|
||||
int HebNameToNum(char const *mname)
|
||||
{
|
||||
int i;
|
||||
int m=-1;
|
||||
@@ -254,7 +253,7 @@ int HebNameToNum(const char *mname)
|
||||
/* year. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *HebMonthName(int m, int y)
|
||||
char const *HebMonthName(int m, int y)
|
||||
{
|
||||
if (m != ADARA && m != ADARB) return HebMonthNames[m];
|
||||
|
||||
@@ -293,7 +292,7 @@ char *HebMonthName(int m, int y)
|
||||
int GetValidHebDate(int yin, int min, int din, int adarbehave,
|
||||
int *mout, int *dout, int jahr)
|
||||
{
|
||||
char *monlen;
|
||||
char const *monlen;
|
||||
int ylen;
|
||||
|
||||
*mout = min;
|
||||
@@ -448,7 +447,7 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
|
||||
/***************************************************************/
|
||||
int ComputeJahr(int y, int m, int d, int *ans)
|
||||
{
|
||||
char *monlen;
|
||||
char const *monlen;
|
||||
int len;
|
||||
|
||||
*ans = JAHR_NONE;
|
||||
|
||||
270
src/init.c
270
src/init.c
@@ -7,11 +7,11 @@
|
||||
/* in normal mode. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2007 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
#include "version.h"
|
||||
#include "config.h"
|
||||
|
||||
#define L_IN_INIT 1
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
#include "err.h"
|
||||
#include "version.h"
|
||||
#include "globals.h"
|
||||
|
||||
/***************************************************************
|
||||
@@ -52,13 +51,14 @@
|
||||
* -h = Hush mode
|
||||
* -f = Do not fork
|
||||
* -dchars = Debugging mode: Chars are:
|
||||
* f = Trace file openings
|
||||
* e = Echo input lines
|
||||
* x = Display expression evaluation
|
||||
* t = Display trigger dates
|
||||
* v = Dump variables at end
|
||||
* l = Display entire line in error messages
|
||||
* -e = Send messages normally sent to stderr to stdout instead
|
||||
* -z[n] = Daemon mode waking up every n (def 5) minutes.
|
||||
* -z[n] = Daemon mode waking up every n (def 1) minutes.
|
||||
* -bn = Time format for cal (0, 1, or 2)
|
||||
* -xn = Max. number of iterations for SATISFY
|
||||
* -uname = Run as user 'name' - only valid when run by root. If run
|
||||
@@ -66,9 +66,13 @@
|
||||
* -kcmd = Run 'cmd' for MSG-type reminders instead of printing to stdout
|
||||
* -iVAR=EXPR = Initialize and preserve VAR.
|
||||
* -m = Start calendar with Monday instead of Sunday.
|
||||
* -j[n] = Purge all junk from reminder files (n = INCLUDE depth)
|
||||
* A minus sign alone indicates to take input from stdin
|
||||
*
|
||||
**************************************************************/
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static void rkrphgvba(int x);
|
||||
#endif
|
||||
|
||||
/* For parsing an integer */
|
||||
#define PARSENUM(var, s) \
|
||||
@@ -79,10 +83,10 @@ while (isdigit(*(s))) { \
|
||||
s++; \
|
||||
}
|
||||
|
||||
static void ChgUser(char *u);
|
||||
static void InitializeVar(char *str);
|
||||
static void ChgUser(char const *u);
|
||||
static void InitializeVar(char const *str);
|
||||
|
||||
static char *BadDate = "Illegal date on command line\n";
|
||||
static char const *BadDate = "Illegal date on command line\n";
|
||||
|
||||
static DynamicBuffer default_filename_buf;
|
||||
|
||||
@@ -94,9 +98,9 @@ static DynamicBuffer default_filename_buf;
|
||||
/* default filename. Use $DOTREMINDERS or $HOME/.reminders */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static char *DefaultFilename(void)
|
||||
static char const *DefaultFilename(void)
|
||||
{
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
DBufInit(&default_filename_buf);
|
||||
|
||||
@@ -122,14 +126,25 @@ static char *DefaultFilename(void)
|
||||
/* Initialize the system - called only once at beginning! */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void InitRemind(int argc, char *argv[])
|
||||
void InitRemind(int argc, char const *argv[])
|
||||
{
|
||||
char *arg;
|
||||
char const *arg;
|
||||
int i;
|
||||
int y, m, d, rep;
|
||||
Token tok;
|
||||
int InvokedAsRem = 0;
|
||||
char *s;
|
||||
char const *s;
|
||||
int weeks;
|
||||
|
||||
int jul;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
rkrphgvba(0);
|
||||
#elif defined(__CYGWIN__)
|
||||
rkrphgvba(1);
|
||||
#endif
|
||||
|
||||
jul = NO_DATE;
|
||||
|
||||
/* Initialize global dynamic buffers */
|
||||
DBufInit(&Banner);
|
||||
@@ -138,6 +153,8 @@ void InitRemind(int argc, char *argv[])
|
||||
|
||||
DBufPuts(&Banner, L_BANNER);
|
||||
|
||||
PurgeFP = NULL;
|
||||
|
||||
/* Make sure remind is not installed set-uid or set-gid */
|
||||
if (getgid() != getegid() ||
|
||||
getuid() != geteuid()) {
|
||||
@@ -187,6 +204,13 @@ void InitRemind(int argc, char *argv[])
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
|
||||
case 'j':
|
||||
case 'J':
|
||||
PurgeMode = 1;
|
||||
if (*arg) {
|
||||
PARSENUM(PurgeIncludeDepth, arg);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
InitializeVar(arg);
|
||||
@@ -222,9 +246,15 @@ void InitRemind(int argc, char *argv[])
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
InfiniteDelta = 1;
|
||||
if (!*arg) {
|
||||
InfiniteDelta = 1;
|
||||
} else {
|
||||
PARSENUM(DeltaOffset, arg);
|
||||
if (DeltaOffset < 0) {
|
||||
DeltaOffset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
ErrFp = stdout;
|
||||
@@ -240,6 +270,7 @@ void InitRemind(int argc, char *argv[])
|
||||
SortByDate = SORT_ASCEND;
|
||||
SortByTime = SORT_ASCEND;
|
||||
SortByPrio = SORT_ASCEND;
|
||||
UntimedBeforeTimed = 0;
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
SortByDate = SORT_DESCEND;
|
||||
@@ -255,6 +286,11 @@ void InitRemind(int argc, char *argv[])
|
||||
SortByPrio = SORT_DESCEND;
|
||||
arg++;
|
||||
}
|
||||
if (*arg) {
|
||||
if (*arg == 'D' || *arg == 'd')
|
||||
UntimedBeforeTimed = 1;
|
||||
arg++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
@@ -280,7 +316,7 @@ void InitRemind(int argc, char *argv[])
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
DontIssueAts = 1;
|
||||
DontIssueAts++;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
@@ -295,8 +331,38 @@ void InitRemind(int argc, char *argv[])
|
||||
case 'c':
|
||||
case 'C':
|
||||
DoCalendar = 1;
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
weeks = 0;
|
||||
/* Parse the flags */
|
||||
while(*arg) {
|
||||
if (*arg == 'a' ||
|
||||
*arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
weeks = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'l' || *arg == 'L') {
|
||||
UseVTChars = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'u' || *arg == 'U') {
|
||||
UseUTF8Chars = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'c' || *arg == 'C') {
|
||||
UseVTColors = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (weeks) {
|
||||
PARSENUM(CalWeeks, arg);
|
||||
if (!CalWeeks) CalWeeks = 1;
|
||||
} else {
|
||||
@@ -308,12 +374,21 @@ void InitRemind(int argc, char *argv[])
|
||||
case 's':
|
||||
case 'S':
|
||||
DoSimpleCalendar = 1;
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
weeks = 0;
|
||||
while(*arg) {
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
weeks = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*arg == '+') {
|
||||
arg++;
|
||||
if (weeks) {
|
||||
PARSENUM(CalWeeks, arg);
|
||||
if (!CalWeeks) CalWeeks = 1;
|
||||
} else {
|
||||
@@ -363,11 +438,12 @@ void InitRemind(int argc, char *argv[])
|
||||
case 'D':
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
||||
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
|
||||
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
|
||||
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
|
||||
default:
|
||||
fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
|
||||
}
|
||||
@@ -431,18 +507,32 @@ void InitRemind(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case T_DateTime:
|
||||
if (SysTime != -1L) Usage();
|
||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
||||
SysTime = (tok.val % MINUTES_PER_DAY) * 60;
|
||||
DontQueue = 1;
|
||||
Daemon = 0;
|
||||
jul = tok.val / MINUTES_PER_DAY;
|
||||
break;
|
||||
|
||||
case T_Date:
|
||||
if (m != NO_MON || d != NO_DAY || y != NO_YR || jul != NO_DATE) Usage();
|
||||
jul = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
if (m != NO_MON) Usage();
|
||||
if (m != NO_MON || jul != NO_DATE) Usage();
|
||||
else m = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
if (d != NO_DAY) Usage();
|
||||
if (d != NO_DAY || jul != NO_DATE) Usage();
|
||||
else d = tok.val;
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
if (y != NO_YR) Usage();
|
||||
if (y != NO_YR || jul != NO_DATE) Usage();
|
||||
else y = tok.val;
|
||||
break;
|
||||
|
||||
@@ -451,7 +541,8 @@ void InitRemind(int argc, char *argv[])
|
||||
else rep = tok.val;
|
||||
break;
|
||||
|
||||
default: Usage();
|
||||
default:
|
||||
Usage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,6 +552,9 @@ void InitRemind(int argc, char *argv[])
|
||||
Daemon = 0;
|
||||
}
|
||||
|
||||
if (jul != NO_DATE) {
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
}
|
||||
/* Must supply date in the form: day, mon, yr OR mon, yr */
|
||||
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
|
||||
if (m == NO_MON || y == NO_YR) {
|
||||
@@ -474,12 +568,12 @@ void InitRemind(int argc, char *argv[])
|
||||
}
|
||||
if (d == NO_DAY) d=1;
|
||||
if (d > DaysInMonth(m, y)) {
|
||||
fprintf(ErrFp, BadDate);
|
||||
fprintf(ErrFp, "%s", BadDate);
|
||||
Usage();
|
||||
}
|
||||
JulianToday = Julian(y, m, d);
|
||||
if (JulianToday == -1) {
|
||||
fprintf(ErrFp, BadDate);
|
||||
fprintf(ErrFp, "%s", BadDate);
|
||||
Usage();
|
||||
}
|
||||
CurYear = y;
|
||||
@@ -491,7 +585,7 @@ void InitRemind(int argc, char *argv[])
|
||||
}
|
||||
/* Figure out the offset from UTC */
|
||||
if (CalculateUTC)
|
||||
(void) CalcMinsFromUTC(JulianToday, SystemTime(1)/60,
|
||||
(void) CalcMinsFromUTC(JulianToday, SystemTime(0)/60,
|
||||
&MinsFromUTC, NULL);
|
||||
}
|
||||
|
||||
@@ -505,8 +599,7 @@ void InitRemind(int argc, char *argv[])
|
||||
#ifndef L_USAGE_OVERRIDE
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2007 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -514,29 +607,30 @@ void Usage(void)
|
||||
fprintf(ErrFp, "Options:\n");
|
||||
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
|
||||
fprintf(ErrFp, " -r Disable RUN directives\n");
|
||||
fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n");
|
||||
fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
|
||||
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
|
||||
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
|
||||
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
|
||||
fprintf(ErrFp, " -s[a][+][n] Produce `simple calendar' for n (1) months (weeks)\n");
|
||||
fprintf(ErrFp, " -p[a][n] Same as -s, but input compatible with rem2ps\n");
|
||||
fprintf(ErrFp, " -l Prefix each simple calendar line with line number and filename comment\n");
|
||||
fprintf(ErrFp, " -v Verbose mode\n");
|
||||
fprintf(ErrFp, " -o Ignore ONCE directives\n");
|
||||
fprintf(ErrFp, " -t Trigger all future reminders regardless of delta\n");
|
||||
fprintf(ErrFp, " -t[n] Trigger all future (or those within `n' days)\n");
|
||||
fprintf(ErrFp, " -h `Hush' mode - be very quiet\n");
|
||||
fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\n");
|
||||
fprintf(ErrFp, " -q Don't queue timed reminders\n");
|
||||
fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
|
||||
fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (5) minutes.\n");
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
|
||||
fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (1) minutes.\n");
|
||||
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline f=tracefiles\n");
|
||||
fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
|
||||
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
|
||||
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
|
||||
fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\n");
|
||||
fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
|
||||
fprintf(ErrFp, " -g[dddd] Sort reminders by date, time, priority, and 'timedness'\n");
|
||||
fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
|
||||
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
|
||||
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
|
||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif /* L_USAGE_OVERRIDE */
|
||||
@@ -550,12 +644,15 @@ void Usage(void)
|
||||
/* USER environment variables. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void ChgUser(char *user)
|
||||
static void ChgUser(char const *user)
|
||||
{
|
||||
uid_t myuid;
|
||||
|
||||
struct passwd *pwent;
|
||||
static char *home, *shell, *username, *logname;
|
||||
static char *home;
|
||||
static char *shell;
|
||||
static char *username;
|
||||
static char *logname;
|
||||
|
||||
myuid = getuid();
|
||||
|
||||
@@ -578,7 +675,7 @@ static void ChgUser(char *user)
|
||||
|
||||
home = malloc(strlen(pwent->pw_dir) + 6);
|
||||
if (!home) {
|
||||
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(home, "HOME=%s", pwent->pw_dir);
|
||||
@@ -586,7 +683,7 @@ static void ChgUser(char *user)
|
||||
|
||||
shell = malloc(strlen(pwent->pw_shell) + 7);
|
||||
if (!shell) {
|
||||
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
||||
@@ -595,20 +692,34 @@ static void ChgUser(char *user)
|
||||
if (pwent->pw_uid) {
|
||||
username = malloc(strlen(pwent->pw_name) + 6);
|
||||
if (!username) {
|
||||
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(username, "USER=%s", pwent->pw_name);
|
||||
putenv(username);
|
||||
logname= malloc(strlen(pwent->pw_name) + 9);
|
||||
if (!logname) {
|
||||
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
|
||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
||||
putenv(logname);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DefineFunction(char const *str)
|
||||
{
|
||||
Parser p;
|
||||
int r;
|
||||
|
||||
CreateParser(str, &p);
|
||||
r = DoFset(&p);
|
||||
DestroyParser(&p);
|
||||
if (r != OK) {
|
||||
fprintf(ErrFp, "-i option: %s: %s\n", str, ErrMsg[r]);
|
||||
}
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* InitializeVar */
|
||||
@@ -616,22 +727,34 @@ static void ChgUser(char *user)
|
||||
/* Initialize and preserve a variable */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void InitializeVar(char *str)
|
||||
static void InitializeVar(char const *str)
|
||||
{
|
||||
char *varname, *expr;
|
||||
char const *expr;
|
||||
char const *ostr = str;
|
||||
char varname[VAR_NAME_LEN+1];
|
||||
|
||||
Value val;
|
||||
|
||||
int r;
|
||||
|
||||
/* Scan for an '=' sign */
|
||||
varname = str;
|
||||
while (*str && *str != '=') str++;
|
||||
r = 0;
|
||||
while (*str && *str != '=') {
|
||||
if (r < VAR_NAME_LEN) {
|
||||
varname[r++] = *str;
|
||||
}
|
||||
if (*str == '(') {
|
||||
/* Do a function definition if we see a paren */
|
||||
DefineFunction(ostr);
|
||||
return;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
varname[r] = 0;
|
||||
if (!*str) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
|
||||
return;
|
||||
}
|
||||
*str = 0;
|
||||
if (!*varname) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
|
||||
return;
|
||||
@@ -642,7 +765,7 @@ static void InitializeVar(char *str)
|
||||
return;
|
||||
}
|
||||
|
||||
r=EvalExpr(&expr, &val);
|
||||
r=EvalExpr(&expr, &val, NULL);
|
||||
if (r) {
|
||||
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
|
||||
return;
|
||||
@@ -664,3 +787,46 @@ static void InitializeVar(char *str)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static char const pmsg1[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x68, 0x61, 0x61, 0x76,
|
||||
0x61, 0x74, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61, 0x71, 0x20, 0x62,
|
||||
0x61, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x63, 0x79, 0x72, 0x20,
|
||||
0x63, 0x65, 0x62, 0x71, 0x68, 0x70, 0x67, 0x2e, 0x20, 0x20, 0x56,
|
||||
0x27, 0x71, 0x20, 0x65, 0x6e, 0x67, 0x75, 0x72, 0x65, 0x20, 0x67,
|
||||
0x75, 0x6e, 0x67, 0x0a, 0x6c, 0x62, 0x68, 0x20, 0x71, 0x76, 0x71,
|
||||
0x61, 0x27, 0x67, 0x2e, 0x20, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61,
|
||||
0x71, 0x20, 0x72, 0x6b, 0x72, 0x70, 0x68, 0x67, 0x76, 0x62, 0x61,
|
||||
0x20, 0x6a, 0x76, 0x79, 0x79, 0x20, 0x70, 0x62, 0x61, 0x67, 0x76,
|
||||
0x61, 0x68, 0x72, 0x20, 0x7a, 0x62, 0x7a, 0x72, 0x61, 0x67, 0x6e,
|
||||
0x65, 0x76, 0x79, 0x6c, 0x2e, 0x0a, 0x00
|
||||
};
|
||||
|
||||
static char const pmsg2[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x68, 0x61, 0x61, 0x76,
|
||||
0x61, 0x74, 0x20, 0x45, 0x72, 0x7a, 0x76, 0x61, 0x71, 0x20, 0x62,
|
||||
0x61, 0x20, 0x6e, 0x20, 0x5a, 0x76, 0x70, 0x65, 0x62, 0x66, 0x62,
|
||||
0x73, 0x67, 0x20, 0x66, 0x6c, 0x66, 0x67, 0x72, 0x7a, 0x2e, 0x20,
|
||||
0x20, 0x56, 0x27, 0x71, 0x20, 0x65, 0x6e, 0x67, 0x75, 0x72, 0x65,
|
||||
0x20, 0x67, 0x75, 0x6e, 0x67, 0x0a, 0x6c, 0x62, 0x68, 0x20, 0x71,
|
||||
0x76, 0x71, 0x61, 0x27, 0x67, 0x2e, 0x20, 0x20, 0x45, 0x72, 0x7a,
|
||||
0x76, 0x61, 0x71, 0x20, 0x72, 0x6b, 0x72, 0x70, 0x68, 0x67, 0x76,
|
||||
0x62, 0x61, 0x20, 0x6a, 0x76, 0x79, 0x79, 0x20, 0x70, 0x62, 0x61,
|
||||
0x67, 0x76, 0x61, 0x68, 0x72, 0x20, 0x7a, 0x62, 0x7a, 0x72, 0x61,
|
||||
0x67, 0x6e, 0x65, 0x76, 0x79, 0x6c, 0x2e, 0x0a, 0x00
|
||||
};
|
||||
|
||||
static void
|
||||
rkrphgvba(int x)
|
||||
{
|
||||
char const *s = (x ? pmsg2 : pmsg1);
|
||||
while(*s) {
|
||||
int c = (int) *s++;
|
||||
c=isalpha(c)?tolower(c)<0x6e?c+13:c-13:c;
|
||||
putchar(c);
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
/* Header file for language support for various languages. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
/* I'm chauvinistic and name each language with its English name... */
|
||||
|
||||
#define ENGLISH 0 /* original by David F. Skoll */
|
||||
#define ENGLISH 0 /* original by Dianne Skoll */
|
||||
#define GERMAN 1 /* translated by Wolfgang Thronicke */
|
||||
#define DUTCH 2 /* translated by Willem Kasdorp and Erik-Jan Vens */
|
||||
#define FINNISH 3 /* translated by Mikko Silvonen */
|
||||
@@ -26,7 +25,7 @@
|
||||
#define SPANISH 11 /* translated by Rafa Couto */
|
||||
#define ICELANDIC 12 /* translated by Björn Davíðsson */
|
||||
|
||||
/* Add more languages here - but please e-mail dfs@roaringpenguin.com
|
||||
/* Add more languages here - but please e-mail dianne@skoll.ca
|
||||
to have your favorite language assigned a number. If you add a
|
||||
language, please send me the header file, and permission to include
|
||||
it in future releases of Remind. Note that you'll get no remuneration
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -100,10 +99,10 @@
|
||||
|
||||
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " om natten" : " om formiddagen" : (hour > 17) ? " om aftenen" : " om eftermiddagen";
|
||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||
#define L_A_OVER 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[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_E_OVER sprintf(s, "den %02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
||||
#define L_F_OVER sprintf(s, "den %02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||
#define L_G_OVER 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[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
||||
#define L_H_OVER sprintf(s, "den %02d%c%02d", d, DateSep, m+1);
|
||||
#define L_I_OVER sprintf(s, "den %02d%c%02d", m+1, DateSep, d);
|
||||
#define L_U_OVER L_A_OVER
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
/* */
|
||||
/* Author: Willem Kasdorp */
|
||||
/* */
|
||||
/* Modified slightly by David Skoll */
|
||||
/* Modified slightly by Dianne Skoll */
|
||||
/* */
|
||||
/* Further corrections by Erik-Jan Vens */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
/* Support for the English language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -161,26 +160,19 @@
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
#define L_A_OVER sprintf(s, "%s%s %d. %s%s %d", DayName[jul%7], L_ON, d, \
|
||||
MonthName[m], L_PARTIT, y);
|
||||
#define L_C_OVER sprintf(s, "%s%s", DayName[jul%7], L_ON);
|
||||
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep, m+1, DateSep, \
|
||||
y);
|
||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s%s %d. %s%s %d", DayName[jul%7], L_ON, d, MonthName[m], L_PARTIT, y); }
|
||||
#define L_C_OVER if (altmode == '*') { sprintf(s, "%s", DayName[jul%7]); } else { sprintf(s, "%s%s", DayName[jul%7], L_ON); }
|
||||
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DateSep, m+1, DateSep, y);
|
||||
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DateSep, d, DateSep, y);
|
||||
#define L_G_OVER sprintf(s, "%s%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[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_H_OVER sprintf(s, "%02d%c%02d", d, DateSep, m+1);
|
||||
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DateSep, d);
|
||||
#define L_J_OVER sprintf(s, "%s%s %sn %d%s %d", DayName[jul%7], L_ON, \
|
||||
MonthName[m], d, plu, y);
|
||||
#define L_K_OVER sprintf(s, "%s%s %sn %d%s", DayName[jul%7], L_ON, \
|
||||
MonthName[m], d, plu);
|
||||
#define L_J_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s %d", DayName[jul%7], MonthName[m], d, plu, y); } else { sprintf(s, "%s%s %sn %d%s %d", DayName[jul%7], L_ON, MonthName[m], d, plu, y); }
|
||||
#define L_K_OVER if (altmode == '*') { sprintf(s, "%s %sn %d%s", DayName[jul%7], MonthName[m], d, plu); } else { sprintf(s, "%s%s %sn %d%s", DayName[jul%7], L_ON, MonthName[m], d, plu); }
|
||||
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DateSep, m+1, DateSep, d);
|
||||
#define L_Q_OVER sprintf(s, "n");
|
||||
#define L_U_OVER sprintf(s, "%s%s %d%s %s%s %d", DayName[jul%7], L_ON, \
|
||||
d, plu, MonthName[m], L_PARTIT, y);
|
||||
#define L_V_OVER sprintf(s, "%s%s %d%s %s%s", DayName[jul%7], L_ON, d, \
|
||||
plu, MonthName[m], L_PARTIT);
|
||||
#define L_U_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s %d", DayName[jul%7], d, plu, MonthName[m], y); } else { sprintf(s, "%s%s %d%s %s%s %d", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT, y); }
|
||||
#define L_V_OVER if (altmode == '*') { sprintf(s, "%s %d%s %s", DayName[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s%s %d%s %s%s", DayName[jul%7], L_ON, d, plu, MonthName[m], L_PARTIT); }
|
||||
#define L_1_OVER \
|
||||
if (tdiff == 0) \
|
||||
sprintf(s, "%s", L_NOW); \
|
||||
@@ -280,7 +272,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\xE4ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\xE4st\xE4 puuttuu aika",
|
||||
"UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"Ep\xE4t\xE4ydellinen p\xE4iv\xE4ys",
|
||||
"FROM/SCANFROM-sanaa k\xE4ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -307,7 +299,11 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n",
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#elif IBMEXTENDED
|
||||
"Ok",
|
||||
@@ -382,7 +378,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\x84ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\x84st\x84 puuttuu aika",
|
||||
"UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"Ep\x84t\x84ydellinen p\x84iv\x84ys",
|
||||
"FROM/SCANFROM-sanaa k\x84ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -409,7 +405,12 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n",
|
||||
"Numero puuttuu"
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#else
|
||||
"Ok",
|
||||
"Puuttuva ']'",
|
||||
@@ -483,7 +484,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k{ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per{st{ puuttuu aika",
|
||||
"UNTIL-sanaa k{ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k{ytetty kahdesti",
|
||||
"Ep{t{ydellinen p{iv{ys",
|
||||
"FROM/SCANFROM-sanaa k{ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -510,7 +511,12 @@ EXTERN char *ErrMsg[] =
|
||||
"%d viesti({) t{m{n p{iv{n jonossa.\n",
|
||||
"Numero puuttuu",
|
||||
"Virheellinen funktio WARN-lausekkeessa",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
@@ -521,8 +527,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||
/* David F. Skoll. */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -129,13 +128,9 @@ else if (tdiff < 0) { \
|
||||
sprintf(s, "dans %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
|
||||
}
|
||||
|
||||
#define L_J_OVER \
|
||||
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[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_K_OVER \
|
||||
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[jul%7], d, plu, MonthName[m]); } else { sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu, MonthName[m]); }
|
||||
|
||||
#endif /* L_IN_DOSUBST */
|
||||
|
||||
@@ -217,7 +212,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour sp\351cifi\351e deux fois",
|
||||
"Mot-cl\351 ONCE utilis\351 deux fois. (Hah.)",
|
||||
"Heure attendue apr\350s AT",
|
||||
"Mot-cl\351 UNTIL utilis\351 deux fois",
|
||||
"Mot-cl\351 THROUGH/UNTIL utilis\351 deux fois",
|
||||
"Sp\351cification de date incompl\350te",
|
||||
"Mot-cl\351 FROM/SCANFROM utilis\351 deux fois",
|
||||
"Variable",
|
||||
@@ -244,7 +239,12 @@ EXTERN char *ErrMsg[] =
|
||||
"%d rappel(s) en file pour aujourd'hui.\n",
|
||||
"Nombre attendu",
|
||||
"Fonction ill\351gale apr\350s WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#else /* ISOLATIN1 */
|
||||
"Ok",
|
||||
"']' manquant",
|
||||
@@ -318,7 +318,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour specifiee deux fois",
|
||||
"Mot-cle ONCE utilise deux fois. (Hah.)",
|
||||
"Heure attendue apres AT",
|
||||
"Mot-cle UNTIL utilise deux fois",
|
||||
"Mot-cle THROUGH/UNTIL utilise deux fois",
|
||||
"Specification de date incomplete",
|
||||
"Mot-cle FROM/SCANFROM utilise deux fois",
|
||||
"Variable",
|
||||
@@ -345,7 +345,11 @@ EXTERN char *ErrMsg[] =
|
||||
"%d rappel(s) en file pour aujourd'hui.\n",
|
||||
"Nombre attendu",
|
||||
"Fonction illegale apres WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
@@ -355,8 +359,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
/* I don't speak German. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -93,8 +92,8 @@
|
||||
See the file dosubst.c for more info. */
|
||||
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
|
||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||
#define L_A_OVER sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
|
||||
#define L_G_OVER sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
|
||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
||||
#define L_U_OVER L_A_OVER
|
||||
#define L_V_OVER L_G_OVER
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
/* Support for the Icelandic language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
/* This file is part of REMIND. */
|
||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||
/* */
|
||||
/* Remind is copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||
/* Remind is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -101,8 +100,8 @@
|
||||
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
|
||||
See the file dosubst.c for more info. */
|
||||
#define L_ORDINAL_OVERRIDE plu = ".";
|
||||
#define L_A_OVER sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
|
||||
#define L_G_OVER sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
|
||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, den %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
||||
#define L_U_OVER L_A_OVER
|
||||
#define L_V_OVER L_G_OVER
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
/* Polish. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -141,8 +140,8 @@ ampm = (hour<12) ? \
|
||||
: " w nocy";
|
||||
#endif
|
||||
#define L_ORDINAL_OVERRIDE plu = "";
|
||||
#define L_A_OVER sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
|
||||
#define L_G_OVER sprintf(s, "%s %s, %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
|
||||
#define L_A_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s %d", DayName[jul%7], d, MonthName[m], y); } else { sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y); }
|
||||
#define L_G_OVER if (altmode == '*') { sprintf(s, "%s, %d. %s", DayName[jul%7], d, MonthName[m]); } else { sprintf(s, "%s %s, %d. %s", L_ON, DayName[jul%7], d, MonthName[m]); }
|
||||
#define L_U_OVER L_A_OVER
|
||||
#define L_V_OVER L_G_OVER
|
||||
|
||||
@@ -252,7 +251,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Warto\266\346 cofni\352cia podana dw\363krotnie",
|
||||
"S\263owo ONCE u\277yte dw\363krotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"S\263owo UNTIL u\277yte dw\363krotnie",
|
||||
"S\263owo THROUGH/UNTIL u\277yte dw\363krotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"S\263owo FROM/SCANFROM u\277yte dw\363krotnie",
|
||||
"Zmienna",
|
||||
@@ -279,7 +278,11 @@ EXTERN char *ErrMsg[] =
|
||||
"%d Przypomnienia zakolejkowane na p\363\274niej.\n",
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#else /* ISOLATIN1 */
|
||||
"OK",
|
||||
"Brakujacy ']'",
|
||||
@@ -353,7 +356,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Wartosc cofniecia podana dwokrotnie",
|
||||
"Slowo ONCE uzyte dwokrotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"Slowo UNTIL uzyte dwokrotnie",
|
||||
"Slowo THROUGH/UNTIL uzyte dwokrotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"Slowo FROM/SCANFROM uzyte dwokrotnie",
|
||||
"Zmienna",
|
||||
@@ -380,7 +383,11 @@ EXTERN char *ErrMsg[] =
|
||||
"%d Przypomnienia zakolejkowane na pozniej.\n",
|
||||
"Spodziewana liczba",
|
||||
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
@@ -390,8 +397,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "Copyright 1999-2000 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||
/* David F. Skoll. */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -218,7 +217,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valor de Back especificado duas vezes",
|
||||
"ONCE usado duas vezes (Eheheh)",
|
||||
"Esperando hora apos AT",
|
||||
"Keyword UNTIL usada duas vezes",
|
||||
"Keyword THROUGH/UNTIL usada duas vezes",
|
||||
"Especificacao de data incompleta",
|
||||
"Keyword FROM/SCANFROM usada duas vezes",
|
||||
"Variavel",
|
||||
@@ -245,7 +244,11 @@ EXTERN char *ErrMsg[] =
|
||||
"%d compromisso(s) colocados na fila para mais tarde.\n",
|
||||
"Esperando numero",
|
||||
"Funcao ilegal na clausula WARN",
|
||||
"Can't convert between time zones"
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -254,8 +257,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "(C) 1999-2000 Roaring Penguin Software Inc.\n");
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -42,7 +41,7 @@
|
||||
#define L_JUL "Julio"
|
||||
#define L_AUG "Agosto"
|
||||
#define L_SEP "Septiembre"
|
||||
#define L_OCT "Octuber"
|
||||
#define L_OCT "Octubre"
|
||||
#define L_NOV "Noviembre"
|
||||
#define L_DEC "Diciembre"
|
||||
|
||||
|
||||
255
src/main.c
255
src/main.c
@@ -6,8 +6,7 @@
|
||||
/* routines, etc. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -19,6 +18,9 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
@@ -57,19 +59,31 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int pid;
|
||||
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
ErrFp = stderr;
|
||||
|
||||
/* Set up global vars */
|
||||
/* Set up global vars */
|
||||
ArgC = argc;
|
||||
ArgV = argv;
|
||||
ArgV = (char const **) argv;
|
||||
|
||||
InitRemind(argc, (char const **) argv);
|
||||
ClearLastTriggers();
|
||||
|
||||
InitRemind(argc, argv);
|
||||
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
||||
ProduceCalendar();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Are we purging old reminders? Then just run through the loop once! */
|
||||
if (PurgeMode) {
|
||||
DoReminders();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not doing a calendar. Do the regular remind loop */
|
||||
ShouldCache = (Iterations > 1);
|
||||
|
||||
@@ -117,12 +131,24 @@ int main(int argc, char *argv[])
|
||||
DestroyOmitContexts();
|
||||
DestroyVars(0);
|
||||
NumTriggered = 0;
|
||||
ClearLastTriggers();
|
||||
JulianToday++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PurgeEchoLine(char const *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
if (PurgeFP != NULL) {
|
||||
(void) vfprintf(PurgeFP, fmt, argptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoReminders */
|
||||
@@ -134,8 +160,9 @@ static void DoReminders(void)
|
||||
{
|
||||
int r;
|
||||
Token tok;
|
||||
char *s;
|
||||
char const *s;
|
||||
Parser p;
|
||||
int purge_handled;
|
||||
|
||||
if (!UseStdin) {
|
||||
FileAccessDate = GetAccessDate(InitialFile);
|
||||
@@ -148,7 +175,7 @@ static void DoReminders(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
r=OpenFile(InitialFile);
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
||||
InitialFile, ErrMsg[r]);
|
||||
@@ -173,23 +200,40 @@ static void DoReminders(void)
|
||||
ShouldIgnoreLine())
|
||||
{
|
||||
/*** IGNORE THE LINE ***/
|
||||
if (PurgeMode) {
|
||||
if (strncmp(CurLine, "#!P", 3)) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
purge_handled = 0;
|
||||
/* Create a parser to parse the line */
|
||||
CreateParser(s, &p);
|
||||
switch(tok.type) {
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
if (!strncmp(CurLine, "#!P", 3)) {
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_Rem: r=DoRem(&p); break;
|
||||
case T_Rem: r=DoRem(&p); purge_handled = 1; break;
|
||||
case T_ErrMsg: r=DoErrMsg(&p); break;
|
||||
case T_If: r=DoIf(&p); break;
|
||||
case T_IfTrig: r=DoIfTrig(&p); break;
|
||||
case T_Else: r=DoElse(&p); break;
|
||||
case T_EndIf: r=DoEndif(&p); break;
|
||||
case T_Include: r=DoInclude(&p); break;
|
||||
case T_Include:
|
||||
/* In purge mode, include closes file, so we
|
||||
need to echo it here! */
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
r=DoInclude(&p);
|
||||
purge_handled = 1;
|
||||
break;
|
||||
case T_Exit: DoExit(&p); break;
|
||||
case T_Flush: r=DoFlush(&p); break;
|
||||
case T_Set: r=DoSet(&p); break;
|
||||
@@ -204,32 +248,42 @@ static void DoReminders(void)
|
||||
DestroyParser(&p);
|
||||
CreateParser(s, &p);
|
||||
r=DoRem(&p);
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
case T_Pop: r=PopOmitContext(&p); break;
|
||||
case T_Preserve: r=DoPreserve(&p); break;
|
||||
case T_Push: r=PushOmitContext(&p); break;
|
||||
case T_RemType: if (tok.val == RUN_TYPE) {
|
||||
r=DoRun(&p);
|
||||
r=DoRun(&p);
|
||||
} else {
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoRem(&p);
|
||||
purge_handled = 1;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
CreateParser(CurLine, &p);
|
||||
r=DoRem(&p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If we don't recognize the command, do a REM by default */
|
||||
/* Note: Since the parser hasn't been used yet, we don't */
|
||||
/* need to destroy it here. */
|
||||
|
||||
default: CreateParser(CurLine, &p); r=DoRem(&p); break;
|
||||
default: CreateParser(CurLine, &p); purge_handled = 1; r=DoRem(&p); break;
|
||||
|
||||
}
|
||||
if (r && (!Hush || r != E_RUN_DISABLED)) {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
|
||||
if (PurgeMode) {
|
||||
if (!purge_handled) {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
} else {
|
||||
if (r) {
|
||||
PurgeEchoLine("#!P! Could not parse next line: %s\n", ErrMsg[r]);
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Destroy the parser - free up resources it may be tying up */
|
||||
DestroyParser(&p);
|
||||
}
|
||||
@@ -330,7 +384,7 @@ int ParseChar(ParsePtr p, int *err, int peek)
|
||||
return *(p->epos++);
|
||||
}
|
||||
}
|
||||
free(p->etext); /* End of substituted expression */
|
||||
free((void *) p->etext); /* End of substituted expression */
|
||||
p->etext = NULL;
|
||||
p->epos = NULL;
|
||||
p->isnested = 0;
|
||||
@@ -345,8 +399,9 @@ int ParseChar(ParsePtr p, int *err, int peek)
|
||||
return *(p->pos++);
|
||||
}
|
||||
}
|
||||
p->expr_happened = 1;
|
||||
p->pos++;
|
||||
r = EvalExpr(&(p->pos), &val);
|
||||
r = EvalExpr(&(p->pos), &val, p);
|
||||
if (r) {
|
||||
*err = r;
|
||||
DestroyParser(p);
|
||||
@@ -382,7 +437,7 @@ int ParseNonSpaceChar(ParsePtr p, int *err, int peek)
|
||||
ch = ParseChar(p, err, 1);
|
||||
if (*err) return 0;
|
||||
|
||||
while (isspace(ch)) {
|
||||
while (isempty(ch)) {
|
||||
ParseChar(p, err, 0); /* Guaranteed to work */
|
||||
ch = ParseChar(p, err, 1);
|
||||
if (*err) return 0;
|
||||
@@ -406,12 +461,12 @@ int ParseToken(ParsePtr p, DynamicBuffer *dbuf)
|
||||
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (c && isspace(c)) {
|
||||
while (c && isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
if (!c) return OK;
|
||||
while (c && !isspace(c)) {
|
||||
while (c && !isempty(c)) {
|
||||
if (DBufPutc(dbuf, c) != OK) {
|
||||
DBufFree(dbuf);
|
||||
return E_NO_MEM;
|
||||
@@ -442,7 +497,7 @@ int ParseIdentifier(ParsePtr p, DynamicBuffer *dbuf)
|
||||
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (c && isspace(c)) {
|
||||
while (c && isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
@@ -483,13 +538,13 @@ int EvaluateExpr(ParsePtr p, Value *v)
|
||||
int r;
|
||||
|
||||
if (p->isnested) return E_PARSE_ERR; /* Can't nest expressions */
|
||||
while (isspace(*p->pos)) (p->pos)++;
|
||||
while (isempty(*p->pos)) (p->pos)++;
|
||||
if (!p->pos) return E_PARSE_ERR; /* Missing expression */
|
||||
if (*p->pos == BEG_OF_EXPR) {
|
||||
(p->pos)++;
|
||||
bracketed = 1;
|
||||
}
|
||||
r = EvalExpr(&(p->pos), v);
|
||||
r = EvalExpr(&(p->pos), v, p);
|
||||
if (r) return r;
|
||||
if (bracketed) {
|
||||
if (*p->pos != END_OF_EXPR) return E_MISS_END;
|
||||
@@ -503,21 +558,23 @@ int EvaluateExpr(ParsePtr p, Value *v)
|
||||
/* Eprint - print an error message. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void Eprint(const char *fmt, ...)
|
||||
void Eprint(char const *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
/* Check if more than one error msg. from this line */
|
||||
if (!FreshLine && !ShowAllErrors) return;
|
||||
|
||||
if (FreshLine) {
|
||||
if (FreshLine && FileName) {
|
||||
FreshLine = 0;
|
||||
if (strcmp(FileName, "-"))
|
||||
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
|
||||
else
|
||||
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
|
||||
if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
|
||||
} else fprintf(ErrFp, " ");
|
||||
} else if (FileName) {
|
||||
fprintf(ErrFp, " ");
|
||||
}
|
||||
|
||||
va_start(argptr, fmt);
|
||||
(void) vfprintf(ErrFp, fmt, argptr);
|
||||
@@ -536,8 +593,8 @@ void Eprint(const char *fmt, ...)
|
||||
/***************************************************************/
|
||||
void OutputLine(FILE *fp)
|
||||
{
|
||||
register char *s = CurLine;
|
||||
register char c = 0;
|
||||
char const *s = CurLine;
|
||||
char c = 0;
|
||||
|
||||
while (*s) {
|
||||
if (*s == '\n') Putc('\\', fp);
|
||||
@@ -554,7 +611,7 @@ void OutputLine(FILE *fp)
|
||||
/* Create a parser given a string buffer */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void CreateParser(char *s, ParsePtr p)
|
||||
void CreateParser(char const *s, ParsePtr p)
|
||||
{
|
||||
p->text = s;
|
||||
p->pos = s;
|
||||
@@ -563,6 +620,8 @@ void CreateParser(char *s, ParsePtr p)
|
||||
p->etext = NULL;
|
||||
p->allownested = 1;
|
||||
p->tokenPushed = NULL;
|
||||
p->expr_happened = 0;
|
||||
p->nonconst_expr = 0;
|
||||
DBufInit(&p->pushedToken);
|
||||
}
|
||||
|
||||
@@ -576,7 +635,7 @@ void CreateParser(char *s, ParsePtr p)
|
||||
void DestroyParser(ParsePtr p)
|
||||
{
|
||||
if (p->isnested && p->etext) {
|
||||
free(p->etext);
|
||||
free((void *) p->etext);
|
||||
p->etext = NULL;
|
||||
p->isnested = 0;
|
||||
}
|
||||
@@ -589,10 +648,10 @@ void DestroyParser(ParsePtr p)
|
||||
/* on a per-parser basis. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int PushToken(const char *tok, ParsePtr p)
|
||||
int PushToken(char const *tok, ParsePtr p)
|
||||
{
|
||||
DBufFree(&p->pushedToken);
|
||||
if (DBufPuts(&p->pushedToken, (char *) tok) != OK ||
|
||||
if (DBufPuts(&p->pushedToken, tok) != OK ||
|
||||
DBufPutc(&p->pushedToken, ' ') != OK) {
|
||||
DBufFree(&p->pushedToken);
|
||||
return E_NO_MEM;
|
||||
@@ -657,7 +716,7 @@ int DoIf(ParsePtr p)
|
||||
int r;
|
||||
unsigned syndrome;
|
||||
|
||||
if (NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
|
||||
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
@@ -666,10 +725,15 @@ int DoIf(ParsePtr p)
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
} else
|
||||
if ( (v.type != STR_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && strcmp(v.v.str, "")) )
|
||||
(v.type == STR_TYPE && strcmp(v.v.str, "")) ) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
} else {
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s\n", "#!P: The next IF evaluated false...");
|
||||
PurgeEchoLine("%s\n", "#!P: REM statements in IF block not checked for purging.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NumIfs++;
|
||||
@@ -689,6 +753,8 @@ int DoElse(ParsePtr p)
|
||||
{
|
||||
unsigned syndrome;
|
||||
|
||||
int was_ignoring = ShouldIgnoreLine();
|
||||
|
||||
if (!NumIfs) return E_ELSE_NO_IF;
|
||||
|
||||
syndrome = IfFlags >> (2 * NumIfs - 2);
|
||||
@@ -696,6 +762,10 @@ int DoElse(ParsePtr p)
|
||||
if ((syndrome & IF_ELSE_MASK) == AFTER_ELSE) return E_ELSE_NO_IF;
|
||||
|
||||
IfFlags |= AFTER_ELSE << (2 * NumIfs - 2);
|
||||
if (PurgeMode && ShouldIgnoreLine() && !was_ignoring) {
|
||||
PurgeEchoLine("%s\n", "#!P: The previous IF evaluated true.");
|
||||
PurgeEchoLine("%s\n", "#!P: REM statements in ELSE block not checked for purging");
|
||||
}
|
||||
return VerifyEoln(p);
|
||||
}
|
||||
|
||||
@@ -720,26 +790,37 @@ int DoEndif(ParsePtr p)
|
||||
/***************************************************************/
|
||||
int DoIfTrig(ParsePtr p)
|
||||
{
|
||||
int r;
|
||||
int r, err;
|
||||
unsigned syndrome;
|
||||
Trigger trig;
|
||||
TimeTrig tim;
|
||||
int jul;
|
||||
|
||||
|
||||
if (NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
if ((size_t) NumIfs >= IF_NEST) return E_NESTED_IF;
|
||||
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
|
||||
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul))
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
else
|
||||
syndrome = IF_FALSE | BEFORE_ELSE;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (!Hush || r != E_RUN_DISABLED) {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
}
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
} 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
}
|
||||
NumIfs++;
|
||||
IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
|
||||
@@ -859,6 +940,11 @@ int DoDebug(ParsePtr p)
|
||||
else DebugFlag &= ~DB_PRTLINE;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
if (val) DebugFlag |= DB_TRACE_FILES;
|
||||
else DebugFlag &= ~DB_TRACE_FILES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -880,7 +966,7 @@ int DoBanner(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
while (isspace(c)) {
|
||||
while (isempty(c)) {
|
||||
c = ParseChar(p, &err, 0);
|
||||
if (err) return err;
|
||||
}
|
||||
@@ -960,6 +1046,8 @@ void DoExit(ParsePtr p)
|
||||
int r;
|
||||
Value v;
|
||||
|
||||
if (PurgeMode) return;
|
||||
|
||||
r = EvaluateExpr(p, &v);
|
||||
if (r || v.type != INT_TYPE) exit(99);
|
||||
exit(v.v.val);
|
||||
@@ -977,10 +1065,12 @@ int DoErrMsg(ParsePtr p)
|
||||
TimeTrig tt;
|
||||
Trigger t;
|
||||
int r;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
DynamicBuffer buf;
|
||||
|
||||
if (PurgeMode) return OK;
|
||||
|
||||
DBufInit(&buf);
|
||||
t.typ = MSG_TYPE;
|
||||
tt.ttime = SystemTime(0) / 60;
|
||||
@@ -988,7 +1078,7 @@ int DoErrMsg(ParsePtr p)
|
||||
return r;
|
||||
}
|
||||
s = DBufValue(&buf);
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
fprintf(ErrFp, "%s\n", s);
|
||||
DBufFree(&buf);
|
||||
return OK;
|
||||
@@ -1079,7 +1169,7 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
|
||||
/* A macro safe ONLY if used with arg with no side effects! */
|
||||
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
||||
|
||||
void FillParagraph(char *s)
|
||||
void FillParagraph(char const *s)
|
||||
{
|
||||
|
||||
int line = 0;
|
||||
@@ -1087,7 +1177,7 @@ void FillParagraph(char *s)
|
||||
int doublespace = 1;
|
||||
int pendspace;
|
||||
int len;
|
||||
char *t;
|
||||
char const *t;
|
||||
|
||||
int roomleft;
|
||||
|
||||
@@ -1220,7 +1310,66 @@ void UTCToLocal(int utcdate, int utctime, int *locdate, int *loctime)
|
||||
|
||||
void SigIntHandler(int d)
|
||||
{
|
||||
UNUSED(d);
|
||||
signal(SIGINT, SigIntHandler);
|
||||
GotSigInt();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
AppendTag(DynamicBuffer *buf, char const *s)
|
||||
{
|
||||
if (*(DBufValue(buf))) {
|
||||
DBufPutc(buf, ',');
|
||||
}
|
||||
DBufPuts(buf, s);
|
||||
}
|
||||
|
||||
void
|
||||
FreeTrig(Trigger *t)
|
||||
{
|
||||
DBufFree(&(t->tags));
|
||||
}
|
||||
|
||||
void
|
||||
ClearLastTriggers(void)
|
||||
{
|
||||
LastTrigger.expired = 0;
|
||||
LastTrigger.wd = NO_WD;
|
||||
LastTrigger.d = NO_DAY;
|
||||
LastTrigger.m = NO_MON;
|
||||
LastTrigger.y = NO_YR;
|
||||
LastTrigger.back = NO_BACK;
|
||||
LastTrigger.delta = NO_DELTA;
|
||||
LastTrigger.rep = NO_REP;
|
||||
LastTrigger.localomit = NO_WD;
|
||||
LastTrigger.skip = NO_SKIP;
|
||||
LastTrigger.until = NO_UNTIL;
|
||||
LastTrigger.typ = NO_TYPE;
|
||||
LastTrigger.once = NO_ONCE;
|
||||
LastTrigger.scanfrom = NO_DATE;
|
||||
LastTrigger.from = NO_DATE;
|
||||
LastTrigger.priority = DefaultPrio;
|
||||
LastTrigger.sched[0] = 0;
|
||||
LastTrigger.warn[0] = 0;
|
||||
LastTrigger.omitfunc[0] = 0;
|
||||
LastTrigger.passthru[0] = 0;
|
||||
|
||||
LastTimeTrig.ttime = NO_TIME;
|
||||
LastTimeTrig.delta = NO_DELTA;
|
||||
LastTimeTrig.rep = NO_REP;
|
||||
LastTimeTrig.duration = NO_TIME;
|
||||
}
|
||||
|
||||
void
|
||||
SaveLastTrigger(Trigger const *t)
|
||||
{
|
||||
memcpy(&LastTrigger, t, sizeof(LastTrigger));
|
||||
DBufInit(&(LastTrigger.tags));
|
||||
}
|
||||
|
||||
void
|
||||
SaveLastTimeTrig(TimeTrig const *t)
|
||||
{
|
||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
MD5Transform(ctx->buf, (uint32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
#ifndef ASM_MD5
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
/* Calculations for figuring out moon phases. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
204
src/omit.c
204
src/omit.c
@@ -6,8 +6,7 @@
|
||||
/* the data structures for OMITted dates. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -20,6 +19,7 @@
|
||||
#include "protos.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "expr.h"
|
||||
|
||||
static int BexistsIntArray (int array[], int num, int key);
|
||||
static void InsertIntoSortedArray (int *array, int num, int key);
|
||||
@@ -113,18 +113,18 @@ int PushOmitContext(ParsePtr p)
|
||||
|
||||
context->numfull = NumFullOmits;
|
||||
context->numpart = NumPartialOmits;
|
||||
context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
|
||||
context->fullsave = malloc(NumFullOmits * sizeof(int));
|
||||
if (NumFullOmits && !context->fullsave) {
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
|
||||
context->partsave = malloc(NumPartialOmits * sizeof(int));
|
||||
if (NumPartialOmits && !context->partsave) {
|
||||
free(context->fullsave);
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the context over */
|
||||
for (i=0; i<NumFullOmits; i++)
|
||||
*(context->fullsave + i) = FullOmitArray[i];
|
||||
@@ -177,26 +177,57 @@ int PopOmitContext(ParsePtr p)
|
||||
/* */
|
||||
/* IsOmitted */
|
||||
/* */
|
||||
/* Return non-zero if date is OMITted, zero if it is not. */
|
||||
/* Set *omit to non-zero if date is omitted, else 0. Returns */
|
||||
/* OK or an error code. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int IsOmitted(int jul, int localomit)
|
||||
int IsOmitted(int jul, int localomit, char const *omitfunc, int *omit)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
/* If we have an omitfunc, we *only* use it and ignore local/global
|
||||
OMITs */
|
||||
if (omitfunc && *omitfunc && UserFuncExists(omitfunc)) {
|
||||
char expr[VAR_NAME_LEN + 32];
|
||||
char const *s;
|
||||
int r;
|
||||
Value v;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
sprintf(expr, "%s('%04d-%02d-%02d')",
|
||||
omitfunc, y, m+1, d);
|
||||
s = expr;
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) return r;
|
||||
if (v.type == INT_TYPE && v.v.val != 0) {
|
||||
*omit = 1;
|
||||
} else {
|
||||
*omit = 0;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of local omits? */
|
||||
if (localomit & (1 << (jul % 7))) return 1;
|
||||
if (localomit & (1 << (jul % 7))) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Is it omitted because of fully-specified omits? */
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
|
||||
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Get the syndrome */
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
|
||||
return 1;
|
||||
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
|
||||
*omit = 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Not omitted */
|
||||
return 0;
|
||||
*omit = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -240,6 +271,9 @@ static void InsertIntoSortedArray(int *array, int num, int key)
|
||||
*cur = key;
|
||||
}
|
||||
|
||||
static int DoThroughOmit(ParsePtr p, int y, int m, int d);
|
||||
static void DumpOmits(void);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoOmit */
|
||||
@@ -253,15 +287,33 @@ int DoOmit(ParsePtr p)
|
||||
Token tok;
|
||||
int parsing=1;
|
||||
int syndrome;
|
||||
int not_first_token = -1;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the OMIT. We need a month and day; year is optional. */
|
||||
while(parsing) {
|
||||
not_first_token++;
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch (tok.type) {
|
||||
case T_Dumpvars:
|
||||
if (not_first_token) return E_PARSE_ERR;
|
||||
DBufFree(&buf);
|
||||
r = VerifyEoln(p);
|
||||
if (r != OK) return r;
|
||||
DumpOmits();
|
||||
return OK;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
if (m != NO_MON) return E_MON_TWICE;
|
||||
if (d != NO_DAY) return E_DAY_TWICE;
|
||||
FromJulian(tok.val, &y, &m, &d);
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
@@ -279,11 +331,16 @@ int DoOmit(ParsePtr p)
|
||||
if (d != NO_DAY) return E_DAY_TWICE;
|
||||
d = tok.val;
|
||||
break;
|
||||
|
||||
|
||||
case T_Delta:
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) return E_INCOMPLETE;
|
||||
return DoThroughOmit(p, y, m, d);
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
@@ -322,7 +379,124 @@ int DoOmit(ParsePtr p)
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
|
||||
{
|
||||
int yend = NO_YR, mend = NO_MON, dend = NO_DAY, r;
|
||||
int start, end, tmp;
|
||||
int parsing = 1;
|
||||
|
||||
Token tok;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
while(parsing) {
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
|
||||
switch(tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
FromJulian(tok.val, ¥d, &mend, &dend);
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
yend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
DBufFree(&buf);
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
mend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
DBufFree(&buf);
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
dend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
case T_Priority:
|
||||
case T_Tag:
|
||||
case T_Duration:
|
||||
DBufFree(&buf);
|
||||
parsing = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
||||
DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return E_UNKNOWN_TOKEN;
|
||||
|
||||
}
|
||||
}
|
||||
if (yend == NO_YR || mend == NO_MON || dend == NO_DAY) return E_INCOMPLETE;
|
||||
if (dend > DaysInMonth(mend, yend)) return E_BAD_DATE;
|
||||
if (dstart > DaysInMonth(mstart, ystart)) return E_BAD_DATE;
|
||||
|
||||
start = Julian(ystart, mstart, dstart);
|
||||
end = Julian(yend, mend, dend);
|
||||
|
||||
if (end < start) {
|
||||
Eprint("Warning: Swapping dates on OMIT ... THROUGH ... line");
|
||||
tmp = start;
|
||||
start = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
tmp = end - start + 1;
|
||||
|
||||
/* Don't create any OMITs if there would be too many. */
|
||||
if (NumFullOmits + tmp >= MAX_FULL_OMITS) return E_2MANY_FULL;
|
||||
for (tmp = start; tmp <= end; tmp++) {
|
||||
if (!BexistsIntArray(FullOmitArray, NumFullOmits, tmp)) {
|
||||
InsertIntoSortedArray(FullOmitArray, NumFullOmits, tmp);
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void
|
||||
DumpOmits(void)
|
||||
{
|
||||
int i;
|
||||
int y, m, d;
|
||||
printf("Global Full OMITs (%d of maximum allowed %d):\n", NumFullOmits, MAX_FULL_OMITS);
|
||||
if (!NumFullOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumFullOmits; i++) {
|
||||
FromJulian(FullOmitArray[i], &y, &m, &d);
|
||||
printf("\t%04d%c%02d%c%02d\n",
|
||||
y, DateSep, m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
printf("Global Partial OMITs (%d of maximum allowed %d):\n", NumPartialOmits, MAX_PARTIAL_OMITS);
|
||||
if (!NumPartialOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumPartialOmits; i++) {
|
||||
m = PartialOmitArray[i] >> 5 & 0xf;
|
||||
d = PartialOmitArray[i] & 0x1f;
|
||||
printf("\t%02d%c%02d\n", m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
121
src/protos.h
121
src/protos.h
@@ -5,60 +5,65 @@
|
||||
/* Function Prototypes. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
/* Suppress unused variable warnings */
|
||||
#define UNUSED(x) (void) x
|
||||
|
||||
/* Define a string assignment macro - be careful!!! */
|
||||
#define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); }
|
||||
|
||||
/* Define a general malloc routine for creating pointers to objects */
|
||||
#define NEW(type) ((type *) malloc(sizeof(type)))
|
||||
#define NEW(type) (malloc(sizeof(type)))
|
||||
|
||||
/* Characters to ignore */
|
||||
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
||||
|
||||
#include "dynbuf.h"
|
||||
|
||||
int CallUserFunc (char *name, int nargs);
|
||||
int CallUserFunc (char const *name, int nargs, ParsePtr p);
|
||||
int DoFset (ParsePtr p);
|
||||
void ProduceCalendar (void);
|
||||
char *SimpleTime (int tim);
|
||||
char const *SimpleTime (int tim);
|
||||
char const *CalendarTime (int tim, int duration);
|
||||
int DoRem (ParsePtr p);
|
||||
int DoFlush (ParsePtr p);
|
||||
void DoExit (ParsePtr p);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim);
|
||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul);
|
||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int jul, int *err);
|
||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
|
||||
int DoSubstFromString (char *source, DynamicBuffer *dbuf, int jul, int tim);
|
||||
int EvalExpr (char **e, Value *v);
|
||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
|
||||
int ParseLiteralDate (char const **s, int *jul, int *tim);
|
||||
int EvalExpr (char const **e, Value *v, ParsePtr p);
|
||||
int DoCoerce (char type, Value *v);
|
||||
void PrintValue (Value *v, FILE *fp);
|
||||
int CopyValue (Value *dest, const Value *src);
|
||||
int ReadLine (void);
|
||||
int OpenFile (const char *fname);
|
||||
int PopFile (void);
|
||||
int OpenFile (char const *fname);
|
||||
int DoInclude (ParsePtr p);
|
||||
int IncludeFile (const char *fname);
|
||||
int GetAccessDate (char *file);
|
||||
int SetAccessDate (char *fname, int jul);
|
||||
int IncludeFile (char const *fname);
|
||||
int GetAccessDate (char const *file);
|
||||
int SetAccessDate (char const *fname, int jul);
|
||||
int TopLevel (void);
|
||||
int CallFunc (Operator *f, int nargs);
|
||||
void InitRemind (int argc, char *argv[]);
|
||||
int CallFunc (BuiltinFunc *f, int nargs);
|
||||
void InitRemind (int argc, char const *argv[]);
|
||||
void Usage (void);
|
||||
int main (int argc, char *argv[]);
|
||||
int Julian (int year, int month, int day);
|
||||
void FromJulian (int jul, int *y, int *m, int *d);
|
||||
int ParseChar (ParsePtr p, int *err, int peek);
|
||||
int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
|
||||
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
|
||||
int EvaluateExpr (ParsePtr p, Value *v);
|
||||
int Evaluate (char **s, Var *locals);
|
||||
int Evaluate (char const **s, Var *locals, ParsePtr p);
|
||||
int FnPopValStack (Value *val);
|
||||
void Eprint (const char *fmt, ...);
|
||||
void Eprint (char const *fmt, ...);
|
||||
void OutputLine (FILE *fp);
|
||||
void CreateParser (char *s, ParsePtr p);
|
||||
void CreateParser (char const *s, ParsePtr p);
|
||||
void DestroyParser (ParsePtr p);
|
||||
int PushToken (const char *tok, ParsePtr p);
|
||||
int PushToken (char const *tok, ParsePtr p);
|
||||
long SystemTime (int realtime);
|
||||
int SystemDate (int *y, int *m, int *d);
|
||||
int DoIf (ParsePtr p);
|
||||
@@ -76,60 +81,70 @@ int DoClear (ParsePtr p);
|
||||
int DestroyOmitContexts (void);
|
||||
int PushOmitContext (ParsePtr p);
|
||||
int PopOmitContext (ParsePtr p);
|
||||
int IsOmitted (int jul, int localomit);
|
||||
int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
|
||||
int DoOmit (ParsePtr p);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, const char *sched);
|
||||
int QueueReminder (ParsePtr p, Trigger *trig, TimeTrig *tim, char const *sched);
|
||||
void HandleQueuedReminders (void);
|
||||
char *FindInitialToken (Token *tok, char *s);
|
||||
void FindToken (const char *s, Token *tok);
|
||||
void FindNumericToken (const char *s, Token *t);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err);
|
||||
char *StrnCpy (char *dest, const char *source, int n);
|
||||
int StrMatch (const char *s1, const char *s2, int n);
|
||||
int StrinCmp (const char *s1, const char *s2, int n);
|
||||
char *StrDup (const char *s);
|
||||
int StrCmpi (const char *s1, const char *s2);
|
||||
Var *FindVar (const char *str, int create);
|
||||
int DeleteVar (const char *str);
|
||||
int SetVar (const char *str, Value *val);
|
||||
int GetVarValue (const char *str, Value *val, Var *locals);
|
||||
char const *FindInitialToken (Token *tok, char const *s);
|
||||
void FindToken (char const *s, Token *tok);
|
||||
void FindNumericToken (char const *s, Token *t);
|
||||
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
||||
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
||||
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
int StrMatch (char const *s1, char const *s2, int n);
|
||||
int StrinCmp (char const *s1, char const *s2, int n);
|
||||
char *StrDup (char const *s);
|
||||
int StrCmpi (char const *s1, char const *s2);
|
||||
Var *FindVar (char const *str, int create);
|
||||
int DeleteVar (char const *str);
|
||||
int SetVar (char const *str, Value *val);
|
||||
int GetVarValue (char const *str, Value *val, Var *locals, ParsePtr p);
|
||||
int DoSet (Parser *p);
|
||||
int DoUnset (Parser *p);
|
||||
int DoDump (ParsePtr p);
|
||||
void DumpVarTable (void);
|
||||
void DestroyVars (int all);
|
||||
int PreserveVar (char *name);
|
||||
int PreserveVar (char const *name);
|
||||
int DoPreserve (Parser *p);
|
||||
int DoSatRemind (Trigger *trig, TimeTrig *tim, ParsePtr p);
|
||||
int DoMsgCommand (char *cmd, char *msg);
|
||||
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
||||
int DoMsgCommand (char const *cmd, char const *msg);
|
||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||
unsigned int HashVal (const char *str);
|
||||
unsigned int HashVal (char const *str);
|
||||
int DateOK (int y, int m, int d);
|
||||
Operator *FindFunc (char *name, Operator where[], int num);
|
||||
int InsertIntoSortBuffer (int jul, int tim, char *body, int typ, int prio);
|
||||
void IssueSortedReminders (void);
|
||||
int UserFuncExists (char *fn);
|
||||
Operator *FindOperator (char const *name, Operator where[], int num);
|
||||
BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
|
||||
int InsertIntoSortBuffer (int jul, int tim, char const *body, int typ, int prio);
|
||||
void IssueSortedReminders (void);
|
||||
int UserFuncExists (char const *fn);
|
||||
void JulToHeb (int jul, int *hy, int *hm, int *hd);
|
||||
int HebNameToNum (const char *mname);
|
||||
char *HebMonthName (int m, int y);
|
||||
int HebNameToNum (char const *mname);
|
||||
char const *HebMonthName (int m, int y);
|
||||
int RoshHashana (int i);
|
||||
long DaysToHebYear (int y);
|
||||
int DaysInHebYear (int y);
|
||||
char *DaysInHebMonths (int ylen);
|
||||
char const *DaysInHebMonths (int ylen);
|
||||
int HebToJul (int hy, int hm, int hd);
|
||||
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
|
||||
int GetNextHebrewDate (int julstart, int hm, int hd, int yahr, int adarbehave, int *ans);
|
||||
int ComputeJahr (int y, int m, int d, int *ans);
|
||||
int GetSysVar (const char *name, Value *val);
|
||||
int SetSysVar (const char *name, Value *val);
|
||||
void DumpSysVarByName (const char *name);
|
||||
int GetSysVar (char const *name, Value *val);
|
||||
int SetSysVar (char const *name, Value *val);
|
||||
void DumpSysVarByName (char const *name);
|
||||
int CalcMinsFromUTC (int jul, int tim, int *mins, int *isdst);
|
||||
void FillParagraph (char *s);
|
||||
void FillParagraph (char const *s);
|
||||
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||
int MoonPhase (int date, int time);
|
||||
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
||||
void SigIntHandler (int d);
|
||||
void GotSigInt (void);
|
||||
void SynthesizeTag(char *);
|
||||
void PurgeEchoLine(char const *fmt, ...);
|
||||
void FreeTrig(Trigger *t);
|
||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||
char const *SynthesizeTag(void);
|
||||
void ClearLastTriggers(void);
|
||||
void SaveLastTrigger(Trigger const *t);
|
||||
void SaveLastTimeTrig(TimeTrig const *t);
|
||||
|
||||
96
src/queue.c
96
src/queue.c
@@ -5,8 +5,7 @@
|
||||
/* Queue up reminders for subsequent execution. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -28,9 +27,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
@@ -40,10 +39,11 @@ typedef struct queuedrem {
|
||||
int typ;
|
||||
int RunDisabled;
|
||||
int ntrig;
|
||||
char *text;
|
||||
char const *text;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
char sched[VAR_NAME_LEN+1];
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
Trigger t;
|
||||
TimeTrig tt;
|
||||
} QueuedRem;
|
||||
|
||||
@@ -69,7 +69,7 @@ static void reread (void);
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
TimeTrig *tim, const char *sched)
|
||||
TimeTrig *tim, char const *sched)
|
||||
{
|
||||
QueuedRem *qelem;
|
||||
|
||||
@@ -92,13 +92,16 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->typ = trig->typ;
|
||||
strcpy(qelem->passthru, trig->passthru);
|
||||
qelem->tt = *tim;
|
||||
qelem->t = *trig;
|
||||
DBufInit(&(qelem->t.tags));
|
||||
qelem->next = QueueHead;
|
||||
qelem->RunDisabled = RunDisabled;
|
||||
qelem->ntrig = 0;
|
||||
strcpy(qelem->sched, sched);
|
||||
strcpy(qelem->tag, trig->tag);
|
||||
if (! *qelem->tag && SynthesizeTags) {
|
||||
SynthesizeTag(qelem->tag);
|
||||
DBufInit(&(qelem->tags));
|
||||
DBufPuts(&(qelem->tags), DBufValue(&(trig->tags)));
|
||||
if (SynthesizeTags) {
|
||||
AppendTag(&(qelem->tags), SynthesizeTag());
|
||||
}
|
||||
QueueHead = qelem;
|
||||
return OK;
|
||||
@@ -151,7 +154,7 @@ void HandleQueuedReminders(void)
|
||||
/* Initialize the queue - initialize all the entries time of issue */
|
||||
|
||||
while (q) {
|
||||
q->tt.nexttime = (int) (SystemTime(0)/60 - 1);
|
||||
q->tt.nexttime = (int) (SystemTime(1)/60 - 1);
|
||||
q->tt.nexttime = CalculateNextTime(q);
|
||||
q = q->next;
|
||||
}
|
||||
@@ -168,25 +171,24 @@ void HandleQueuedReminders(void)
|
||||
if (Daemon && !q) {
|
||||
if (Daemon < 0) {
|
||||
/* Sleep until midnight */
|
||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(0);
|
||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||
} else {
|
||||
TimeToSleep = 60*Daemon;
|
||||
}
|
||||
} else {
|
||||
TimeToSleep = q->tt.nexttime * 60L - SystemTime(0);
|
||||
TimeToSleep = q->tt.nexttime * 60L - SystemTime(1);
|
||||
}
|
||||
|
||||
while (TimeToSleep > 0L) {
|
||||
SleepTime = TimeToSleep;
|
||||
|
||||
if (Daemon > 0 && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
|
||||
if (Daemon > 0 && SleepTime > (unsigned int) 60*Daemon) SleepTime = 60*Daemon;
|
||||
|
||||
/* Wake up once a minute to recalibrate sleep time in
|
||||
case of laptop hibernation */
|
||||
if (Daemon <= 0) {
|
||||
if (SleepTime > 60) {
|
||||
SleepTime = 60;
|
||||
}
|
||||
/* Wake up on the next exact minute */
|
||||
SleepTime = 60 - (SystemTime(1)%60);
|
||||
}
|
||||
|
||||
if (Daemon >= 0) {
|
||||
@@ -209,12 +211,12 @@ void HandleQueuedReminders(void)
|
||||
if (Daemon && !q) {
|
||||
if (Daemon < 0) {
|
||||
/* Sleep until midnight */
|
||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(0);
|
||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||
} else {
|
||||
TimeToSleep = 60*Daemon;
|
||||
}
|
||||
} else {
|
||||
TimeToSleep = q->tt.nexttime * 60L - SystemTime(0);
|
||||
TimeToSleep = q->tt.nexttime * 60L - SystemTime(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -224,7 +226,7 @@ void HandleQueuedReminders(void)
|
||||
changed or a laptop awakes from hibernation.
|
||||
However, DO triger if tt.nexttime == tt.ttime so all
|
||||
queued reminders are triggered at least once. */
|
||||
if ((SystemTime(0) - (q->tt.nexttime * 60) <= 60) ||
|
||||
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
||||
(q->tt.nexttime == q->tt.ttime)) {
|
||||
/* Trigger the reminder */
|
||||
CreateParser(q->text, &p);
|
||||
@@ -232,15 +234,14 @@ void HandleQueuedReminders(void)
|
||||
strcpy(trig.passthru, q->passthru);
|
||||
RunDisabled = q->RunDisabled;
|
||||
if (Daemon < 0) {
|
||||
printf("NOTE reminder %s ",
|
||||
printf("NOTE reminder %s",
|
||||
SimpleTime(q->tt.ttime));
|
||||
printf("%s ", SimpleTime(SystemTime(0)/60));
|
||||
if (!*q->tag) {
|
||||
printf("*");
|
||||
printf("%s", SimpleTime(SystemTime(1)/60));
|
||||
if (!*DBufValue(&q->tags)) {
|
||||
printf("*\n");
|
||||
} else {
|
||||
printf("%s", q->tag);
|
||||
printf("%s\n", DBufValue(&(q->tags)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Set up global variables so some functions like trigdate()
|
||||
@@ -248,6 +249,8 @@ void HandleQueuedReminders(void)
|
||||
LastTriggerDate = JulianToday;
|
||||
LastTriggerTime = q->tt.ttime;
|
||||
LastTrigValid = 1;
|
||||
SaveLastTrigger(&(q->t));
|
||||
SaveLastTimeTrig(&(q->tt));
|
||||
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
|
||||
if (Daemon < 0) {
|
||||
printf("NOTE endreminder\n");
|
||||
@@ -396,7 +399,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
||||
/* Use LineBuffer for temp. string storage. */
|
||||
int r;
|
||||
Value v;
|
||||
char *s;
|
||||
char const *s;
|
||||
int LastTime = -1;
|
||||
int ThisTime;
|
||||
|
||||
@@ -411,7 +414,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
||||
char exprBuf[VAR_NAME_LEN+32];
|
||||
sprintf(exprBuf, "%s(%d)", q->sched, q->ntrig);
|
||||
s = exprBuf;
|
||||
r = EvalExpr(&s, &v);
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (r) {
|
||||
q->sched[0] = 0;
|
||||
return NO_TIME;
|
||||
@@ -420,7 +423,11 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
||||
ThisTime = v.v.val;
|
||||
} else if (v.type == INT_TYPE) {
|
||||
if (v.v.val > 0)
|
||||
ThisTime = q->tt.nexttime + v.v.val;
|
||||
if (LastTime >= 0) {
|
||||
ThisTime = LastTime + v.v.val;
|
||||
} else {
|
||||
ThisTime = q->tt.nexttime + v.v.val;
|
||||
}
|
||||
else
|
||||
ThisTime = q->tt.ttime + v.v.val;
|
||||
|
||||
@@ -431,6 +438,10 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
|
||||
}
|
||||
if (ThisTime < 0) ThisTime = 0; /* Can't be less than 00:00 */
|
||||
if (ThisTime > (MINUTES_PER_DAY-1)) ThisTime = (MINUTES_PER_DAY-1); /* or greater than 11:59 */
|
||||
if (DebugFlag & DB_PRTEXPR) {
|
||||
fprintf(ErrFp, "SCHED: Considering %02d%c%02d\n",
|
||||
ThisTime / 60, TimeSep, ThisTime % 60);
|
||||
}
|
||||
if (ThisTime > q->tt.nexttime) return ThisTime;
|
||||
if (ThisTime <= LastTime) {
|
||||
q->sched[0] = 0;
|
||||
@@ -498,6 +509,33 @@ static void DaemonWait(unsigned int sleeptime)
|
||||
}
|
||||
printf("NOTE queued %d\n", nqueued);
|
||||
fflush(stdout);
|
||||
} else if (!strcmp(cmdLine, "QUEUE\n")) {
|
||||
printf("NOTE queue\n");
|
||||
QueuedRem *q = QueueHead;
|
||||
while (q) {
|
||||
if (q->tt.nexttime != NO_TIME) {
|
||||
switch (q->typ) {
|
||||
case NO_TYPE: printf("NO_TYPE "); break;
|
||||
case MSG_TYPE: printf("MSG_TYPE "); break;
|
||||
case RUN_TYPE: printf("RUN_TYPE "); break;
|
||||
case CAL_TYPE: printf("CAL_TYPE "); break;
|
||||
case SAT_TYPE: printf("SAT_TYPE "); break;
|
||||
case PS_TYPE: printf("PS_TYPE "); break;
|
||||
case PSF_TYPE: printf("PSF_TYPE "); break;
|
||||
case MSF_TYPE: printf("MSF_TYPE "); break;
|
||||
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE "); break;
|
||||
default: printf("? "); break;
|
||||
}
|
||||
printf("RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
|
||||
printf("%s %s %s\n",
|
||||
(q->passthru[0] ? q->passthru : "*"),
|
||||
(q->sched[0] ? q->sched : "*"),
|
||||
q->text ? q->text : "NULL");
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
printf("NOTE endqueue\n");
|
||||
fflush(stdout);
|
||||
} else if (!strcmp(cmdLine, "REREAD\n")) {
|
||||
printf("NOTE reread\n");
|
||||
fflush(stdout);
|
||||
@@ -517,6 +555,6 @@ static void DaemonWait(unsigned int sleeptime)
|
||||
/***************************************************************/
|
||||
static void reread(void)
|
||||
{
|
||||
execvp(ArgV[0], ArgV);
|
||||
execvp(ArgV[0], (char **) ArgV);
|
||||
}
|
||||
|
||||
|
||||
142
src/rem2ps.c
142
src/rem2ps.c
@@ -5,11 +5,11 @@
|
||||
/* Print a PostScript calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
#include "version.h"
|
||||
#include "config.h"
|
||||
#include "dynbuf.h"
|
||||
|
||||
@@ -20,16 +20,27 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "rem2ps.h"
|
||||
#include "version.h"
|
||||
|
||||
#define NEW(type) ((type *) malloc(sizeof(type)))
|
||||
#define NEW(type) (malloc(sizeof(type)))
|
||||
|
||||
#define SPECIAL_NORMAL 0
|
||||
#define SPECIAL_POSTSCRIPT 1
|
||||
#define SPECIAL_PSFILE 2
|
||||
#define SPECIAL_MOON 3
|
||||
#define SPECIAL_SHADE 4
|
||||
#define SPECIAL_COLOR 5
|
||||
#define SPECIAL_COLOR 4
|
||||
#define SPECIAL_WEEK 5
|
||||
#define SPECIAL_SHADE 6
|
||||
|
||||
/* Array holding how specials sort */
|
||||
static int SpecialSortOrder[] = {
|
||||
0, /* NORMAL */
|
||||
1, /* POSTSCRIPT */
|
||||
1, /* PSFILE */
|
||||
2, /* MOON */
|
||||
0, /* COLOR */
|
||||
4, /* WEEK */
|
||||
5 /* SHADE */
|
||||
};
|
||||
|
||||
typedef struct calentry {
|
||||
struct calentry *next;
|
||||
@@ -38,21 +49,21 @@ typedef struct calentry {
|
||||
} CalEntry;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char const *name;
|
||||
int xsize, ysize;
|
||||
} PageType;
|
||||
|
||||
char DayName[7][33];
|
||||
|
||||
char *SmallCalLoc[] = {
|
||||
char const *SmallCalLoc[] = {
|
||||
"",
|
||||
"bt",
|
||||
"tb",
|
||||
"sbt",
|
||||
};
|
||||
|
||||
#define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0]))
|
||||
char *SmallLocation;
|
||||
#define NUMSMALL ((int) (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0])))
|
||||
char const *SmallLocation;
|
||||
int SmallCol1, SmallCol2;
|
||||
|
||||
PageType Pages[] =
|
||||
@@ -88,20 +99,20 @@ char PortraitMode;
|
||||
char NoSmallCal;
|
||||
char UseISO;
|
||||
|
||||
char *HeadFont="Helvetica";
|
||||
char *TitleFont="Helvetica";
|
||||
char *DayFont="Helvetica-BoldOblique";
|
||||
char *EntryFont="Helvetica";
|
||||
char *SmallFont="Helvetica";
|
||||
char *LineWidth = "1";
|
||||
char const *HeadFont="Helvetica";
|
||||
char const *TitleFont="Helvetica";
|
||||
char const *DayFont="Helvetica-BoldOblique";
|
||||
char const *EntryFont="Helvetica";
|
||||
char const *SmallFont="Helvetica";
|
||||
char const *LineWidth = "1";
|
||||
|
||||
char *HeadSize="14";
|
||||
char *TitleSize="14";
|
||||
char *DaySize="14";
|
||||
char *EntrySize="8";
|
||||
char *BorderSize = "6";
|
||||
char const *HeadSize="14";
|
||||
char const *TitleSize="14";
|
||||
char const *DaySize="14";
|
||||
char const *EntrySize="8";
|
||||
char const *BorderSize = "6";
|
||||
|
||||
char *UserProlog = NULL;
|
||||
char const *UserProlog = NULL;
|
||||
|
||||
int validfile = 0;
|
||||
|
||||
@@ -116,15 +127,15 @@ int FillPage;
|
||||
int Verbose = 0;
|
||||
|
||||
void Init (int argc, char *argv[]);
|
||||
void Usage (char *s);
|
||||
void Usage (char const *s);
|
||||
void DoPsCal (void);
|
||||
int DoQueuedPs (void);
|
||||
void DoSmallCal (char *m, int days, int first, int col, int which);
|
||||
void DoSmallCal (char const *m, int days, int first, int col, int which);
|
||||
void WriteProlog (void);
|
||||
void WriteCalEntry (void);
|
||||
void WriteOneEntry (CalEntry *c);
|
||||
void GetSmallLocations (void);
|
||||
char *EatToken(char *in, char *out, int maxlen);
|
||||
char const *EatToken(char const *in, char *out, int maxlen);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -149,7 +160,7 @@ int main(int argc, char *argv[])
|
||||
if (!strcmp(DBufValue(&buf), PSBEGIN)) {
|
||||
if (!validfile) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-1998 by David F. Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Generating PostScript calendar\n");
|
||||
}
|
||||
}
|
||||
@@ -182,10 +193,10 @@ void DoPsCal(void)
|
||||
int i;
|
||||
int is_ps;
|
||||
int firstcol;
|
||||
char *startOfBody;
|
||||
char const *startOfBody;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
DynamicBuffer buf;
|
||||
CalEntry *c, *d;
|
||||
CalEntry *c, *d, *p;
|
||||
|
||||
/* Read the month and year name, followed by # days in month and 1st day of
|
||||
month */
|
||||
@@ -306,6 +317,7 @@ void DoPsCal(void)
|
||||
if (!strcmp(passthru, "PostScript") ||
|
||||
!strcmp(passthru, "PSFile") ||
|
||||
!strcmp(passthru, "MOON") ||
|
||||
!strcmp(passthru, "WEEK") ||
|
||||
!strcmp(passthru, "SHADE")) {
|
||||
is_ps = 1;
|
||||
}
|
||||
@@ -324,6 +336,8 @@ void DoPsCal(void)
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!strcmp(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!strcmp(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
}
|
||||
@@ -332,10 +346,26 @@ void DoPsCal(void)
|
||||
PsEntries[DayNum] = c;
|
||||
} else {
|
||||
d = PsEntries[DayNum];
|
||||
while(d->next) d = d->next;
|
||||
d->next = c;
|
||||
p = NULL;
|
||||
/* Slot it into the right place */
|
||||
while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) {
|
||||
p = d;
|
||||
d = d->next;
|
||||
}
|
||||
if (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special]) {
|
||||
c->next = d->next;
|
||||
d->next = c;
|
||||
} else {
|
||||
if (p) {
|
||||
p->next = c;
|
||||
} else {
|
||||
PsEntries[DayNum] = c;
|
||||
}
|
||||
c->next = d;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(passthru, "*") ||
|
||||
!strcmp(passthru, "COLOUR") ||
|
||||
!strcmp(passthru, "COLOR")) {
|
||||
/* Put on linked list */
|
||||
if (!CurEntries) {
|
||||
@@ -345,7 +375,8 @@ void DoPsCal(void)
|
||||
while(d->next) d = d->next;
|
||||
d->next = c;
|
||||
}
|
||||
if (!strcmp(passthru, "COLOR")) {
|
||||
if (!strcmp(passthru, "COLOR") ||
|
||||
!strcmp(passthru, "COLOUR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
}
|
||||
}
|
||||
@@ -388,7 +419,7 @@ void WriteProlog(void)
|
||||
int i;
|
||||
int x = CurPage->xsize;
|
||||
int y = CurPage->ysize;
|
||||
char *isostuff;
|
||||
char const *isostuff;
|
||||
FILE *fp;
|
||||
int nread;
|
||||
char buffer[512];
|
||||
@@ -574,7 +605,7 @@ void WriteCalEntry(void)
|
||||
void WriteOneEntry(CalEntry *c)
|
||||
{
|
||||
int ch, i;
|
||||
char *s = c->entry;
|
||||
char const *s = c->entry;
|
||||
|
||||
printf(" [");
|
||||
|
||||
@@ -635,9 +666,11 @@ void WriteOneEntry(CalEntry *c)
|
||||
/***************************************************************/
|
||||
void Init(int argc, char *argv[])
|
||||
{
|
||||
char *s, *t;
|
||||
char const *s;
|
||||
char const *t;
|
||||
int i=1;
|
||||
int j;
|
||||
size_t j;
|
||||
int k;
|
||||
int offset;
|
||||
|
||||
PortraitMode = 1;
|
||||
@@ -739,7 +772,7 @@ void Init(int argc, char *argv[])
|
||||
case 'o':
|
||||
if (i == argc) Usage("Offset must be supplied");
|
||||
offset = atoi(argv[i++]);
|
||||
if (offset < 36) offset = 36;
|
||||
if (offset < 0) offset = 0;
|
||||
if (!*s) Usage("Offset must specify l, r, t or b");
|
||||
while(*s) {
|
||||
switch(*s++) {
|
||||
@@ -766,13 +799,13 @@ void Init(int argc, char *argv[])
|
||||
|
||||
case 'i': UseISO = 1; break;
|
||||
|
||||
case 'c': j=(*s);
|
||||
if (!j) {
|
||||
case 'c': k=(*s);
|
||||
if (!k) {
|
||||
SmallLocation = SmallCalLoc[0];
|
||||
} else {
|
||||
j -= '0';
|
||||
if (j>=0 && j<NUMSMALL) {
|
||||
SmallLocation = SmallCalLoc[j];
|
||||
k -= '0';
|
||||
if (k>=0 && k<NUMSMALL) {
|
||||
SmallLocation = SmallCalLoc[k];
|
||||
} else {
|
||||
SmallLocation = SmallCalLoc[0];
|
||||
}
|
||||
@@ -791,7 +824,7 @@ void Init(int argc, char *argv[])
|
||||
/* Usage - print usage information */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void Usage(char *s)
|
||||
void Usage(char const *s)
|
||||
{
|
||||
if (s) fprintf(stderr, "Rem2PS: %s\n\n", s);
|
||||
|
||||
@@ -820,7 +853,7 @@ void Usage(char *s)
|
||||
/* month. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void DoSmallCal(char *m, int days, int first, int col, int which)
|
||||
void DoSmallCal(char const *m, int days, int first, int col, int which)
|
||||
{
|
||||
/* Do the small calendar */
|
||||
int i, j;
|
||||
@@ -885,7 +918,8 @@ int DoQueuedPs(void)
|
||||
FILE *fp;
|
||||
int fnoff;
|
||||
char buffer[512];
|
||||
char *size, *extra;
|
||||
char const *size, *extra;
|
||||
char const *s;
|
||||
int num, r, g, b, phase, fontsize, moonsize;
|
||||
unsigned char c;
|
||||
|
||||
@@ -953,6 +987,22 @@ int DoQueuedPs(void)
|
||||
r/255.0, g/255.0, b/255.0);
|
||||
break;
|
||||
|
||||
case SPECIAL_WEEK: /* Week number */
|
||||
printf("gsave Border Border 2 div moveto /EntryFont findfont EntrySize 1.2 div scalefont setfont (");
|
||||
s = e->entry+fnoff;
|
||||
while(*s && isspace(*s)) {
|
||||
s++;
|
||||
}
|
||||
while(*s) {
|
||||
if (*s == '\\' || *s == '(' || *s == ')') {
|
||||
PutChar('\\');
|
||||
}
|
||||
PutChar(*s);
|
||||
s++;
|
||||
}
|
||||
printf(") show grestore\n");
|
||||
break;
|
||||
|
||||
case SPECIAL_MOON: /* Moon phase */
|
||||
num = sscanf(e->entry+fnoff, "%d %d %d", &phase, &moonsize,
|
||||
&fontsize);
|
||||
@@ -1060,7 +1110,7 @@ int DoQueuedPs(void)
|
||||
void GetSmallLocations(void)
|
||||
{
|
||||
char c;
|
||||
char *s = SmallLocation;
|
||||
char const *s = SmallLocation;
|
||||
int colfirst, collast;
|
||||
|
||||
/* Figure out the first and last columns */
|
||||
@@ -1122,7 +1172,7 @@ void GetSmallLocations(void)
|
||||
/* Read a space-delimited token into an output buffer. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *EatToken(char *in, char *out, int maxlen)
|
||||
char const *EatToken(char const *in, char *out, int maxlen)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
/* Define the PostScript prologue */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
char *PSProlog1[] =
|
||||
{
|
||||
"% This file was produced by Remind and Rem2PS, written by",
|
||||
"% David F. Skoll.",
|
||||
"% Remind and Rem2PS are Copyright 1992-1997 David F. Skoll.",
|
||||
"% Dianne Skoll.",
|
||||
"% Remind and Rem2PS are Copyright 1992-2020 Dianne Skoll.",
|
||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||
|
||||
38
src/sort.c
38
src/sort.c
@@ -5,8 +5,7 @@
|
||||
/* Routines for sorting reminders by trigger date */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -25,7 +24,7 @@
|
||||
/* The structure of a sorted entry */
|
||||
typedef struct sortrem {
|
||||
struct sortrem *next;
|
||||
char *text;
|
||||
char const *text;
|
||||
int trigdate;
|
||||
int trigtime;
|
||||
int typ;
|
||||
@@ -35,7 +34,7 @@ typedef struct sortrem {
|
||||
/* The sorted reminder queue */
|
||||
static Sortrem *SortedQueue = (Sortrem *) NULL;
|
||||
|
||||
static Sortrem *MakeSortRem (int jul, int tim, char *body, int typ, int prio);
|
||||
static Sortrem *MakeSortRem (int jul, int tim, char const *body, int typ, int prio);
|
||||
static void IssueSortBanner (int jul);
|
||||
|
||||
/***************************************************************/
|
||||
@@ -45,7 +44,7 @@ static void IssueSortBanner (int jul);
|
||||
/* Create a new Sortrem entry - return NULL on failure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static Sortrem *MakeSortRem(int jul, int tim, char *body, int typ, int prio)
|
||||
static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int prio)
|
||||
{
|
||||
Sortrem *new = NEW(Sortrem);
|
||||
if (!new) return NULL;
|
||||
@@ -71,7 +70,7 @@ static Sortrem *MakeSortRem(int jul, int tim, char *body, int typ, int prio)
|
||||
/* Insert a reminder into the sort buffer */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
|
||||
int InsertIntoSortBuffer(int jul, int tim, char const *body, int typ, int prio)
|
||||
{
|
||||
Sortrem *new = MakeSortRem(jul, tim, body, typ, prio);
|
||||
Sortrem *cur = SortedQueue, *prev = NULL;
|
||||
@@ -83,6 +82,7 @@ int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
|
||||
SortByDate = 0;
|
||||
SortByTime = 0;
|
||||
SortByPrio = 0;
|
||||
UntimedBeforeTimed = 0;
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
|
||||
while (cur) {
|
||||
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
|
||||
cur->trigdate, cur->trigtime, cur->priority,
|
||||
SortByDate, SortByTime, SortByPrio);
|
||||
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed);
|
||||
|
||||
if (ShouldGoAfter <= 0) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
@@ -154,7 +154,7 @@ void IssueSortedReminders(void)
|
||||
break;
|
||||
}
|
||||
|
||||
free(cur->text);
|
||||
free((char *) cur->text);
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
@@ -173,14 +173,14 @@ static void IssueSortBanner(int jul)
|
||||
char BanExpr[64];
|
||||
int y, m, d;
|
||||
Value v;
|
||||
char *s = BanExpr;
|
||||
char const *s = BanExpr;
|
||||
DynamicBuffer buf;
|
||||
|
||||
if (UserFuncExists("sortbanner") != 1) return;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
|
||||
y = EvalExpr(&s, &v);
|
||||
y = EvalExpr(&s, &v, NULL);
|
||||
if (y) return;
|
||||
if (DoCoerce(STR_TYPE, &v)) return;
|
||||
DBufInit(&buf);
|
||||
@@ -203,19 +203,27 @@ static void IssueSortBanner(int jul)
|
||||
/***************************************************************/
|
||||
int CompareRems(int dat1, int tim1, int prio1,
|
||||
int dat2, int tim2, int prio2,
|
||||
int bydate, int bytime, int byprio)
|
||||
int bydate, int bytime, int byprio,
|
||||
int untimed_first)
|
||||
{
|
||||
int dafter, tafter, pafter;
|
||||
int dafter, tafter, pafter, uafter;
|
||||
|
||||
dafter = (bydate != SORT_DESCEND) ? 1 : -1;
|
||||
tafter = (bytime != SORT_DESCEND) ? 1 : -1;
|
||||
pafter = (byprio != SORT_DESCEND) ? 1 : -1;
|
||||
uafter = (untimed_first) ? -1 : 1;
|
||||
|
||||
if (dat1 < dat2) return dafter;
|
||||
if (dat1 > dat2) return -dafter;
|
||||
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) return -1;
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) return 1;
|
||||
if (tim1 == NO_TIME && tim2 != NO_TIME) {
|
||||
return -uafter;
|
||||
}
|
||||
|
||||
if (tim1 != NO_TIME && tim2 == NO_TIME) {
|
||||
return uafter;
|
||||
}
|
||||
|
||||
if (tim1 < tim2) return tafter;
|
||||
if (tim1 > tim2) return -tafter;
|
||||
|
||||
|
||||
11
src/test-all-languages.sh
Executable file
11
src/test-all-languages.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# Make sure Remind compiles with all supported languages; show
|
||||
# tstlang.rem output for each language.
|
||||
|
||||
ALL=`grep ^#define lang.h | grep -v '#define LANG' | awk '{print $2}'`
|
||||
|
||||
for i in $ALL ; do
|
||||
make clean all LANGDEF=-DLANG=$i || exit 1
|
||||
./remind -q -r ../tests/tstlang.rem
|
||||
done
|
||||
exit 0
|
||||
53
src/token.c
53
src/token.c
@@ -6,8 +6,7 @@
|
||||
/* classifying the tokens parsed. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -74,6 +73,7 @@ Token TokArray[] = {
|
||||
{ "november", 3, T_Month, 10 },
|
||||
{ "october", 3, T_Month, 9 },
|
||||
{ "omit", 3, T_Omit, 0 },
|
||||
{ "omitfunc", 8, T_OmitFunc, 0 },
|
||||
{ "once", 3, T_Once, 0 },
|
||||
{ "pop-omit-context", 3, T_Pop, 0 },
|
||||
{ "preserve", 8, T_Preserve, 0 },
|
||||
@@ -93,6 +93,7 @@ Token TokArray[] = {
|
||||
{ "special", 7, T_RemType, PASSTHRU_TYPE },
|
||||
{ "sunday", 3, T_WkDay, 6 },
|
||||
{ "tag", 3, T_Tag, 0 },
|
||||
{ "through", 7, T_Through, 0 },
|
||||
{ "thursday", 3, T_WkDay, 3 },
|
||||
{ "tuesday", 3, T_WkDay, 1 },
|
||||
{ "unset", 5, T_UnSet, 0 },
|
||||
@@ -128,7 +129,7 @@ Token NonEnglishToks[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static int TokStrCmp (const Token *t, const char *s);
|
||||
static int TokStrCmp (Token const *t, char const *s);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -138,16 +139,16 @@ static int TokStrCmp (const Token *t, const char *s);
|
||||
/* left square bracket, return a T_Illegal type. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *FindInitialToken(Token *tok, char *s)
|
||||
char const *FindInitialToken(Token *tok, char const *s)
|
||||
{
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
tok->type = T_Illegal;
|
||||
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
|
||||
while (*s && !isspace(*s)) {
|
||||
while (*s && !isempty(*s)) {
|
||||
if (DBufPutc(&buf, *s++) != OK) return s;
|
||||
}
|
||||
|
||||
@@ -165,7 +166,7 @@ char *FindInitialToken(Token *tok, char *s)
|
||||
/* Given a string, which token is it? */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void FindToken(const char *s, Token *tok)
|
||||
void FindToken(char const *s, Token *tok)
|
||||
{
|
||||
int top, bot, mid, r, max;
|
||||
int l;
|
||||
@@ -227,11 +228,11 @@ void FindToken(const char *s, Token *tok)
|
||||
/* If language is other than English, search the DayNames[] and MonthNames[]
|
||||
array. */
|
||||
#if LANG != ENGLISH
|
||||
for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
|
||||
if (l >= NonEnglishToks[r].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[r], s)) {
|
||||
tok->type = NonEnglishToks[r].type;
|
||||
tok->val = NonEnglishToks[r].val;
|
||||
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
|
||||
if (l >= NonEnglishToks[x].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[x], s)) {
|
||||
tok->type = NonEnglishToks[x].type;
|
||||
tok->val = NonEnglishToks[x].val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -252,15 +253,33 @@ void FindToken(const char *s, Token *tok)
|
||||
/* Rep - *n */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void FindNumericToken(const char *s, Token *t)
|
||||
void FindNumericToken(char const *s, Token *t)
|
||||
{
|
||||
int mult = 1, hour, min;
|
||||
char const *s_orig = s;
|
||||
|
||||
t->type = T_Illegal;
|
||||
t->val = 0;
|
||||
if (isdigit(*s)) {
|
||||
PARSENUM(t->val, s);
|
||||
|
||||
/* If we hit a '-' or a '/', we may have a date or a datetime */
|
||||
if (*s == '-' || *s == '/') {
|
||||
char const *p = s_orig;
|
||||
int jul, tim;
|
||||
if (ParseLiteralDate(&p, &jul, &tim) == OK) {
|
||||
if (*p) return;
|
||||
if (tim == NO_TIME) {
|
||||
t->type = T_Date;
|
||||
t->val = jul;
|
||||
return;
|
||||
}
|
||||
t->type = T_DateTime;
|
||||
t->val = MINUTES_PER_DAY * jul + tim;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we hit a comma, swallow it. This allows stuff
|
||||
like Jan 6, 1998 */
|
||||
if (*s == ',') {
|
||||
@@ -335,12 +354,12 @@ void FindNumericToken(const char *s, Token *t)
|
||||
/* Compare a token to a string. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int TokStrCmp(const Token *t, const char *s)
|
||||
static int TokStrCmp(Token const *t, char const *s)
|
||||
{
|
||||
register int r;
|
||||
char *tk = t->name;
|
||||
char const *tk = t->name;
|
||||
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
|
||||
r = *tk - tolower(*s);
|
||||
r = tolower(*tk) - tolower(*s);
|
||||
tk++;
|
||||
s++;
|
||||
if (r) return r;
|
||||
@@ -348,5 +367,5 @@ static int TokStrCmp(const Token *t, const char *s)
|
||||
/* Ignore trailing commas on s */
|
||||
|
||||
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
||||
return (*tk - *s);
|
||||
return (tolower(*tk) - tolower(*s));
|
||||
}
|
||||
|
||||
303
src/trigger.c
303
src/trigger.c
@@ -5,8 +5,7 @@
|
||||
/* Routines for figuring out the trigger date of a reminder */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -206,16 +205,27 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
||||
*err = E_BAD_DATE;
|
||||
return -1;
|
||||
}
|
||||
/* Back up a year in case we'll cross a year boundary*/
|
||||
if (y > BASE) {
|
||||
y--;
|
||||
}
|
||||
|
||||
/* Move up to the first valid year */
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
|
||||
/* Try last year */
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Try this year */
|
||||
y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
if (j >= startdate) return j;
|
||||
|
||||
/* Must be next year */
|
||||
y = y + 1;
|
||||
y++;
|
||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||
j = Julian(y, trig->m, trig->d);
|
||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
||||
@@ -286,16 +296,33 @@ static int JYear(int jul)
|
||||
/***************************************************************/
|
||||
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
|
||||
{
|
||||
int simple, mod;
|
||||
int simple, mod, omit;
|
||||
|
||||
/* First: Have we passed the UNTIL date? */
|
||||
if (trig->until != NO_UNTIL &&
|
||||
trig->until < start) return -1; /* expired */
|
||||
trig->until < start) {
|
||||
trig->expired = 1;
|
||||
return -1; /* expired */
|
||||
}
|
||||
|
||||
/* Next: If it's an "AFTER"-type skip, back up
|
||||
until we're at the start of a block of holidays */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(start-1, trig->localomit)) start--;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(start-1, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
start--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
/* omitfunc must have returned "true" too often */
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the next simple trigger */
|
||||
simple = NextSimpleTrig(start, trig, err);
|
||||
@@ -309,12 +336,29 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* If there's a BACK, back up... */
|
||||
if (trig->back != NO_BACK) {
|
||||
mod = trig->back;
|
||||
if (mod < 0) simple += mod;
|
||||
else
|
||||
while(mod) {
|
||||
simple--;
|
||||
if (!IsOmitted(simple, trig->localomit)) mod--;
|
||||
if (mod < 0) {
|
||||
simple += mod;
|
||||
}
|
||||
else {
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
if (max < mod*2) {
|
||||
max = mod*2;
|
||||
}
|
||||
while(iter++ <= max) {
|
||||
if (!mod) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) mod--;
|
||||
}
|
||||
if (iter > max) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's a REP, calculate the next occurrence */
|
||||
@@ -327,17 +371,98 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
}
|
||||
|
||||
/* If it's a "BEFORE"-type skip, back up */
|
||||
if (trig->skip == BEFORE_SKIP)
|
||||
while(IsOmitted(simple, trig->localomit)) simple--;
|
||||
if (trig->skip == BEFORE_SKIP) {
|
||||
int iter = 0;
|
||||
while(iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple--;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's an "AFTER"-type skip, jump ahead */
|
||||
if (trig->skip == AFTER_SKIP)
|
||||
while (IsOmitted(simple, trig->localomit)) simple++;
|
||||
if (trig->skip == AFTER_SKIP) {
|
||||
int iter = 0;
|
||||
while (iter++ <= MaxSatIter) {
|
||||
*err = IsOmitted(simple, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -2;
|
||||
if (!omit) {
|
||||
break;
|
||||
}
|
||||
simple++;
|
||||
}
|
||||
if (iter > MaxSatIter) {
|
||||
*err = E_CANT_TRIG;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the date */
|
||||
return simple;
|
||||
}
|
||||
|
||||
int
|
||||
AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
int y, m, d;
|
||||
/* If we have an AT, save the original event start */
|
||||
if (tim->ttime != NO_TIME) {
|
||||
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
|
||||
if (tim->duration != NO_TIME) {
|
||||
trig->eventduration = tim->duration;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now potentially adjust */
|
||||
if (r < today && r + trig->duration_days >= today) {
|
||||
/* Adjust duration down */
|
||||
tim->duration -= (today - r) * MINUTES_PER_DAY;
|
||||
tim->duration += tim->ttime;
|
||||
|
||||
/* Start at midnight */
|
||||
tim->ttime = 0;
|
||||
|
||||
/* Change trigger date to today */
|
||||
r = today;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(r, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[r % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tim->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tim->ttime / 60),
|
||||
(tim->ttime % 60));
|
||||
if (tim->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tim->duration / 60),
|
||||
(tim->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
SaveLastTrigger(trig);
|
||||
LastTriggerDate = r;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeTrigger */
|
||||
@@ -346,25 +471,58 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* today's date. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
|
||||
int *err, int save_in_globals)
|
||||
{
|
||||
int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals);
|
||||
if (*err != OK) {
|
||||
return r;
|
||||
}
|
||||
r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeTriggerNoAdjustDuration */
|
||||
/* */
|
||||
/* Compute a trigger, but do NOT adjust the time trigger */
|
||||
/* duration. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
int *err, int save_in_globals)
|
||||
{
|
||||
int nattempts = 0,
|
||||
start = today,
|
||||
start = today - trig->duration_days,
|
||||
nextstart = 0,
|
||||
y, m, d,
|
||||
y, m, d, omit,
|
||||
result;
|
||||
|
||||
LastTrigValid = 0;
|
||||
trig->expired = 0;
|
||||
if (save_in_globals) {
|
||||
LastTrigValid = 0;
|
||||
}
|
||||
|
||||
/* Assume everything works */
|
||||
/* Assume everything works */
|
||||
*err = OK;
|
||||
|
||||
/* But check for obvious problems... */
|
||||
/* But check for obvious problems... */
|
||||
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
|
||||
*err = E_2MANY_LOCALOMIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
*err = E_DATE_OVER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tim->duration != NO_TIME && tim->ttime == NO_TIME) {
|
||||
*err = E_DURATION_NO_AT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (trig->rep != NO_REP &&
|
||||
(trig->d == NO_DAY ||
|
||||
trig->m == NO_MON ||
|
||||
@@ -373,14 +531,20 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
*err = E_REP_FULSPEC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Save the trigger */
|
||||
if (save_in_globals) {
|
||||
SaveLastTrigger(trig);
|
||||
}
|
||||
|
||||
while (nattempts++ < TRIG_ATTEMPTS) {
|
||||
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
||||
|
||||
/* If there's an error, die immediately */
|
||||
if (*err) return -1;
|
||||
if (result == -1) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
@@ -389,18 +553,39 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
}
|
||||
|
||||
/* If result is >= today, great! */
|
||||
if (result >= today &&
|
||||
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
if (trig->skip == SKIP_SKIP) {
|
||||
*err = IsOmitted(result, trig->localomit, trig->omitfunc, &omit);
|
||||
if (*err) return -1;
|
||||
} else {
|
||||
omit = 0;
|
||||
}
|
||||
|
||||
/** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */
|
||||
if (result+trig->duration_days >= today &&
|
||||
(trig->skip != SKIP_SKIP || !omit)) {
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[result % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tim->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tim->ttime / 60),
|
||||
(tim->ttime % 60));
|
||||
if (tim->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tim->duration / 60),
|
||||
(tim->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -409,22 +594,36 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
if (trig->back == NO_BACK &&
|
||||
trig->skip == NO_SKIP &&
|
||||
trig->rep == NO_REP) {
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
}
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (trig->skip == SKIP_SKIP &&
|
||||
omit &&
|
||||
nextstart <= start &&
|
||||
result >= start) {
|
||||
nextstart = result + 1;
|
||||
}
|
||||
|
||||
/* Keep scanning... unless there's no point in doing it.*/
|
||||
if (nextstart <= start) {
|
||||
if (result != -1) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
}
|
||||
trig->expired = 1;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
fprintf(ErrFp, "%s(%d): %s\n",
|
||||
FileName, LineNo, ErrMsg[E_EXPIRED]);
|
||||
@@ -439,3 +638,41 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
|
||||
*err = E_CANT_TRIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeScanStart */
|
||||
/* */
|
||||
/* Figure out where to start scan from by examining SCANFROM */
|
||||
/* and DURATION */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int
|
||||
ComputeScanStart(int today, Trigger *trig, TimeTrig *tt)
|
||||
{
|
||||
int minutes, days;
|
||||
|
||||
/* If we don't have a time/duration, just use scanfrom */
|
||||
if (tt->ttime == NO_TIME ||
|
||||
tt->duration == NO_TIME) {
|
||||
if (trig->scanfrom == NO_DATE) {
|
||||
return today;
|
||||
}
|
||||
return trig->scanfrom;
|
||||
}
|
||||
|
||||
/* Calculate time-based SCANFROM */
|
||||
minutes = tt->ttime + tt->duration - 1;
|
||||
|
||||
/* Figure out how many days to scan backwards from */
|
||||
days = minutes / MINUTES_PER_DAY;
|
||||
|
||||
if (trig->scanfrom != NO_DATE) {
|
||||
if (trig->scanfrom <= today - days) {
|
||||
return trig->scanfrom;
|
||||
} else {
|
||||
return today - days;
|
||||
}
|
||||
}
|
||||
return today - days;
|
||||
}
|
||||
|
||||
61
src/types.h
61
src/types.h
@@ -5,8 +5,7 @@
|
||||
/* Type definitions all dumped here. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -24,12 +23,27 @@ typedef struct {
|
||||
|
||||
/* Define the type of operators */
|
||||
typedef struct {
|
||||
char *name;
|
||||
char const *name;
|
||||
char prec;
|
||||
char type;
|
||||
int (*func)(void);
|
||||
} Operator;
|
||||
|
||||
/* Structure for passing in Nargs and out RetVal from functions */
|
||||
typedef struct {
|
||||
int nargs;
|
||||
Value retval;
|
||||
} func_info;
|
||||
|
||||
/* Define the type of user-functions */
|
||||
typedef struct {
|
||||
char const *name;
|
||||
char minargs;
|
||||
char maxargs;
|
||||
char is_constant;
|
||||
int (*func)(func_info *);
|
||||
} BuiltinFunc;
|
||||
|
||||
/* Define the structure of a variable */
|
||||
typedef struct var {
|
||||
struct var *next;
|
||||
@@ -40,6 +54,7 @@ typedef struct var {
|
||||
|
||||
/* A trigger */
|
||||
typedef struct {
|
||||
int expired;
|
||||
int wd;
|
||||
int d;
|
||||
int m;
|
||||
@@ -53,10 +68,15 @@ typedef struct {
|
||||
int typ;
|
||||
int once;
|
||||
int scanfrom;
|
||||
int from;
|
||||
int priority;
|
||||
int duration_days; /* Duration converted to days to search */
|
||||
int eventstart; /* Original event start (datetime) */
|
||||
int eventduration; /* Original event duration (minutes) */
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char tag[TAG_LEN+1];
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
} Trigger;
|
||||
|
||||
@@ -71,14 +91,16 @@ typedef struct {
|
||||
|
||||
/* The parse pointer */
|
||||
typedef struct {
|
||||
char isnested; /* Is it a nested expression? */
|
||||
char allownested;
|
||||
char *text; /* Start of text */
|
||||
char *pos; /* Current position */
|
||||
char *etext; /* Substituted text */
|
||||
char *epos; /* Position in substituted text */
|
||||
DynamicBuffer pushedToken; /* Pushed-back token */
|
||||
char *tokenPushed; /* NULL if no pushed-back token */
|
||||
char const *text; /* Start of text */
|
||||
char const *pos; /* Current position */
|
||||
char const *etext; /* Substituted text */
|
||||
char const *epos; /* Position in substituted text */
|
||||
char const *tokenPushed; /* NULL if no pushed-back token */
|
||||
unsigned char isnested; /* Is it a nested expression? */
|
||||
unsigned char allownested;
|
||||
unsigned char expr_happened; /* Did we encounter an [expression] ? */
|
||||
unsigned char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
|
||||
} Parser;
|
||||
|
||||
typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
@@ -116,11 +138,12 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
|
||||
|
||||
/* DEFINES for debugging flags */
|
||||
#define DB_PRTLINE 1
|
||||
#define DB_PRTEXPR 2
|
||||
#define DB_PRTTRIG 4
|
||||
#define DB_DUMP_VARS 8
|
||||
#define DB_ECHO_LINE 16
|
||||
#define DB_PRTLINE 1
|
||||
#define DB_PRTEXPR 2
|
||||
#define DB_PRTTRIG 4
|
||||
#define DB_DUMP_VARS 8
|
||||
#define DB_ECHO_LINE 16
|
||||
#define DB_TRACE_FILES 32
|
||||
|
||||
/* Enumeration of the tokens */
|
||||
enum TokTypes
|
||||
@@ -130,7 +153,7 @@ enum TokTypes
|
||||
T_IfTrig, T_ErrMsg,
|
||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
||||
T_WkDay,
|
||||
T_Month, T_Time,
|
||||
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_Back,
|
||||
T_Once,
|
||||
T_Empty,
|
||||
@@ -146,7 +169,9 @@ enum TokTypes
|
||||
T_Warn,
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime
|
||||
T_LongTime,
|
||||
T_OmitFunc,
|
||||
T_Through
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
/* functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -29,7 +28,7 @@
|
||||
typedef struct udf_struct {
|
||||
struct udf_struct *next;
|
||||
char name[VAR_NAME_LEN+1];
|
||||
char *text;
|
||||
char const *text;
|
||||
Var *locals;
|
||||
char IsActive;
|
||||
int nargs;
|
||||
@@ -40,14 +39,14 @@ static UserFunc *FuncHash[FUNC_HASH_SIZE];
|
||||
|
||||
/* Access to built-in functions */
|
||||
extern int NumFuncs;
|
||||
extern Operator Func[];
|
||||
extern BuiltinFunc Func[];
|
||||
|
||||
/* We need access to the expression evaluation stack */
|
||||
extern Value ValStack[];
|
||||
extern int ValStackPtr;
|
||||
|
||||
static void DestroyUserFunc (UserFunc *f);
|
||||
static void FUnset (char *name);
|
||||
static void FUnset (char const *name);
|
||||
static void FSet (UserFunc *f);
|
||||
static int SetUpLocalVars (UserFunc *f);
|
||||
static void DestroyLocalVals (UserFunc *f);
|
||||
@@ -65,6 +64,7 @@ int DoFset(ParsePtr p)
|
||||
int c;
|
||||
UserFunc *func;
|
||||
Var *v;
|
||||
int orig_namelen;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
@@ -75,6 +75,7 @@ int DoFset(ParsePtr p)
|
||||
DBufFree(&buf);
|
||||
return E_BAD_ID;
|
||||
}
|
||||
orig_namelen = buf.len;
|
||||
|
||||
/* Should be followed by '(' */
|
||||
c = ParseNonSpaceChar(p, &r, 0);
|
||||
@@ -95,9 +96,8 @@ int DoFset(ParsePtr p)
|
||||
StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN);
|
||||
DBufFree(&buf);
|
||||
if (!Hush) {
|
||||
if (FindFunc(DBufValue(&buf), Func, NumFuncs)) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_REDEF_FUNC],
|
||||
DBufValue(&buf));
|
||||
if (FindFunc(func->name, Func, NumFuncs)) {
|
||||
Eprint("%s: `%s'", ErrMsg[E_REDEF_FUNC], func->name);
|
||||
}
|
||||
}
|
||||
func->locals = NULL;
|
||||
@@ -119,6 +119,7 @@ int DoFset(ParsePtr p)
|
||||
if ( (r=ParseIdentifier(p, &buf)) ) return r;
|
||||
if (*DBufValue(&buf) == '$') {
|
||||
DBufFree(&buf);
|
||||
DestroyUserFunc(func);
|
||||
return E_BAD_ID;
|
||||
}
|
||||
v = NEW(Var);
|
||||
@@ -142,6 +143,11 @@ int DoFset(ParsePtr p)
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow an optional = sign: FSET f(x) = x*x */
|
||||
c = ParseNonSpaceChar(p, &r, 1);
|
||||
if (c == '=') {
|
||||
c = ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
/* Copy the text over */
|
||||
if (p->isnested) {
|
||||
Eprint("%s", ErrMsg[E_CANTNEST_FDEF]);
|
||||
@@ -160,6 +166,10 @@ int DoFset(ParsePtr p)
|
||||
|
||||
/* Add the function definition */
|
||||
FSet(func);
|
||||
if (orig_namelen > VAR_NAME_LEN) {
|
||||
Eprint("Warning: Function name `%s...' truncated to `%s'",
|
||||
func->name, func->name);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -184,7 +194,7 @@ static void DestroyUserFunc(UserFunc *f)
|
||||
}
|
||||
|
||||
/* Free the function definition */
|
||||
if (f->text) free(f->text);
|
||||
if (f->text) free( (char *) f->text);
|
||||
|
||||
/* Free the data structure itself */
|
||||
free(f);
|
||||
@@ -198,7 +208,7 @@ static void DestroyUserFunc(UserFunc *f)
|
||||
/* it exists. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void FUnset(char *name)
|
||||
static void FUnset(char const *name)
|
||||
{
|
||||
UserFunc *cur, *prev;
|
||||
int h;
|
||||
@@ -238,12 +248,12 @@ static void FSet(UserFunc *f)
|
||||
/* Call a user-defined function. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int CallUserFunc(char *name, int nargs)
|
||||
int CallUserFunc(char const *name, int nargs, ParsePtr p)
|
||||
{
|
||||
UserFunc *f;
|
||||
int h = HashVal(name) % FUNC_HASH_SIZE;
|
||||
int i;
|
||||
char *s;
|
||||
char const *s;
|
||||
|
||||
/* Search for the function */
|
||||
f = FuncHash[h];
|
||||
@@ -269,7 +279,7 @@ int CallUserFunc(char *name, int nargs)
|
||||
}
|
||||
return E_RECURSIVE;
|
||||
}
|
||||
|
||||
|
||||
/* Check number of args */
|
||||
if (nargs != f->nargs) {
|
||||
if (DebugFlag &DB_PRTEXPR) {
|
||||
@@ -294,9 +304,9 @@ int CallUserFunc(char *name, int nargs)
|
||||
s = f->text;
|
||||
|
||||
/* Skip the opening bracket, if there's one */
|
||||
while (isspace(*s)) s++;
|
||||
while (isempty(*s)) s++;
|
||||
if (*s == BEG_OF_EXPR) s++;
|
||||
h = Evaluate(&s, f->locals);
|
||||
h = Evaluate(&s, f->locals, p);
|
||||
f->IsActive = 0;
|
||||
DestroyLocalVals(f);
|
||||
if (DebugFlag &DB_PRTEXPR) {
|
||||
@@ -356,7 +366,7 @@ static void DestroyLocalVals(UserFunc *f)
|
||||
/* it is defined, or -1 if it is not defined. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int UserFuncExists(char *fn)
|
||||
int UserFuncExists(char const *fn)
|
||||
{
|
||||
UserFunc *f;
|
||||
int h = HashVal(fn) % FUNC_HASH_SIZE;
|
||||
|
||||
19
src/utils.c
19
src/utils.c
@@ -5,8 +5,7 @@
|
||||
/* Useful utility functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -30,9 +29,9 @@
|
||||
/* Just like strncpy EXCEPT we ALWAYS copy the trailing 0. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *StrnCpy(char *dest, const char *source, int n)
|
||||
char *StrnCpy(char *dest, char const *source, int n)
|
||||
{
|
||||
register char *odest = dest;
|
||||
char *odest = dest;
|
||||
|
||||
while (n-- && (*dest++ = *source++)) ;
|
||||
if (*(dest-1)) *dest = 0;
|
||||
@@ -48,7 +47,7 @@ char *StrnCpy(char *dest, const char *source, int n)
|
||||
/* of the first string, whichever is greater. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrMatch(const char *s1, const char *s2, int n)
|
||||
int StrMatch(char const *s1, char const *s2, int n)
|
||||
{
|
||||
int l;
|
||||
if ((l = strlen(s1)) < n) return 0;
|
||||
@@ -60,7 +59,7 @@ int StrMatch(const char *s1, const char *s2, int n)
|
||||
/* StrinCmp - compare strings, case-insensitive */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrinCmp(const char *s1, const char *s2, int n)
|
||||
int StrinCmp(char const *s1, char const *s2, int n)
|
||||
{
|
||||
register int r;
|
||||
while (n && *s1 && *s2) {
|
||||
@@ -80,10 +79,10 @@ int StrinCmp(const char *s1, const char *s2, int n)
|
||||
/* Like ANSI strdup */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *StrDup(const char *s)
|
||||
char *StrDup(char const *s)
|
||||
{
|
||||
char *ret = (char *) malloc(strlen(s)+1);
|
||||
if (!ret) return (char *) NULL;
|
||||
char *ret = malloc(strlen(s)+1);
|
||||
if (!ret) return NULL;
|
||||
strcpy(ret, s);
|
||||
return ret;
|
||||
}
|
||||
@@ -95,7 +94,7 @@ char *StrDup(const char *s)
|
||||
/* Compare strings, case insensitive. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrCmpi(const char *s1, const char *s2)
|
||||
int StrCmpi(char const *s1, char const *s2)
|
||||
{
|
||||
int r;
|
||||
while (*s1 && *s2) {
|
||||
|
||||
286
src/var.c
286
src/var.c
@@ -6,8 +6,7 @@
|
||||
/* user- and system-defined variables. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2007 by Roaring Penguin Software Inc. */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -36,6 +35,139 @@ static Var *VHashTbl[VAR_HASH_SIZE];
|
||||
|
||||
typedef int (*SysVarFunc)(int, Value *);
|
||||
|
||||
static int trig_date_func(int do_set, Value *val)
|
||||
{
|
||||
UNUSED(do_set);
|
||||
val->type = DATE_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
val->v.val = 0;
|
||||
} else {
|
||||
val->v.val = LastTriggerDate;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
static int trig_day_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
val->v.val = -1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
||||
val->v.val = d;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int trig_mon_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
val->v.val = -1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
||||
val->v.val = m+1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int trig_year_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
if (!LastTrigValid) {
|
||||
val->v.val = -1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
||||
val->v.val = y;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int trig_wday_func(int do_set, Value *val)
|
||||
{
|
||||
val->type = INT_TYPE;
|
||||
UNUSED(do_set);
|
||||
if (!LastTrigValid) {
|
||||
val->v.val = -1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
val->v.val = (LastTriggerDate + 1) % 7;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_date_func(int do_set, Value *val)
|
||||
{
|
||||
UNUSED(do_set);
|
||||
val->type = DATE_TYPE;
|
||||
val->v.val = JulianToday;
|
||||
return OK;
|
||||
}
|
||||
static int today_day_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
val->v.val = d;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_mon_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
val->v.val = m+1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_year_func(int do_set, Value *val)
|
||||
{
|
||||
int y, m, d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
val->v.val = y;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_wday_func(int do_set, Value *val)
|
||||
{
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
val->v.val = (JulianToday + 1) % 7;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int datetime_sep_func(int do_set, Value *val)
|
||||
{
|
||||
if (!do_set) {
|
||||
val->v.str = malloc(2);
|
||||
if (!val->v.str) return E_NO_MEM;
|
||||
val->v.str[0] = DateTimeSep;
|
||||
val->v.str[1] = 0;
|
||||
val->type = STR_TYPE;
|
||||
return OK;
|
||||
}
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (strcmp(val->v.str, "T") &&
|
||||
strcmp(val->v.str, "@")) {
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
DateTimeSep = val->v.str[0];
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int date_sep_func(int do_set, Value *val)
|
||||
{
|
||||
if (!do_set) {
|
||||
@@ -80,7 +212,7 @@ static int time_sep_func(int do_set, Value *val)
|
||||
/* Given a string, compute the hash value. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
unsigned int HashVal(const char *str)
|
||||
unsigned int HashVal(char const *str)
|
||||
{
|
||||
register unsigned int i=0;
|
||||
register unsigned int j=1;
|
||||
@@ -102,7 +234,7 @@ unsigned int HashVal(const char *str)
|
||||
/* string. If create is 1, create the variable. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
Var *FindVar(const char *str, int create)
|
||||
Var *FindVar(char const *str, int create)
|
||||
{
|
||||
register int h;
|
||||
register Var *v;
|
||||
@@ -139,7 +271,7 @@ Var *FindVar(const char *str, int create)
|
||||
/* string and delete it. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DeleteVar(const char *str)
|
||||
int DeleteVar(char const *str)
|
||||
{
|
||||
register int h;
|
||||
register Var *v;
|
||||
@@ -168,7 +300,7 @@ int DeleteVar(const char *str)
|
||||
/* Set the indicate variable to the specified value. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int SetVar(const char *str, Value *val)
|
||||
int SetVar(char const *str, Value *val)
|
||||
{
|
||||
Var *v = FindVar(str, 1);
|
||||
|
||||
@@ -186,7 +318,7 @@ int SetVar(const char *str, Value *val)
|
||||
/* Get a copy of the value of the variable. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int GetVarValue(const char *str, Value *val, Var *locals)
|
||||
int GetVarValue(char const *str, Value *val, Var *locals, ParsePtr p)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
@@ -198,6 +330,8 @@ int GetVarValue(const char *str, Value *val, Var *locals)
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
/* Global variable... mark expression as non-constant */
|
||||
if (p) p->nonconst_expr = 1;
|
||||
v=FindVar(str, 0);
|
||||
|
||||
if (!v) {
|
||||
@@ -223,6 +357,11 @@ int DoSet (Parser *p)
|
||||
r = ParseIdentifier(p, &buf);
|
||||
if (r) return r;
|
||||
|
||||
/* Allow optional equals-sign: SET var = value */
|
||||
if (ParseNonSpaceChar(p, &r, 1) == '=') {
|
||||
ParseNonSpaceChar(p, &r, 0);
|
||||
}
|
||||
|
||||
r = EvaluateExpr(p, &v);
|
||||
if (r) {
|
||||
DBufFree(&buf);
|
||||
@@ -231,6 +370,10 @@ int DoSet (Parser *p)
|
||||
|
||||
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
||||
else r = SetVar(DBufValue(&buf), &v);
|
||||
if (buf.len > VAR_NAME_LEN) {
|
||||
Eprint("Warning: Variable name `%.*s...' truncated to `%.*s'",
|
||||
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
|
||||
}
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
}
|
||||
@@ -281,6 +424,8 @@ int DoDump(ParsePtr p)
|
||||
Var *v;
|
||||
DynamicBuffer buf;
|
||||
|
||||
if (PurgeMode) return OK;
|
||||
|
||||
DBufInit(&buf);
|
||||
r = ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
@@ -383,7 +528,7 @@ void DestroyVars(int all)
|
||||
/* Given the name of a variable, "preserve" it. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int PreserveVar(char *name)
|
||||
int PreserveVar(char const *name)
|
||||
{
|
||||
Var *v;
|
||||
|
||||
@@ -440,7 +585,7 @@ int DoPreserve (Parser *p)
|
||||
|
||||
/* The structure of a system variable */
|
||||
typedef struct {
|
||||
char *name;
|
||||
char const *name;
|
||||
char modifiable;
|
||||
int type;
|
||||
void *value;
|
||||
@@ -457,49 +602,63 @@ typedef struct {
|
||||
|
||||
/* All of the system variables sorted alphabetically */
|
||||
static SysVar SysVarArr[] = {
|
||||
/* name mod type value min/mal max */
|
||||
{ "CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
|
||||
{ "CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
|
||||
{ "Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||
{ "DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||
{ "DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
|
||||
{ "DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
|
||||
{ "DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
|
||||
{ "DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
|
||||
{ "EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
|
||||
{ "EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
|
||||
{ "FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
|
||||
{ "FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
|
||||
{ "FormWidth", 1, INT_TYPE, &FormWidth, 20, 132 },
|
||||
{ "HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||
{ "IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
||||
{ "InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
||||
{ "LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
||||
{ "LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
||||
{ "LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
||||
{ "Location", 1, STR_TYPE, &Location, 0, 0 },
|
||||
{ "LongDeg", 1, INT_TYPE, &LongDeg, -180, 180 },
|
||||
{ "LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
|
||||
{ "LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
|
||||
{ "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||
{ "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 },
|
||||
{ "NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||
{ "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||
{ "NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
||||
{ "PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo,0, 0 },
|
||||
{ "PSCal", 0, INT_TYPE, &PsCal, 0, 0 },
|
||||
{ "RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
|
||||
{ "SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
|
||||
{ "SortByDate", 0, INT_TYPE, &SortByDate, 0, 0},
|
||||
{ "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0},
|
||||
{ "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0},
|
||||
{ "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132},
|
||||
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 }
|
||||
/* name mod type value min/mal max */
|
||||
{"CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
|
||||
{"CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
|
||||
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
|
||||
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999},
|
||||
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
|
||||
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
|
||||
{"DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
|
||||
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
|
||||
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
|
||||
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
|
||||
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
|
||||
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
|
||||
{"FormWidth", 1, INT_TYPE, &FormWidth, 20, 132 },
|
||||
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
||||
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
||||
{"LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
||||
{"LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
||||
{"LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
||||
{"Location", 1, STR_TYPE, &Location, 0, 0 },
|
||||
{"LongDeg", 1, INT_TYPE, &LongDeg, -180, 180 },
|
||||
{"LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
|
||||
{"LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
|
||||
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||
{"MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -780, 780 },
|
||||
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
||||
{"PrefixLineNo", 0, INT_TYPE, &DoPrefixLineNo, 0, 0 },
|
||||
{"PSCal", 0, INT_TYPE, &PsCal, 0, 0 },
|
||||
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
|
||||
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
|
||||
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 },
|
||||
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 },
|
||||
{"SortByTime", 0, INT_TYPE, &SortByTime, 0, 0 },
|
||||
{"SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132 },
|
||||
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
|
||||
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
|
||||
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
|
||||
{"Tw", 0, SPECIAL_TYPE, trig_wday_func, 0, 0 },
|
||||
{"Ty", 0, SPECIAL_TYPE, trig_year_func, 0, 0 },
|
||||
{"U", 0, SPECIAL_TYPE, today_date_func, 0, 0 },
|
||||
{"Ud", 0, SPECIAL_TYPE, today_day_func, 0, 0 },
|
||||
{"Um", 0, SPECIAL_TYPE, today_mon_func, 0, 0 },
|
||||
{"UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 },
|
||||
{"Uw", 0, SPECIAL_TYPE, today_wday_func, 0, 0 },
|
||||
{"Uy", 0, SPECIAL_TYPE, today_year_func, 0, 0 }
|
||||
};
|
||||
|
||||
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
|
||||
static SysVar *FindSysVar (const char *name);
|
||||
static void DumpSysVar (const char *name, const SysVar *v);
|
||||
static SysVar *FindSysVar (char const *name);
|
||||
static void DumpSysVar (char const *name, const SysVar *v);
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* SetSysVar */
|
||||
@@ -507,7 +666,7 @@ static void DumpSysVar (const char *name, const SysVar *v);
|
||||
/* Set a system variable to the indicated value. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int SetSysVar(const char *name, Value *value)
|
||||
int SetSysVar(char const *name, Value *value)
|
||||
{
|
||||
SysVar *v = FindSysVar(name);
|
||||
if (!v) return E_NOSUCH_VAR;
|
||||
@@ -542,7 +701,7 @@ int SetSysVar(const char *name, Value *value)
|
||||
/* Get the value of a system variable */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int GetSysVar(const char *name, Value *val)
|
||||
int GetSysVar(char const *name, Value *val)
|
||||
{
|
||||
SysVar *v = FindSysVar(name);
|
||||
|
||||
@@ -577,7 +736,7 @@ int GetSysVar(const char *name, Value *val)
|
||||
/* Find a system var with specified name. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static SysVar *FindSysVar(const char *name)
|
||||
static SysVar *FindSysVar(char const *name)
|
||||
{
|
||||
int top=NUMSYSVARS-1, bottom=0;
|
||||
int mid=(top + bottom) / 2;
|
||||
@@ -601,9 +760,9 @@ static SysVar *FindSysVar(const char *name)
|
||||
/* If name is "", dump all system variables. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
void DumpSysVarByName(const char *name)
|
||||
void DumpSysVarByName(char const *name)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
SysVar *v;
|
||||
|
||||
if (!name || !*name) {
|
||||
@@ -623,7 +782,7 @@ void DumpSysVarByName(const char *name)
|
||||
/* Dump the system variable. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void DumpSysVar(const char *name, const SysVar *v)
|
||||
static void DumpSysVar(char const *name, const SysVar *v)
|
||||
{
|
||||
char buffer[VAR_NAME_LEN+10];
|
||||
|
||||
@@ -631,6 +790,10 @@ static void DumpSysVar(const char *name, const SysVar *v)
|
||||
if (!v && !name) return; /* Shouldn't happen... */
|
||||
|
||||
buffer[0]='$'; buffer[1] = 0;
|
||||
if (name && strlen(name) > VAR_NAME_LEN) {
|
||||
fprintf(ErrFp, "$%s: Name too long\n", name);
|
||||
return;
|
||||
}
|
||||
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
||||
fprintf(ErrFp, "%*s ", VAR_NAME_LEN+1, buffer);
|
||||
if (v) {
|
||||
@@ -638,12 +801,11 @@ static void DumpSysVar(const char *name, const SysVar *v)
|
||||
Value val;
|
||||
SysVarFunc f = (SysVarFunc) v->value;
|
||||
f(0, &val);
|
||||
if (DoCoerce(STR_TYPE, &val) == OK) {
|
||||
fprintf(ErrFp, "\"%s\"\n", val.v.str);
|
||||
}
|
||||
PrintValue(&val, ErrFp);
|
||||
Putc('\n', ErrFp);
|
||||
DestroyValue(val);
|
||||
} else if (v->type == STR_TYPE) {
|
||||
char *s = *((char **)v->value);
|
||||
char const *s = *((char **)v->value);
|
||||
int y;
|
||||
Putc('"', ErrFp);
|
||||
for (y=0; y<MAX_PRT_LEN && *s; y++) {
|
||||
@@ -657,6 +819,12 @@ static void DumpSysVar(const char *name, const SysVar *v)
|
||||
Putc('"', ErrFp);
|
||||
if (*s) fprintf(ErrFp, "...");
|
||||
Putc('\n', ErrFp);
|
||||
} else if (v->type == DATE_TYPE) {
|
||||
Value val;
|
||||
val.type = DATE_TYPE;
|
||||
val.v.val = * (int *) v->value;
|
||||
PrintValue(&val, ErrFp);
|
||||
Putc('\n', ErrFp);
|
||||
} else {
|
||||
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));
|
||||
else {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* VERSION.H */
|
||||
/* */
|
||||
/* What version of remind do we have? */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-1998 by David F. Skoll */
|
||||
/* Copyright (C) 1999-2007 by Roaring Penguin Software Inc. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
#define VERSION "03.01.02"
|
||||
1
src/version.h.in
Normal file
1
src/version.h.in
Normal file
@@ -0,0 +1 @@
|
||||
#define VERSION "@VERSION@"
|
||||
8
sync-to-dianne-git
Executable file
8
sync-to-dianne-git
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
cd /home/dfs/Software/Remind.git || exit 1
|
||||
|
||||
rm -f .git/COMMIT_EDITMSG .git/*~
|
||||
|
||||
git update-server-info && cd .git && rsync --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
|
||||
exit $?
|
||||
|
||||
17
tests/colors.rem
Normal file
17
tests/colors.rem
Normal file
@@ -0,0 +1,17 @@
|
||||
REM 28 SPECIAL COLOR 0 0 0 Black
|
||||
REM 28 SPECIAL COLOR 65 0 0 Dim Red
|
||||
REM 28 SPECIAL COLOR 0 65 0 Dim Green
|
||||
REM 28 SPECIAL COLOR 0 0 65 Dim Blue
|
||||
REM 28 SPECIAL COLOR 0 65 65 Dim Cyan
|
||||
REM 28 SPECIAL COLOR 65 0 65 Dim Magenta
|
||||
REM 28 SPECIAL COLOR 65 65 0 Dim Yellow
|
||||
REM 28 SPECIAL COLOR 65 65 65 Dim White
|
||||
|
||||
REM 28 SPECIAL COLOUR 129 0 0 Bright Red
|
||||
REM 28 SPECIAL COLOUR 0 129 0 Bright Green
|
||||
REM 28 SPECIAL COLOUR 0 0 129 Bright Blue
|
||||
REM 28 SPECIAL COLOUR 0 129 129 Bright Cyan
|
||||
REM 28 SPECIAL COLOUR 129 0 129 Bright Magenta
|
||||
REM 28 SPECIAL COLOUR 129 129 0 Bright Yellow
|
||||
REM 28 SPECIAL COLOUR 129 129 129 Bright White
|
||||
|
||||
1
tests/file.ps
Normal file
1
tests/file.ps
Normal file
@@ -0,0 +1 @@
|
||||
(Second-Bit-Of-PS)
|
||||
1
tests/file2.ps
Normal file
1
tests/file2.ps
Normal file
@@ -0,0 +1 @@
|
||||
(Fourth-Bit-Of-PS)
|
||||
1
tests/include_dir/01.rem
Normal file
1
tests/include_dir/01.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG 01
|
||||
1
tests/include_dir/02.rem
Normal file
1
tests/include_dir/02.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG 02
|
||||
1
tests/include_dir/03.notrem
Normal file
1
tests/include_dir/03.notrem
Normal file
@@ -0,0 +1 @@
|
||||
REM MSG IGNORE
|
||||
1
tests/include_dir/04cantread.rem
Normal file
1
tests/include_dir/04cantread.rem
Normal file
@@ -0,0 +1 @@
|
||||
REM 15 MSG You can't read this file.
|
||||
1
tests/include_dir_no_rems/03.notrem
Normal file
1
tests/include_dir_no_rems/03.notrem
Normal file
@@ -0,0 +1 @@
|
||||
REM MSG IGNORE
|
||||
5
tests/include_test.rem
Normal file
5
tests/include_test.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
INCLUDE include_dir
|
||||
INCLUDE include_dir_no_rems
|
||||
INCLUDE nonexistent_include_dir
|
||||
|
||||
REM 15 MSG Whee!!!!
|
||||
7
tests/purge_dir/f1.rem
Normal file
7
tests/purge_dir/f1.rem
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is f1.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
INCLUDE [filedir()]/f2.rem
|
||||
|
||||
REM 1 Oct 1991 MSG old1.
|
||||
|
||||
REM Monday UNTIL 1 Oct 1991 MSG old2.
|
||||
6
tests/purge_dir/f2.rem
Normal file
6
tests/purge_dir/f2.rem
Normal file
@@ -0,0 +1,6 @@
|
||||
# This is f2.rem
|
||||
|
||||
REM 3 feb 2012 MSG new
|
||||
REM 3 1998 MSG old
|
||||
|
||||
INCLUDE [filedir()]/f3.rem
|
||||
92
tests/purge_dir/f3.rem
Normal file
92
tests/purge_dir/f3.rem
Normal file
@@ -0,0 +1,92 @@
|
||||
# This is f3.rem
|
||||
|
||||
REM Mon MSG repeat
|
||||
|
||||
REM Mon SATISFY [1] MSG repeat
|
||||
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
IF 1
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
|
||||
IFTRIG 1991
|
||||
REM MSG wookie
|
||||
ENDIF
|
||||
|
||||
# More complex conditional statements
|
||||
IF 1
|
||||
IF 0
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
ELSE
|
||||
IF 1
|
||||
REM 1991 MSG wookie
|
||||
ELSE
|
||||
REM 1991 MSG wookie
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
REM [1990+1] MSG old-with-constant-expression
|
||||
|
||||
REM [1990+1] \
|
||||
MSG Continued line-old-with-constant-expression
|
||||
|
||||
REM 1990 \
|
||||
MSG expired-continued-line
|
||||
|
||||
set y 1990
|
||||
|
||||
REM [y+1] MSG old-with-nonconstant-expression
|
||||
|
||||
# A comment that should be preserved
|
||||
|
||||
#!P A comment that should be nuked because it \
|
||||
starts with #!P
|
||||
|
||||
REM [y+1] \
|
||||
MSG Continued-line-old-with-nonconstant-expression
|
||||
|
||||
OMIT 25 Dec MSG woaaahh!
|
||||
OMIT 24 Dec
|
||||
|
||||
OMIT 1 Jan 1992 MSG woaaahah... expired
|
||||
OMIT 2 Jan 1992
|
||||
|
||||
# Complicated expressions
|
||||
SET a 3
|
||||
FSET const(x) x+3
|
||||
FSET nonconst(x) x+a
|
||||
|
||||
REM [const(5)] Jan 1992 MSG expired... should be commented out
|
||||
REM [const(a)] Jan 1992 MSG nonconstant expression
|
||||
REM [nonconst(5)] Jan 1992 MSG nonconstant expression
|
||||
REM [value("a")] Jan 1992 MSG nonconstant expression
|
||||
|
||||
IF 0
|
||||
# A comment in a false IF block
|
||||
#!P This should be nuked
|
||||
ENDIF
|
||||
|
||||
# Busted line
|
||||
REM [0/0] Jan 1992 MSG ouch
|
||||
|
||||
ERRMSG blorky
|
||||
FLUSH
|
||||
SET a 1
|
||||
FSET a(x) x*x
|
||||
UNSET a
|
||||
CLEAR-OMIT-CONTEXT
|
||||
PUSH-OMIT-CONTEXT
|
||||
POP-OMIT-CONTEXT
|
||||
BANNER wow
|
||||
DEBUG +x
|
||||
DEBUG -x
|
||||
DUMP $
|
||||
EXIT 0
|
||||
PRESERVE i
|
||||
|
||||
3
tests/runinc.rem
Normal file
3
tests/runinc.rem
Normal file
@@ -0,0 +1,3 @@
|
||||
set s shell("echo 3")
|
||||
run on
|
||||
set s shell("echo 3")
|
||||
6
tests/runtest.rem
Normal file
6
tests/runtest.rem
Normal file
@@ -0,0 +1,6 @@
|
||||
run off
|
||||
set a shell("echo 2")
|
||||
run on
|
||||
set a shell("echo 2")
|
||||
run off
|
||||
include ../tests/runinc.rem
|
||||
30
tests/shade.rem
Normal file
30
tests/shade.rem
Normal file
@@ -0,0 +1,30 @@
|
||||
set $MinsFromUTC -240
|
||||
set $CalcUTC 0
|
||||
set $Location "Ottawa"
|
||||
set $LongDeg 75
|
||||
set $LongMin 39
|
||||
set $LongSec 0
|
||||
set $LatDeg 45
|
||||
set $LatMin 24
|
||||
set $LatSec 0
|
||||
|
||||
IF $PSCAL
|
||||
[trigger(moondate(0))] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||
[trigger(moondate(1))] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||
[trigger(moondate(2))] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||
[trigger(moondate(3))] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||
ENDIF
|
||||
|
||||
REM 4 PS (First-Bit-Of-PS)
|
||||
REM 4 PSFILE file.ps
|
||||
REM 4 PS (Third-Bit-Of-PS)
|
||||
REM 4 PSFILE file2.ps
|
||||
|
||||
REM Mon SPECIAL SHADE 255 255 255
|
||||
REM Tue SPECIAL SHADE 255 255 204
|
||||
REM Wed SPECIAL SHADE 255 204 255
|
||||
REM Thu SPECIAL SHADE 204 255 255
|
||||
REM Fri SPECIAL SHADE 255 204 204
|
||||
REM Sat SPECIAL SHADE 204 255 204
|
||||
REM Sun SPECIAL SHADE 204 204 255
|
||||
|
||||
13
tests/sun.rem
Normal file
13
tests/sun.rem
Normal file
@@ -0,0 +1,13 @@
|
||||
SET $LatDeg 45
|
||||
SET $LatMin 24
|
||||
SET $LatSec 0
|
||||
SET $LongDeg 75
|
||||
SET $LongMin 39
|
||||
SET $LongSec 0
|
||||
SET $MinsFromUTC -300
|
||||
SET $CalcUTC 0
|
||||
|
||||
MSG Dawn: [dawn()]
|
||||
MSG Sunrise: [sunrise()]
|
||||
MSG Sunset: [sunset()]
|
||||
MSG Dusk: [dusk()]
|
||||
@@ -7,26 +7,98 @@
|
||||
# in the build directory.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-1997 David F. Skoll
|
||||
# Copyright (C) 1999-2000 Roaring Penguin Software Inc.
|
||||
# Copyright (C) 1992-2018 Dianne Skoll
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
DIR=`dirname $0`
|
||||
cd $DIR
|
||||
if test $? != 0 ; then
|
||||
echo "Unable to cd $DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 000 include_dir/04cantread.rem
|
||||
TEST_GETENV="foo bar baz" ; export TEST_GETENV
|
||||
echo "Test 1" > ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 2" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 3" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 4" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 5" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 6" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 7" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Test 8" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -df -p -l -b2 ../tests/include_dir 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Test 9" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -df -p -l -b2 ../tests/nonexistent_include_dir 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
../src/remind -df -p -l -b2 ../tests/include_dir_no_rems 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
../src/remind -df -p -l -b2 ../tests/include_test.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
chmod 644 include_dir/04cantread.rem
|
||||
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "MON WKDAY DAY across year test" >> ../tests/test.out
|
||||
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Sort Test" >> ../tests/test.out
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Purge Test" >> ../tests/test.out
|
||||
../src/remind -j999 ../tests/purge_dir/f1.rem 3 Feb 2012 >> ../tests/test.out 2>&1
|
||||
echo "F1" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f1.rem.purged >> ../tests/test.out
|
||||
echo "F2" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f2.rem.purged >> ../tests/test.out
|
||||
echo "F3" >> ../tests/test.out
|
||||
cat ../tests/purge_dir/f3.rem.purged >> ../tests/test.out
|
||||
|
||||
rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
|
||||
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
|
||||
|
||||
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
|
||||
|
||||
# The sun tests can fail due to math roundoff error changing the times
|
||||
# by a minute...
|
||||
# ../src/remind -p12 ../tests/sun.rem 1 Jan 2011 >> ../tests/test.out 2>&1
|
||||
|
||||
# Test -a vs -aa
|
||||
../src/remind -q -a - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
|
||||
REM 1 Jan 2012 AT 8:00 MSG 8am: Should not show up
|
||||
REM 1 Jan 2012 AT 9:00 MSG 9am: Should not show up
|
||||
REM 1 Jan 2012 AT 10:00 MSG 10am: Should not show up
|
||||
MSG [$DontTrigAts]
|
||||
EOF
|
||||
|
||||
../src/remind -q -a -a - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
|
||||
REM 1 Jan 2012 AT 8:00 MSG 8am: Should not show up
|
||||
REM 1 Jan 2012 AT 9:00 MSG 9am: Should show up
|
||||
REM 1 Jan 2012 AT 10:00 MSG 10am: Should show up
|
||||
MSG [$DontTrigAts]
|
||||
EOF
|
||||
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
|
||||
3001
tests/test.cmp
3001
tests/test.cmp
File diff suppressed because it is too large
Load Diff
157
tests/test.rem
157
tests/test.rem
@@ -5,6 +5,16 @@
|
||||
#
|
||||
# ./test-rem # From WITHIN Remind source directory!
|
||||
|
||||
# Should issue a warning
|
||||
fset year(x) 1
|
||||
|
||||
# Don't evaluate SATISFY expressions if reminder has expired
|
||||
|
||||
REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
|
||||
|
||||
# bad AT
|
||||
REM AT 0:00 0:01 0:02 MSG foo
|
||||
|
||||
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
|
||||
fset _h(x, y) trigger(hebdate(x,y))
|
||||
|
||||
@@ -41,6 +51,9 @@ fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
|
||||
[_i(29, "Adar A", today(), 5755)] MSG Leap
|
||||
[_i(29, "Adar A", today(), 5756)] MSG Illegal
|
||||
|
||||
# This causes a parse error on version 03.01.01
|
||||
REM 1990-01-01 SATISFY 1
|
||||
|
||||
# Test each possible case of the basic reminders.
|
||||
|
||||
REM MSG Every Day
|
||||
@@ -128,7 +141,7 @@ CLEAR-OMIT-CONTEXT
|
||||
REM 1 Mar -1 MSG 1 mar -1
|
||||
REM 1 Mar --1 MSG 1 mar --1
|
||||
REM 28 Feb BEFORE MSG 28 Feb BEFORE
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb SKIP MSG 28 Feb SKIP
|
||||
REM 28 Feb AFTER MSG 28 Feb AFTER
|
||||
|
||||
POP-OMIT-CONTEXT
|
||||
@@ -140,7 +153,7 @@ REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
|
||||
|
||||
|
||||
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
|
||||
|
||||
|
||||
# Test BACK
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
|
||||
@@ -159,6 +172,29 @@ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
REM Fri after MSG 16 Feb 1991
|
||||
CLEAR-OMIT-CONTEXT
|
||||
REM Fri SCANFROM -7 SATISFY 1
|
||||
OMIT [trigger(trigdate())]
|
||||
REM Fri after MSG 16 Feb 1991
|
||||
CLEAR-OMIT-CONTEXT
|
||||
|
||||
# Test omitfunc
|
||||
fset _ofunc(x) (day(x) < 7 || day(x) % 2)
|
||||
REM 1 March OMITFUNC _ofunc AFTER MSG OmitFunc Test
|
||||
REM 8 March OMITFUNC _ofunc -1 MSG OmitFunc Test 2
|
||||
|
||||
# omitfunc ignores local/global omits
|
||||
fset _ofunc(x) 0
|
||||
OMIT 1 March
|
||||
OMIT 2 March 1991
|
||||
REM 1 March OMIT Sun OMITFUNC _ofunc AFTER MSG Should trigger 1 March
|
||||
REM 1 March OMIT Sun AFTER MSG Should trigger 4 March
|
||||
|
||||
# Test shorthand reminders
|
||||
REM 1991-02-28 MSG Feb 28
|
||||
REM 1991/02/28@14:45 MSG Feb 28
|
||||
REM Wed UNTIL 1991-01-01 MSG Expired
|
||||
REM Wed SCANFROM 1991-02-26 MSG SCANFROM
|
||||
|
||||
set a000 abs(1)
|
||||
set a001 abs(-1)
|
||||
set a002 asc("foo")
|
||||
@@ -244,10 +280,125 @@ set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
|
||||
msg [a075]%
|
||||
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
|
||||
msg [a076]%
|
||||
set a077 dosubst("%y %z", '1992/5/5')
|
||||
set a074 dosubst("%*a %*b %*c %*d %*e %*f %*g %*h", '1992/5/5')
|
||||
msg [a074]%
|
||||
set a075 dosubst("%*i %*j %*k %*l %*m %*n %*o %*p", '1992/5/5')
|
||||
msg [a075]%
|
||||
set a076 dosubst("%*q %*r %*s %*t %*u %*v %*w %*x", '1992/5/5')
|
||||
msg [a076]%
|
||||
set a077 dosubst("%*y %*z", '1992/5/5')
|
||||
msg [a077]%
|
||||
set a074 dosubst("%A %B %C %D %E %F %G %H", '1992/5/5')
|
||||
msg [a074]%
|
||||
set a075 dosubst("%I %J %K %L %M %N %O %P", '1992/5/5')
|
||||
msg [a075]%
|
||||
set a076 dosubst("%Q %R %S %T %U %V %W %X", '1992/5/5')
|
||||
msg [a076]%
|
||||
set a077 dosubst("%Y %Z", '1992/5/5')
|
||||
msg [a077]%
|
||||
set a074 dosubst("%*A %*B %*C %*D %*E %*F %*G %*H", '1992/5/5')
|
||||
msg [a074]%
|
||||
set a075 dosubst("%*I %*J %*K %*L %*M %*N %*O %*P", '1992/5/5')
|
||||
msg [a075]%
|
||||
set a076 dosubst("%*Q %*R %*S %*T %*U %*V %*W %*X", '1992/5/5')
|
||||
msg [a076]%
|
||||
set a077 dosubst("%*Y %*Z", '1992/5/5')
|
||||
msg [a077]%
|
||||
set a078 easterdate(today())
|
||||
set a079 easterdate(1992)
|
||||
set a080 easterdate(1995)
|
||||
set a081 ""
|
||||
OMIT 1991-03-11
|
||||
set a082 slide('1991-03-01', 7, "Sat", "Sun")
|
||||
set a083 slide('1991-04-01', -7, "Sat")
|
||||
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
|
||||
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
|
||||
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 MSG foo
|
||||
set a086 trigback()
|
||||
set a087 trigdelta()
|
||||
set a088 trigrep()
|
||||
set a089 triguntil()
|
||||
set a090 trigscanfrom()
|
||||
set a091 trigfrom()
|
||||
set a092 trigpriority()
|
||||
set a093 trigtimedelta()
|
||||
set a094 trigtimerep()
|
||||
set a095 trigduration()
|
||||
|
||||
REM Mon Wed FROM 2010-09-03 ++3 --4 MSG foo
|
||||
set a096 trigback()
|
||||
set a097 trigdelta()
|
||||
set a098 trigrep()
|
||||
set a099 triguntil()
|
||||
set a100 trigscanfrom()
|
||||
set a101 trigfrom()
|
||||
set a102 trigpriority()
|
||||
set a103 trigtimedelta()
|
||||
set a104 trigtimerep()
|
||||
set a105 trigduration()
|
||||
|
||||
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 AT 14:41 +15 *2 DURATION 3:33 MSG foo
|
||||
set a106 trigback()
|
||||
set a107 trigdelta()
|
||||
set a108 trigrep()
|
||||
set a109 triguntil()
|
||||
set a110 trigscanfrom()
|
||||
set a111 trigfrom()
|
||||
set a112 trigpriority()
|
||||
set a113 trigtimedelta()
|
||||
set a114 trigtimerep()
|
||||
set a115 trigduration()
|
||||
|
||||
REM Mon Wed FROM 2010-09-03 ++3 --4 AT 14:44 MSG foo
|
||||
set a116 trigback()
|
||||
set a117 trigdelta()
|
||||
set a118 trigrep()
|
||||
set a119 triguntil()
|
||||
set a120 trigscanfrom()
|
||||
set a121 trigfrom()
|
||||
set a122 trigpriority()
|
||||
set a123 trigtimedelta()
|
||||
set a124 trigtimerep()
|
||||
set a125 trigduration()
|
||||
|
||||
# Test adding TIME+TIME and DATETIME+TIME
|
||||
set a126 11:00 + 3:00
|
||||
set a127 23:00 + 5:30
|
||||
set a128 '2018-02-03@10:00' + 6:45
|
||||
set a129 23:30 + '2019-02-02@16:44'
|
||||
|
||||
# Multi-day reminder
|
||||
REM 13 AT 16:00 DURATION 72:00 MSG 72-hour event
|
||||
set a130 trigdate()
|
||||
set a131 trigtime()
|
||||
set a132 trigdatetime()
|
||||
set a133 trigduration()
|
||||
set a134 trigeventstart()
|
||||
set a135 trigeventduration()
|
||||
|
||||
dump
|
||||
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
OMIT December 25 MSG X
|
||||
# Next should give a parse error
|
||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
OMIT DUMP
|
||||
# Regression test for bugfix in Hebrew calendar Adar jahrzeit
|
||||
[_i(14, "Adar", today(), 5761)] MSG Purim
|
||||
|
||||
# Check combo of SATISFY and long-duration events
|
||||
REM 14 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 8:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 8:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 32:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 32:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 40:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
|
||||
# This is now an error
|
||||
REM DURATION 15:00 MSG Should fail... need AT if you have DURATION.
|
||||
|
||||
__EOF__
|
||||
REM This line should not even be seen
|
||||
And you can put whatever you like here.
|
||||
[+f=asdfasdasde3ir0a]
|
||||
|
||||
|
||||
@@ -38,3 +38,6 @@ REM 22 AUG SPECIAL PostScript (cabbage) show
|
||||
REM 23 AUG AT 16:44 SPECIAL blort snoo glup
|
||||
REM 24 AUG SPECIAL blort gulp wookie
|
||||
|
||||
# Bug discovered by Paul Pelzl
|
||||
OMIT 13 August
|
||||
REM 6 August 2007 *7 SKIP SATISFY [1] MSG Blort
|
||||
|
||||
29
tests/test3.rem
Normal file
29
tests/test3.rem
Normal file
@@ -0,0 +1,29 @@
|
||||
REM 1 AT 11:00 MSG Wookie
|
||||
REM 1 AT 12:00 MSG Cookie
|
||||
REM 1 AT 13:00 MSG Snookie
|
||||
|
||||
REM 1 AT 11:00 DURATION 0:45 MSG Lettuce
|
||||
REM 1 AT 12:00 DURATION 0:45 MSG Cabbage
|
||||
REM 1 AT 13:00 DURATION 0:45 MSG Tomato
|
||||
|
||||
REM 1 AT 11:00 DURATION 1:45 MSG Apple
|
||||
REM 1 AT 12:00 DURATION 2:45 MSG Pear
|
||||
REM 1 AT 13:00 DURATION 3:45 MSG Grape
|
||||
|
||||
REM 1 AT 11:00 DURATION 14:45 MSG Green
|
||||
REM 1 AT 12:00 DURATION 14:45 MSG Blue
|
||||
REM 1 AT 13:00 DURATION 14:45 MSG Red
|
||||
|
||||
REM 1 AT 11:00 DURATION 24:45 MSG Yellow
|
||||
REM 1 AT 12:00 DURATION 24:45 MSG Orange
|
||||
REM 1 AT 13:00 DURATION 24:45 MSG Magenta
|
||||
|
||||
REM 1 AT 11:00 DURATION 36:45 MSG Purple
|
||||
REM 1 AT 12:00 DURATION 36:45 MSG Black
|
||||
REM 1 AT 13:00 DURATION 36:45 MSG Brown
|
||||
|
||||
REM 1 AT 11:00 DURATION 48:45 MSG Sad
|
||||
REM 1 AT 12:00 DURATION 48:45 MSG Happy
|
||||
REM 1 AT 13:00 DURATION 48:45 MSG Strange
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user