Compare commits

..

138 Commits

Author SHA1 Message Date
David F. Skoll
e18b4ed119 Update copyright. 2009-05-31 13:06:05 -04:00
David F. Skoll
51f6ffc093 Document changes. 2009-05-31 13:05:05 -04:00
David F. Skoll
72de7c6b14 Make CallFunc and built-in functions re-entrant. 2009-05-26 22:35:57 -04:00
David F. Skoll
bd4785d631 Remove spurious trigger() function calls from examples.
Bump version to 3.1.7
2009-05-16 10:56:12 -04:00
David F. Skoll
cb08f12470 Add another test. 2009-05-16 10:47:54 -04:00
David F. Skoll
04146db69b More man page updates. 2009-05-16 10:47:10 -04:00
David F. Skoll
d3fe045a39 Make slide function diagnose "Can't OMIT every weekday" 2009-05-16 10:42:43 -04:00
David F. Skoll
2be1e16087 Add some tests. 2009-05-16 10:30:25 -04:00
David F. Skoll
051e44ae3e Update man page. 2009-05-16 10:22:43 -04:00
David F. Skoll
6d5ae7a258 Allow short-hand date specs after UNTIL and SCANFROM.
Start updating man page.
2009-05-16 10:07:57 -04:00
David F. Skoll
2e69e140eb Accept a T_Date or T_DateTime on cmdline to set now() and today(). 2009-05-12 22:46:01 -04:00
David F. Skoll
516c4e2c39 Allow literal dates and datetimes in REM and OMIT statements.
This lets us avoid cluttering up files with [trigger(expr)]; we can
use [expr] directly.
2009-05-09 16:41:15 -04:00
David F. Skoll
b58ed62000 Simplify. 2009-05-09 00:17:11 -04:00
David F. Skoll
c685818783 Use macro to refer to RetVal.v.val 2009-05-09 00:10:45 -04:00
David F. Skoll
3e20ce56c9 Add the slide(date, amt [,localomits]) built-in function. 2009-05-09 00:07:59 -04:00
David F. Skoll
dd8d67f659 Update man page. 2009-02-03 23:11:50 -05:00
David F. Skoll
5ef4061819 Let Remind accept a date of the form YYYY-MM-DD on cmdline. 2009-02-03 23:08:27 -05:00
David F. Skoll
a146a0c819 Update WHATSNEW; fix typo in man page. 2008-11-16 11:01:01 -05:00
David F. Skoll
0f5a93cdf1 Fix up man page. 2008-11-16 10:51:10 -05:00
David F. Skoll
7db51e913e Clarify WEEK example. 2008-11-15 09:24:09 -05:00
David F. Skoll
93ac1aebf7 Document WEEK special. Clean up rem2ps handling of WEEK. 2008-11-15 09:20:54 -05:00
David F. Skoll
56ebedb9de Proper implementation of WEEK special. 2008-11-14 17:02:51 -05:00
David F. Skoll
e87d33de50 Handle the WEEK special. 2008-11-14 16:56:08 -05:00
David F. Skoll
a5774fd793 Document weekno() function. 2008-11-14 16:16:13 -05:00
David F. Skoll
adb60f3400 Fix example in man page. 2008-11-14 16:07:25 -05:00
David F. Skoll
47a0f63caa Fix tests. 2008-10-05 14:29:31 -04:00
David F. Skoll
30a385a7bb Fix bug in IsTopLevel. 2008-10-05 14:29:03 -04:00
David F. Skoll
9f2ae1773c Document evaltrig. 2008-10-05 14:11:58 -04:00
David F. Skoll
f470297958 Make max. string length controllable with $MaxStringLen system variable. 2008-10-05 13:49:45 -04:00
David F. Skoll
93dfc7995c Fix man page. 2008-09-23 22:39:12 -04:00
David F. Skoll
c96869817f Rejigger infrastructure to detect recursive OMITFUNC calls in evaltrig() 2008-09-23 22:21:39 -04:00
David F. Skoll
1bffa0e00b Allow any of the args to date() function to be a date,
in which case we just extract the appropriate part.
2008-09-20 11:07:33 -04:00
David F. Skoll
36035dda01 Issue a warning if we detect a SCANFROM used in two-arg evaltrig(). 2008-09-20 00:14:13 -04:00
David F. Skoll
50a15cf089 Make evaltrig return a DATETIME if there's an AT clause. 2008-09-20 00:03:38 -04:00
David F. Skoll
b59d4ed4a4 Add "evaltrig" function. 2008-09-19 23:49:11 -04:00
David F. Skoll
4c53710279 Set maximum string length to 65535 to minimize chances of self-DOS. 2008-09-19 23:28:19 -04:00
David F. Skoll
2274e88485 Remove extraneous semicolon 2008-09-19 23:10:57 -04:00
David F. Skoll
984a4677f2 Clean up funcs.c; add weekno function for ISO week number. 2008-09-19 23:08:15 -04:00
David F. Skoll
5e3dc54725 Document sorting of timed vs. untimed reminders.
Add an $UntimedFirst system variable.
2008-09-18 17:30:31 -04:00
David F. Skoll
53a7bf9773 Make tests pass. 2008-09-18 17:20:09 -04:00
David F. Skoll
1dcc3897d6 Allow sorting of untimed before timed. 2008-09-18 17:17:38 -04:00
David F. Skoll
fbc0375739 Fix bug if MON DAY WKDAY crosses year boundary. 2008-09-16 22:10:09 -04:00
David F. Skoll
4a74c03fa4 Small man-page fix. 2008-08-31 15:51:25 -04:00
David F. Skoll
d8833e6ce2 Updated man page. 2008-08-31 15:44:57 -04:00
David F. Skoll
2b8b9a56aa Fix typo. 2008-08-31 10:32:25 -04:00
David F. Skoll
85a8ebb357 Slight efficiency improvement in OMIT testing. 2008-08-31 10:30:59 -04:00
David F. Skoll
a67d9e2524 Change behaviour: OMITFUNC ignores local/global OMIT context. Only sane
way to solve garbage-day problem; also allows for more flexibility.
2008-08-31 10:29:28 -04:00
David F. Skoll
6845e72fd5 Communicate errors back for bad OMITFUNCs. 2008-08-30 22:10:06 -04:00
David F. Skoll
0ab977fa05 Whitespace cleanup 2008-08-30 21:43:38 -04:00
David F. Skoll
ad64a12b2a Update man page. 2008-08-30 16:35:48 -04:00
David F. Skoll
cfde4b50bb Updated man page. 2008-08-29 21:28:25 -04:00
David F. Skoll
f302c8eb95 Document OMITFUNC and fix huge bug. :-) 2008-08-29 21:22:48 -04:00
David F. Skoll
7ecc355358 Add test for OMITFUNC. 2008-08-29 21:03:01 -04:00
David F. Skoll
a52216d7e7 Update test.cmp for version. 2008-08-29 20:56:22 -04:00
David F. Skoll
8d8d4b667d Implement OMITFUNC clause in REM command. 2008-08-29 20:48:58 -04:00
David F. Skoll
670369121e Remove -a flag from "ShowTodaysReminders" 2008-08-28 12:29:38 -04:00
David F. Skoll
4365e580ee If main reminder file is a directory and AppendFile does not exist,
create AppendFile.
2008-04-16 21:54:05 -04:00
David F. Skoll
a8a09a905e Update test.cmp for new version. 2008-04-16 21:45:58 -04:00
David F. Skoll
dbb7381eb1 Update version number in configure. 2008-04-16 21:44:44 -04:00
David F. Skoll
aa3531a6bf Merge branch 'master' of ssh://source.roaringpenguin.com/home/dfs/personal-git-repos/Remind 2008-04-16 13:35:36 -04:00
David F. Skoll
2848203d75 Note new behaviour: set var [expr] no longer works. 2008-04-16 13:34:38 -04:00
David F. Skoll
f0aef0703c Update WHATSNEW file. 2008-04-15 18:26:25 -04:00
David F. Skoll
7356a511e0 Update release notes and man page. 2008-04-14 21:30:35 -04:00
David F. Skoll
5be26a3cff Add "c" flag to -c option that causes Remind to approximate
SPECIAL COLOR reminders with vt100 escape sequences.
2008-04-14 21:03:45 -04:00
David F. Skoll
36a80acb0c Make tkremind handle the case when ~/.reminders is a directory better.
It uses ~/.reminders/100-tkremind.rem as the append file.
2008-03-31 14:00:09 -04:00
David F. Skoll
37ab03b49d Make tkremind work better on small-screen devices like eeepc. 2008-03-30 12:11:07 -04:00
David F. Skoll
75209cb40e Update tkremind copyright date. 2008-03-27 22:13:24 -04:00
David F. Skoll
4b2d274748 Add "l" flag to -c to draw calendar
using VT100 line-drawing characters.
2008-03-27 22:04:06 -04:00
David F. Skoll
1423495b88 Document -tn option
Implement "-ca" which is analagous to "-pa" and "-sa".
2008-03-26 21:51:30 -04:00
David F. Skoll
42e4ec8890 Make DEBUG command handle "f" flag. 2008-03-25 17:21:07 -04:00
David F. Skoll
58fbd51ef4 Call globfree to free memory used by glob. 2008-03-24 23:12:27 -04:00
David F. Skoll
7552dbb812 Update copyright. Put -df in online usage blurb. 2008-03-24 21:36:29 -04:00
David F. Skoll
31e0ecb71d Fix tests for version change. 2008-03-24 20:42:19 -04:00
David F. Skoll
f6743a4f87 Bump version to 03.01.05. 2008-03-24 20:41:12 -04:00
David F. Skoll
5f574949e6 Nicer -df output. Document -df. 2008-03-24 20:39:47 -04:00
David F. Skoll
724bce4fb9 Add "-df" debugging flag to track file opens. 2008-03-24 20:22:00 -04:00
David F. Skoll
8d59f025af Patch from Ian! Allen. 2008-03-24 14:10:01 -04:00
David F. Skoll
aad44f4716 Spit out errors if we can't open a non-readable file in a dir/*.rem. 2008-03-24 14:02:39 -04:00
David F. Skoll
0a38d7d213 Output fileinfo lines in tests. 2008-03-24 13:56:51 -04:00
David F. Skoll
4fcd60fd95 Increase INCLUDE_DEPTH to account for (wasted) top-of-stack entry.
Document that filename argument for INCLUDE and command-line can be a directory.
2008-03-24 13:54:21 -04:00
David F. Skoll
38beeb8cb0 Add some tests for INCLUDE functionality. 2008-03-24 13:29:31 -04:00
David F. Skoll
26f0acab35 Opening of directories works properly. 2008-03-24 13:16:28 -04:00
David F. Skoll
3897973bc1 Improve error messages. 2008-03-24 13:11:21 -04:00
David F. Skoll
7b3da27461 Fix parse error bug in calendar mode. 2008-03-24 13:02:05 -04:00
David F. Skoll
a85ee5f31c INCLUDE /directory works. Still need more futzing to fix parse error. 2008-03-24 12:58:23 -04:00
David F. Skoll
b272863aa0 Prep for push. 2008-03-24 10:00:34 -04:00
David F. Skoll
8249964380 Start coding feature allowing "INCLUDE /directory" which basically
includes "/directory/*.rem" files in glob-order.
2008-03-22 23:28:51 -04:00
David F. Skoll
af81bbb299 Preserve "\n" in continued lines.
Set a flag if parser encounters [expr].
2008-03-15 14:06:12 -04:00
David F. Skoll
d818dd9c80 Fix bug in AM/PM option setting for existing reminders. 2008-03-09 11:23:27 -04:00
David F. Skoll
fe8e34dece Better error message if nonsensical -i option given. 2008-02-06 23:42:12 -05:00
David F. Skoll
ba928989f7 Make expression parser accept backslashes in strings so we can do:
SET a "Some \"embedded\" quotes"
2008-02-06 23:35:46 -05:00
David F. Skoll
742f973028 Allow command-line '-i' option to define a function as well as a var.
Example:  remind ... '-isquare(x)=x*x' ...

Also, allow the syntax:

      SET var = expr
      FSET func(args) = defn

Old syntax still works, of course:

      SET var expr
      FSET func(args) defn
2008-02-06 23:12:51 -05:00
David F. Skoll
043932fcbe Add a $DeltaOffset read-only system variable that is set by "-tNNN" option. 2008-02-06 22:24:45 -05:00
David F. Skoll
ad5e096caa Make '-t' take a numeric argument that sets the "DeltaOffset" to that
value.  We trigger any reminder that will trigger between today and
today+DeltaOffset days.  A bare '-t' sets InfiniteDelta as before.
2008-02-06 22:16:47 -05:00
David F. Skoll
06c8fc8f78 Oops... forgot a release note. 2008-02-03 17:14:31 -05:00
David F. Skoll
487338d10c Updated for 3.1.4 release. 2008-02-03 17:12:16 -05:00
David F. Skoll
3d1c0e5667 Fix awful bug in rem2html for a 28-day February that starts on Sunday... 2008-01-31 23:31:45 -05:00
David F. Skoll
ce3bb191c4 More code cleanups and const-correctness. 2008-01-30 21:37:19 -05:00
David F. Skoll
03e9dbf364 More const qualification. 2008-01-28 11:39:15 -05:00
David F. Skoll
518aab3d02 Don't trash argv[] so reread works properly. 2008-01-28 11:28:17 -05:00
David F. Skoll
f055664f77 More const-correctness. 2008-01-27 11:02:03 -05:00
David F. Skoll
ba3e01f2ce Add a bunch of const qualifiers. 2008-01-26 21:55:58 -05:00
David F. Skoll
b6883c8a45 Keep version number in ONE place (configure.in) instead of two. 2008-01-26 15:34:32 -05:00
David F. Skoll
9e49ee3acb Make tkremind obey -b1 option (24-hour mode.) 2008-01-26 12:01:43 -05:00
David F. Skoll
7481f68bb2 Make tkremind work better with Tk8.5. 2007-12-24 11:40:22 -05:00
David F. Skoll
99792eec03 Add a test. 2007-11-05 11:52:50 -05:00
David F. Skoll
91458c7845 Better patch for parsing bug. 2007-11-05 11:44:48 -05:00
David F. Skoll
cad5849dc0 Merge branch 'master' of ssh://magnesium.roaringpenguin.com/home/dfs/personal-git-repos/Remind 2007-11-05 11:38:17 -05:00
David F. Skoll
a38e120e99 Fix weird parsing bug if you have a SKIP on an omitted day with a SATISFY. 2007-11-05 11:37:48 -05:00
David F. Skoll
0b31a78cf2 Patch to clean up HTML output (Jorey Bump) 2007-10-16 11:46:58 -04:00
David F. Skoll
861858c1a6 Bump version to 03.01.04. 2007-10-15 14:17:09 -04:00
David F. Skoll
d43a2277da Updated WHATSNEW. 2007-10-15 14:00:09 -04:00
David F. Skoll
f678dc96b8 Write man page for rem2html 2007-10-07 22:24:35 -04:00
David F. Skoll
c2e371904e Update distclean target. 2007-10-07 22:10:25 -04:00
David F. Skoll
2a1cbff22e Add www/Makfile to gitignore. 2007-10-07 22:09:47 -04:00
David F. Skoll
a2d9f277c4 Minor tweaks to Makefile.in 2007-10-07 22:09:37 -04:00
David F. Skoll
d939059417 Improve www/Makefile stuff. 2007-10-07 22:05:35 -04:00
David F. Skoll
740cd4cfed Update README. 2007-10-06 11:41:40 -04:00
David F. Skoll
91a5306a67 Fix typo. 2007-10-06 11:38:23 -04:00
David F. Skoll
b78ffcbffd Tidy up option processing. 2007-10-06 11:35:57 -04:00
David F. Skoll
4f72f557b7 Minor fix to --nostyle output. 2007-10-05 11:52:16 -04:00
David F. Skoll
e3b21d6d0d More tweaks. 2007-10-04 22:02:27 -04:00
David F. Skoll
af28c49d8d Fixed up the www stuff. 2007-10-04 22:01:09 -04:00
David F. Skoll
67f4635573 Fix DST rules. 2007-10-04 13:41:42 -04:00
David F. Skoll
5f8d10908d Minor cleanups. 2007-10-03 12:32:41 -04:00
David F. Skoll
7307421812 Add --nostyle option to rem2html so it can produce basic HTML that does
not rely on an external stylesheet.
2007-10-02 18:47:38 -04:00
David F. Skoll
5cd3b628c5 Minor tweaks. 2007-10-02 14:03:19 -04:00
David F. Skoll
29e483ab64 Updated Makefile and rem2html to use IMGBASE for stylesheet also. 2007-10-02 11:31:06 -04:00
David F. Skoll
66ddba45af Add support for HTMLCLASS special. Add CSS code for rem-today class to
highlight "today".
2007-10-02 11:21:40 -04:00
David F. Skoll
9325b3f035 Minor tweaks to CSS. 2007-10-01 18:03:21 -04:00
David F. Skoll
522c4c94e1 Add --imgbase option. 2007-10-01 17:59:33 -04:00
David F. Skoll
730505cff3 Less verbose. 2007-10-01 17:27:58 -04:00
David F. Skoll
019783e1fa Redo rem2html. Uses CSS instead of hard-coded stuff. 2007-10-01 17:21:59 -04:00
David F. Skoll
8612bb6480 Do not evaluate SATISFY expression if reminder has expired. 2007-09-26 08:41:34 -04:00
David F. Skoll
7f1e6d21d9 Update version number and copyright year. 2007-09-24 10:32:06 -04:00
David F. Skoll
e6c0371be1 Make calendar times show duration. 2007-09-16 17:44:33 -04:00
David F. Skoll
58feaa7e0c Update version in test.cmp 2007-09-12 10:08:04 -04:00
David F. Skoll
a828378466 Update version. 2007-09-12 09:55:40 -04:00
72 changed files with 7886 additions and 4049 deletions

2
.gitignore vendored
View File

@@ -3,6 +3,7 @@ autom4te.cache
config.log config.log
config.status config.status
src/Makefile src/Makefile
www/Makefile
*.o *.o
src/config.h src/config.h
src/remind src/remind
@@ -11,3 +12,4 @@ tests/test.out
.gitignore .gitignore
*~ *~
src/rem2ps src/rem2ps
src/version.h

View File

@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
1. REMIND refers to the entire set of files and documentation in the 1. REMIND refers to the entire set of files and documentation in the
REMIND package. REMIND package.
2. REMIND is Copyright 1999-2005 Roaring Penguin Software Inc., 2. REMIND is Copyright 1999-2008 Roaring Penguin Software Inc.,
except where noted in individual files. except where noted in individual files.
3. DISTRIBUTION AND USE 3. DISTRIBUTION AND USE

View File

@@ -28,7 +28,7 @@ test:
cd src && $(MAKE) test cd src && $(MAKE) test
distclean: clean 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 src/Makefile: src/Makefile.in
./configure ./configure

5307
configure vendored

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,7 @@ AC_CHECK_SIZEOF(unsigned int)
AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long)
dnl Checks for header files. dnl Checks for header files.
AC_CHECK_HEADERS(sys/file.h) AC_CHECK_HEADERS(sys/file.h glob.h)
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_STRUCT_TM AC_STRUCT_TM
@@ -44,5 +44,7 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes" CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
fi fi
AC_CHECK_FUNCS(setenv unsetenv) AC_CHECK_FUNCS(setenv unsetenv glob)
AC_OUTPUT(src/Makefile) VERSION=03.01.07
AC_SUBST(VERSION)
AC_OUTPUT(src/Makefile www/Makefile src/version.h)

View File

@@ -1,5 +1,113 @@
CHANGES TO REMIND CHANGES TO REMIND
* 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 * Version 3.1 Patch 2 - 2007-09-12
+ MINOR ENHANCEMENTS + MINOR ENHANCEMENTS

View File

@@ -27,8 +27,8 @@ RUN OFF
################################################ ################################################
# Ensure required version of remind is used... # # Ensure required version of remind is used... #
################################################ ################################################
IF version() < "03.00.19" IF version() < "03.01.07"
ERRMSG This file requires at least version 03.00.19 of Remind.% ERRMSG This file requires at least version 03.01.07 of Remind.%
ERRMSG This version is version [version()]. ERRMSG This version is version [version()].
EXIT EXIT
ENDIF ENDIF
@@ -93,53 +93,10 @@ SET Week_1 1
SET Week_2 8 SET Week_2 8
SET Week_3 15 SET Week_3 15
SET Week_4 22 SET Week_4 22
FSET _last(mo) "1 " + MON((mo%12)+1)+" --7" FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
# Shorthand for commonly used expression...
FSET _trig() TRIGGER(TRIGDATE())
# Handy function to provide SCANFROM dates... # Handy function to provide SCANFROM dates...
FSET _back(days) TRIGGER(TODAY()-days) FSET _back(days) 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
########################################################### ###########################################################
# Function which returns a string in "am/pm" format based # # Function which returns a string in "am/pm" format based #
@@ -209,14 +166,14 @@ FSET _mail(from, subj) "fastmail -f " + \
REM 4 July SCANFROM [_back(7)] SATISFY 1 REM 4 July SCANFROM [_back(7)] SATISFY 1
IF WKDAYNUM(TRIGDATE()) == Sat IF WKDAYNUM(TRIGDATE()) == Sat
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual) REM [TRIGDATE()] MSG Independence day (actual)
OMIT [TRIGGER(TRIGDATE()-1)] MSG Independence day (observed) OMIT [TRIGDATE()-1] MSG Independence day (observed)
ELSE ELSE
IF WKDAYNUM(TRIGDATE()) == Sun IF WKDAYNUM(TRIGDATE()) == Sun
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual) REM [TRIGDATE()] MSG Independence day (actual)
OMIT [TRIGGER(TRIGDATE()+1)] MSG Independence day (observed) OMIT [TRIGDATE()+1] MSG Independence day (observed)
ELSE ELSE
OMIT [TRIGGER(TRIGDATE())] MSG Independence day OMIT [TRIGDATE()] MSG Independence day
ENDIF ENDIF
ENDIF ENDIF
@@ -237,7 +194,7 @@ REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous # But only actually trigger the delayed meeting if the previous
# Monday was a holiday # Monday was a holiday
IF ISOMITTED(TRIGDATE()-7) IF ISOMITTED(TRIGDATE()-7)
REM [TRIGGER(TRIGDATE())] MSG Delayed meeting REM [TRIGDATE()] MSG Delayed meeting
ENDIF ENDIF
############################################################################ ############################################################################
@@ -328,12 +285,12 @@ REM Sat Sun SPECIAL SHADE 220
SET SaveTrig $NumTrig SET SaveTrig $NumTrig
SET easter EASTERDATE(YEAR(TODAY())) SET easter EASTERDATE(YEAR(TODAY()))
REM [TRIGGER(easter-46)] MSG %"Ash Wednesday%" REM [easter-46] MSG %"Ash Wednesday%"
REM [TRIGGER(easter-7)] MSG %"Palm Sunday%" REM [easter-7] MSG %"Palm Sunday%"
OMIT [TRIGGER(easter-2)] MSG %"Good Friday%" OMIT [easter-2] MSG %"Good Friday%"
OMIT [TRIGGER(easter)] MSG %"Easter%" Sunday OMIT [easter] MSG %"Easter%" Sunday
REM [TRIGGER(easter+39)] MSG %"Ascension Day%" REM [easter+39] MSG %"Ascension Day%"
REM [TRIGGER(easter+49)] MSG %"Pentecost%" REM [easter+49] MSG %"Pentecost%"
# Some holidays are omitted, some are not. You may want to change # Some holidays are omitted, some are not. You may want to change
# which ones are omitted - use the general forms shown below. # which ones are omitted - use the general forms shown below.
@@ -345,9 +302,14 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%" REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day REM Feb 14 MSG %"Valentine's%" Day
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1 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 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 Savings Time - %"DST starts%" %b
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Savings Time - %"DST starts%" %b
REM Apr 1 MSG %"April Fool's%" Day REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
REM May 5 MSG %"Cinco de Mayo%" REM May 5 MSG %"Cinco de Mayo%"
@@ -355,23 +317,28 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%" REM Sun May [Week_2] MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%" REM Sat May [Week_3] MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1 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 Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%" REM Sun Jun [Week_3] MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1 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 Mon Oct [Week_2] MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%" REM Nov 11 MSG %"Veterans Day%"
REM Sun [_last(Oct)] MSG Daylight Savings Time - %"DST over%"
# The DST rules are accurate for most locations in
# North America
REM Sun [_last(Oct)] UNTIL 1 Jan 2007 MSG Daylight Savings Time - %"DST over%"
REM Sun 1 Nov FROM 1 Jan 2007 MSG Daylight Savings Time - %"DST over%"
REM Oct 30 MSG %"Mischief Night%" REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%" REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM [_back(7)] \ REM Tue Nov 2 SCANFROM [_back(7)] \
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \ SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \
MSG %"Election%" Day MSG %"Election%" Day
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1 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 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 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day OMIT Dec 25 MSG %"Christmas%" Day
@@ -409,10 +376,10 @@ REM PS Border Border moveto \
([hebday(today())] [hebmon(today())]) show ([hebday(today())] [hebmon(today())]) show
# Fill in the phases of the moon on the PostScript calendar # Fill in the phases of the moon on the PostScript calendar
[trigger(moondate(0))] SPECIAL MOON 0 [moondate(0)] SPECIAL MOON 0
[trigger(moondate(1))] SPECIAL MOON 1 [moondate(1)] SPECIAL MOON 1
[trigger(moondate(2))] SPECIAL MOON 2 [moondate(2)] SPECIAL MOON 2
[trigger(moondate(3))] SPECIAL MOON 3 [moondate(3)] SPECIAL MOON 3
# The following example puts sunrise and sunset times in PostScript in the # The following example puts sunrise and sunset times in PostScript in the
# calendar - the sizes are hard-coded, however, and work best in landscape. # calendar - the sizes are hard-coded, however, and work best in landscape.
@@ -465,11 +432,11 @@ SET InIsrael 0
SET Reform 0 SET Reform 0
# Convenient function definition to save typing # 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 _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 _PastSat(x, y) 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 _PastSun(x, y) 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 _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 # Default values in case InIsrael and Reform are not set
SET InIsrael VALUE("InIsrael", 0) SET InIsrael VALUE("InIsrael", 0)
@@ -500,7 +467,7 @@ ELSE
ENDIF ENDIF
# Because Kislev can change length, we must be more careful about Chanukah # 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(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%" [_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%" [_chan(3)] MSG %"Chanukah 3%"
@@ -523,9 +490,9 @@ ENDIF
# If Purim is on Sunday, then Fast of Esther is 11 Adar. # If Purim is on Sunday, then Fast of Esther is 11 Adar.
IF WKDAYNUM(_h2(13, "Adar")) != 6 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 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 ENDIF
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b. [_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
[_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b. [_h(15, "Adar")] ++4 MSG %"Shushan Purim%" is %b.
@@ -551,7 +518,7 @@ IF WKDAYNUM(_h2(4, "Iyar")) == 5
[_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b. [_h(2, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
[_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b. [_h(3, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
ELSE ELSE
IF WKDAYNUM(_h2, 4, "Iyar") == 0 IF WKDAYNUM(_h2(4, "Iyar")) == 0
[_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b. [_h(5, "Iyar")] ++4 MSG %"Yom Hazikaron%" is %b.
[_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b. [_h(6, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
ELSE ELSE

View File

@@ -1,4 +1,4 @@
.TH REMIND 1 "1 July 2007" .TH REMIND 1 "31 August 2008"
.UC 4 .UC 4
.SH NAME .SH NAME
remind \- a sophisticated reminder service remind \- a sophisticated reminder service
@@ -13,6 +13,13 @@ a program to be executed.
If \fIfilename\fR is specified as a single dash '-', then \fBRemind\fR If \fIfilename\fR is specified as a single dash '-', then \fBRemind\fR
takes its input from standard input. This also implicitly enables takes its input from standard input. This also implicitly enables
the \fB\-o\fR option, described below. the \fB\-o\fR option, described below.
.PP
If \fIfilename\fR happens to
be a directory rather than a plain file, then \fBRemind\fR reads all of
the files in that directory that match the pattern "*.rem". The files
are read in sorted order; the sort order may depend on your locale, but
should match the sort order used by the shell to expand "*.rem".
.SH OPTIONS .SH OPTIONS
\fBRemind\fR has a slew of options. If you're new to the program, \fBRemind\fR has a slew of options. If you're new to the program,
ignore them for now and skip to the section "Reminder Files". ignore them for now and skip to the section "Reminder Files".
@@ -26,12 +33,38 @@ date by piping the output through \fBsort(1)\fR.
The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR The \fB\-r\fR option disables \fBRUN\fR directives and the \fBshell()\fR
function. As of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR. function. As of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR.
.TP .TP
.B \-c\fR\fIn\fR .B \-c\fI[flags]\fIn\fR
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is sent to The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
standard output. If you supply a number \fIn\fR, then a calendar will sent to standard output. If you supply a number \fIn\fR, then a
be generated for \fIn\fR months, starting with the current month. By calendar will be generated for \fIn\fR months, starting with the
default, a calendar for only the current month is produced. If \fIn\fR current month. By default, a calendar for only the current month is
starts with '+', then a calendar for \fIn\fR weeks is produced. produced.
.PP
You can precede \fIn\fR (if any) with a set of flags. The flags
are as follows:
.TP
.B '+'
causes a calendar for \fIn\fR
weeks to be produced.
.TP
.B 'a'
causes \fBRemind\fR to display reminders on the calendar on the
day they actually occur \fIas well as\fR on any preceding days
specified by the reminder's \fIdelta\fR.
.TP
.B 'l'
causes \fBRemind\fR to use VT100 line-drawing characters to draw
the calendar. The characters are hard-coded and will only work
on terminals that emulate the VT00 line-drawing character set.
.TP
.B 'c'
causes \fBRemind\fR to use VT100 escape sequences to approximate
SPECIAL COLOR reminders. The approximation is (of necessity) very
coarse, because the VT100 only has eight different color sequences,
each with one of two brightnesses. A color component greater than
64 is considered "on", and if any of the three color components is
greater than 128, the color is considered "bright".
.TP .TP
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]] .B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
The \fB\-w\fR option specifies the output width, padding and spacing The \fB\-w\fR option specifies the output width, padding and spacing
@@ -97,6 +130,11 @@ The \fB\-o\fR option causes \fBRemind\fR to ignore all \fBONCE\fR directives.
The \fB\-t\fR option causes \fBRemind\fR to trigger all non-expired reminders, The \fB\-t\fR option causes \fBRemind\fR to trigger all non-expired reminders,
regardless of the \fIdelta\fR supplied for each reminder. regardless of the \fIdelta\fR supplied for each reminder.
.TP .TP
.B \-t\fR\fIn\fR
If you supply a number \fIn\fR after the \fB\-t\fR option, then
\fBRemind\fR pretends that each non-expired reminder has a \fIdelta\fR
of \fIn\fR days and triggers reminders accordingly.
.TP
.B \-h .B \-h
The \fB\-h\fR option ("hush...") suppresses certain warning and information The \fB\-h\fR option ("hush...") suppresses certain warning and information
messages. In particular, if no reminders are triggered, this mode messages. In particular, if no reminders are triggered, this mode
@@ -139,15 +177,19 @@ Dump the variable table after execution of the reminder script
.TP .TP
.B l .B l
Echo lines when displaying error messages Echo lines when displaying error messages
.TP
.B f
Trace the reading of reminder files
.RE .RE
.TP .TP
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]] \fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
Normally, reminders are issued in the order in which they are encountered Normally, reminders are issued in the order in which they are
in the reminder script. The \fB\-g\fR option cause \fBRemind\fR to encountered in the reminder script. The \fB\-g\fR option cause
sort reminders by date and time prior to issuing them. The optional \fBRemind\fR to sort reminders by date and time prior to issuing them.
\fBa\fR and \fBd\fR characters specify the sort order (ascending or The optional \fBa\fR and \fBd\fR characters specify the sort order
descending) for the date, time and priority fields. See the section "Sorting (ascending or descending) for the date, time and priority fields. See
Reminders" for more information. the section "Sorting Reminders" for more information.
.TP .TP
\fB\-b\fR[\fIn\fR] \fB\-b\fR[\fIn\fR]
Set the time format for the calendar and simple-calendar outputs. \fIN\fR Set the time format for the calendar and simple-calendar outputs. \fIN\fR
@@ -225,6 +267,9 @@ TAG clause.
Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
\fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the \fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the
section "Initializing Variables on the Command Line" for more details. section "Initializing Variables on the Command Line" for more details.
.TP
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
Allows you to define a function on the command line.
.PP .PP
If you supply a \fIdate\fR on the command line, it must consist of If you supply a \fIdate\fR on the command line, it must consist of
\fIday month year\fR, where \fIday\fR is the day of the month, \fIday month year\fR, where \fIday\fR is the day of the month,
@@ -241,6 +286,10 @@ set \fBRemind\fR's notion of "now" to a particular time. Supplying
a \fItime\fR on the command line also implicitly enables the \fB\-q\fR a \fItime\fR on the command line also implicitly enables the \fB\-q\fR
option and disables the \fB\-z\fR option. option and disables the \fB\-z\fR option.
.PP .PP
If you would rather specify the date more succinctly, you can supply
it as YYYY-MM-DD or YYYY/MM/DD. You can even supply a date and
time on the command line as one argument: YYYY-MM-DD@HH:MM.
.PP
In addition, you can supply a \fIrepeat\fR parameter, which has the In addition, you can supply a \fIrepeat\fR parameter, which has the
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times, form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
with the date incrementing on each iteration. You may have to enclose with the date incrementing on each iteration. You may have to enclose
@@ -261,7 +310,7 @@ very simple and almost immediately understandable:
to the baroque and obscure: to the baroque and obscure:
.PP .PP
.nf .nf
REM [trigger(date(thisyear, 1, 1) + 180)] ++5 OMIT \\ REM [date(thisyear, 1, 1) + 180] ++5 OMIT \\
sat sun BEFORE MSG [ord(thisyear-1980)] payment due %b! sat sun BEFORE MSG [ord(thisyear-1980)] payment due %b!
.fi .fi
.PP .PP
@@ -293,6 +342,7 @@ Its syntax is:
[\fBPRIORITY\fR \fIprio\fR] [\fBPRIORITY\fR \fIprio\fR]
[\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR] [\fBSKIP\fR | \fBBEFORE\fR | \fBAFTER\fR]
[\fBOMIT\fR \fIomit_list\fR] [\fBOMIT\fR \fIomit_list\fR]
[\fBOMITFUNC\fR \fIomit_function\fR]
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]] [\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
[\fBSCHED\fR \fIsched_function\fR] [\fBSCHED\fR \fIsched_function\fR]
[\fBWARN\fR \fIwarn_function\fR] [\fBWARN\fR \fIwarn_function\fR]
@@ -587,6 +637,37 @@ the
.I weekday .I weekday
constraints. constraints.
.PP .PP
.B SHORT-HAND DATE SPECIFICATIONS
.PP
In addition to spelling out the day, month and year separately, you
can specify YYYY-MM-DD or YYYY/MM/DD. For example, the following statements
are equivalent:
.PP
.nf
REM 5 June 2010 MSG Cool!
REM 2010-06-05 MSG Cool!
.fi
.PP
You can also specify a date and time as YYYY-MM-DD@HH:MM. These
statements are equivalent:
.PP
.nf
REM 19 Dec 2010 AT 16:45 MSG Hi
REM 2010-12-19@16:45 MSG Hi
.fi
.PP
There's one subtlety with short-hand date specifications: The following
statements are \fInot\fR equivalent:
.PP
.nf
REM 19 Dec 2010 AT 16:45 +60 MSG Hi
REM 2010-12-19@16:45 +60 MSG Hi
.fi
.PP
In the second statement, the "+60" is a \fIdelta\fR that applies to the
date rather than a \fItdelta\fR that applies to the time. We recommend
explicitly using the AT keyword with timed reminders.
.PP
.B BACKWARD SCANNING .B BACKWARD SCANNING
.PP .PP
Sometimes, it is necessary to specify a date as being a set amount of Sometimes, it is necessary to specify a date as being a set amount of
@@ -684,7 +765,7 @@ Another example: Suppose you have jury duty from 30 November 1992 until
of your jury duty, as well as 2 days ahead of time: of your jury duty, as well as 2 days ahead of time:
.PP .PP
.nf .nf
REM 30 Nov 1992 *1 +2 UNTIL 4 Dec 1992 MSG Jury duty REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
.fi .fi
.PP .PP
Note that the \fIrepeat\fR of *1 is necessary; without it, the reminder Note that the \fIrepeat\fR of *1 is necessary; without it, the reminder
@@ -750,6 +831,50 @@ also. See "The OMIT command" for more details.)
By comparison, if we had used "\-\-1", the reminder would be triggered on By comparison, if we had used "\-\-1", the reminder would be triggered on
the last day of the month, regardless of the \fBOMIT\fR. the last day of the month, regardless of the \fBOMIT\fR.
.PP .PP
.B COMPUTED LOCAL OMITS
.PP
The \fBOMITFUNC\fR phrase of the \fBREM\fR command allows you to
supply a function that determines whether or not a date is omitted.
The function is passed a single parameter of type \fBDATE\fR, and must
return a non-zero integer if the date is considered "omitted" and 0
otherwise. Here's an example:
.PP
.nf
FSET _third(x) (day(x) % 3) || \\
(wkdaynum(x) == 0) || \\
(wkdaynum(x) == 6)
REM OMITFUNC _third AFTER MSG Working day divisible by 3
.fi
.PP
In the example above, the reminder is triggered every Monday to Friday whose
day-of-month number is divisible by three. Here's how it works:
.TP
.B o
The \fBOMITFUNC _third\fR portion causes all days for which \fB_third(x)\fR
returns non-zero to be considered "omitted". This causes all days whose
day-of-month number is \fInot\fR a multiple of three to be omitted. Note
that _third also returns non-zero if the weekday is Sunday or Saturday.
.TP
.B o
The \fBAFTER\fR keyword causes the reminder to be moved after a block of
omitted days.
.PP
The combination of OMITFUNC and AFTER keyword causes the reminder to
be issued on all days whose day-of-month number is divisible by three,
but not on Saturday or Sunday.
.PP
Note that if you use \fBOMITFUNC\fR, then a local \fBOMIT\fR is
\fIignored\fR as are \fIall global OMITs\fR. If you want to omit specific
weekdays, your omit function will need to test for them specifically. If
you want to take into account the global \fBOMIT\fR context, then your omit
function will need to test for that explicitly (using the \fBisomitted()\fR
function.)
.PP
Note that an incorrect \fBOMITFUNC\fR might cause all days to be considered
omitted. For that reason, when \fBRemind\fR searches through omitted days,
it terminates the search after the \fBSATISFY\fR iteration limit
(command-line option \fB\-x\fR.)
.PP
.B TIMED REMINDERS .B TIMED REMINDERS
.PP .PP
Timed reminders are those that have an \fBAT\fR keyword followed Timed reminders are those that have an \fBAT\fR keyword followed
@@ -1167,6 +1292,14 @@ must create an \fBOMIT\fR command for each year. (Later, in the
description of expressions and some of the more advanced features of description of expressions and some of the more advanced features of
\fBRemind\fR, you will see how to automate this for some cases.) \fBRemind\fR, you will see how to automate this for some cases.)
.PP .PP
As with the REM command, you can use shorthand specifiers for dates;
the following are equivalent:
.PP
.nf
OMIT 7 Sep 1992
OMIT 1992-09-07
.fi
.PP
For convenience, you can use a \fIdelta\fR and \fBMSG\fR or \fBRUN\fR For convenience, you can use a \fIdelta\fR and \fBMSG\fR or \fBRUN\fR
keyword in the \fBOMIT\fR command. The following sequences are exactly keyword in the \fBOMIT\fR command. The following sequences are exactly
equivalent: equivalent:
@@ -1182,11 +1315,11 @@ equivalent:
.PP .PP
.B THE BEFORE, AFTER AND SKIP KEYWORDS .B THE BEFORE, AFTER AND SKIP KEYWORDS
.PP .PP
Normally, days that are omitted, whether by a global \fBOMIT\fR command Normally, days that are omitted, whether by a global \fBOMIT\fR
or the local \fBOMIT\fR keyword in a \fBREM\fR statement, only affect the command or the local \fBOMIT\fR or \fBOMITFUNC\fR keywords in a
counting of the \-\fIback\fR or the +\fIdelta\fR. For example, suppose \fBREM\fR statement, only affect the counting of the \-\fIback\fR or
you have a meeting every Wednesday. Suppose, too, that you have indicated the +\fIdelta\fR. For example, suppose you have a meeting every
11 Nov as a holiday: Wednesday. Suppose, too, that you have indicated 11 Nov as a holiday:
.PP .PP
.nf .nf
OMIT 11 Nov +4 MSG Remembrance Day OMIT 11 Nov +4 MSG Remembrance Day
@@ -1248,6 +1381,12 @@ administrator.)
.PP .PP
If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR If you specify a filename of "-" in the \fBINCLUDE\fR command, \fBRemind\fR
will begin reading from standard input. will begin reading from standard input.
.PP
If you specify a \fIdirectory\fR as the argument to \fBINCLDUE\fR, then
\fBRemind\fR will process all files in that directory that match the shell
patterm "*.rem". The files are processed in sorted order; the sort order
matches that used by the shell when it expands "*.rem".
.SH THE RUN COMMAND .SH THE RUN COMMAND
.PP .PP
If you include other files in your reminder script, you may not always If you include other files in your reminder script, you may not always
@@ -1838,6 +1977,10 @@ $IgnoreOnce, $InfDelta, and $NextMode are not meaningful.
This variable can be set only to ":" or ".". It holds the character This variable can be set only to ":" or ".". It holds the character
used to separate portions of a time when \fBRemind\fR prints a TIME or used to separate portions of a time when \fBRemind\fR prints a TIME or
DATETIME value. DATETIME value.
.TP
.B $UntimedFirst (read-only)
Set to 1 if the \fB\-g\fR option is used with a fourth sort character
of "d"; set to 0 otherwise.
.PP .PP
.B BUILT-IN FUNCTIONS .B BUILT-IN FUNCTIONS
.PP .PP
@@ -2043,6 +2186,37 @@ for the specified year. If \fIarg\fR is a \fBDATE\fR or
\fBDATETIME\fR, then returns the date of the next Easter Sunday on or \fBDATETIME\fR, then returns the date of the next Easter Sunday on or
after \fIarg\fR. (The time component of a datetime is ignored.) after \fIarg\fR. (The time component of a datetime is ignored.)
.TP .TP
.B evaltrig(s_trigger [,dq_start])
Evaluates \fItrigger\fR as if it were a REM or IFTRIG trigger specification
and returns the trigger date as a \fBDATE\fR (or as a \fBDATETIME\fR if
there is an \fBAT\fR clause.) Returns a negative \fBINT\fR if no trigger
could be computed.
.RS
.PP
Normally, \fBevaltrig\fR finds a trigger date on or after today. If
you supply the \fIstart\fR argument, then it scans starting from there.
.PP
For example, the expression:
.PP
.nf
evaltrig("Mon 1", '2008-10-07')
.fi
.PP
returns '2008-11-03', since that is the first date on or after
7 October 2008 that satisfies "Mon 1".
.PP
If you want to see how many days it is from the first Monday in October, 2008
to the first Monday in November, 2008, use:
.PP
.nf
evaltrig("Mon 1", '2008-11-01') - evaltrig("Mon 1", '2008-10-01')
.fi
.PP
and the answer is 28. The trigger argument to \fBevaltrig\fR can have
all the usual trigger clauses (\fBOMIT\fR, \fBAT\fR, \fBSKIP\fR, etc.) but
\fIcannot\fR have a \fBSATISFY\fR, \fBMSG\fR, etc. reminder-type clause.
.RE
.TP
.B filedate(s_filename) .B filedate(s_filename)
Returns the modification date of \fIfilename\fR. If \fIfilename\fR Returns the modification date of \fIfilename\fR. If \fIfilename\fR
does not exist, or its modification date is before the year does not exist, or its modification date is before the year
@@ -2120,7 +2294,8 @@ or \fBDATETIME\fR is supplied, then the year component is used in the test.
.B isomitted(dq_date) .B isomitted(dq_date)
Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR Returns 1 if \fIdate\fR is omitted, given the current global \fBOMIT\fR
context. Returns 0 otherwise. (If a datetime is supplied, only the context. Returns 0 otherwise. (If a datetime is supplied, only the
date part is used.) date part is used.) Note that any local \fBOMIT\fR or \fBOMITFUNC\fR
clauses are \fInot\fR taken into account by this function.
.TP .TP
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]]) .B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "The Hebrew Calendar"
@@ -2234,10 +2409,11 @@ This function returns the number of \fInon-\fRomitted days between
counted. \fIend\fR is never counted. counted. \fIend\fR is never counted.
.RS .RS
.PP .PP
Note that \fIend\fR must be greater than or Note that \fIend\fR must be greater than or equal to \fIstart\fR or an
equal to \fIstart\fR or an error is reported. In addition to using error is reported. In addition to using the global OMIT context, you
the global OMIT context, you can supply additional arguments that are can supply additional arguments that are names of weekdays to be
names of weekdays to be omitted. omitted. However, in a \fBREM\fR command, any local \fBOMITFUNC\fR
clause is \fInot\fR taken into account by this function.
.PP .PP
For example, the following line sets a to 11 (assuming no global OMITs): For example, the following line sets a to 11 (assuming no global OMITs):
.PP .PP
@@ -2260,36 +2436,30 @@ reminder will label day numbers in a calendar:
ENDIF ENDIF
.fi .fi
.PP .PP
Here's a more complex example: Suppose your normal garbage-collection
day is Thursday, but if any of Monday through Thursday of a week is a holiday,
the collection day moves to Friday. Here's one way to solve it:
.PP
.nf
FSET prev_monday(x) x - wkdaynum(x-1)
REM Thu Fri SATISFY [wkdaynum(trigdate()) == 4 && \\
nonomitted(prev_monday(today()), today()+1) == 4 || \\
wkdaynum(trigdate()) == 5 && \\
nonomitted(prev_monday(today()), today()+1) <= 4] \\
MSG Garbage Day
.fi
.PP
Whew! (You'll need to see "THE SATISFY CLAUSE" later on.) We'd
better explain that one: The prev_monday helper function takes a date
and returns the date of the previous Monday. The REM command will
trigger on the first Thursday or Friday that satisfies one of the
following conditions:
.PP
1) Either it's a Thursday and there are exactly four non-omitted days between
the previous Monday and tomorrow, or
.PP
2) It's a Friday and there are four or fewer non-omitted days between the
previous Monday and tomorrow. We need the "or fewer" condition to handle
the case of more than one holiday in a given week. If that happens,
garbage day still only moves by one day.
.PP
Obviously, the answer you get from \fBnonomitted\fR depends on the global Obviously, the answer you get from \fBnonomitted\fR depends on the global
OMIT context. If you use moveable OMITs, you may get inconsistent results. OMIT context. If you use moveable OMITs, you may get inconsistent results.
.PP
Here is a more complex use for \fBnonomitted\fR. My garbage collection
follows two interleaved 14-day cycles: One Friday, garbage and paper
recycling ("Black Box") are collected. The next Friday, garbage and
plastic recycling ("Blue Box") are collected. If any of Monday-Friday
is a holiday, collection is delayed until the Saturday. Here's a way
to encode these rules:
.PP
.nf
fset _garbhol(x) wkdaynum(x) == 5 && nonomitted(x-4, x+1) < 5
REM 12 November 1999 *14 AFTER OMITFUNC _garbhol MSG Black Box
REM 19 November 1999 *14 AFTER OMITFUNC _garbhol MSG Blue Box
.fi
.PP
Here's how it works: The _garbhol(x) user-defined function returns 1
if and only if (1) \fIx\fR is a Friday and (2) there is at least one
OMITted day from the previous Monday up to and including the Friday.
.PP
The first REM statement sets up the 14-day black-box cycle. The AFTER
keyword makes it move collection to the Saturday if _garbhol returns 1.
The second REM statement sets up the 14-day blue-box cycle with a similar
adjustment made by AFTER in conjunction with _garbhol.
.RE .RE
.TP .TP
.B now() .B now()
@@ -2331,10 +2501,10 @@ For example, the following four lines place moon symbols on the PostScript
calendar: calendar:
.PP .PP
.nf .nf
REM [trigger(moondate(0))] PS [psmoon(0)] REM [moondate(0)] PS [psmoon(0)]
REM [trigger(moondate(1))] PS [psmoon(1)] REM [moondate(1)] PS [psmoon(1)]
REM [trigger(moondate(2))] PS [psmoon(2)] REM [moondate(2)] PS [psmoon(2)]
REM [trigger(moondate(3))] PS [psmoon(3)] REM [moondate(3)] PS [psmoon(3)]
.fi .fi
.PP .PP
If \fInote\fR is specified, the text is used to annotate the moon If \fInote\fR is specified, the text is used to annotate the moon
@@ -2347,7 +2517,7 @@ does not check for this.) For example, if you want the time of each new
moon displayed, you could use this in your reminder script: moon displayed, you could use this in your reminder script:
.PP .PP
.nf .nf
REM [trigger(moondate(0))] PS [psmoon(0, -1, moontime(0)+"")] REM [moondate(0)] PS [psmoon(0, -1, moontime(0)+"")]
.fi .fi
.PP .PP
Note how the time is coerced to a string by concatenating the null string. Note how the time is coerced to a string by concatenating the null string.
@@ -2399,11 +2569,38 @@ character in the output is converted to a space. Note that if \fBRUN
OFF\fR has been executed, or the \fB\-r\fR command-line option has OFF\fR has been executed, or the \fB\-r\fR command-line option has
been used, \fBshell()\fR will result in an error, and \fIcmd\fR will been used, \fBshell()\fR will result in an error, and \fIcmd\fR will
not be executed. not be executed.
.RS
.PP .PP
If \fImaxlen\fR is specified, then \fBshell()\fR returns the first If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
\fImaxlen\fR characters of output (rather than the first 511). If \fImaxlen\fR characters of output (rather than the first 511). If
\fImaxlen\fR is specified as a negative number, then \fIall\fR the \fImaxlen\fR is specified as a negative number, then \fIall\fR the
output from \fIcmd\fR is returned. output from \fIcmd\fR is returned.
.RE
.TP
.B slide(d_start, i_amt [,s_wkday...])
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
days (which can be negative) to \fIstart\fR, \fInot counting omitted days\fR.
The optional \fIwkday\fR arguments are additional weekday names to omit.
.RS
.PP
Consider this example:
.PP
.nf
OMIT 14 May 2009
SET a slide('2009-05-13', 5, "Sat", "Sun")
.fi
.PP
In this case, \fIa\fR is set to 2009-05-21. That's because we slide forward
by 5 days, not including Thursday, May 14 or Saturday and Sunday,
May 16 and 17. You can go backwards, too, so:
.PP
.nf
OMIT 14 May 2009
SET a slide('2009-05-21', -5, "Sat", "Sun")
.fi
.PP
takes \fIa\fR back to 2009-05-13.
.RE
.TP .TP
.B strlen(s_str) .B strlen(s_str)
Returns the length of \fIstr\fR. Returns the length of \fIstr\fR.
@@ -2461,15 +2658,18 @@ triggerable \fBREM\fR command had an \fBAT\fR clause. If there was no
returns the integer 0. returns the integer 0.
.TP .TP
.B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag]) .B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag])
Returns a string suitable for use in a \fBREM\fR command, allowing you Returns a string suitable for use in a \fBREM\fR command or a SCANFROM
to calculate trigger dates in advance. (See the section "Expression or UNTIL clause, allowing you to calculate trigger dates in advance.
pasting" for more information.) Note that \fBtrigger()\fR Note that in earlier versions of \fBRemind\fR, \fBtrigger\fR was
\fIalways\fR returns its result in English, even for foreign-language required to convert a date into something the \fBREM\fR command could
versions of \fBRemind\fR. This is to avoid problems with certain C consume. However, in this version of \fBRemind\fR, you can omit it.
libraries that do not handle accented characters properly. Normally, Note that \fBtrigger()\fR \fIalways\fR returns its result in English,
the \fIdate\fR and \fItime\fR are the local date and time; however, if even for foreign-language versions of \fBRemind\fR. This is to avoid
\fIutcflag\fR is non-zero, the \fIdate\fR and \fItime\fR are problems with certain C libraries that do not handle accented
interpreted as UTC times, and are converted to local time. Examples: characters properly. Normally, the \fIdate\fR and \fItime\fR are the
local date and time; however, if \fIutcflag\fR is non-zero, the
\fIdate\fR and \fItime\fR are interpreted as UTC times, and are
converted to local time. Examples:
.RS .RS
.PP .PP
trigger('1993/04/01') trigger('1993/04/01')
@@ -2546,6 +2746,21 @@ Returns a string specifying the version of \fBRemind\fR. For version
\fBRemind\fR are released, the value returned by \fBversion()\fR will \fBRemind\fR are released, the value returned by \fBversion()\fR will
strictly increase, according to the rules for string ordering. strictly increase, according to the rules for string ordering.
.TP .TP
.B weekno([dq_date, [i_wkstart, [i_daystart]]])
Returns the week number of the year. If no arguments are supplied,
returns the ISO 8601 week number for \fBtoday()\fR. If one
argument \fIdate\fR is supplied, then returns the ISO 8601 week
number for that date. If two arguments are supplied, then
\fIwkstart\fR must range from 0 to 6, and represents the first
day of the week (with 0 being Sunday and 6 being Saturday.). If
\fIwkstart\fR is not supplied, then it defaults to 1. If the
third argument \fIdaystart\fR is supplied, then it specifies
when Week 1 starts. If \fIdaystart\fR is less than or equal to 7,
then Week 1 starts on the first \fIwkstart\fR on or after
January \fIdaystart\fR. Otherwise, Week 1 starts on the first
\fIwkstart\fR on or after December \fIdaystart\fR. If omitted,
\fIdaystart\fR defaults to 29 (following the ISO 8601 definition.)
.TP
.B wkday(dqi_arg) .B wkday(dqi_arg)
If \fIarg\fR is a \fBDATE\fR or \fBDATETIME\fR, returns a string If \fIarg\fR is a \fBDATE\fR or \fBDATETIME\fR, returns a string
representing the day of the week of the date. If \fIarg\fR is an representing the day of the week of the date. If \fIarg\fR is an
@@ -2568,10 +2783,10 @@ you can "paste" an expression in. To do this, surround the expression
with square brackets. For example: with square brackets. For example:
.PP .PP
.nf .nf
REM [trigger(mydate)] MSG foo REM [mydate] MSG foo
.fi .fi
.PP .PP
This evaluates the expression "trigger(mydate)", where "mydate" is This evaluates the expression "mydate", where "mydate" is
presumably some pre-computed variable, and then "pastes" the result presumably some pre-computed variable, and then "pastes" the result
into the command-line for the parser to process. into the command-line for the parser to process.
.PP .PP
@@ -2594,8 +2809,16 @@ exceptions:
.TP .TP
o o
If \fBRemind\fR is expecting an expression, as in the \fBSET\fR command, If \fBRemind\fR is expecting an expression, as in the \fBSET\fR command,
or the \fBIF\fR command, then no expression pasting takes place. The or the \fBIF\fR command, you should \fBnot\fR include square brackets.
expression is simply evaluated as if the square brackets were not there. FOr example, use:
.PP
.nf
SET a 4+5
.fi
and not:
.nf
SET a [4+5]
.fi
.TP .TP
o o
You cannot use expression pasting for the first token on a line. You cannot use expression pasting for the first token on a line.
@@ -2943,7 +3166,7 @@ more complicated sequence:
.nf .nf
REM 13 SATISFY wkdaynum(trigdate()) == 5 REM 13 SATISFY wkdaynum(trigdate()) == 5
IF trigvalid() IF trigvalid()
REM [trigger(trigdate())] +2 MSG \\ REM [trigdate()] +2 MSG \\
Friday the 13th is %b. Friday the 13th is %b.
ENDIF ENDIF
.fi .fi
@@ -2951,8 +3174,7 @@ more complicated sequence:
Let's see how this works. The \fBSATISFY\fR clause iterates through Let's see how this works. The \fBSATISFY\fR clause iterates through
all the 13ths of successive months, until a trigger date is found whose all the 13ths of successive months, until a trigger date is found whose
day-of-week is Friday (== 5). If a valid date was found, we use the day-of-week is Friday (== 5). If a valid date was found, we use the
calculated trigger date (converted into a trigger format with the calculated trigger date to set up the next reminder.
\fBtrigger()\fR function) to set up the next reminder.
.PP .PP
We could also have written: We could also have written:
.PP .PP
@@ -2971,7 +3193,7 @@ could use:
.nf .nf
# Note: SATISFY 1 is an idiom for "do nothing" # Note: SATISFY 1 is an idiom for "do nothing"
REM Mon 1 Sept SATISFY 1 REM Mon 1 Sept SATISFY 1
OMIT [trigger(trigdate())] OMIT [trigdate()]
.fi .fi
.PP .PP
\fBCAVEAT:\fR This \fIonly\fR omits the \fInext\fR Labour Day, not \fBCAVEAT:\fR This \fIonly\fR omits the \fInext\fR Labour Day, not
@@ -3023,6 +3245,10 @@ occurring on odd-numbered days of the month with the following:
MSG Here it is!!! MSG Here it is!!!
.fi .fi
.PP .PP
Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
.PP
.SH DEBUGGING REMINDER SCRIPTS .SH DEBUGGING REMINDER SCRIPTS
.PP .PP
Although the command-line \fB\-d\fR option is useful for debugging, it Although the command-line \fB\-d\fR option is useful for debugging, it
@@ -3033,7 +3259,7 @@ under program control. The format is:
.PP .PP
\fBDEBUG\fR [+\fIflagson\fR] [\-\fIflagsoff\fR] \fBDEBUG\fR [+\fIflagson\fR] [\-\fIflagsoff\fR]
.PP .PP
\fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "extvl" \fIFlagson\fR and \fIflagsoff\fR consist of strings of the characters "extvlf"
that correspond to the debugging options discussed in the command-line that correspond to the debugging options discussed in the command-line
options section. If preceded with a "+", the corresponding group of options section. If preceded with a "+", the corresponding group of
debugging options is switched on. Otherwise, they are switched off. debugging options is switched on. Otherwise, they are switched off.
@@ -3244,6 +3470,11 @@ You should not have any spaces between the \fB\-i\fR option and the equal
sign; otherwise, strange variable names are created that can only be accessed sign; otherwise, strange variable names are created that can only be accessed
with the \fBvalue()\fR or \fBdefined()\fR functions. with the \fBvalue()\fR or \fBdefined()\fR functions.
.PP .PP
You can also define a function on the command line by using:
.PP
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
.PP
Be sure to protect special characters from shell interpretation.
.SH MORE ABOUT POSTSCRIPT .SH MORE ABOUT POSTSCRIPT
.PP .PP
The \fBPS\fR and \fBPSFILE\fR reminders pass PostScript code directly The \fBPS\fR and \fBPSFILE\fR reminders pass PostScript code directly
@@ -3357,24 +3588,26 @@ to ensure that the daemon is not killed when you log out.
.PP .PP
.SH SORTING REMINDERS .SH SORTING REMINDERS
.PP .PP
The \fB\-g\fR option causes \fBRemind\fR to sort reminders by
trigger date, time and priority before issuing them. Note that reminders are The \fB\-g\fR option causes \fBRemind\fR to sort reminders by trigger
still calculated in the order encountered in the script. However, rather date, time and priority before issuing them. Note that reminders are
than being issued immediately, they are saved in an internal buffer. still calculated in the order encountered in the script. However,
When \fBRemind\fR has finished processing the script, it issues the rather than being issued immediately, they are saved in an internal
saved reminders in sorted order. The \fB\-g\fR option can be followed buffer. When \fBRemind\fR has finished processing the script, it
by up to three characters that must all be "a" or "d". The first character issues the saved reminders in sorted order. The \fB\-g\fR option can
specifies the sort order by trigger date (ascending or descending), be followed by up to four characters that must all be "a" or "d". The
the second specifies the sort order by trigger time and the third first character specifies the sort order by trigger date (ascending or
specifies the sort order by priority. The default is descending), the second specifies the sort order by trigger time and
to sort all fields in ascending order. the third specifies the sort order by priority. If the fourth
character is "d", the untimed reminders are sorted before timed
reminders. The default is to sort all fields in ascending order and
to sort untimed reminders after timed reminders.
.PP .PP
In ascending order, reminders are issued with the most imminent first. In ascending order, reminders are issued with the most imminent first.
Descending order is the reverse. Reminders are always sorted by Descending order is the reverse. Reminders are always sorted by
trigger date, and reminders with the same trigger date are then sorted trigger date, and reminders with the same trigger date are then sorted
by trigger time. Non-timed reminders are always issued after timed by trigger time. If two reminders have the same date and time, then
reminders in this mode. If two reminders have the same date and time, the priority is used to break ties. Reminders with the same date,
then the priority is used to break ties. Reminders with the same date,
time and priority are issued in the order they were encountered. time and priority are issued in the order they were encountered.
.PP .PP
You can define a user-defined function called SORTBANNER that takes one You can define a user-defined function called SORTBANNER that takes one
@@ -3727,10 +3960,10 @@ in calendars produced by \fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.)
The \fBMOON\fR special replaces the \fBpsmoon()\fR function. Use it The \fBMOON\fR special replaces the \fBpsmoon()\fR function. Use it
like this: like this:
.nf .nf
REM [trigger(moondate(0))] SPECIAL MOON 0 REM [moondate(0)] SPECIAL MOON 0
REM [trigger(moondate(1))] SPECIAL MOON 1 REM [moondate(1)] SPECIAL MOON 1
REM [trigger(moondate(2))] SPECIAL MOON 2 REM [moondate(2)] SPECIAL MOON 2
REM [trigger(moondate(3))] SPECIAL MOON 3 REM [moondate(3)] SPECIAL MOON 3
.fi .fi
These draw little moons on the various calendars. The complete syntax These draw little moons on the various calendars. The complete syntax
of the \fBMOON\fR special is as follows: of the \fBMOON\fR special is as follows:
@@ -3766,6 +3999,19 @@ The rest of the line is the text to put in the calendar.
.PP .PP
The COLOR special is "doubly special", because in its normal operating The COLOR special is "doubly special", because in its normal operating
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder. mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
Also, if you invoke \fBRemind\fR with \fB\-cc\fR..., then it approximates
SPECIAL COLOR reminders on your terminal.
.PP
The \fBWEEK\fR special lets you place annotations such as the week
number in the calendar. For example, this would number each Monday
with the ISO 8601 week number. The week number is shown like this:
"(W\fIn\fR)" in this example, but you can put whatever text you like
after the WEEK keyword.
.nf
REM Monday SPECIAL WEEK (W[weekno()])
.fi
.SH MISCELLANEOUS .SH MISCELLANEOUS
.PP .PP
.B COMMAND ABBREVIATIONS .B COMMAND ABBREVIATIONS
@@ -3846,7 +4092,7 @@ This example puts an entry in each box of a calendar showing the number
.nf .nf
REM Tue 2 Nov SATISFY (year(trigdate())%4) == 0 REM Tue 2 Nov SATISFY (year(trigdate())%4) == 0
IF trigvalid() IF trigvalid()
REM [trigger(trigdate())] ++5 MSG \\ REM [trigdate()] ++5 MSG \\
U.S. Presidential Election!! U.S. Presidential Election!!
ENDIF ENDIF
.fi .fi
@@ -3897,8 +4143,8 @@ in September. It can move over a range of 7 days. Consider the
following sequence: following sequence:
.PP .PP
.nf .nf
REM Mon 1 Sept SCANFROM [trigger(today()-7)] SATISFY 1 REM Mon 1 Sept SCANFROM [today()-7] SATISFY 1
OMIT [trigger(trigdate())] OMIT [trigdate()]
REM Mon AFTER MSG Hello REM Mon AFTER MSG Hello
.fi .fi
@@ -3928,7 +4174,7 @@ will trigger on Mondays and Thursdays between 23 July 2007 and
the reminder above as follows: the reminder above as follows:
.PP .PP
.nf .nf
REM Mon Thu SCANFROM [trigger(max(today(), '2007-07-23'))] \\ REM Mon Thu SCANFROM [max(today(), '2007-07-23')] \\
UNTIL 2 Aug 2007 MSG Test UNTIL 2 Aug 2007 MSG Test
.fi .fi
.PP .PP
@@ -4021,8 +4267,9 @@ Hebrew dates in \fBRemind\fR change at midnight instead of sunset.
.PP .PP
Language should be selectable at run-time, not compile-time. Don't Language should be selectable at run-time, not compile-time. Don't
expect this to happen soon! expect this to happen soon!
\fBRemind\fR has some built-in limits (for example, .PP
number of global \fBOMIT\fRs.) \fBRemind\fR has some built-in limits (for example, number of global
\fBOMIT\fRs.)
.PP .PP
.SH BIBLIOGRAPHY .SH BIBLIOGRAPHY
.PP .PP

View File

@@ -21,6 +21,8 @@ extra features as you become a more sophisticated \fBRemind\fR programmer.
on to \fBRemind\fR. The options it passes are 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. \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. 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. \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 It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file

View File

@@ -8,7 +8,7 @@
# #
# This file is part of REMIND. # This file is part of REMIND.
# Copyright (C) 1992-1998 David F. Skoll # Copyright (C) 1992-1998 David F. Skoll
# Copyright (C) 1999-2005 Roaring Penguin Software Inc. # Copyright (C) 1999-2009 Roaring Penguin Software Inc.
# #
#-------------------------------------------------------------- #--------------------------------------------------------------
@@ -93,8 +93,12 @@ set EditorPid -1
set AppendFile {NOSUCHFILE} set AppendFile {NOSUCHFILE}
catch {set AppendFile $ReminderFile} catch {set AppendFile $ReminderFile}
set SetFontsWorked 0
#---------------- DON'T CHANGE STUFF BELOW HERE ------------------ #---------------- DON'T CHANGE STUFF BELOW HERE ------------------
# 24-hour clock mode
set TwentyFourHourMode 0
# Is Monday in first column? # Is Monday in first column?
set MondayFirst 0 set MondayFirst 0
@@ -153,7 +157,7 @@ set HighestTagSoFar 0
proc Initialize {} { proc Initialize {} {
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
global MondayFirst global MondayFirst TwentyFourHourMode
set CommandLine "|$Remind -itkremind=1 -p -y -l" set CommandLine "|$Remind -itkremind=1 -p -y -l"
set PSCmd "$Remind -p -l" set PSCmd "$Remind -p -l"
@@ -165,6 +169,9 @@ proc Initialize {} {
if {[regexp -- {m} [lindex $argv $i]]} { if {[regexp -- {m} [lindex $argv $i]]} {
set MondayFirst 1 set MondayFirst 1
} }
if {"[lindex $argv $i]" == "-b1"} {
set TwentyFourHourMode 1
}
} else { } else {
break break
} }
@@ -180,6 +187,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 # Check system sanity
if {! [file readable $ReminderFile]} { if {! [file readable $ReminderFile]} {
set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"] set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"]
@@ -193,6 +208,12 @@ proc Initialize {} {
exit 1 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]} { if {! [file writable $AppendFile]} {
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
exit 1 exit 1
@@ -271,9 +292,14 @@ proc CalEntryOffset { firstDay } {
#*********************************************************************** #***********************************************************************
proc CreateCalFrame { w dayNames } { proc CreateCalFrame { w dayNames } {
# Figure out reasonable height for text frames # Figure out reasonable height for text frames
global SetFontsWorked
set h [winfo screenheight .] set h [winfo screenheight .]
if {$h <= 480} { if {$h <= 480} {
set h 2 if {$SetFontsWorked} {
set h 3
} else {
set h 2
}
} elseif {$h <= 600} { } elseif {$h <= 600} {
set h 4 set h 4
} else { } else {
@@ -329,10 +355,17 @@ proc CreateCalFrame { w dayNames } {
#*********************************************************************** #***********************************************************************
proc ConfigureCalFrame { w firstDay numDays } { proc ConfigureCalFrame { w firstDay numDays } {
global CurMonth CurYear TodayMonth TodayYear TodayDay global CurMonth CurYear TodayMonth TodayYear TodayDay
global tk_version
set offset [CalEntryOffset $firstDay] set offset [CalEntryOffset $firstDay]
set first [expr $offset+1] set first [expr $offset+1]
set last [expr $offset+$numDays] set last [expr $offset+$numDays]
if {$tk_version >= 8.5} {
set bg "#d9d9d9"
} else {
set bg [lindex [$w.t0 configure -background] 3]
}
for {set i 0} {$i < $first} {incr i} { for {set i 0} {$i < $first} {incr i} {
grid $w.l$i $w.t$i grid $w.l$i $w.t$i
$w.l$i configure -text "" -command "" -state disabled -relief flat $w.l$i configure -text "" -command "" -state disabled -relief flat
@@ -344,8 +377,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $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 tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled
$w.t$i configure -background [lindex [$w.t$i configure -background] 3] $w.t$i configure -background $bg
$w.l$i configure -background [lindex [$w.l$i configure -background] 3] $w.l$i configure -background $bg
} }
for {set i $first} {$i <= $last} {incr i} { for {set i $first} {$i <= $last} {incr i} {
grid $w.l$i $w.t$i grid $w.l$i $w.t$i
@@ -360,8 +393,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $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 tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled
$w.t$i configure -background [lindex [$w.t$i configure -background] 3] $w.t$i configure -background $bg
$w.l$i configure -background [lindex [$w.l$i configure -background] 3] $w.l$i configure -background $bg
} }
set forgetIt 0 set forgetIt 0
for {set i [expr $last+1]} {$i < 42} {incr i} { for {set i [expr $last+1]} {$i < 42} {incr i} {
@@ -385,8 +418,8 @@ proc ConfigureCalFrame { w firstDay numDays } {
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $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 tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled
$w.t$i configure -background [lindex [$w.t$i configure -background] 3] $w.t$i configure -background $bg
$w.l$i configure -background [lindex [$w.l$i configure -background] 3] $w.l$i configure -background $bg
} }
if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } { if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
set n [expr $TodayDay + $offset] set n [expr $TodayDay + $offset]
@@ -720,6 +753,13 @@ proc FillCalWindow {} {
set month [string trimleft $month 0] set month [string trimleft $month 0]
set extratags "" set extratags ""
switch -exact -- $type { 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" { "SHADE" {
DoShadeSpecial $n $stuff DoShadeSpecial $n $stuff
continue continue
@@ -1067,7 +1107,7 @@ proc CreateModifyDialog {w day firstDay args} {
# Set up: Year, Month, Day, WeekdayName # Set up: Year, Month, Day, WeekdayName
global CurYear CurMonth EnglishDayNames MonthNames OptionType SkipType global CurYear CurMonth EnglishDayNames MonthNames OptionType SkipType
global ModifyDialogResult global ModifyDialogResult TwentyFourHourMode
set OptionType 1 set OptionType 1
set SkipType 1 set SkipType 1
@@ -1187,7 +1227,11 @@ proc CreateModifyDialog {w day firstDay args} {
checkbutton $w.timebut -text "Timed reminder at" checkbutton $w.timebut -text "Timed reminder at"
$w.timebut deselect $w.timebut deselect
menubutton $w.timehour -text "12" -menu $w.timehour.menu -relief raised 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 menubutton $w.timemin -text "00" -menu $w.timemin.menu -relief raised
menu $w.timemin.menu -tearoff 0 menu $w.timemin.menu -tearoff 0
foreach i {00 05 10 15 20 25 30 35 40 45 50 55} { foreach i {00 05 10 15 20 25 30 35 40 45 50 55} {
@@ -1195,10 +1239,12 @@ proc CreateModifyDialog {w day firstDay args} {
-command "$w.timemin configure -text $i" -command "$w.timemin configure -text $i"
} }
menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised if {!$TwentyFourHourMode} {
menu $w.ampm.menu -tearoff 0 menubutton $w.ampm -text "PM" -menu $w.ampm.menu -relief raised
$w.ampm.menu add command -label "AM" -command "$w.ampm configure -text {AM}" menu $w.ampm.menu -tearoff 0
$w.ampm.menu add command -label "PM" -command "$w.ampm configure -text {PM}" $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" checkbutton $w.timeadvbut -text "with"
$w.timeadvbut deselect $w.timeadvbut deselect
@@ -1217,7 +1263,11 @@ proc CreateModifyDialog {w day firstDay args} {
$w.timerep.menu add command -label $i -command "$w.timerep configure -text $i" $w.timerep.menu add command -label $i -command "$w.timerep configure -text $i"
} }
label $w.timelab2 -text "minutes" 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
}
# SKIP TYPE # SKIP TYPE
label $w.labhol -text "On holidays or weekends:" label $w.labhol -text "On holidays or weekends:"
@@ -1295,13 +1345,20 @@ proc RemindDialogToOptions { w } {
#*********************************************************************** #***********************************************************************
proc OptionsToRemindDialog { w opts } { proc OptionsToRemindDialog { w opts } {
global OptionType SkipType repbut expbut advbut advcount global OptionType SkipType repbut expbut advbut advcount
global timebut timeadvbut timerepbut global timebut timeadvbut timerepbut TwentyFourHourMode
global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday global dSaturday dSunday dMonday dTuesday dWednesday dThursday dFriday
set hour ""
set ampm ""
foreach {flag value} $opts { foreach {flag value} $opts {
switch -glob -- $flag { switch -glob -- $flag {
"-text-*" { "-text-*" {
set win [string range $flag 6 end] 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-*" { "-global-*" {
set win [string range $flag 8 end] set win [string range $flag 8 end]
@@ -1314,6 +1371,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"
}
}
}
}
} }
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@@ -1467,7 +1544,7 @@ proc CenterWindow {w} {
# The reminder as a string. # The reminder as a string.
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
proc CreateReminder {w} { proc CreateReminder {w} {
global DidOmit global DidOmit TwentyFourHourMode
set body [string trim [$w.entry get]] set body [string trim [$w.entry get]]
@@ -1504,13 +1581,15 @@ proc CreateReminder {w} {
if {$timebut} { if {$timebut} {
set hour [$w.timehour cget -text] set hour [$w.timehour cget -text]
set min [$w.timemin cget -text] set min [$w.timemin cget -text]
if {[$w.ampm cget -text] == "PM"} { if {!$TwentyFourHourMode} {
if {$hour < 12} { if {[$w.ampm cget -text] == "PM"} {
incr hour 12 if {$hour < 12} {
} incr hour 12
} else { }
if {$hour == 12} { } else {
set hour 0 if {$hour == 12} {
set hour 0
}
} }
} }
append rem " AT $hour:$min" append rem " AT $hour:$min"
@@ -2192,8 +2271,9 @@ proc main {} {
global AppendFile HighestTagSoFar DayNames global AppendFile HighestTagSoFar DayNames
catch { catch {
puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll" puts "\nTkRemind Copyright (C) 1996-1998 David F. Skoll"
puts "Copyright (C) 1999-2007 Roaring Penguin Software Inc." puts "Copyright (C) 1999-2009 Roaring Penguin Software Inc."
} }
catch { SetFonts }
LoadOptions LoadOptions
CreateMoonImages CreateMoonImages
Initialize Initialize
@@ -2647,7 +2727,12 @@ proc DoMoonSpecial { n stuff } {
# Displays current date and time in status window # Displays current date and time in status window
#*********************************************************************** #***********************************************************************
proc DisplayTime {} { 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 Status $msg
} }
@@ -2724,7 +2809,7 @@ proc ShowTodaysReminders {} {
CenterWindow $w CenterWindow $w
# Grab the reminders # Grab the reminders
set stuff [exec -keepnewline $Remind -g -q -a -r $ReminderFile 2>/dev/null] set stuff [exec -keepnewline $Remind -g -q -r $ReminderFile 2>/dev/null]
$w.text insert end $stuff $w.text insert end $stuff
$w.text configure -state disabled $w.text configure -state disabled
} }
@@ -2784,4 +2869,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 main

View File

@@ -1,7 +1,6 @@
# Makefile.in for REMIND # Makefile.in for REMIND
# #
VERSION=03.01.02
SHELL= /bin/sh SHELL= /bin/sh
BETA = 1 BETA = 1
srcdir=@srcdir@ srcdir=@srcdir@
@@ -12,6 +11,7 @@ bindir=@bindir@
datadir=@datadir@ datadir=@datadir@
datarootdir=@datarootdir@ datarootdir=@datarootdir@
VPATH=$(srcdir) VPATH=$(srcdir)
VERSION=@VERSION@
INSTALL=@INSTALL@ INSTALL=@INSTALL@
INSTALL_PROGRAM=@INSTALL_PROGRAM@ INSTALL_PROGRAM=@INSTALL_PROGRAM@
@@ -92,3 +92,4 @@ beta-tgz:
#---------------- Stuff after this added by "make depend" ----------------- #---------------- Stuff after this added by "make depend" -----------------

View File

@@ -28,28 +28,103 @@
/* Data structures used by the calendar */ /* Data structures used by the calendar */
typedef struct cal_entry { typedef struct cal_entry {
struct cal_entry *next; struct cal_entry *next;
char *text; char const *text;
char *pos; char const *pos;
int is_color;
int r, g, b;
int time; int time;
int priority; int priority;
char tag[TAG_LEN+1]; char tag[TAG_LEN+1];
char passthru[PASSTHRU_LEN+1]; char passthru[PASSTHRU_LEN+1];
int duration; int duration;
char *filename; char const *filename;
int lineno; int lineno;
} CalEntry; } CalEntry;
/* Line-drawing sequences */
struct line_drawing {
char const *graphics_on;
char const *graphics_off;
char tlr, bl, tbl, blr, tblr, tr, tb, br, tbr, tl, lr;
};
static struct line_drawing NormalDrawing = {
"", "", '+', '+', '+', '+', '+', '+', '|', '+', '+', '+', '-'
};
static struct line_drawing VT100Drawing = {
"\x1B(0", "\x1B(B",
'\x76', '\x6b', '\x75', '\x77', '\x6e', '\x6d', '\x78',
'\x6c', '\x74', '\x6a', '\x71'
};
static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
{
/*** DIM COLORS ***/
{
{
/* 0, 0, 0 = Black */ "\x1B[0;30m",
/* 0, 0, 1 = Blue */ "\x1B[0;34m"
},
{
/* 0, 1, 0 = Green */ "\x1B[0;32m",
/* 0, 1, 1 = Cyan */ "\x1B[0;36m"
}
},
{
{
/* 1, 0, 0 = Red */ "\x1B[0;31m",
/* 1, 0, 1 = Magenta */ "\x1B[0;35m"
},
{
/* 1, 1, 0 = Yellow */ "\x1B[0;33m",
/* 1, 1, 1 = White */ "\x1B[0;37m"
}
}
},
{
/*** BRIGHT COLORS ***/
{
{
/* 0, 0, 0 = Grey */ "\x1B[30;1m",
/* 0, 0, 1 = Blue */ "\x1B[34;1m"
},
{
/* 0, 1, 0 = Green */ "\x1B[32;1m",
/* 0, 1, 1 = Cyan */ "\x1B[36;1m"
}
},
{
{
/* 1, 0, 0 = Red */ "\x1B[31;1m",
/* 1, 0, 1 = Magenta */ "\x1B[35;1m"
},
{
/* 1, 1, 0 = Yellow */ "\x1B[33;1m",
/* 1, 1, 1 = White */ "\x1B[37;1m"
}
}
}
};
static struct line_drawing *linestruct;
#define DRAW(x) putchar(linestruct->x)
/* Global variables */ /* Global variables */
static CalEntry *CalColumn[7]; static CalEntry *CalColumn[7];
static int ColSpaces; static int ColSpaces;
static void Colorize(CalEntry const *e);
static void Decolorize(void);
static void SortCol (CalEntry **col); static void SortCol (CalEntry **col);
static void DoCalendarOneWeek (void); static void DoCalendarOneWeek (int nleft);
static void DoCalendarOneMonth (void); static void DoCalendarOneMonth (void);
static int WriteCalendarRow (void); static int WriteCalendarRow (void);
static void PrintLeft (char *s, int width, char pad); static void WriteWeekHeaderLine (void);
static void PrintCentered (char *s, int width, char pad); static void WritePostHeaderLine (void);
static void PrintLeft (char const *s, int width, char pad);
static void PrintCentered (char const *s, int width, char pad);
static int WriteOneCalLine (void); static int WriteOneCalLine (void);
static int WriteOneColLine (int col); static int WriteOneColLine (int col);
static void GenerateCalEntries (int col); static void GenerateCalEntries (int col);
@@ -57,10 +132,42 @@ static void WriteCalHeader (void);
static void WriteCalTrailer (void); static void WriteCalTrailer (void);
static int DoCalRem (ParsePtr p, int col); static int DoCalRem (ParsePtr p, int col);
static void WriteSimpleEntries (int col, int jul); static void WriteSimpleEntries (int col, int jul);
static void WriteSolidCalLine (void); static void WriteTopCalLine (void);
static void WriteBottomCalLine (void);
static void WriteIntermediateCalLine (void); static void WriteIntermediateCalLine (void);
static void WriteCalDays (void); static void WriteCalDays (void);
static void gon(void)
{
printf("%s", linestruct->graphics_on);
}
static void goff(void)
{
printf("%s", linestruct->graphics_off);
}
static void Decolorize(void)
{
printf("%s", "\x1B[0m");
}
static void Colorize(CalEntry const *e)
{
int bright = 0;
int r, g, b;
if (e->r > 128 || e->g > 128 || e->b > 128) {
bright = 1;
}
if (e->r > 64) r = 1;
else r = 0;
if (e->g > 64) g = 1;
else g = 0;
if (e->b > 64) b = 1;
else b = 0;
printf("%s", VT100Colors[bright][r][g][b]);
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* ProduceCalendar */ /* ProduceCalendar */
@@ -72,6 +179,11 @@ void ProduceCalendar(void)
{ {
int y, m, d; int y, m, d;
if (UseVTChars) {
linestruct = &VT100Drawing;
} else {
linestruct = &NormalDrawing;
}
ShouldCache = 1; ShouldCache = 1;
ColSpaces = (CalWidth - 9) / 7; ColSpaces = (CalWidth - 9) / 7;
@@ -88,13 +200,13 @@ void ProduceCalendar(void)
else JulianToday -= ((JulianToday+1)%7); else JulianToday -= ((JulianToday+1)%7);
if (!DoSimpleCalendar) { if (!DoSimpleCalendar) {
WriteIntermediateCalLine(); WriteWeekHeaderLine();
WriteCalDays(); WriteCalDays();
WriteIntermediateCalLine(); WriteIntermediateCalLine();
} }
while (CalWeeks--) while (CalWeeks--)
DoCalendarOneWeek(); DoCalendarOneWeek(CalWeeks);
return; return;
} }
} }
@@ -106,7 +218,7 @@ void ProduceCalendar(void)
/* Write a calendar for a single week */ /* Write a calendar for a single week */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void DoCalendarOneWeek(void) static void DoCalendarOneWeek(nleft)
{ {
int y, m, d, done, i, l, wd; int y, m, d, done, i, l, wd;
char buf[81]; char buf[81];
@@ -132,7 +244,9 @@ static void DoCalendarOneWeek(void)
} }
/* Here come the first few lines... */ /* Here come the first few lines... */
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
FromJulian(OrigJul+i, &y, &m, &d); FromJulian(OrigJul+i, &y, &m, &d);
sprintf(buf, "%d %c%c%c ", d, MonthName[m][0], MonthName[m][1], sprintf(buf, "%d %c%c%c ", d, MonthName[m][0], MonthName[m][1],
@@ -141,14 +255,20 @@ static void DoCalendarOneWeek(void)
PrintLeft(buf, ColSpaces, '*'); PrintLeft(buf, ColSpaces, '*');
else else
PrintLeft(buf, ColSpaces, ' '); PrintLeft(buf, ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
for (l=0; l<CalPad; l++) { for (l=0; l<CalPad; l++) {
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
} }
@@ -162,16 +282,24 @@ static void DoCalendarOneWeek(void)
/* Write any blank lines required */ /* Write any blank lines required */
while (LinesWritten++ < CalLines) { while (LinesWritten++ < CalLines) {
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
} }
/* Write the final line */ /* Write the final line */
WriteIntermediateCalLine(); if (nleft) {
WriteIntermediateCalLine();
} else {
WriteBottomCalLine();
}
} }
/***************************************************************/ /***************************************************************/
@@ -228,6 +356,7 @@ static int WriteCalendarRow(void)
char buf[81]; char buf[81];
int OrigJul = JulianToday; int OrigJul = JulianToday;
int LinesWritten = 0; int LinesWritten = 0;
int moreleft;
/* Get the date of the first day */ /* Get the date of the first day */
FromJulian(JulianToday, &y, &m, &d); FromJulian(JulianToday, &y, &m, &d);
@@ -253,7 +382,9 @@ static int WriteCalendarRow(void)
/* Here come the first few lines... */ /* Here come the first few lines... */
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
if (i < wd || d+i-wd>DaysInMonth(m, y)) if (i < wd || d+i-wd>DaysInMonth(m, y))
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
@@ -261,14 +392,20 @@ static int WriteCalendarRow(void)
sprintf(buf, "%d", d+i-wd); sprintf(buf, "%d", d+i-wd);
PrintLeft(buf, ColSpaces, ' '); PrintLeft(buf, ColSpaces, ' ');
} }
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
for (l=0; l<CalPad; l++) { for (l=0; l<CalPad; l++) {
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
} }
@@ -282,18 +419,27 @@ static int WriteCalendarRow(void)
/* Write any blank lines required */ /* Write any blank lines required */
while (LinesWritten++ < CalLines) { while (LinesWritten++ < CalLines) {
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
} }
WriteIntermediateCalLine(); moreleft = (d+7-wd <= DaysInMonth(m, y));
if (moreleft) {
WriteIntermediateCalLine();
} else {
WriteBottomCalLine();
}
/* Return non-zero if we have not yet finished */ /* Return non-zero if we have not yet finished */
return (d+7-wd <= DaysInMonth(m, y)); return moreleft;
} }
/***************************************************************/ /***************************************************************/
@@ -303,7 +449,7 @@ static int WriteCalendarRow(void)
/* Left-justify a piece of text. */ /* Left-justify a piece of text. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void PrintLeft(char *s, int width, char pad) static void PrintLeft(char const *s, int width, char pad)
{ {
int len = strlen(s); int len = strlen(s);
printf("%s", s); printf("%s", s);
@@ -317,7 +463,7 @@ static void PrintLeft(char *s, int width, char pad)
/* Center a piec of text */ /* Center a piec of text */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void PrintCentered(char *s, int width, char pad) static void PrintCentered(char const *s, int width, char pad)
{ {
int len = strlen(s); int len = strlen(s);
int d = (width - len) / 2; int d = (width - len) / 2;
@@ -341,14 +487,18 @@ static int WriteOneCalLine(void)
{ {
int done = 1, i; int done = 1, i;
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
if (CalColumn[i]) { if (CalColumn[i]) {
if (WriteOneColLine(i)) done = 0; if (WriteOneColLine(i)) done = 0;
} else { } else {
PrintCentered("", ColSpaces, ' '); PrintCentered("", ColSpaces, ' ');
} }
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
@@ -367,8 +517,8 @@ static int WriteOneCalLine(void)
static int WriteOneColLine(int col) static int WriteOneColLine(int col)
{ {
CalEntry *e = CalColumn[col]; CalEntry *e = CalColumn[col];
char *s; char const *s;
char *space; char const *space;
int numwritten = 0; int numwritten = 0;
/* Print as many characters as possible within the column */ /* Print as many characters as possible within the column */
@@ -380,8 +530,8 @@ static int WriteOneColLine(int col)
if (!*s && e->next) { if (!*s && e->next) {
PrintLeft("", ColSpaces, ' '); PrintLeft("", ColSpaces, ' ');
CalColumn[col] = e->next; CalColumn[col] = e->next;
free(e->text); free((char *) e->text);
free(e->filename); free((char *) e->filename);
free(e); free(e);
return 1; return 1;
} }
@@ -393,6 +543,11 @@ static int WriteOneColLine(int col)
s++; s++;
} }
/* Colorize reminder if necessary */
if (UseVTColors && e->is_color) {
Colorize(e);
}
/* If we couldn't find a space char, print what we have. */ /* If we couldn't find a space char, print what we have. */
if (!space) { if (!space) {
for (s = e->pos; s - e->pos < ColSpaces; s++) { for (s = e->pos; s - e->pos < ColSpaces; s++) {
@@ -411,6 +566,11 @@ static int WriteOneColLine(int col)
} }
} }
/* Decolorize reminder if necessary */
if (UseVTColors && e->is_color) {
Decolorize();
}
/* Flesh out the rest of the column */ /* Flesh out the rest of the column */
while(numwritten++ < ColSpaces) PutChar(' '); while(numwritten++ < ColSpaces) PutChar(' ');
@@ -420,8 +580,8 @@ static int WriteOneColLine(int col)
/* If done, free memory if no next entry. */ /* If done, free memory if no next entry. */
if (!*s && !e->next) { if (!*s && !e->next) {
CalColumn[col] = e->next; CalColumn[col] = e->next;
free(e->text); free((char *) e->text);
free(e->filename); free((char *) e->filename);
free(e); free(e);
} else { } else {
e->pos = s; e->pos = s;
@@ -440,7 +600,7 @@ static void GenerateCalEntries(int col)
{ {
int r; int r;
Token tok; Token tok;
char *s; char const *s;
Parser p; Parser p;
/* Do some initialization first... */ /* Do some initialization first... */
@@ -449,7 +609,7 @@ static void GenerateCalEntries(int col)
DestroyVars(0); DestroyVars(0);
NumTriggered = 0; NumTriggered = 0;
r=OpenFile(InitialFile); r=IncludeFile(InitialFile);
if (r) { if (r) {
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]); fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
exit(1); exit(1);
@@ -549,14 +709,18 @@ static void WriteCalHeader(void)
FromJulian(JulianToday, &y, &m, &d); FromJulian(JulianToday, &y, &m, &d);
sprintf(buf, "%s %d", MonthName[m], y); sprintf(buf, "%s %d", MonthName[m], y);
WriteSolidCalLine(); WriteTopCalLine();
PutChar('|'); gon();
DRAW(tb);
goff();
PrintCentered(buf, CalWidth-2, ' '); PrintCentered(buf, CalWidth-2, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
PutChar('\n'); PutChar('\n');
WriteIntermediateCalLine(); WritePostHeaderLine();
WriteCalDays(); WriteCalDays();
WriteIntermediateCalLine(); WriteIntermediateCalLine();
} }
@@ -584,19 +748,22 @@ static int DoCalRem(ParsePtr p, int col)
Trigger trig; Trigger trig;
TimeTrig tim; TimeTrig tim;
Value v; Value v;
int r; int r, err;
int jul; int jul;
CalEntry *CurCol = CalColumn[col]; CalEntry *CurCol = CalColumn[col];
CalEntry *e; CalEntry *e;
char *s, *s2; char const *s, *s2;
DynamicBuffer buf, obuf, pre_buf; DynamicBuffer buf, obuf, pre_buf;
Token tok; Token tok;
int is_color, col_r, col_g, col_b;
is_color = 0;
DBufInit(&buf); DBufInit(&buf);
DBufInit(&pre_buf); DBufInit(&pre_buf);
/* Parse the trigger date and time */ /* Parse the trigger date and time */
if ( (r=ParseRem(p, &trig, &tim)) ) return r; if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
/* Don't include timed reminders in calendar if -a option supplied. */ /* Don't include timed reminders in calendar if -a option supplied. */
if (DontIssueAts && tim.ttime != NO_TIME) return OK; if (DontIssueAts && tim.ttime != NO_TIME) return OK;
@@ -604,6 +771,7 @@ static int DoCalRem(ParsePtr p, int col)
if (trig.typ == SAT_TYPE) { if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, &tim, p); r=DoSatRemind(&trig, &tim, p);
if (r) return r; if (r) return r;
if (!LastTrigValid) return OK;
r=ParseToken(p, &buf); r=ParseToken(p, &buf);
if (r) return r; if (r) return r;
FindToken(DBufValue(&buf), &tok); FindToken(DBufValue(&buf), &tok);
@@ -625,7 +793,7 @@ static int DoCalRem(ParsePtr p, int col)
if (!LastTrigValid) return OK; if (!LastTrigValid) return OK;
} else { } else {
/* Calculate the trigger date */ /* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r); jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
if (r) return r; if (r) return r;
} }
@@ -640,6 +808,7 @@ static int DoCalRem(ParsePtr p, int col)
if (trig.typ == PASSTHRU_TYPE) { if (trig.typ == PASSTHRU_TYPE) {
if (!PsCal && strcmp(trig.passthru, "COLOR")) return OK; if (!PsCal && strcmp(trig.passthru, "COLOR")) return OK;
if (!strcmp(trig.passthru, "COLOR")) { if (!strcmp(trig.passthru, "COLOR")) {
is_color = 1;
/* Strip off the three color numbers */ /* Strip off the three color numbers */
DBufFree(&buf); DBufFree(&buf);
r=ParseToken(p, &buf); r=ParseToken(p, &buf);
@@ -657,6 +826,15 @@ static int DoCalRem(ParsePtr p, int col)
DBufPutc(&pre_buf, ' '); DBufPutc(&pre_buf, ' ');
DBufFree(&buf); DBufFree(&buf);
if (r) return r; if (r) return r;
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
&col_r, &col_g, &col_b);
if (col_r < 0) col_r = 0;
else if (col_r > 255) col_r = 255;
if (col_g < 0) col_g = 0;
else if (col_g > 255) col_g = 255;
if (col_b < 0) col_b = 0;
else if (col_b > 255) col_b = 255;
if (!PsCal && !DoSimpleCalendar) { if (!PsCal && !DoSimpleCalendar) {
DBufFree(&pre_buf); DBufFree(&pre_buf);
} }
@@ -666,9 +844,8 @@ static int DoCalRem(ParsePtr p, int col)
/* If trigger date == today, add it to the current entry */ /* If trigger date == today, add it to the current entry */
DBufInit(&obuf); DBufInit(&obuf);
if ((jul == JulianToday) || if ((jul == JulianToday) ||
(DoSimpleCalendar && (DoSimpleCalDelta &&
DoSimpleCalDelta && ShouldTriggerReminder(&trig, &tim, jul, &err))) {
ShouldTriggerReminder(&trig, &tim, jul))) {
NumTriggered++; NumTriggered++;
if (DoSimpleCalendar || tim.ttime != NO_TIME) { if (DoSimpleCalendar || tim.ttime != NO_TIME) {
@@ -682,7 +859,7 @@ static int DoCalRem(ParsePtr p, int col)
return E_NO_MEM; return E_NO_MEM;
} }
} else { } else {
if (DBufPuts(&obuf, SimpleTime(tim.ttime)) != OK) { if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) {
DBufFree(&obuf); DBufFree(&obuf);
DBufFree(&pre_buf); DBufFree(&pre_buf);
return E_NO_MEM; return E_NO_MEM;
@@ -749,6 +926,10 @@ static int DoCalRem(ParsePtr p, int col)
DBufPuts(&pre_buf, s); DBufPuts(&pre_buf, s);
s = DBufValue(&pre_buf); s = DBufValue(&pre_buf);
e = NEW(CalEntry); e = NEW(CalEntry);
e->is_color = is_color;
e->r = col_r;
e->g = col_g;
e->b = col_b;
if (!e) { if (!e) {
DBufFree(&obuf); DBufFree(&obuf);
DBufFree(&pre_buf); DBufFree(&pre_buf);
@@ -830,8 +1011,8 @@ static void WriteSimpleEntries(int col, int jul)
printf("* "); printf("* ");
} }
printf("%s\n", e->text); printf("%s\n", e->text);
free(e->text); free((char *) e->text);
free(e->filename); free((char *) e->filename);
n = e->next; n = e->next;
free(e); free(e);
e = n; e = n;
@@ -844,11 +1025,64 @@ static void WriteSimpleEntries(int col, int jul)
/* Various functions for writing different types of lines. */ /* Various functions for writing different types of lines. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void WriteSolidCalLine(void) static void WriteTopCalLine(void)
{ {
PutChar('+'); gon();
PrintCentered("", CalWidth-2, '-'); DRAW(br);
PutChar('+'); PrintCentered("", CalWidth-2, linestruct->lr);
DRAW(bl);
goff();
PutChar('\n');
}
static void WriteBottomCalLine(void)
{
int i;
gon();
DRAW(tr);
for (i=0; i<7; i++) {
PrintCentered("", ColSpaces, linestruct->lr);
if (i != 6) {
DRAW(tlr);
} else {
DRAW(tl);
}
}
goff();
PutChar('\n');
}
static void WritePostHeaderLine(void)
{
int i;
gon();
DRAW(tbr);
for (i=0; i<7; i++) {
PrintCentered("", ColSpaces, linestruct->lr);
if (i != 6) {
DRAW(blr);
} else {
DRAW(tbl);
}
}
goff();
PutChar('\n');
}
static void WriteWeekHeaderLine(void)
{
int i;
gon();
DRAW(br);
for (i=0; i<7; i++) {
PrintCentered("", ColSpaces, linestruct->lr);
if (i != 6) {
DRAW(blr);
} else {
DRAW(bl);
}
}
goff();
PutChar('\n'); PutChar('\n');
} }
@@ -856,28 +1090,121 @@ static void WriteIntermediateCalLine(void)
{ {
int i; int i;
PutChar('+'); gon();
DRAW(tbr);
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
PrintCentered("", ColSpaces, '-'); PrintCentered("", ColSpaces, linestruct->lr);
PutChar('+'); if (i != 6) {
DRAW(tblr);
} else {
DRAW(tbl);
}
} }
goff();
PutChar('\n'); PutChar('\n');
} }
static void WriteCalDays(void) static void WriteCalDays(void)
{ {
int i; int i;
PutChar('|'); gon();
DRAW(tb);
goff();
for (i=0; i<7; i++) { for (i=0; i<7; i++) {
if (!MondayFirst) if (!MondayFirst)
PrintCentered(DayName[(i+6)%7], ColSpaces, ' '); PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
else else
PrintCentered(DayName[i%7], ColSpaces, ' '); PrintCentered(DayName[i%7], ColSpaces, ' ');
PutChar('|'); gon();
DRAW(tb);
goff();
} }
PutChar('\n'); PutChar('\n');
} }
/***************************************************************/
/* */
/* CalendarTime */
/* */
/* Format the time according to simple time format. */
/* Answer is returned in a static buffer. */
/* A trailing space is always added. */
/* This takes into account duration */
/* */
/***************************************************************/
char const *
CalendarTime(int tim, int duration)
{
static char buf[128];
int h, min, hh;
int h2, min2, hh2, newtim, days;
char const *ampm1;
char const *ampm2;
char daybuf[64];
buf[0] = 0;
if (duration == NO_TIME) {
/* No duration... just call into SimpleTime */
return SimpleTime(tim);
}
if (tim == NO_TIME) {
/* No time... nothing to return */
return buf;
}
h = tim/60;
min = tim % 60;
if (h == 0) hh=12;
else if (h > 12) hh=h-12;
else hh = h;
newtim = tim + duration;
/* How many days in duration? */
days = newtim / MINUTES_PER_DAY;
newtim = newtim % MINUTES_PER_DAY;
h2 = newtim/60;
min2 = newtim % 60;
if (h2 == 0) hh2=12;
else if (h2 > 12) hh2=h2-12;
else hh2 = h2;
if (days) {
sprintf(daybuf, "+%d", days);
} else {
daybuf[0] = 0;
}
if (h >= 12) {
ampm1 = L_PM;
} else {
ampm1 = L_AM;
}
if (h2 >= 12) {
ampm2 = L_PM;
} else {
ampm2 = L_AM;
}
if (!days) {
if (!strcmp(ampm1, ampm2)) {
ampm1 = "";
}
}
switch(ScFormat) {
case SC_AMPM:
sprintf(buf, "%d%c%02d%s-%d%c%02d%s%s ",
hh, TimeSep, min, ampm1, hh2, TimeSep, min2, ampm2, daybuf);
break;
case SC_MIL:
sprintf(buf, "%02d%c%02d-%02d%c%02d%s ",
h, TimeSep, min, h2, TimeSep, min2, daybuf);
break;
}
return buf;
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* SimpleTime */ /* SimpleTime */
@@ -887,7 +1214,7 @@ static void WriteCalDays(void)
/* A trailing space is always added. */ /* A trailing space is always added. */
/* */ /* */
/***************************************************************/ /***************************************************************/
char *SimpleTime(int tim) char const *SimpleTime(int tim)
{ {
static char buf[32]; static char buf[32];
int h, min, hh; int h, min, hh;
@@ -903,7 +1230,7 @@ char *SimpleTime(int tim)
if (h == 0) hh=12; if (h == 0) hh=12;
else if (h > 12) hh=h-12; else if (h > 12) hh=h-12;
else hh=h; else hh=h;
sprintf(buf, "%2d%c%02d%s ", hh, TimeSep, min, (h>=12) ? L_PM : L_AM); sprintf(buf, "%d%c%02d%s ", hh, TimeSep, min, (h>=12) ? L_PM : L_AM);
} }
break; break;
@@ -938,7 +1265,7 @@ static void SortCol(CalEntry **col)
while (cur->next && while (cur->next &&
CompareRems(0, cur->time, cur->priority, CompareRems(0, cur->time, cur->priority,
0, cur->next->time, cur->next->priority, 0, cur->next->time, cur->next->priority,
SortByDate, SortByTime, SortByPrio) <= 0) { SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed) <= 0) {
next = cur->next; next = cur->next;
/* Swap cur and next */ /* Swap cur and next */
if (!prev) { if (!prev) {

View File

@@ -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. */ /* Define if utime(file, NULL) sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL #undef HAVE_UTIME_NULL
@@ -12,6 +10,11 @@
/* Define if you have the <sys/file.h> header file. */ /* Define if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H #undef HAVE_SYS_FILE_H
/* Define if you have the <glob.h> header file */
#undef HAVE_GLOB_H
#undef HAVE_GLOB
#undef HAVE_SETENV #undef HAVE_SETENV
#undef HAVE_UNSETENV #undef HAVE_UNSETENV

View File

@@ -148,6 +148,12 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define MAX_PRT_LEN 40 #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 */ /* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
@@ -161,7 +167,7 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */ /* 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 */ /* IF_NEST: How many nested IFs do we handle? Maximum is the number */

View File

@@ -148,6 +148,12 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define MAX_PRT_LEN 40 #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 */ /* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
@@ -161,7 +167,7 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */ /* 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 */ /* IF_NEST: How many nested IFs do we handle? Maximum is the number */

View File

@@ -29,12 +29,12 @@
static char const DontEscapeMe[] = static char const DontEscapeMe[] =
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,"; "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 ParseLocalOmit (ParsePtr s, Trigger *t);
static int ParseScanFrom (ParsePtr s, Trigger *t, int type); static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
static int ParsePriority (ParsePtr s, Trigger *t); static int ParsePriority (ParsePtr s, Trigger *t);
static int ParseUntil (ParsePtr s, Trigger *t); static int ParseUntil (ParsePtr s, Trigger *t);
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul); static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -48,7 +48,7 @@ int DoRem(ParsePtr p)
Trigger trig; Trigger trig;
TimeTrig tim; TimeTrig tim;
int r; int r, err;
int jul; int jul;
DynamicBuffer buf; DynamicBuffer buf;
Token tok; Token tok;
@@ -56,12 +56,13 @@ int DoRem(ParsePtr p)
DBufInit(&buf); DBufInit(&buf);
/* Parse the trigger date and time */ /* Parse the trigger date and time */
if ( (r=ParseRem(p, &trig, &tim)) ) return r; if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
if (trig.typ == NO_TYPE) return E_EOLN; if (trig.typ == NO_TYPE) return E_EOLN;
if (trig.typ == SAT_TYPE) { if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, &tim, p); r=DoSatRemind(&trig, &tim, p);
if (r) return r; if (r) return r;
if (!LastTrigValid) return OK;
r=ParseToken(p, &buf); r=ParseToken(p, &buf);
if (r) return r; if (r) return r;
FindToken(DBufValue(&buf), &tok); FindToken(DBufValue(&buf), &tok);
@@ -89,7 +90,7 @@ int DoRem(ParsePtr p)
if (!LastTrigValid) return OK; if (!LastTrigValid) return OK;
} else { } else {
/* Calculate the trigger date */ /* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r); jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
if (r) return r; if (r) return r;
} }
@@ -102,7 +103,7 @@ int DoRem(ParsePtr p)
/* If we're in daemon mode, do nothing over here */ /* If we're in daemon mode, do nothing over here */
if (Daemon) return OK; if (Daemon) return OK;
if (ShouldTriggerReminder(&trig, &tim, jul)) { if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
{ {
return r; return r;
@@ -120,12 +121,14 @@ int DoRem(ParsePtr p)
/* trigger structure. */ /* 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; register int r;
DynamicBuffer buf; DynamicBuffer buf;
Token tok; Token tok;
int y, m, d;
DBufInit(&buf); DBufInit(&buf);
trig->y = NO_YR; trig->y = NO_YR;
@@ -144,13 +147,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
trig->priority = DefaultPrio; trig->priority = DefaultPrio;
trig->sched[0] = 0; trig->sched[0] = 0;
trig->warn[0] = 0; trig->warn[0] = 0;
trig->omitfunc[0] = 0;
trig->tag[0] = 0; trig->tag[0] = 0;
trig->passthru[0] = 0; trig->passthru[0] = 0;
tim->ttime = NO_TIME; tim->ttime = NO_TIME;
tim->delta = NO_DELTA; tim->delta = NO_DELTA;
tim->rep = NO_REP; tim->rep = NO_REP;
tim->duration = NO_TIME; tim->duration = NO_TIME;
LastTriggerTime = NO_TIME; if (save_in_globals) {
LastTriggerTime = NO_TIME;
}
while(1) { while(1) {
/* Read space-delimited string */ /* Read space-delimited string */
@@ -160,6 +166,32 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
/* Figure out what we've got */ /* Figure out what we've got */
FindToken(DBufValue(&buf), &tok); FindToken(DBufValue(&buf), &tok);
switch(tok.type) { 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;
}
break;
case T_WkDay: case T_WkDay:
DBufFree(&buf); DBufFree(&buf);
if (trig->wd & (1 << tok.val)) return E_WD_TWICE; if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
@@ -186,7 +218,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
case T_At: case T_At:
DBufFree(&buf); DBufFree(&buf);
r=ParseTimeTrig(s, tim); r=ParseTimeTrig(s, tim, save_in_globals);
if (r) return r; if (r) return r;
break; break;
@@ -256,6 +288,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
case T_Omit: case T_Omit:
DBufFree(&buf); DBufFree(&buf);
if (trig->omitfunc[0]) {
Eprint("Warning: OMIT is ignored if you use OMITFUNC");
}
r = ParseLocalOmit(s, trig); r = ParseLocalOmit(s, trig);
if (r) return r; if (r) return r;
break; break;
@@ -265,6 +301,16 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
return OK; 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: case T_Warn:
r=ParseToken(s, &buf); r=ParseToken(s, &buf);
if(r) return r; if(r) return r;
@@ -321,7 +367,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
/* ParseTimeTrig - parse the AT part of a timed reminder */ /* 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; Token tok;
int r; int r;
@@ -353,7 +399,9 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
if (tim->ttime == NO_TIME) return E_EXPECT_TIME; if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
/* Save trigger time in global variable */ /* Save trigger time in global variable */
LastTriggerTime = tim->ttime; if (save_in_globals) {
LastTriggerTime = tim->ttime;
}
PushToken(DBufValue(&buf), s); PushToken(DBufValue(&buf), s);
DBufFree(&buf); DBufFree(&buf);
return OK; return OK;
@@ -442,6 +490,23 @@ static int ParseUntil(ParsePtr s, Trigger *t)
d = tok.val; d = tok.val;
break; 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: default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) { if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]); Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]);
@@ -517,6 +582,23 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
d = tok.val; d = tok.val;
break; 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;
default: default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) { if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]); Eprint("%s: %s", word, ErrMsg[E_INCOMPLETE]);
@@ -550,11 +632,11 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul) int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
{ {
int r, y, m, d; int r, y, m, d;
char PrioExpr[25]; char PrioExpr[VAR_NAME_LEN+25];
char tmpBuf[64]; char tmpBuf[64];
DynamicBuffer buf, calRow; DynamicBuffer buf, calRow;
DynamicBuffer pre_buf; DynamicBuffer pre_buf;
char *s; char const *s;
Value v; Value v;
DBufInit(&buf); DBufInit(&buf);
@@ -743,7 +825,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
DBufFree(&buf); DBufFree(&buf);
NumTriggered++; NumTriggered++;
return OK; return OK;
} }
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -751,12 +833,13 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
/* */ /* */
/* Return 1 if we should trigger a reminder, based on today's */ /* Return 1 if we should trigger a reminder, based on today's */
/* date and the trigger. Return 0 if reminder should not be */ /* 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. */ /* Handle the ONCE modifier in the reminder. */
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday) if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
@@ -780,7 +863,12 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
/* If there's a "warn" function, it overrides any deltas */ /* If there's a "warn" function, it overrides any deltas */
if (t->warn[0] != 0) { 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 */ /* Move back by delta days, if any */
@@ -789,15 +877,28 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
jul = jul + t->delta; jul = jul + t->delta;
else { else {
r = t->delta; r = t->delta;
while(r && jul > JulianToday) { int iter = 0;
int max = MaxSatIter;
if (max < r*2) max = r*2;
while(iter++ < max) {
if (!r || (jul <= JulianToday)) {
break;
}
jul--; 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? */ /* Should we trigger the reminder? */
return (jul <= JulianToday); return (jul <= JulianToday + DeltaOffset);
} }
/***************************************************************/ /***************************************************************/
@@ -811,16 +912,20 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
{ {
int iter, jul, r; int iter, jul, r;
Value v; Value v;
char *s, *t; char const *s;
char const *t;
t = p->pos; t = p->pos;
iter = 0; iter = 0;
jul = trig->scanfrom; jul = trig->scanfrom;
while (iter++ < MaxSatIter) { while (iter++ < MaxSatIter) {
jul = ComputeTrigger(jul, trig, &r); jul = ComputeTrigger(jul, trig, &r, 1);
if (r) { if (r) {
if (r == E_CANT_TRIG) return OK; else return r; if (r == E_CANT_TRIG) return OK; else return r;
} }
if (jul == -1) {
return OK;
}
s = p->pos; s = p->pos;
r = EvaluateExpr(p, &v); r = EvaluateExpr(p, &v);
t = p->pos; t = p->pos;
@@ -844,7 +949,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
static int ParsePriority(ParsePtr s, Trigger *t) static int ParsePriority(ParsePtr s, Trigger *t)
{ {
int p, r; int p, r;
char *u; char const *u;
DynamicBuffer buf; DynamicBuffer buf;
DBufInit(&buf); DBufInit(&buf);
@@ -882,14 +987,14 @@ static int ParsePriority(ParsePtr s, Trigger *t)
/* Execute the '-k' command, escaping shell chars in message. */ /* Execute the '-k' command, escaping shell chars in message. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int DoMsgCommand(char *cmd, char *msg) int DoMsgCommand(char const *cmd, char const *msg)
{ {
int r; int r;
int i, l; int i, l;
DynamicBuffer execBuffer; DynamicBuffer execBuffer;
DynamicBuffer buf; DynamicBuffer buf;
char *s; char const *s;
DBufInit(&buf); DBufInit(&buf);
DBufInit(&execBuffer); DBufInit(&execBuffer);
@@ -943,12 +1048,12 @@ finished:
/* function. */ /* function. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static int ShouldTriggerBasedOnWarn(Trigger *t, int jul) static int ShouldTriggerBasedOnWarn(Trigger *t, int jul, int *err)
{ {
char buffer[VAR_NAME_LEN+32]; char buffer[VAR_NAME_LEN+32];
int i; int i;
char *s; char const *s;
int r; int r, omit;
Value v; Value v;
int lastReturnVal = 0; /* Silence compiler warning */ int lastReturnVal = 0; /* Silence compiler warning */
@@ -986,9 +1091,21 @@ static int ShouldTriggerBasedOnWarn(Trigger *t, int jul)
if (JulianToday + v.v.val == jul) return 1; if (JulianToday + v.v.val == jul) return 1;
} else { } else {
int j = jul; 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--; 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; if (j == JulianToday) return 1;
} }

View File

@@ -54,11 +54,12 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
int d, m, y; int d, m, y;
int tim = tt->ttime; int tim = tt->ttime;
int h, min, hh, ch, cmin, chh; int h, min, hh, ch, cmin, chh;
char *pm, *cpm; char const *pm, *cpm;
int tdiff, adiff, mdiff, hdiff; int tdiff, adiff, mdiff, hdiff;
char *mplu, *hplu, *when, *plu; char const *mplu, *hplu, *when, *plu;
int has_quote = 0; int has_quote = 0;
char *ss, *os; char *ss;
char *os;
char s[256]; char s[256];
int origLen = DBufLen(dbuf); int origLen = DBufLen(dbuf);
@@ -649,7 +650,7 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
/* default triggers and a mode of NORMAL_MODE. */ /* 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) int jul, int tim)
{ {
Trigger tempTrig; Trigger tempTrig;

View File

@@ -42,7 +42,7 @@ static int DBufMakeRoom(DynamicBuffer *dbuf, int n)
} }
/* Allocate memory */ /* Allocate memory */
buf = (char *) malloc(size); buf = malloc(size);
if (!buf) return E_NO_MEM; if (!buf) return E_NO_MEM;
/* Copy contents */ /* Copy contents */
@@ -102,7 +102,7 @@ int DBufPutcFN(DynamicBuffer *dbuf, char c)
%DESCRIPTION: %DESCRIPTION:
Appends a string to the buffer. Appends a string to the buffer.
**********************************************************************/ **********************************************************************/
int DBufPuts(DynamicBuffer *dbuf, char *str) int DBufPuts(DynamicBuffer *dbuf, char const *str)
{ {
int l = strlen(str); int l = strlen(str);
if (!l) return OK; if (!l) return OK;

View File

@@ -25,7 +25,7 @@ typedef struct {
void DBufInit(DynamicBuffer *dbuf); void DBufInit(DynamicBuffer *dbuf);
int DBufPutcFN(DynamicBuffer *dbuf, char c); int DBufPutcFN(DynamicBuffer *dbuf, char c);
int DBufPuts(DynamicBuffer *dbuf, char *str); int DBufPuts(DynamicBuffer *dbuf, char const *str);
void DBufFree(DynamicBuffer *dbuf); void DBufFree(DynamicBuffer *dbuf);
int DBufGets(DynamicBuffer *dbuf, FILE *fp); int DBufGets(DynamicBuffer *dbuf, FILE *fp);

View File

@@ -117,6 +117,8 @@
#define E_EXPECTING_NUMBER 97 #define E_EXPECTING_NUMBER 97
#define M_BAD_WARN_FUNC 98 #define M_BAD_WARN_FUNC 98
#define E_CANT_CONVERT_TZ 99 #define E_CANT_CONVERT_TZ 99
#define E_NO_MATCHING_REMS 100
#define E_STRING_TOO_LONG 101
#ifdef MK_GLOBALS #ifdef MK_GLOBALS
#undef EXTERN #undef EXTERN
@@ -189,7 +191,7 @@ EXTERN char *ErrMsg[]
"Too many partial OMITs", "Too many partial OMITs",
"Too many full OMITs", "Too many full OMITs",
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT", "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
"Error reading file", "Error reading",
"Expecting end-of-line", "Expecting end-of-line",
"Invalid Hebrew date", "Invalid Hebrew date",
"IIF needs odd number of arguments", "IIF needs odd number of arguments",
@@ -230,7 +232,9 @@ EXTERN char *ErrMsg[]
"%d reminder(s) queued for later today.\n", "%d reminder(s) queued for later today.\n",
"Expecting number", "Expecting number",
"Bad function in WARN clause", "Bad function in WARN clause",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
} }
#endif /* MK_GLOBALS */ #endif /* MK_GLOBALS */
; ;

View File

@@ -41,8 +41,7 @@ static int Multiply(void), Divide(void), Mod(void), Add(void),
UnMinus(void), LogNot(void), UnMinus(void), LogNot(void),
Compare(int); Compare(int);
static int MakeValue (char *s, Value *v, Var *locals); static int MakeValue (char const *s, Value *v, Var *locals);
static int ParseLiteralDate (char **s, int *jul, int *tim);
/* Binary operators - all left-associative */ /* Binary operators - all left-associative */
@@ -73,9 +72,7 @@ Operator UnOp[] = {
}; };
#define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator)) #define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator))
/* Functions have the same definitions as operators, except the prec field extern BuiltinFunc Func[];
is used to indicate how many arguments are needed. */
extern Operator Func[];
Operator OpStack[OP_STACK_SIZE]; Operator OpStack[OP_STACK_SIZE];
Value ValStack[VAL_STACK_SIZE]; Value ValStack[VAL_STACK_SIZE];
@@ -132,9 +129,9 @@ static void CleanStack(void)
/* PeekChar - peek ahead to next char. */ /* PeekChar - peek ahead to next char. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static char PeekChar(char **s) static char PeekChar(char const **s)
{ {
char *t = *s; char const *t = *s;
while (*t && isspace(*t)) t++; while (*t && isspace(*t)) t++;
return *t; return *t;
} }
@@ -146,7 +143,7 @@ static char PeekChar(char **s)
/* Read a token. */ /* Read a token. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static int ParseExprToken(DynamicBuffer *buf, char **in) static int ParseExprToken(DynamicBuffer *buf, char const **in)
{ {
char c; char c;
@@ -204,6 +201,46 @@ static int ParseExprToken(DynamicBuffer *buf, char **in)
if (c == '\"') { if (c == '\"') {
if (!**in) return E_MISS_QUOTE; if (!**in) return E_MISS_QUOTE;
while (**in) { 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)++; c = *(*in)++;
if (DBufPutc(buf, c) != OK) { if (DBufPutc(buf, c) != OK) {
DBufFree(buf); DBufFree(buf);
@@ -266,7 +303,7 @@ static int ParseExprToken(DynamicBuffer *buf, char **in)
/* Put the result into value pointed to by v. */ /* Put the result into value pointed to by v. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int EvalExpr(char **e, Value *v) int EvalExpr(char const **e, Value *v)
{ {
int r; int r;
@@ -289,15 +326,16 @@ int EvalExpr(char **e, Value *v)
} }
/* Evaluate - do the actual work of evaluation. */ /* Evaluate - do the actual work of evaluation. */
int Evaluate(char **s, Var *locals) int Evaluate(char const **s, Var *locals)
{ {
int OpBase, ValBase; int OpBase, ValBase;
int r; int r;
Operator *f; Operator *o;
BuiltinFunc *f;
int args; /* Number of function arguments */ int args; /* Number of function arguments */
Operator op, op2; Operator op, op2;
Value va; 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; OpBase = OpStackPtr;
ValBase = ValStackPtr; ValBase = ValStackPtr;
@@ -339,7 +377,7 @@ int Evaluate(char **s, Var *locals)
if (f) r = CallFunc(f, 0); if (f) r = CallFunc(f, 0);
else { else {
r = CallUserFunc(ufname, 0); r = CallUserFunc(ufname, 0);
free(ufname); free((char *) ufname);
} }
if (r) return r; if (r) return r;
r = ParseExprToken(&ExprBuf, s); /* Guaranteed to be right paren. */ r = ParseExprToken(&ExprBuf, s); /* Guaranteed to be right paren. */
@@ -349,12 +387,12 @@ int Evaluate(char **s, Var *locals)
args++; args++;
r = Evaluate(s, locals); r = Evaluate(s, locals);
if (r) { if (r) {
if (!f) free(ufname); if (!f) free((char *) ufname);
return r; return r;
} }
if (*DBufValue(&ExprBuf) == ')') break; if (*DBufValue(&ExprBuf) == ')') break;
else if (*DBufValue(&ExprBuf) != ',') { else if (*DBufValue(&ExprBuf) != ',') {
if (!f) free(ufname); if (!f) free((char *) ufname);
Eprint("%s: `%c'", ErrMsg[E_EXPECT_COMMA], Eprint("%s: `%c'", ErrMsg[E_EXPECT_COMMA],
*DBufValue(&ExprBuf)); *DBufValue(&ExprBuf));
DBufFree(&ExprBuf); DBufFree(&ExprBuf);
@@ -364,16 +402,16 @@ int Evaluate(char **s, Var *locals)
if (f) r = CallFunc(f, args); if (f) r = CallFunc(f, args);
else { else {
r = CallUserFunc(ufname, args); r = CallUserFunc(ufname, args);
free(ufname); free((char *) ufname);
} }
DBufFree(&ExprBuf); DBufFree(&ExprBuf);
if (r) return r; if (r) return r;
} }
} else { /* Unary operator */ } else { /* Unary operator */
f = FindFunc(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS); o = FindOperator(DBufValue(&ExprBuf), UnOp, NUM_UN_OPS);
if (f) { if (o) {
DBufFree(&ExprBuf); DBufFree(&ExprBuf);
PushOpStack(*f); PushOpStack(*o);
continue; /* Still looking for an atomic vlue */ continue; /* Still looking for an atomic vlue */
} else if (!ISID(*DBufValue(&ExprBuf)) && } else if (!ISID(*DBufValue(&ExprBuf)) &&
*DBufValue(&ExprBuf) != '$' && *DBufValue(&ExprBuf) != '$' &&
@@ -419,13 +457,13 @@ int Evaluate(char **s, Var *locals)
return OK; return OK;
} }
/* Must be a binary operator */ /* Must be a binary operator */
f = FindFunc(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS); o = FindOperator(DBufValue(&ExprBuf), BinOp, NUM_BIN_OPS);
DBufFree(&ExprBuf); 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, /* While operators of higher or equal precedence are on the stack,
pop them off and evaluate */ 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); PopOpStack(op2);
if (r) return r; if (r) return r;
if (DebugFlag & DB_PRTEXPR) if (DebugFlag & DB_PRTEXPR)
@@ -437,7 +475,7 @@ int Evaluate(char **s, Var *locals)
return r; return r;
} }
} }
PushOpStack(*f); PushOpStack(*o);
} }
} }
@@ -448,7 +486,7 @@ int Evaluate(char **s, Var *locals)
/* a date or the value of a symbol. */ /* 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)
{ {
int len; int len;
int h, m, r; int h, m, r;
@@ -456,7 +494,7 @@ static int MakeValue(char *s, Value *v, Var *locals)
if (*s == '\"') { /* It's a literal string "*/ if (*s == '\"') { /* It's a literal string "*/
len = strlen(s)-1; len = strlen(s)-1;
v->type = STR_TYPE; v->type = STR_TYPE;
v->v.str = (char *) malloc(len); v->v.str = malloc(len);
if (! v->v.str) { if (! v->v.str) {
v->type = ERR_TYPE; v->type = ERR_TYPE;
return E_NO_MEM; return E_NO_MEM;
@@ -533,7 +571,7 @@ static int MakeValue(char *s, Value *v, Var *locals)
int DoCoerce(char type, Value *v) int DoCoerce(char type, Value *v)
{ {
int h, d, m, y, i, k; int h, d, m, y, i, k;
char *s; char const *s;
/* Do nothing if value is already the right type */ /* Do nothing if value is already the right type */
if (type == v->type) return OK; if (type == v->type) return OK;
@@ -697,6 +735,8 @@ static int Add(void)
Value v1, v2, v3; Value v1, v2, v3;
int r; int r;
size_t l1, l2;
PopValStack(v2); PopValStack(v2);
if ( (r = FnPopValStack(&v1)) ) { if ( (r = FnPopValStack(&v1)) ) {
DestroyValue(v2); DestroyValue(v2);
@@ -751,7 +791,13 @@ static int Add(void)
return r; return r;
} }
v3.type = STR_TYPE; 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 > MaxStringLen)) {
DestroyValue(v1); DestroyValue(v2);
return E_STRING_TOO_LONG;
}
v3.v.str = malloc(l1 + l2 + 1);
if (!v3.v.str) { if (!v3.v.str) {
DestroyValue(v1); DestroyValue(v2); DestroyValue(v1); DestroyValue(v2);
return E_NO_MEM; return E_NO_MEM;
@@ -1078,7 +1124,28 @@ static int LogNot(void)
/* Find a function. */ /* 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 top=num-1, bot=0;
int mid, r; int mid, r;
@@ -1102,7 +1169,7 @@ Operator *FindFunc(char *name, Operator where[], int num)
void PrintValue (Value *v, FILE *fp) void PrintValue (Value *v, FILE *fp)
{ {
int y, m, d; int y, m, d;
char *s; char const *s;
if (v->type == STR_TYPE) { if (v->type == STR_TYPE) {
s=v->v.str; s=v->v.str;
@@ -1154,7 +1221,7 @@ int CopyValue(Value *dest, const Value *src)
/* and tim; update s. */ /* 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 y, m, d;
int hour, min; int hour, min;

View File

@@ -30,6 +30,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
#include "types.h" #include "types.h"
#include "protos.h" #include "protos.h"
#include "globals.h" #include "globals.h"
@@ -42,20 +46,34 @@
/* Define the structures needed by the file caching system */ /* Define the structures needed by the file caching system */
typedef struct cache { typedef struct cache {
struct cache *next; struct cache *next;
char *text; char const *text;
int LineNo; int LineNo;
} CachedLine; } CachedLine;
typedef struct cheader { typedef struct cheader {
struct cheader *next; struct cheader *next;
char *filename; char const *filename;
CachedLine *cache; CachedLine *cache;
int ownedByMe; int ownedByMe;
} CachedFile; } 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 */ /* Define the structures needed by the INCLUDE file system */
typedef struct { typedef struct {
char *filename; char const *filename;
FilenameChain *chain;
int LineNo; int LineNo;
unsigned int IfFlags; unsigned int IfFlags;
int NumIfs; int NumIfs;
@@ -66,6 +84,7 @@ typedef struct {
static CachedFile *CachedFiles = (CachedFile *) NULL; static CachedFile *CachedFiles = (CachedFile *) NULL;
static CachedLine *CLine = (CachedLine *) NULL; static CachedLine *CLine = (CachedLine *) NULL;
static DirectoryFilenameChain *CachedDirectoryChains = NULL;
static FILE *fp; static FILE *fp;
@@ -73,9 +92,26 @@ static IncludeStruct IStack[INCLUDE_NEST];
static int IStackPtr = 0; static int IStackPtr = 0;
static int ReadLineFromFile (void); static int ReadLineFromFile (void);
static int CacheFile (const char *fname); static int CacheFile (char const *fname);
static void DestroyCache (CachedFile *cf); static void DestroyCache (CachedFile *cf);
static int CheckSafety (void); static int CheckSafety (void);
static int PopFile (void);
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;
}
}
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -140,7 +176,7 @@ static int ReadLineFromFile(void)
} }
l = DBufLen(&buf); l = DBufLen(&buf);
if (l && (DBufValue(&buf)[l-1] == '\\')) { if (l && (DBufValue(&buf)[l-1] == '\\')) {
DBufValue(&buf)[l-1] = 0; DBufValue(&buf)[l-1] = '\n';
if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) { if (DBufPuts(&LineBuffer, DBufValue(&buf)) != OK) {
DBufFree(&buf); DBufFree(&buf);
DBufFree(&LineBuffer); DBufFree(&LineBuffer);
@@ -171,7 +207,7 @@ static int ReadLineFromFile(void)
/* ShouldCache is 1, cache the file */ /* ShouldCache is 1, cache the file */
/* */ /* */
/***************************************************************/ /***************************************************************/
int OpenFile(const char *fname) int OpenFile(char const *fname)
{ {
CachedFile *h = CachedFiles; CachedFile *h = CachedFiles;
int r; int r;
@@ -183,6 +219,9 @@ int OpenFile(const char *fname)
while (h) { while (h) {
if (!strcmp(fname, h->filename)) { if (!strcmp(fname, h->filename)) {
if (DebugFlag & DB_TRACE_FILES) {
fprintf(ErrFp, "Reading `%s': Found in cache\n", fname);
}
CLine = h->cache; CLine = h->cache;
STRSET(FileName, fname); STRSET(FileName, fname);
LineNo = 0; LineNo = 0;
@@ -197,8 +236,14 @@ int OpenFile(const char *fname)
/* If it's a dash, then it's stdin */ /* If it's a dash, then it's stdin */
if (!strcmp(fname, "-")) { if (!strcmp(fname, "-")) {
fp = stdin; fp = stdin;
if (DebugFlag & DB_TRACE_FILES) {
fprintf(ErrFp, "Reading `-': Reading stdin\n");
}
} else { } else {
fp = fopen(fname, "r"); fp = fopen(fname, "r");
if (DebugFlag & DB_TRACE_FILES) {
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
}
} }
if (!fp || !CheckSafety()) return E_CANT_OPEN; if (!fp || !CheckSafety()) return E_CANT_OPEN;
CLine = NULL; CLine = NULL;
@@ -230,13 +275,16 @@ int OpenFile(const char *fname)
/* Returns an indication of success or failure. */ /* Returns an indication of success or failure. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static int CacheFile(const char *fname) static int CacheFile(char const *fname)
{ {
int r; int r;
CachedFile *cf; CachedFile *cf;
CachedLine *cl; CachedLine *cl;
char *s; char const *s;
if (DebugFlag & DB_TRACE_FILES) {
fprintf(ErrFp, "Caching file `%s' in memory\n", fname);
}
cl = NULL; cl = NULL;
/* Create a file header */ /* Create a file header */
cf = NEW(CachedFile); cf = NEW(CachedFile);
@@ -311,13 +359,33 @@ static int CacheFile(const char *fname)
return OK; 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 */ /* PopFile - we've reached the end. Pop up to the previous */
/* file, or return E_EOF */ /* file, or return E_EOF */
/* */ /* */
/***************************************************************/ /***************************************************************/
int PopFile(void) static int PopFile(void)
{ {
IncludeStruct *i; IncludeStruct *i;
@@ -326,8 +394,21 @@ int PopFile(void)
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]); if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
if (!IStackPtr) return E_EOF; 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--; IStackPtr--;
i = &IStack[IStackPtr];
LineNo = i->LineNo; LineNo = i->LineNo;
IfFlags = i->IfFlags; IfFlags = i->IfFlags;
@@ -349,7 +430,7 @@ int PopFile(void)
if (fp != stdin) if (fp != stdin)
(void) fseek(fp, i->offset, 0); /* Trust that it works... */ (void) fseek(fp, i->offset, 0); /* Trust that it works... */
} }
free(i->filename); free((char *) i->filename);
return OK; return OK;
} }
@@ -361,13 +442,13 @@ int PopFile(void)
/* */ /* */
/***************************************************************/ /***************************************************************/
int DoInclude(ParsePtr p) int DoInclude(ParsePtr p)
{ {
DynamicBuffer buf; DynamicBuffer buf;
int r, e; int r, e;
DBufInit(&buf); DBufInit(&buf);
if ( (r=ParseToken(p, &buf)) ) return r; if ( (r=ParseToken(p, &buf)) ) return r;
e = VerifyEoln(p); e = VerifyEoln(p);
if (e) Eprint("%s", ErrMsg[e]); if (e) Eprint("%s", ErrMsg[e]);
if ( (r=IncludeFile(DBufValue(&buf))) ) { if ( (r=IncludeFile(DBufValue(&buf))) ) {
DBufFree(&buf); DBufFree(&buf);
@@ -379,6 +460,114 @@ int DoInclude(ParsePtr p)
return OK; 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)) {
free(dir);
i->chain = dc->chain;
return OK;
}
dc = dc->next;
}
if (ShouldCache) {
dc = malloc(sizeof(DirectoryFilenameChain));
if (dc) {
dc->dirname = StrDup(dir);
if (!dc->dirname) {
free(dc);
dc = NULL;
}
}
if (dc) {
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 */ /* IncludeFile */
@@ -387,22 +576,28 @@ int DoInclude(ParsePtr p)
/* inclusion. */ /* inclusion. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int IncludeFile(const char *fname) int IncludeFile(char const *fname)
{ {
IncludeStruct *i; IncludeStruct *i;
int r;
int oldRunDisabled; int oldRunDisabled;
struct stat statbuf;
FreshLine = 1;
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE; if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
i = &IStack[IStackPtr]; i = &IStack[IStackPtr];
i->filename = StrDup(FileName); if (FileName) {
if (!i->filename) return E_NO_MEM; i->filename = StrDup(FileName);
if (!i->filename) return E_NO_MEM;
} else {
i->filename = NULL;
}
i->LineNo = LineNo; i->LineNo = LineNo;
i->NumIfs = NumIfs; i->NumIfs = NumIfs;
i->IfFlags = IfFlags; i->IfFlags = IfFlags;
i->CLine = CLine; i->CLine = CLine;
i->offset = -1L; i->offset = -1L;
i->chain = NULL;
if (RunDisabled & RUN_NOTOWNER) { if (RunDisabled & RUN_NOTOWNER) {
i->ownedByMe = 0; i->ownedByMe = 0;
} else { } else {
@@ -415,15 +610,55 @@ int IncludeFile(const char *fname)
IStackPtr++; 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 (DebugFlag & DB_TRACE_FILES) {
fprintf(ErrFp, "Scanning directory `%s' for *.rem files\n", fname);
}
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; oldRunDisabled = RunDisabled;
/* Try to open the new file */ /* Try to open the new file */
if (!OpenFile(fname)) { if (!OpenFile(fname)) {
return OK; return OK;
} }
RunDisabled = oldRunDisabled; RunDisabled = oldRunDisabled;
/* Ugh! We failed! */
if ( (r=PopFile()) ) return r;
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fname); Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fname);
/* Ugh! We failed! */
PopFile();
return E_CANT_OPEN; return E_CANT_OPEN;
} }
@@ -432,7 +667,7 @@ int IncludeFile(const char *fname)
/* GetAccessDate - get the access date of a file. */ /* GetAccessDate - get the access date of a file. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int GetAccessDate(char *file) int GetAccessDate(char const *file)
{ {
struct stat statbuf; struct stat statbuf;
struct tm *t1; struct tm *t1;
@@ -457,10 +692,10 @@ static void DestroyCache(CachedFile *cf)
{ {
CachedLine *cl, *cnext; CachedLine *cl, *cnext;
CachedFile *temp; CachedFile *temp;
if (cf->filename) free(cf->filename); if (cf->filename) free((char *) cf->filename);
cl = cf->cache; cl = cf->cache;
while (cl) { while (cl) {
if (cl->text) free (cl->text); if (cl->text) free ((char *) cl->text);
cnext = cl->next; cnext = cl->next;
free(cl); free(cl);
cl = cnext; cl = cnext;
@@ -488,7 +723,7 @@ static void DestroyCache(CachedFile *cf)
/***************************************************************/ /***************************************************************/
int TopLevel(void) int TopLevel(void)
{ {
return !IStackPtr; return IStackPtr <= 1;
} }
/***************************************************************/ /***************************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@ EXTERN int CurMon;
EXTERN int CurYear; EXTERN int CurYear;
EXTERN int LineNo; EXTERN int LineNo;
EXTERN int FreshLine; EXTERN int FreshLine;
EXTERN INIT( char *MsgCommand, NULL); EXTERN INIT( char const *MsgCommand, NULL);
EXTERN INIT( int ShowAllErrors, 0); EXTERN INIT( int ShowAllErrors, 0);
EXTERN INIT( int DebugFlag, 0); EXTERN INIT( int DebugFlag, 0);
EXTERN INIT( int DoCalendar, 0); EXTERN INIT( int DoCalendar, 0);
@@ -53,15 +53,17 @@ EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0); EXTERN INIT( int Hush, 0);
EXTERN INIT( int NextMode, 0); EXTERN INIT( int NextMode, 0);
EXTERN INIT( int InfiniteDelta, 0); EXTERN INIT( int InfiniteDelta, 0);
EXTERN INIT( int DeltaOffset, 0);
EXTERN INIT( int RunDisabled, 0); EXTERN INIT( int RunDisabled, 0);
EXTERN INIT( int IgnoreOnce, 0); EXTERN INIT( int IgnoreOnce, 0);
EXTERN INIT( int SortByTime, 0); EXTERN INIT( int SortByTime, 0);
EXTERN INIT( int SortByDate, 0); EXTERN INIT( int SortByDate, 0);
EXTERN INIT( int SortByPrio, 0); EXTERN INIT( int SortByPrio, 0);
EXTERN INIT( int UntimedBeforeTimed, 0);
EXTERN INIT( int DefaultPrio, NO_PRIORITY); EXTERN INIT( int DefaultPrio, NO_PRIORITY);
EXTERN INIT( long SysTime, -1L); EXTERN INIT( long SysTime, -1L);
EXTERN char *InitialFile; EXTERN char const *InitialFile;
EXTERN int FileAccessDate; EXTERN int FileAccessDate;
EXTERN INIT( int DontFork, 0); EXTERN INIT( int DontFork, 0);
@@ -74,6 +76,7 @@ EXTERN INIT( char TimeSep, TIMESEP);
EXTERN INIT( int SynthesizeTags, 0); EXTERN INIT( int SynthesizeTags, 0);
EXTERN INIT( int ScFormat, SC_AMPM); EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 150); EXTERN INIT( int MaxSatIter, 150);
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
EXTERN INIT( char *FileName, NULL); EXTERN INIT( char *FileName, NULL);
EXTERN INIT( int UseStdin, 0); EXTERN INIT( int UseStdin, 0);
EXTERN FILE *ErrFp; EXTERN FILE *ErrFp;
@@ -83,12 +86,14 @@ EXTERN INIT( int LastTriggerDate, 0);
EXTERN INIT( int LastTrigValid, 0); EXTERN INIT( int LastTrigValid, 0);
EXTERN INIT( int LastTriggerTime, 0); EXTERN INIT( int LastTriggerTime, 0);
EXTERN INIT( int ShouldCache, 0); EXTERN INIT( int ShouldCache, 0);
EXTERN char *CurLine; EXTERN char const *CurLine;
EXTERN INIT( int NumTriggered, 0); EXTERN INIT( int NumTriggered, 0);
EXTERN int ArgC; EXTERN int ArgC;
EXTERN char **ArgV; EXTERN char const **ArgV;
EXTERN INIT( int CalLines, CAL_LINES); EXTERN INIT( int CalLines, CAL_LINES);
EXTERN INIT( int CalPad, 1); EXTERN INIT( int CalPad, 1);
EXTERN INIT( int UseVTChars, 0);
EXTERN INIT( int UseVTColors, 0);
/* Latitude and longitude */ /* Latitude and longitude */
EXTERN INIT( int LatDeg, LAT_DEG); EXTERN INIT( int LatDeg, LAT_DEG);

View File

@@ -55,7 +55,7 @@
#define ADAR2ADARA 1 #define ADAR2ADARA 1
#define ADAR2BOTH 2 #define ADAR2BOTH 2
static char *HebMonthNames[] = { static char const *HebMonthNames[] = {
"Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B", "Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B",
"Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"}; "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"};
@@ -137,7 +137,7 @@ int DaysInHebYear(int y)
/* given the LENGTH of the Hebrew year. */ /* given the LENGTH of the Hebrew year. */
/* */ /* */
/***************************************************************/ /***************************************************************/
char *DaysInHebMonths(int ylen) char const *DaysInHebMonths(int ylen)
{ {
static char monlen[13] = static char monlen[13] =
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29}; {30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29};
@@ -166,7 +166,7 @@ char *DaysInHebMonths(int ylen)
int HebToJul(int hy, int hm, int hd) int HebToJul(int hy, int hm, int hd)
{ {
int ylen; int ylen;
char *monlens; char const *monlens;
int rh; int rh;
int m; int m;
@@ -201,7 +201,7 @@ void JulToHeb(int jul, int *hy, int *hm, int *hd)
int y, m, d; int y, m, d;
int rh; int rh;
int ylen; int ylen;
char *monlen; char const *monlen;
/* Get the common year */ /* Get the common year */
FromJulian(jul, &y, &m, &d); FromJulian(jul, &y, &m, &d);
y += 3763; /* Over-estimate a bit to be on the safe side below... */ y += 3763; /* Over-estimate a bit to be on the safe side below... */
@@ -232,7 +232,7 @@ void JulToHeb(int jul, int *hy, int *hm, int *hd)
/* year. */ /* year. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int HebNameToNum(const char *mname) int HebNameToNum(char const *mname)
{ {
int i; int i;
int m=-1; int m=-1;
@@ -254,7 +254,7 @@ int HebNameToNum(const char *mname)
/* year. */ /* year. */
/* */ /* */
/***************************************************************/ /***************************************************************/
char *HebMonthName(int m, int y) char const *HebMonthName(int m, int y)
{ {
if (m != ADARA && m != ADARB) return HebMonthNames[m]; if (m != ADARA && m != ADARB) return HebMonthNames[m];
@@ -293,7 +293,7 @@ char *HebMonthName(int m, int y)
int GetValidHebDate(int yin, int min, int din, int adarbehave, int GetValidHebDate(int yin, int min, int din, int adarbehave,
int *mout, int *dout, int jahr) int *mout, int *dout, int jahr)
{ {
char *monlen; char const *monlen;
int ylen; int ylen;
*mout = min; *mout = min;
@@ -448,7 +448,7 @@ int GetNextHebrewDate(int julstart, int hm, int hd,
/***************************************************************/ /***************************************************************/
int ComputeJahr(int y, int m, int d, int *ans) int ComputeJahr(int y, int m, int d, int *ans)
{ {
char *monlen; char const *monlen;
int len; int len;
*ans = JAHR_NONE; *ans = JAHR_NONE;

View File

@@ -12,6 +12,7 @@
/* */ /* */
/***************************************************************/ /***************************************************************/
#include "version.h"
#include "config.h" #include "config.h"
#define L_IN_INIT 1 #define L_IN_INIT 1
@@ -28,7 +29,6 @@
#include "protos.h" #include "protos.h"
#include "expr.h" #include "expr.h"
#include "err.h" #include "err.h"
#include "version.h"
#include "globals.h" #include "globals.h"
/*************************************************************** /***************************************************************
@@ -52,6 +52,7 @@
* -h = Hush mode * -h = Hush mode
* -f = Do not fork * -f = Do not fork
* -dchars = Debugging mode: Chars are: * -dchars = Debugging mode: Chars are:
* f = Trace file openings
* e = Echo input lines * e = Echo input lines
* x = Display expression evaluation * x = Display expression evaluation
* t = Display trigger dates * t = Display trigger dates
@@ -79,10 +80,10 @@ while (isdigit(*(s))) { \
s++; \ s++; \
} }
static void ChgUser(char *u); static void ChgUser(char const *u);
static void InitializeVar(char *str); 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; static DynamicBuffer default_filename_buf;
@@ -94,9 +95,9 @@ static DynamicBuffer default_filename_buf;
/* default filename. Use $DOTREMINDERS or $HOME/.reminders */ /* 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); DBufInit(&default_filename_buf);
@@ -122,14 +123,20 @@ static char *DefaultFilename(void)
/* Initialize the system - called only once at beginning! */ /* 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 i;
int y, m, d, rep; int y, m, d, rep;
Token tok; Token tok;
int InvokedAsRem = 0; int InvokedAsRem = 0;
char *s; char const *s;
int weeks;
int jul, tim;
jul = NO_DATE;
tim = NO_TIME;
/* Initialize global dynamic buffers */ /* Initialize global dynamic buffers */
DBufInit(&Banner); DBufInit(&Banner);
@@ -222,9 +229,15 @@ void InitRemind(int argc, char *argv[])
case 't': case 't':
case 'T': case 'T':
InfiniteDelta = 1; if (!*arg) {
InfiniteDelta = 1;
} else {
PARSENUM(DeltaOffset, arg);
if (DeltaOffset < 0) {
DeltaOffset = 0;
}
}
break; break;
case 'e': case 'e':
case 'E': case 'E':
ErrFp = stdout; ErrFp = stdout;
@@ -240,6 +253,7 @@ void InitRemind(int argc, char *argv[])
SortByDate = SORT_ASCEND; SortByDate = SORT_ASCEND;
SortByTime = SORT_ASCEND; SortByTime = SORT_ASCEND;
SortByPrio = SORT_ASCEND; SortByPrio = SORT_ASCEND;
UntimedBeforeTimed = 0;
if (*arg) { if (*arg) {
if (*arg == 'D' || *arg == 'd') if (*arg == 'D' || *arg == 'd')
SortByDate = SORT_DESCEND; SortByDate = SORT_DESCEND;
@@ -255,6 +269,11 @@ void InitRemind(int argc, char *argv[])
SortByPrio = SORT_DESCEND; SortByPrio = SORT_DESCEND;
arg++; arg++;
} }
if (*arg) {
if (*arg == 'D' || *arg == 'd')
UntimedBeforeTimed = 1;
arg++;
}
break; break;
case 'u': case 'u':
@@ -295,8 +314,33 @@ void InitRemind(int argc, char *argv[])
case 'c': case 'c':
case 'C': case 'C':
DoCalendar = 1; DoCalendar = 1;
if (*arg == '+') { weeks = 0;
arg++; /* 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 == 'c' || *arg == 'C') {
UseVTColors = 1;
arg++;
continue;
}
break;
}
if (weeks) {
PARSENUM(CalWeeks, arg); PARSENUM(CalWeeks, arg);
if (!CalWeeks) CalWeeks = 1; if (!CalWeeks) CalWeeks = 1;
} else { } else {
@@ -308,12 +352,21 @@ void InitRemind(int argc, char *argv[])
case 's': case 's':
case 'S': case 'S':
DoSimpleCalendar = 1; DoSimpleCalendar = 1;
if (*arg == 'a' || *arg == 'A') { weeks = 0;
while(*arg) {
if (*arg == 'a' || *arg == 'A') {
DoSimpleCalDelta = 1; DoSimpleCalDelta = 1;
arg++; arg++;
continue;
}
if (*arg == '+') {
arg++;
weeks = 1;
continue;
}
break;
} }
if (*arg == '+') { if (weeks) {
arg++;
PARSENUM(CalWeeks, arg); PARSENUM(CalWeeks, arg);
if (!CalWeeks) CalWeeks = 1; if (!CalWeeks) CalWeeks = 1;
} else { } else {
@@ -363,11 +416,12 @@ void InitRemind(int argc, char *argv[])
case 'D': case 'D':
while (*arg) { while (*arg) {
switch(*arg++) { switch(*arg++) {
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break; case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break; case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break; case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break; case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break; case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
case 'f': case 'F': DebugFlag |= DB_TRACE_FILES; break;
default: default:
fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1)); fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
} }
@@ -431,18 +485,32 @@ void InitRemind(int argc, char *argv[])
} }
break; 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: case T_Month:
if (m != NO_MON) Usage(); if (m != NO_MON || jul != NO_DATE) Usage();
else m = tok.val; else m = tok.val;
break; break;
case T_Day: case T_Day:
if (d != NO_DAY) Usage(); if (d != NO_DAY || jul != NO_DATE) Usage();
else d = tok.val; else d = tok.val;
break; break;
case T_Year: case T_Year:
if (y != NO_YR) Usage(); if (y != NO_YR || jul != NO_DATE) Usage();
else y = tok.val; else y = tok.val;
break; break;
@@ -451,7 +519,8 @@ void InitRemind(int argc, char *argv[])
else rep = tok.val; else rep = tok.val;
break; break;
default: Usage(); default:
Usage();
} }
} }
@@ -461,6 +530,9 @@ void InitRemind(int argc, char *argv[])
Daemon = 0; Daemon = 0;
} }
if (jul != NO_DATE) {
FromJulian(jul, &y, &m, &d);
}
/* Must supply date in the form: day, mon, yr OR mon, yr */ /* Must supply date in the form: day, mon, yr OR mon, yr */
if (m != NO_MON || y != NO_YR || d != NO_DAY) { if (m != NO_MON || y != NO_YR || d != NO_DAY) {
if (m == NO_MON || y == NO_YR) { if (m == NO_MON || y == NO_YR) {
@@ -506,7 +578,7 @@ void InitRemind(int argc, char *argv[])
void Usage(void) void Usage(void)
{ {
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1998 David F. Skoll\n", VERSION, L_LANGNAME); 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, "Copyright 1999-2009 Roaring Penguin Software Inc.\n");
#ifdef BETA #ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n"); fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif #endif
@@ -514,26 +586,26 @@ void Usage(void)
fprintf(ErrFp, "Options:\n"); fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n"); fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
fprintf(ErrFp, " -r Disable RUN directives\n"); fprintf(ErrFp, " -r Disable RUN directives\n");
fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n"); fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n"); fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n"); fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
fprintf(ErrFp, " -s[a][+][n] Produce `simple calendar' for n (1) months (weeks)\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, " -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, " -l Prefix each simple calendar line with line number and filename comment\n");
fprintf(ErrFp, " -v Verbose mode\n"); fprintf(ErrFp, " -v Verbose mode\n");
fprintf(ErrFp, " -o Ignore ONCE directives\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, " -h `Hush' mode - be very quiet\n");
fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\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, " -q Don't queue timed reminders\n");
fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\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, " -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, " -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, " -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, " -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, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\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, " -ivar=val Initialize var to val and preserve var\n");
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n"); fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n"); fprintf(ErrFp, " -y Synthesize tags for tagless reminders\n");
@@ -550,12 +622,15 @@ void Usage(void)
/* USER environment variables. */ /* USER environment variables. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void ChgUser(char *user) static void ChgUser(char const *user)
{ {
uid_t myuid; uid_t myuid;
struct passwd *pwent; struct passwd *pwent;
static char *home, *shell, *username, *logname; static char *home;
static char *shell;
static char *username;
static char *logname;
myuid = getuid(); myuid = getuid();
@@ -609,6 +684,20 @@ static void ChgUser(char *user)
putenv(logname); 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 */ /* InitializeVar */
@@ -616,22 +705,34 @@ static void ChgUser(char *user)
/* Initialize and preserve a variable */ /* 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; Value val;
int r; int r;
/* Scan for an '=' sign */ /* Scan for an '=' sign */
varname = str; r = 0;
while (*str && *str != '=') str++; 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) { if (!*str) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]); fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
return; return;
} }
*str = 0;
if (!*varname) { if (!*varname) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]); fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
return; return;

View File

@@ -307,7 +307,9 @@ EXTERN char *ErrMsg[] =
"%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n", "%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n",
"Numero puuttuu", "Numero puuttuu",
"Virheellinen funktio WARN-lausekkeessa", "Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
#elif IBMEXTENDED #elif IBMEXTENDED
"Ok", "Ok",
@@ -409,7 +411,10 @@ EXTERN char *ErrMsg[] =
"%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n", "%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n",
"Numero puuttuu" "Numero puuttuu"
"Virheellinen funktio WARN-lausekkeessa", "Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
#else #else
"Ok", "Ok",
"Puuttuva ']'", "Puuttuva ']'",
@@ -510,7 +515,10 @@ EXTERN char *ErrMsg[] =
"%d viesti({) t{m{n p{iv{n jonossa.\n", "%d viesti({) t{m{n p{iv{n jonossa.\n",
"Numero puuttuu", "Numero puuttuu",
"Virheellinen funktio WARN-lausekkeessa", "Virheellinen funktio WARN-lausekkeessa",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
#endif #endif
}; };

View File

@@ -244,7 +244,10 @@ EXTERN char *ErrMsg[] =
"%d rappel(s) en file pour aujourd'hui.\n", "%d rappel(s) en file pour aujourd'hui.\n",
"Nombre attendu", "Nombre attendu",
"Fonction ill\351gale apr\350s WARN", "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"
#else /* ISOLATIN1 */ #else /* ISOLATIN1 */
"Ok", "Ok",
"']' manquant", "']' manquant",
@@ -345,7 +348,9 @@ EXTERN char *ErrMsg[] =
"%d rappel(s) en file pour aujourd'hui.\n", "%d rappel(s) en file pour aujourd'hui.\n",
"Nombre attendu", "Nombre attendu",
"Fonction illegale apres WARN", "Fonction illegale apres WARN",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
#endif /* ISOLATIN1 */ #endif /* ISOLATIN1 */
}; };
#endif /* MK_GLOBALS */ #endif /* MK_GLOBALS */

View File

@@ -279,7 +279,9 @@ EXTERN char *ErrMsg[] =
"%d Przypomnienia zakolejkowane na p\363\274niej.\n", "%d Przypomnienia zakolejkowane na p\363\274niej.\n",
"Spodziewana liczba", "Spodziewana liczba",
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)", "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"
#else /* ISOLATIN1 */ #else /* ISOLATIN1 */
"OK", "OK",
"Brakujacy ']'", "Brakujacy ']'",
@@ -380,7 +382,9 @@ EXTERN char *ErrMsg[] =
"%d Przypomnienia zakolejkowane na pozniej.\n", "%d Przypomnienia zakolejkowane na pozniej.\n",
"Spodziewana liczba", "Spodziewana liczba",
"Illegal function in WARN clause (NEEDS TRANSLATION TO POLISH)", "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"
#endif /* ISOLATIN1 */ #endif /* ISOLATIN1 */
}; };
#endif /* MK_GLOBALS */ #endif /* MK_GLOBALS */

View File

@@ -245,7 +245,9 @@ EXTERN char *ErrMsg[] =
"%d compromisso(s) colocados na fila para mais tarde.\n", "%d compromisso(s) colocados na fila para mais tarde.\n",
"Esperando numero", "Esperando numero",
"Funcao ilegal na clausula WARN", "Funcao ilegal na clausula WARN",
"Can't convert between time zones" "Can't convert between time zones",
"No files matching *.rem",
"String too long"
}; };
#endif /* MK_GLOBALS */ #endif /* MK_GLOBALS */

View File

@@ -7,7 +7,7 @@
/* */ /* */
/* This file is part of REMIND. */ /* This file is part of REMIND. */
/* Copyright (C) 1992-1998 by David F. Skoll */ /* Copyright (C) 1992-1998 by David F. Skoll */
/* Copyright (C) 1999-2000 by Roaring Penguin Software Inc. */ /* Copyright (C) 1999-2009 by Roaring Penguin Software Inc. */
/* */ /* */
/***************************************************************/ /***************************************************************/
@@ -62,9 +62,9 @@ int main(int argc, char *argv[])
/* Set up global vars */ /* Set up global vars */
ArgC = argc; ArgC = argc;
ArgV = argv; ArgV = (char const **) argv;
InitRemind(argc, argv); InitRemind(argc, (char const **) argv);
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) { if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
ProduceCalendar(); ProduceCalendar();
return 0; return 0;
@@ -134,7 +134,7 @@ static void DoReminders(void)
{ {
int r; int r;
Token tok; Token tok;
char *s; char const *s;
Parser p; Parser p;
if (!UseStdin) { if (!UseStdin) {
@@ -148,7 +148,7 @@ static void DoReminders(void)
exit(1); exit(1);
} }
r=OpenFile(InitialFile); r=IncludeFile(InitialFile);
if (r) { if (r) {
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
InitialFile, ErrMsg[r]); InitialFile, ErrMsg[r]);
@@ -330,7 +330,7 @@ int ParseChar(ParsePtr p, int *err, int peek)
return *(p->epos++); return *(p->epos++);
} }
} }
free(p->etext); /* End of substituted expression */ free((void *) p->etext); /* End of substituted expression */
p->etext = NULL; p->etext = NULL;
p->epos = NULL; p->epos = NULL;
p->isnested = 0; p->isnested = 0;
@@ -345,6 +345,7 @@ int ParseChar(ParsePtr p, int *err, int peek)
return *(p->pos++); return *(p->pos++);
} }
} }
p->expr_happened = 1;
p->pos++; p->pos++;
r = EvalExpr(&(p->pos), &val); r = EvalExpr(&(p->pos), &val);
if (r) { if (r) {
@@ -503,21 +504,23 @@ int EvaluateExpr(ParsePtr p, Value *v)
/* Eprint - print an error message. */ /* Eprint - print an error message. */
/* */ /* */
/***************************************************************/ /***************************************************************/
void Eprint(const char *fmt, ...) void Eprint(char const *fmt, ...)
{ {
va_list argptr; va_list argptr;
/* Check if more than one error msg. from this line */ /* Check if more than one error msg. from this line */
if (!FreshLine && !ShowAllErrors) return; if (!FreshLine && !ShowAllErrors) return;
if (FreshLine) { if (FreshLine && FileName) {
FreshLine = 0; FreshLine = 0;
if (strcmp(FileName, "-")) if (strcmp(FileName, "-"))
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo); (void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
else else
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo); (void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp); if (DebugFlag & DB_PRTLINE) OutputLine(ErrFp);
} else fprintf(ErrFp, " "); } else if (FileName) {
fprintf(ErrFp, " ");
}
va_start(argptr, fmt); va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr); (void) vfprintf(ErrFp, fmt, argptr);
@@ -536,8 +539,8 @@ void Eprint(const char *fmt, ...)
/***************************************************************/ /***************************************************************/
void OutputLine(FILE *fp) void OutputLine(FILE *fp)
{ {
register char *s = CurLine; char const *s = CurLine;
register char c = 0; char c = 0;
while (*s) { while (*s) {
if (*s == '\n') Putc('\\', fp); if (*s == '\n') Putc('\\', fp);
@@ -554,7 +557,7 @@ void OutputLine(FILE *fp)
/* Create a parser given a string buffer */ /* Create a parser given a string buffer */
/* */ /* */
/***************************************************************/ /***************************************************************/
void CreateParser(char *s, ParsePtr p) void CreateParser(char const *s, ParsePtr p)
{ {
p->text = s; p->text = s;
p->pos = s; p->pos = s;
@@ -563,6 +566,7 @@ void CreateParser(char *s, ParsePtr p)
p->etext = NULL; p->etext = NULL;
p->allownested = 1; p->allownested = 1;
p->tokenPushed = NULL; p->tokenPushed = NULL;
p->expr_happened = 0;
DBufInit(&p->pushedToken); DBufInit(&p->pushedToken);
} }
@@ -576,7 +580,7 @@ void CreateParser(char *s, ParsePtr p)
void DestroyParser(ParsePtr p) void DestroyParser(ParsePtr p)
{ {
if (p->isnested && p->etext) { if (p->isnested && p->etext) {
free(p->etext); free((void *) p->etext);
p->etext = NULL; p->etext = NULL;
p->isnested = 0; p->isnested = 0;
} }
@@ -589,10 +593,10 @@ void DestroyParser(ParsePtr p)
/* on a per-parser basis. */ /* on a per-parser basis. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int PushToken(const char *tok, ParsePtr p) int PushToken(char const *tok, ParsePtr p)
{ {
DBufFree(&p->pushedToken); DBufFree(&p->pushedToken);
if (DBufPuts(&p->pushedToken, (char *) tok) != OK || if (DBufPuts(&p->pushedToken, tok) != OK ||
DBufPutc(&p->pushedToken, ' ') != OK) { DBufPutc(&p->pushedToken, ' ') != OK) {
DBufFree(&p->pushedToken); DBufFree(&p->pushedToken);
return E_NO_MEM; return E_NO_MEM;
@@ -720,7 +724,7 @@ int DoEndif(ParsePtr p)
/***************************************************************/ /***************************************************************/
int DoIfTrig(ParsePtr p) int DoIfTrig(ParsePtr p)
{ {
int r; int r, err;
unsigned syndrome; unsigned syndrome;
Trigger trig; Trigger trig;
TimeTrig tim; TimeTrig tim;
@@ -730,12 +734,12 @@ int DoIfTrig(ParsePtr p)
if (NumIfs >= IF_NEST) return E_NESTED_IF; if (NumIfs >= IF_NEST) return E_NESTED_IF;
if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE; if (ShouldIgnoreLine()) syndrome = IF_TRUE | BEFORE_ELSE;
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; if (trig.typ != NO_TYPE) return E_PARSE_ERR;
jul = ComputeTrigger(trig.scanfrom, &trig, &r); jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
if (r) syndrome = IF_TRUE | BEFORE_ELSE; if (r) syndrome = IF_TRUE | BEFORE_ELSE;
else { else {
if (ShouldTriggerReminder(&trig, &tim, jul)) if (ShouldTriggerReminder(&trig, &tim, jul, &err))
syndrome = IF_TRUE | BEFORE_ELSE; syndrome = IF_TRUE | BEFORE_ELSE;
else else
syndrome = IF_FALSE | BEFORE_ELSE; syndrome = IF_FALSE | BEFORE_ELSE;
@@ -859,6 +863,11 @@ int DoDebug(ParsePtr p)
else DebugFlag &= ~DB_PRTLINE; else DebugFlag &= ~DB_PRTLINE;
break; break;
case 'f':
case 'F':
if (val) DebugFlag |= DB_TRACE_FILES;
else DebugFlag &= ~DB_TRACE_FILES;
break;
} }
} }
} }
@@ -977,7 +986,7 @@ int DoErrMsg(ParsePtr p)
TimeTrig tt; TimeTrig tt;
Trigger t; Trigger t;
int r; int r;
char *s; char const *s;
DynamicBuffer buf; DynamicBuffer buf;
@@ -1079,7 +1088,7 @@ int CalcMinsFromUTC(int jul, int tim, int *mins, int *isdst)
/* A macro safe ONLY if used with arg with no side effects! */ /* A macro safe ONLY if used with arg with no side effects! */
#define ISBLANK(c) (isspace(c) && (c) != '\n') #define ISBLANK(c) (isspace(c) && (c) != '\n')
void FillParagraph(char *s) void FillParagraph(char const *s)
{ {
int line = 0; int line = 0;
@@ -1087,7 +1096,7 @@ void FillParagraph(char *s)
int doublespace = 1; int doublespace = 1;
int pendspace; int pendspace;
int len; int len;
char *t; char const *t;
int roomleft; int roomleft;

View File

@@ -20,6 +20,7 @@
#include "protos.h" #include "protos.h"
#include "globals.h" #include "globals.h"
#include "err.h" #include "err.h"
#include "expr.h"
static int BexistsIntArray (int array[], int num, int key); static int BexistsIntArray (int array[], int num, int key);
static void InsertIntoSortedArray (int *array, int num, int key); static void InsertIntoSortedArray (int *array, int num, int key);
@@ -113,12 +114,12 @@ int PushOmitContext(ParsePtr p)
context->numfull = NumFullOmits; context->numfull = NumFullOmits;
context->numpart = NumPartialOmits; context->numpart = NumPartialOmits;
context->fullsave = (int *) malloc(NumFullOmits * sizeof(int)); context->fullsave = malloc(NumFullOmits * sizeof(int));
if (NumFullOmits && !context->fullsave) { if (NumFullOmits && !context->fullsave) {
free(context); free(context);
return E_NO_MEM; return E_NO_MEM;
} }
context->partsave = (int *) malloc(NumPartialOmits * sizeof(int)); context->partsave = malloc(NumPartialOmits * sizeof(int));
if (NumPartialOmits && !context->partsave) { if (NumPartialOmits && !context->partsave) {
free(context->fullsave); free(context->fullsave);
free(context); free(context);
@@ -177,26 +178,57 @@ int PopOmitContext(ParsePtr p)
/* */ /* */
/* IsOmitted */ /* 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; 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);
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? */ /* 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? */ /* 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); FromJulian(jul, &y, &m, &d);
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d)) {
return 1; *omit = 1;
return OK;
}
/* Not omitted */ /* Not omitted */
return 0; *omit = 0;
return OK;
} }
/***************************************************************/ /***************************************************************/
@@ -262,6 +294,14 @@ int DoOmit(ParsePtr p)
if ( (r=ParseToken(p, &buf)) ) return r; if ( (r=ParseToken(p, &buf)) ) return r;
FindToken(DBufValue(&buf), &tok); FindToken(DBufValue(&buf), &tok);
switch (tok.type) { switch (tok.type) {
case T_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: case T_Year:
DBufFree(&buf); DBufFree(&buf);
if (y != NO_YR) return E_YR_TWICE; if (y != NO_YR) return E_YR_TWICE;
@@ -279,7 +319,7 @@ int DoOmit(ParsePtr p)
if (d != NO_DAY) return E_DAY_TWICE; if (d != NO_DAY) return E_DAY_TWICE;
d = tok.val; d = tok.val;
break; break;
case T_Delta: case T_Delta:
DBufFree(&buf); DBufFree(&buf);
break; break;

View File

@@ -14,51 +14,51 @@
#define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); } #define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); }
/* Define a general malloc routine for creating pointers to objects */ /* Define a general malloc routine for creating pointers to objects */
#define NEW(type) ((type *) malloc(sizeof(type))) #define NEW(type) (malloc(sizeof(type)))
#include "dynbuf.h" #include "dynbuf.h"
int CallUserFunc (char *name, int nargs); int CallUserFunc (char const *name, int nargs);
int DoFset (ParsePtr p); int DoFset (ParsePtr p);
void ProduceCalendar (void); void ProduceCalendar (void);
char *SimpleTime (int tim); char const *SimpleTime (int tim);
char const *CalendarTime (int tim, int duration);
int DoRem (ParsePtr p); int DoRem (ParsePtr p);
int DoFlush (ParsePtr p); int DoFlush (ParsePtr p);
void DoExit (ParsePtr p); void DoExit (ParsePtr p);
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim); int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int jul); int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int 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 DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode);
int DoSubstFromString (char *source, DynamicBuffer *dbuf, int jul, int tim); int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int jul, int tim);
int EvalExpr (char **e, Value *v); int ParseLiteralDate (char const **s, int *jul, int *tim);
int EvalExpr (char const **e, Value *v);
int DoCoerce (char type, Value *v); int DoCoerce (char type, Value *v);
void PrintValue (Value *v, FILE *fp); void PrintValue (Value *v, FILE *fp);
int CopyValue (Value *dest, const Value *src); int CopyValue (Value *dest, const Value *src);
int ReadLine (void); int ReadLine (void);
int OpenFile (const char *fname); int OpenFile (char const *fname);
int PopFile (void);
int DoInclude (ParsePtr p); int DoInclude (ParsePtr p);
int IncludeFile (const char *fname); int IncludeFile (char const *fname);
int GetAccessDate (char *file); int GetAccessDate (char const *file);
int SetAccessDate (char *fname, int jul); int SetAccessDate (char const *fname, int jul);
int TopLevel (void); int TopLevel (void);
int CallFunc (Operator *f, int nargs); int CallFunc (BuiltinFunc *f, int nargs);
void InitRemind (int argc, char *argv[]); void InitRemind (int argc, char const *argv[]);
void Usage (void); void Usage (void);
int main (int argc, char *argv[]);
int Julian (int year, int month, int day); int Julian (int year, int month, int day);
void FromJulian (int jul, int *y, int *m, int *d); void FromJulian (int jul, int *y, int *m, int *d);
int ParseChar (ParsePtr p, int *err, int peek); int ParseChar (ParsePtr p, int *err, int peek);
int ParseToken (ParsePtr p, DynamicBuffer *dbuf); int ParseToken (ParsePtr p, DynamicBuffer *dbuf);
int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf); int ParseIdentifier (ParsePtr p, DynamicBuffer *dbuf);
int EvaluateExpr (ParsePtr p, Value *v); int EvaluateExpr (ParsePtr p, Value *v);
int Evaluate (char **s, Var *locals); int Evaluate (char const **s, Var *locals);
int FnPopValStack (Value *val); int FnPopValStack (Value *val);
void Eprint (const char *fmt, ...); void Eprint (char const *fmt, ...);
void OutputLine (FILE *fp); void OutputLine (FILE *fp);
void CreateParser (char *s, ParsePtr p); void CreateParser (char const *s, ParsePtr p);
void DestroyParser (ParsePtr p); void DestroyParser (ParsePtr p);
int PushToken (const char *tok, ParsePtr p); int PushToken (char const *tok, ParsePtr p);
long SystemTime (int realtime); long SystemTime (int realtime);
int SystemDate (int *y, int *m, int *d); int SystemDate (int *y, int *m, int *d);
int DoIf (ParsePtr p); int DoIf (ParsePtr p);
@@ -76,60 +76,61 @@ int DoClear (ParsePtr p);
int DestroyOmitContexts (void); int DestroyOmitContexts (void);
int PushOmitContext (ParsePtr p); int PushOmitContext (ParsePtr p);
int PopOmitContext (ParsePtr p); int PopOmitContext (ParsePtr p);
int IsOmitted (int jul, int localomit); int IsOmitted (int jul, int localomit, char const *omitfunc, int *omit);
int DoOmit (ParsePtr p); 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); void HandleQueuedReminders (void);
char *FindInitialToken (Token *tok, char *s); char const *FindInitialToken (Token *tok, char const *s);
void FindToken (const char *s, Token *tok); void FindToken (char const *s, Token *tok);
void FindNumericToken (const char *s, Token *t); void FindNumericToken (char const *s, Token *t);
int ComputeTrigger (int today, Trigger *trig, int *err); int ComputeTrigger (int today, Trigger *trig, int *err, int save_in_globals);
char *StrnCpy (char *dest, const char *source, int n); char *StrnCpy (char *dest, char const *source, int n);
int StrMatch (const char *s1, const char *s2, int n); int StrMatch (char const *s1, char const *s2, int n);
int StrinCmp (const char *s1, const char *s2, int n); int StrinCmp (char const *s1, char const *s2, int n);
char *StrDup (const char *s); char *StrDup (char const *s);
int StrCmpi (const char *s1, const char *s2); int StrCmpi (char const *s1, char const *s2);
Var *FindVar (const char *str, int create); Var *FindVar (char const *str, int create);
int DeleteVar (const char *str); int DeleteVar (char const *str);
int SetVar (const char *str, Value *val); int SetVar (char const *str, Value *val);
int GetVarValue (const char *str, Value *val, Var *locals); int GetVarValue (char const *str, Value *val, Var *locals);
int DoSet (Parser *p); int DoSet (Parser *p);
int DoUnset (Parser *p); int DoUnset (Parser *p);
int DoDump (ParsePtr p); int DoDump (ParsePtr p);
void DumpVarTable (void); void DumpVarTable (void);
void DestroyVars (int all); void DestroyVars (int all);
int PreserveVar (char *name); int PreserveVar (char const *name);
int DoPreserve (Parser *p); int DoPreserve (Parser *p);
int DoSatRemind (Trigger *trig, TimeTrig *tim, ParsePtr p); int DoSatRemind (Trigger *trig, TimeTrig *tim, ParsePtr p);
int DoMsgCommand (char *cmd, char *msg); int DoMsgCommand (char const *cmd, char const *msg);
int ParseNonSpaceChar (ParsePtr p, int *err, int peek); 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); int DateOK (int y, int m, int d);
Operator *FindFunc (char *name, Operator where[], int num); Operator *FindOperator (char const *name, Operator where[], int num);
int InsertIntoSortBuffer (int jul, int tim, char *body, int typ, int prio); BuiltinFunc *FindFunc (char const *name, BuiltinFunc where[], int num);
void IssueSortedReminders (void); int InsertIntoSortBuffer (int jul, int tim, char const *body, int typ, int prio);
int UserFuncExists (char *fn); void IssueSortedReminders (void);
int UserFuncExists (char const *fn);
void JulToHeb (int jul, int *hy, int *hm, int *hd); void JulToHeb (int jul, int *hy, int *hm, int *hd);
int HebNameToNum (const char *mname); int HebNameToNum (char const *mname);
char *HebMonthName (int m, int y); char const *HebMonthName (int m, int y);
int RoshHashana (int i); int RoshHashana (int i);
long DaysToHebYear (int y); long DaysToHebYear (int y);
int DaysInHebYear (int y); int DaysInHebYear (int y);
char *DaysInHebMonths (int ylen); char const *DaysInHebMonths (int ylen);
int HebToJul (int hy, int hm, int hd); 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 GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
int GetNextHebrewDate (int julstart, int hm, int hd, int yahr, int adarbehave, int *ans); int GetNextHebrewDate (int julstart, int hm, int hd, int yahr, int adarbehave, int *ans);
int ComputeJahr (int y, int m, int d, int *ans); int ComputeJahr (int y, int m, int d, int *ans);
int GetSysVar (const char *name, Value *val); int GetSysVar (char const *name, Value *val);
int SetSysVar (const char *name, Value *val); int SetSysVar (char const *name, Value *val);
void DumpSysVarByName (const char *name); void DumpSysVarByName (char const *name);
int CalcMinsFromUTC (int jul, int tim, int *mins, int *isdst); 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 LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime); void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
int MoonPhase (int date, int time); int MoonPhase (int date, int time);
void HuntPhase (int startdate, int starttim, int phas, int *date, int *time); void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio); int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
void SigIntHandler (int d); void SigIntHandler (int d);
void GotSigInt (void); void GotSigInt (void);
void SynthesizeTag(char *); void SynthesizeTag(char *);

View File

@@ -40,7 +40,7 @@ typedef struct queuedrem {
int typ; int typ;
int RunDisabled; int RunDisabled;
int ntrig; int ntrig;
char *text; char const *text;
char passthru[PASSTHRU_LEN+1]; char passthru[PASSTHRU_LEN+1];
char sched[VAR_NAME_LEN+1]; char sched[VAR_NAME_LEN+1];
char tag[TAG_LEN+1]; char tag[TAG_LEN+1];
@@ -69,7 +69,7 @@ static void reread (void);
/* */ /* */
/***************************************************************/ /***************************************************************/
int QueueReminder(ParsePtr p, Trigger *trig, int QueueReminder(ParsePtr p, Trigger *trig,
TimeTrig *tim, const char *sched) TimeTrig *tim, char const *sched)
{ {
QueuedRem *qelem; QueuedRem *qelem;
@@ -232,9 +232,9 @@ void HandleQueuedReminders(void)
strcpy(trig.passthru, q->passthru); strcpy(trig.passthru, q->passthru);
RunDisabled = q->RunDisabled; RunDisabled = q->RunDisabled;
if (Daemon < 0) { if (Daemon < 0) {
printf("NOTE reminder %s ", printf("NOTE reminder %s",
SimpleTime(q->tt.ttime)); SimpleTime(q->tt.ttime));
printf("%s ", SimpleTime(SystemTime(0)/60)); printf("%s", SimpleTime(SystemTime(0)/60));
if (!*q->tag) { if (!*q->tag) {
printf("*"); printf("*");
} else { } else {
@@ -396,7 +396,7 @@ static int CalculateNextTimeUsingSched(QueuedRem *q)
/* Use LineBuffer for temp. string storage. */ /* Use LineBuffer for temp. string storage. */
int r; int r;
Value v; Value v;
char *s; char const *s;
int LastTime = -1; int LastTime = -1;
int ThisTime; int ThisTime;
@@ -517,6 +517,6 @@ static void DaemonWait(unsigned int sleeptime)
/***************************************************************/ /***************************************************************/
static void reread(void) static void reread(void)
{ {
execvp(ArgV[0], ArgV); execvp(ArgV[0], (char **) ArgV);
} }

View File

@@ -10,6 +10,7 @@
/* */ /* */
/***************************************************************/ /***************************************************************/
#include "version.h"
#include "config.h" #include "config.h"
#include "dynbuf.h" #include "dynbuf.h"
@@ -20,9 +21,8 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "rem2ps.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_NORMAL 0
#define SPECIAL_POSTSCRIPT 1 #define SPECIAL_POSTSCRIPT 1
@@ -30,6 +30,7 @@
#define SPECIAL_MOON 3 #define SPECIAL_MOON 3
#define SPECIAL_SHADE 4 #define SPECIAL_SHADE 4
#define SPECIAL_COLOR 5 #define SPECIAL_COLOR 5
#define SPECIAL_WEEK 6
typedef struct calentry { typedef struct calentry {
struct calentry *next; struct calentry *next;
@@ -38,13 +39,13 @@ typedef struct calentry {
} CalEntry; } CalEntry;
typedef struct { typedef struct {
char *name; char const *name;
int xsize, ysize; int xsize, ysize;
} PageType; } PageType;
char DayName[7][33]; char DayName[7][33];
char *SmallCalLoc[] = { char const *SmallCalLoc[] = {
"", "",
"bt", "bt",
"tb", "tb",
@@ -52,7 +53,7 @@ char *SmallCalLoc[] = {
}; };
#define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0])) #define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0]))
char *SmallLocation; char const *SmallLocation;
int SmallCol1, SmallCol2; int SmallCol1, SmallCol2;
PageType Pages[] = PageType Pages[] =
@@ -88,20 +89,20 @@ char PortraitMode;
char NoSmallCal; char NoSmallCal;
char UseISO; char UseISO;
char *HeadFont="Helvetica"; char const *HeadFont="Helvetica";
char *TitleFont="Helvetica"; char const *TitleFont="Helvetica";
char *DayFont="Helvetica-BoldOblique"; char const *DayFont="Helvetica-BoldOblique";
char *EntryFont="Helvetica"; char const *EntryFont="Helvetica";
char *SmallFont="Helvetica"; char const *SmallFont="Helvetica";
char *LineWidth = "1"; char const *LineWidth = "1";
char *HeadSize="14"; char const *HeadSize="14";
char *TitleSize="14"; char const *TitleSize="14";
char *DaySize="14"; char const *DaySize="14";
char *EntrySize="8"; char const *EntrySize="8";
char *BorderSize = "6"; char const *BorderSize = "6";
char *UserProlog = NULL; char const *UserProlog = NULL;
int validfile = 0; int validfile = 0;
@@ -116,15 +117,15 @@ int FillPage;
int Verbose = 0; int Verbose = 0;
void Init (int argc, char *argv[]); void Init (int argc, char *argv[]);
void Usage (char *s); void Usage (char const *s);
void DoPsCal (void); void DoPsCal (void);
int DoQueuedPs (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 WriteProlog (void);
void WriteCalEntry (void); void WriteCalEntry (void);
void WriteOneEntry (CalEntry *c); void WriteOneEntry (CalEntry *c);
void GetSmallLocations (void); void GetSmallLocations (void);
char *EatToken(char *in, char *out, int maxlen); char const *EatToken(char const *in, char *out, int maxlen);
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -182,7 +183,7 @@ void DoPsCal(void)
int i; int i;
int is_ps; int is_ps;
int firstcol; int firstcol;
char *startOfBody; char const *startOfBody;
char passthru[PASSTHRU_LEN+1]; char passthru[PASSTHRU_LEN+1];
DynamicBuffer buf; DynamicBuffer buf;
CalEntry *c, *d; CalEntry *c, *d;
@@ -306,6 +307,7 @@ void DoPsCal(void)
if (!strcmp(passthru, "PostScript") || if (!strcmp(passthru, "PostScript") ||
!strcmp(passthru, "PSFile") || !strcmp(passthru, "PSFile") ||
!strcmp(passthru, "MOON") || !strcmp(passthru, "MOON") ||
!strcmp(passthru, "WEEK") ||
!strcmp(passthru, "SHADE")) { !strcmp(passthru, "SHADE")) {
is_ps = 1; is_ps = 1;
} }
@@ -324,6 +326,8 @@ void DoPsCal(void)
c->special = SPECIAL_SHADE; c->special = SPECIAL_SHADE;
} else if (!strcmp(passthru, "MOON")) { } else if (!strcmp(passthru, "MOON")) {
c->special = SPECIAL_MOON; c->special = SPECIAL_MOON;
} else if (!strcmp(passthru, "WEEK")) {
c->special = SPECIAL_WEEK;
} else { } else {
c->special = SPECIAL_PSFILE; c->special = SPECIAL_PSFILE;
} }
@@ -388,7 +392,7 @@ void WriteProlog(void)
int i; int i;
int x = CurPage->xsize; int x = CurPage->xsize;
int y = CurPage->ysize; int y = CurPage->ysize;
char *isostuff; char const *isostuff;
FILE *fp; FILE *fp;
int nread; int nread;
char buffer[512]; char buffer[512];
@@ -574,7 +578,7 @@ void WriteCalEntry(void)
void WriteOneEntry(CalEntry *c) void WriteOneEntry(CalEntry *c)
{ {
int ch, i; int ch, i;
char *s = c->entry; char const *s = c->entry;
printf(" ["); printf(" [");
@@ -635,7 +639,8 @@ void WriteOneEntry(CalEntry *c)
/***************************************************************/ /***************************************************************/
void Init(int argc, char *argv[]) void Init(int argc, char *argv[])
{ {
char *s, *t; char const *s;
char const *t;
int i=1; int i=1;
int j; int j;
int offset; int offset;
@@ -791,7 +796,7 @@ void Init(int argc, char *argv[])
/* Usage - print usage information */ /* Usage - print usage information */
/* */ /* */
/***************************************************************/ /***************************************************************/
void Usage(char *s) void Usage(char const *s)
{ {
if (s) fprintf(stderr, "Rem2PS: %s\n\n", s); if (s) fprintf(stderr, "Rem2PS: %s\n\n", s);
@@ -820,7 +825,7 @@ void Usage(char *s)
/* month. */ /* 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 */ /* Do the small calendar */
int i, j; int i, j;
@@ -885,7 +890,8 @@ int DoQueuedPs(void)
FILE *fp; FILE *fp;
int fnoff; int fnoff;
char buffer[512]; char buffer[512];
char *size, *extra; char const *size, *extra;
char const *s;
int num, r, g, b, phase, fontsize, moonsize; int num, r, g, b, phase, fontsize, moonsize;
unsigned char c; unsigned char c;
@@ -953,6 +959,22 @@ int DoQueuedPs(void)
r/255.0, g/255.0, b/255.0); r/255.0, g/255.0, b/255.0);
break; 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 */ case SPECIAL_MOON: /* Moon phase */
num = sscanf(e->entry+fnoff, "%d %d %d", &phase, &moonsize, num = sscanf(e->entry+fnoff, "%d %d %d", &phase, &moonsize,
&fontsize); &fontsize);
@@ -1060,7 +1082,7 @@ int DoQueuedPs(void)
void GetSmallLocations(void) void GetSmallLocations(void)
{ {
char c; char c;
char *s = SmallLocation; char const *s = SmallLocation;
int colfirst, collast; int colfirst, collast;
/* Figure out the first and last columns */ /* Figure out the first and last columns */
@@ -1122,7 +1144,7 @@ void GetSmallLocations(void)
/* Read a space-delimited token into an output buffer. */ /* 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; int i = 0;

View File

@@ -25,7 +25,7 @@
/* The structure of a sorted entry */ /* The structure of a sorted entry */
typedef struct sortrem { typedef struct sortrem {
struct sortrem *next; struct sortrem *next;
char *text; char const *text;
int trigdate; int trigdate;
int trigtime; int trigtime;
int typ; int typ;
@@ -35,7 +35,7 @@ typedef struct sortrem {
/* The sorted reminder queue */ /* The sorted reminder queue */
static Sortrem *SortedQueue = (Sortrem *) NULL; static Sortrem *SortedQueue = (Sortrem *) NULL;
static Sortrem *MakeSortRem (int jul, int tim, char *body, int typ, int prio); static Sortrem *MakeSortRem (int jul, int tim, char const *body, int typ, int prio);
static void IssueSortBanner (int jul); static void IssueSortBanner (int jul);
/***************************************************************/ /***************************************************************/
@@ -45,7 +45,7 @@ static void IssueSortBanner (int jul);
/* Create a new Sortrem entry - return NULL on failure. */ /* Create a new Sortrem entry - return NULL on failure. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static Sortrem *MakeSortRem(int jul, int tim, char *body, int typ, int prio) static Sortrem *MakeSortRem(int jul, int tim, char const *body, int typ, int prio)
{ {
Sortrem *new = NEW(Sortrem); Sortrem *new = NEW(Sortrem);
if (!new) return NULL; if (!new) return NULL;
@@ -71,7 +71,7 @@ static Sortrem *MakeSortRem(int jul, int tim, char *body, int typ, int prio)
/* Insert a reminder into the sort buffer */ /* 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 *new = MakeSortRem(jul, tim, body, typ, prio);
Sortrem *cur = SortedQueue, *prev = NULL; Sortrem *cur = SortedQueue, *prev = NULL;
@@ -83,6 +83,7 @@ int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
SortByDate = 0; SortByDate = 0;
SortByTime = 0; SortByTime = 0;
SortByPrio = 0; SortByPrio = 0;
UntimedBeforeTimed = 0;
return E_NO_MEM; return E_NO_MEM;
} }
@@ -94,8 +95,8 @@ int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
while (cur) { while (cur) {
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority, ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
cur->trigdate, cur->trigtime, cur->priority, cur->trigdate, cur->trigtime, cur->priority,
SortByDate, SortByTime, SortByPrio); SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed);
if (ShouldGoAfter <= 0) { if (ShouldGoAfter <= 0) {
prev = cur; prev = cur;
cur = cur->next; cur = cur->next;
@@ -154,7 +155,7 @@ void IssueSortedReminders(void)
break; break;
} }
free(cur->text); free((char *) cur->text);
free(cur); free(cur);
cur = next; cur = next;
} }
@@ -173,7 +174,7 @@ static void IssueSortBanner(int jul)
char BanExpr[64]; char BanExpr[64];
int y, m, d; int y, m, d;
Value v; Value v;
char *s = BanExpr; char const *s = BanExpr;
DynamicBuffer buf; DynamicBuffer buf;
if (UserFuncExists("sortbanner") != 1) return; if (UserFuncExists("sortbanner") != 1) return;
@@ -203,19 +204,27 @@ static void IssueSortBanner(int jul)
/***************************************************************/ /***************************************************************/
int CompareRems(int dat1, int tim1, int prio1, int CompareRems(int dat1, int tim1, int prio1,
int dat2, int tim2, int prio2, 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; dafter = (bydate != SORT_DESCEND) ? 1 : -1;
tafter = (bytime != SORT_DESCEND) ? 1 : -1; tafter = (bytime != SORT_DESCEND) ? 1 : -1;
pafter = (byprio != 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 (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) {
if (tim1 != NO_TIME && tim2 == NO_TIME) return 1; return -uafter;
}
if (tim1 != NO_TIME && tim2 == NO_TIME) {
return uafter;
}
if (tim1 < tim2) return tafter; if (tim1 < tim2) return tafter;
if (tim1 > tim2) return -tafter; if (tim1 > tim2) return -tafter;

View File

@@ -74,6 +74,7 @@ Token TokArray[] = {
{ "november", 3, T_Month, 10 }, { "november", 3, T_Month, 10 },
{ "october", 3, T_Month, 9 }, { "october", 3, T_Month, 9 },
{ "omit", 3, T_Omit, 0 }, { "omit", 3, T_Omit, 0 },
{ "omitfunc", 8, T_OmitFunc, 0 },
{ "once", 3, T_Once, 0 }, { "once", 3, T_Once, 0 },
{ "pop-omit-context", 3, T_Pop, 0 }, { "pop-omit-context", 3, T_Pop, 0 },
{ "preserve", 8, T_Preserve, 0 }, { "preserve", 8, T_Preserve, 0 },
@@ -128,7 +129,7 @@ Token NonEnglishToks[] = {
}; };
#endif #endif
static int TokStrCmp (const Token *t, const char *s); static int TokStrCmp (Token const *t, char const *s);
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -138,7 +139,7 @@ static int TokStrCmp (const Token *t, const char *s);
/* left square bracket, return a T_Illegal type. */ /* left square bracket, return a T_Illegal type. */
/* */ /* */
/***************************************************************/ /***************************************************************/
char *FindInitialToken(Token *tok, char *s) char const *FindInitialToken(Token *tok, char const *s)
{ {
DynamicBuffer buf; DynamicBuffer buf;
DBufInit(&buf); DBufInit(&buf);
@@ -165,7 +166,7 @@ char *FindInitialToken(Token *tok, char *s)
/* Given a string, which token is it? */ /* 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 top, bot, mid, r, max;
int l; int l;
@@ -252,15 +253,33 @@ void FindToken(const char *s, Token *tok)
/* Rep - *n */ /* Rep - *n */
/* */ /* */
/***************************************************************/ /***************************************************************/
void FindNumericToken(const char *s, Token *t) void FindNumericToken(char const *s, Token *t)
{ {
int mult = 1, hour, min; int mult = 1, hour, min;
char const *s_orig = s;
t->type = T_Illegal; t->type = T_Illegal;
t->val = 0; t->val = 0;
if (isdigit(*s)) { if (isdigit(*s)) {
PARSENUM(t->val, 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 /* If we hit a comma, swallow it. This allows stuff
like Jan 6, 1998 */ like Jan 6, 1998 */
if (*s == ',') { if (*s == ',') {
@@ -335,10 +354,10 @@ void FindNumericToken(const char *s, Token *t)
/* Compare a token to a string. */ /* 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; register int r;
char *tk = t->name; char const *tk = t->name;
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) { while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
r = *tk - tolower(*s); r = *tk - tolower(*s);
tk++; tk++;

View File

@@ -206,16 +206,27 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
*err = E_BAD_DATE; *err = E_BAD_DATE;
return -1; 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 */ /* Move up to the first valid year */
while (trig->d > DaysInMonth(trig->m, y)) y++; 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 */ /* Try this year */
y++;
j = Julian(y, trig->m, trig->d); j = Julian(y, trig->m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++; while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j; if (j >= startdate) return j;
/* Must be next year */ /* Must be next year */
y = y + 1; y++;
while (trig->d > DaysInMonth(trig->m, y)) y++; while (trig->d > DaysInMonth(trig->m, y)) y++;
j = Julian(y, trig->m, trig->d); j = Julian(y, trig->m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++; while(! (trig->wd & (1 << (j%7)))) j++;
@@ -286,7 +297,7 @@ static int JYear(int jul)
/***************************************************************/ /***************************************************************/
static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart) 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? */ /* First: Have we passed the UNTIL date? */
if (trig->until != NO_UNTIL && if (trig->until != NO_UNTIL &&
@@ -294,8 +305,22 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* Next: If it's an "AFTER"-type skip, back up /* Next: If it's an "AFTER"-type skip, back up
until we're at the start of a block of holidays */ until we're at the start of a block of holidays */
if (trig->skip == AFTER_SKIP) if (trig->skip == AFTER_SKIP) {
while (IsOmitted(start-1, trig->localomit)) start--; 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 */ /* Find the next simple trigger */
simple = NextSimpleTrig(start, trig, err); simple = NextSimpleTrig(start, trig, err);
@@ -309,12 +334,29 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* If there's a BACK, back up... */ /* If there's a BACK, back up... */
if (trig->back != NO_BACK) { if (trig->back != NO_BACK) {
mod = trig->back; mod = trig->back;
if (mod < 0) simple += mod; if (mod < 0) {
else simple += mod;
while(mod) { }
simple--; else {
if (!IsOmitted(simple, trig->localomit)) mod--; 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 */ /* If there's a REP, calculate the next occurrence */
@@ -327,12 +369,38 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
} }
/* If it's a "BEFORE"-type skip, back up */ /* If it's a "BEFORE"-type skip, back up */
if (trig->skip == BEFORE_SKIP) if (trig->skip == BEFORE_SKIP) {
while(IsOmitted(simple, trig->localomit)) simple--; 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 it's an "AFTER"-type skip, jump ahead */
if (trig->skip == AFTER_SKIP) if (trig->skip == AFTER_SKIP) {
while (IsOmitted(simple, trig->localomit)) simple++; 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 the date */
return simple; return simple;
@@ -346,15 +414,15 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
/* today's date. */ /* today's date. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int ComputeTrigger(int today, Trigger *trig, int *err) int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
{ {
int nattempts = 0, int nattempts = 0,
start = today, start = today,
nextstart = 0, nextstart = 0,
y, m, d, y, m, d, omit,
result; result;
LastTrigValid = 0; if (save_in_globals) LastTrigValid = 0;
/* Assume everything works */ /* Assume everything works */
*err = OK; *err = OK;
@@ -373,8 +441,8 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
*err = E_REP_FULSPEC; *err = E_REP_FULSPEC;
return -1; return -1;
} }
while (nattempts++ < TRIG_ATTEMPTS) { while (nattempts++ < TRIG_ATTEMPTS) {
result = GetNextTriggerDate(trig, start, err, &nextstart); result = GetNextTriggerDate(trig, start, err, &nextstart);
@@ -389,10 +457,18 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
} }
/* If result is >= today, great! */ /* If result is >= today, great! */
if (trig->skip == SKIP_SKIP) {
*err = IsOmitted(result, trig->localomit, trig->omitfunc, &omit);
if (*err) return -1;
} else {
omit = 0;
}
if (result >= today && if (result >= today &&
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) { (trig->skip != SKIP_SKIP || !omit)) {
LastTriggerDate = result; /* Save in global var */ if (save_in_globals) {
LastTrigValid = 1; LastTriggerDate = result; /* Save in global var */
LastTrigValid = 1;
}
if (DebugFlag & DB_PRTTRIG) { if (DebugFlag & DB_PRTTRIG) {
FromJulian(result, &y, &m, &d); FromJulian(result, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n", fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
@@ -414,16 +490,28 @@ int ComputeTrigger(int today, Trigger *trig, int *err)
FileName, LineNo, ErrMsg[E_EXPIRED]); FileName, LineNo, ErrMsg[E_EXPIRED]);
} }
if (result != -1) { if (result != -1) {
LastTriggerDate = result; if (save_in_globals) {
LastTrigValid = 1; LastTriggerDate = result;
LastTrigValid = 1;
}
} }
return -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.*/ /* Keep scanning... unless there's no point in doing it.*/
if (nextstart <= start) { if (nextstart <= start) {
if (result != -1) { if (result != -1) {
LastTriggerDate = result; if (save_in_globals) {
LastTrigValid = 1; LastTriggerDate = result;
LastTrigValid = 1;
}
} }
if (DebugFlag & DB_PRTTRIG) { if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%d): %s\n", fprintf(ErrFp, "%s(%d): %s\n",

View File

@@ -24,12 +24,26 @@ typedef struct {
/* Define the type of operators */ /* Define the type of operators */
typedef struct { typedef struct {
char *name; char const *name;
char prec; char prec;
char type; char type;
int (*func)(void); int (*func)(void);
} Operator; } 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;
int (*func)(func_info *);
} BuiltinFunc;
/* Define the structure of a variable */ /* Define the structure of a variable */
typedef struct var { typedef struct var {
struct var *next; struct var *next;
@@ -56,6 +70,7 @@ typedef struct {
int priority; int priority;
char sched[VAR_NAME_LEN+1]; /* Scheduling function */ char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */ char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
char tag[TAG_LEN+1]; char tag[TAG_LEN+1];
char passthru[PASSTHRU_LEN+1]; char passthru[PASSTHRU_LEN+1];
} Trigger; } Trigger;
@@ -71,14 +86,15 @@ typedef struct {
/* The parse pointer */ /* The parse pointer */
typedef struct { typedef struct {
char isnested; /* Is it a nested expression? */ char isnested; /* Is it a nested expression? */
char allownested; char allownested;
char *text; /* Start of text */ char const *text; /* Start of text */
char *pos; /* Current position */ char const *pos; /* Current position */
char *etext; /* Substituted text */ char const *etext; /* Substituted text */
char *epos; /* Position in substituted text */ char const *epos; /* Position in substituted text */
DynamicBuffer pushedToken; /* Pushed-back token */ DynamicBuffer pushedToken; /* Pushed-back token */
char *tokenPushed; /* NULL if no pushed-back token */ char const *tokenPushed; /* NULL if no pushed-back token */
char expr_happened; /* Did we encounter an [expression] ? */
} Parser; } Parser;
typedef Parser *ParsePtr; /* Pointer to parser structure */ typedef Parser *ParsePtr; /* Pointer to parser structure */
@@ -116,11 +132,12 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
/* DEFINES for debugging flags */ /* DEFINES for debugging flags */
#define DB_PRTLINE 1 #define DB_PRTLINE 1
#define DB_PRTEXPR 2 #define DB_PRTEXPR 2
#define DB_PRTTRIG 4 #define DB_PRTTRIG 4
#define DB_DUMP_VARS 8 #define DB_DUMP_VARS 8
#define DB_ECHO_LINE 16 #define DB_ECHO_LINE 16
#define DB_TRACE_FILES 32
/* Enumeration of the tokens */ /* Enumeration of the tokens */
enum TokTypes enum TokTypes
@@ -130,7 +147,7 @@ enum TokTypes
T_IfTrig, T_ErrMsg, T_IfTrig, T_ErrMsg,
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit, T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
T_WkDay, 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_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta, T_Back,
T_Once, T_Once,
T_Empty, T_Empty,
@@ -146,7 +163,8 @@ enum TokTypes
T_Warn, T_Warn,
T_Tag, T_Tag,
T_Duration, T_Duration,
T_LongTime T_LongTime,
T_OmitFunc
}; };
/* The structure of a token */ /* The structure of a token */

View File

@@ -29,7 +29,7 @@
typedef struct udf_struct { typedef struct udf_struct {
struct udf_struct *next; struct udf_struct *next;
char name[VAR_NAME_LEN+1]; char name[VAR_NAME_LEN+1];
char *text; char const *text;
Var *locals; Var *locals;
char IsActive; char IsActive;
int nargs; int nargs;
@@ -40,14 +40,14 @@ static UserFunc *FuncHash[FUNC_HASH_SIZE];
/* Access to built-in functions */ /* Access to built-in functions */
extern int NumFuncs; extern int NumFuncs;
extern Operator Func[]; extern BuiltinFunc Func[];
/* We need access to the expression evaluation stack */ /* We need access to the expression evaluation stack */
extern Value ValStack[]; extern Value ValStack[];
extern int ValStackPtr; extern int ValStackPtr;
static void DestroyUserFunc (UserFunc *f); static void DestroyUserFunc (UserFunc *f);
static void FUnset (char *name); static void FUnset (char const *name);
static void FSet (UserFunc *f); static void FSet (UserFunc *f);
static int SetUpLocalVars (UserFunc *f); static int SetUpLocalVars (UserFunc *f);
static void DestroyLocalVals (UserFunc *f); static void DestroyLocalVals (UserFunc *f);
@@ -142,6 +142,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 */ /* Copy the text over */
if (p->isnested) { if (p->isnested) {
Eprint("%s", ErrMsg[E_CANTNEST_FDEF]); Eprint("%s", ErrMsg[E_CANTNEST_FDEF]);
@@ -184,7 +189,7 @@ static void DestroyUserFunc(UserFunc *f)
} }
/* Free the function definition */ /* Free the function definition */
if (f->text) free(f->text); if (f->text) free( (char *) f->text);
/* Free the data structure itself */ /* Free the data structure itself */
free(f); free(f);
@@ -198,7 +203,7 @@ static void DestroyUserFunc(UserFunc *f)
/* it exists. */ /* it exists. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void FUnset(char *name) static void FUnset(char const *name)
{ {
UserFunc *cur, *prev; UserFunc *cur, *prev;
int h; int h;
@@ -238,12 +243,12 @@ static void FSet(UserFunc *f)
/* Call a user-defined function. */ /* Call a user-defined function. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int CallUserFunc(char *name, int nargs) int CallUserFunc(char const *name, int nargs)
{ {
UserFunc *f; UserFunc *f;
int h = HashVal(name) % FUNC_HASH_SIZE; int h = HashVal(name) % FUNC_HASH_SIZE;
int i; int i;
char *s; char const *s;
/* Search for the function */ /* Search for the function */
f = FuncHash[h]; f = FuncHash[h];
@@ -356,7 +361,7 @@ static void DestroyLocalVals(UserFunc *f)
/* it is defined, or -1 if it is not defined. */ /* it is defined, or -1 if it is not defined. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int UserFuncExists(char *fn) int UserFuncExists(char const *fn)
{ {
UserFunc *f; UserFunc *f;
int h = HashVal(fn) % FUNC_HASH_SIZE; int h = HashVal(fn) % FUNC_HASH_SIZE;

View File

@@ -30,9 +30,9 @@
/* Just like strncpy EXCEPT we ALWAYS copy the trailing 0. */ /* 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++)) ; while (n-- && (*dest++ = *source++)) ;
if (*(dest-1)) *dest = 0; if (*(dest-1)) *dest = 0;
@@ -48,7 +48,7 @@ char *StrnCpy(char *dest, const char *source, int n)
/* of the first string, whichever is greater. */ /* 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; int l;
if ((l = strlen(s1)) < n) return 0; if ((l = strlen(s1)) < n) return 0;
@@ -60,7 +60,7 @@ int StrMatch(const char *s1, const char *s2, int n)
/* StrinCmp - compare strings, case-insensitive */ /* 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; register int r;
while (n && *s1 && *s2) { while (n && *s1 && *s2) {
@@ -80,10 +80,10 @@ int StrinCmp(const char *s1, const char *s2, int n)
/* Like ANSI strdup */ /* Like ANSI strdup */
/* */ /* */
/***************************************************************/ /***************************************************************/
char *StrDup(const char *s) char *StrDup(char const *s)
{ {
char *ret = (char *) malloc(strlen(s)+1); char *ret = malloc(strlen(s)+1);
if (!ret) return (char *) NULL; if (!ret) return NULL;
strcpy(ret, s); strcpy(ret, s);
return ret; return ret;
} }
@@ -95,7 +95,7 @@ char *StrDup(const char *s)
/* Compare strings, case insensitive. */ /* Compare strings, case insensitive. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int StrCmpi(const char *s1, const char *s2) int StrCmpi(char const *s1, char const *s2)
{ {
int r; int r;
while (*s1 && *s2) { while (*s1 && *s2) {

View File

@@ -80,7 +80,7 @@ static int time_sep_func(int do_set, Value *val)
/* Given a string, compute the hash value. */ /* 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 i=0;
register unsigned int j=1; register unsigned int j=1;
@@ -102,7 +102,7 @@ unsigned int HashVal(const char *str)
/* string. If create is 1, create the variable. */ /* 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 int h;
register Var *v; register Var *v;
@@ -139,7 +139,7 @@ Var *FindVar(const char *str, int create)
/* string and delete it. */ /* string and delete it. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int DeleteVar(const char *str) int DeleteVar(char const *str)
{ {
register int h; register int h;
register Var *v; register Var *v;
@@ -168,7 +168,7 @@ int DeleteVar(const char *str)
/* Set the indicate variable to the specified value. */ /* 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); Var *v = FindVar(str, 1);
@@ -186,7 +186,7 @@ int SetVar(const char *str, Value *val)
/* Get a copy of the value of the variable. */ /* 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)
{ {
Var *v; Var *v;
@@ -223,6 +223,11 @@ int DoSet (Parser *p)
r = ParseIdentifier(p, &buf); r = ParseIdentifier(p, &buf);
if (r) return r; if (r) return r;
/* Allow optional equals-sign: SET var = value */
if (ParseNonSpaceChar(p, &r, 1) == '=') {
ParseNonSpaceChar(p, &r, 0);
}
r = EvaluateExpr(p, &v); r = EvaluateExpr(p, &v);
if (r) { if (r) {
DBufFree(&buf); DBufFree(&buf);
@@ -383,7 +388,7 @@ void DestroyVars(int all)
/* Given the name of a variable, "preserve" it. */ /* Given the name of a variable, "preserve" it. */
/* */ /* */
/***************************************************************/ /***************************************************************/
int PreserveVar(char *name) int PreserveVar(char const *name)
{ {
Var *v; Var *v;
@@ -440,7 +445,7 @@ int DoPreserve (Parser *p)
/* The structure of a system variable */ /* The structure of a system variable */
typedef struct { typedef struct {
char *name; char const *name;
char modifiable; char modifiable;
int type; int type;
void *value; void *value;
@@ -463,6 +468,7 @@ static SysVar SysVarArr[] = {
{ "Daemon", 0, INT_TYPE, &Daemon, 0, 0 }, { "Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
{ "DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 }, { "DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
{ "DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 }, { "DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
{ "DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
{ "DontFork", 0, INT_TYPE, &DontFork, 0, 0 }, { "DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
{ "DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 }, { "DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
{ "DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 }, { "DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
@@ -482,6 +488,7 @@ static SysVar SysVarArr[] = {
{ "LongMin", 1, INT_TYPE, &LongMin, -59, 59 }, { "LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
{ "LongSec", 1, INT_TYPE, &LongSec, -59, 59 }, { "LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
{ "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY }, { "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
{ "MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
{ "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 }, { "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 },
{ "NextMode", 0, INT_TYPE, &NextMode, 0, 0 }, { "NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
{ "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 }, { "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
@@ -494,12 +501,13 @@ static SysVar SysVarArr[] = {
{ "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0}, { "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0},
{ "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0}, { "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0},
{ "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132}, { "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132},
{ "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 } { "TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
{ "UntimedFirst", 0, INT_TYPE, &UntimedBeforeTimed, 0, 0 }
}; };
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) ) #define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
static SysVar *FindSysVar (const char *name); static SysVar *FindSysVar (char const *name);
static void DumpSysVar (const char *name, const SysVar *v); static void DumpSysVar (char const *name, const SysVar *v);
/***************************************************************/ /***************************************************************/
/* */ /* */
/* SetSysVar */ /* SetSysVar */
@@ -507,7 +515,7 @@ static void DumpSysVar (const char *name, const SysVar *v);
/* Set a system variable to the indicated value. */ /* 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); SysVar *v = FindSysVar(name);
if (!v) return E_NOSUCH_VAR; if (!v) return E_NOSUCH_VAR;
@@ -542,7 +550,7 @@ int SetSysVar(const char *name, Value *value)
/* Get the value of a system variable */ /* 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); SysVar *v = FindSysVar(name);
@@ -577,7 +585,7 @@ int GetSysVar(const char *name, Value *val)
/* Find a system var with specified name. */ /* 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 top=NUMSYSVARS-1, bottom=0;
int mid=(top + bottom) / 2; int mid=(top + bottom) / 2;
@@ -601,7 +609,7 @@ static SysVar *FindSysVar(const char *name)
/* If name is "", dump all system variables. */ /* If name is "", dump all system variables. */
/* */ /* */
/***************************************************************/ /***************************************************************/
void DumpSysVarByName(const char *name) void DumpSysVarByName(char const *name)
{ {
int i; int i;
SysVar *v; SysVar *v;
@@ -623,7 +631,7 @@ void DumpSysVarByName(const char *name)
/* Dump the system variable. */ /* 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]; char buffer[VAR_NAME_LEN+10];
@@ -643,7 +651,7 @@ static void DumpSysVar(const char *name, const SysVar *v)
} }
DestroyValue(val); DestroyValue(val);
} else if (v->type == STR_TYPE) { } else if (v->type == STR_TYPE) {
char *s = *((char **)v->value); char const *s = *((char **)v->value);
int y; int y;
Putc('"', ErrFp); Putc('"', ErrFp);
for (y=0; y<MAX_PRT_LEN && *s; y++) { for (y=0; y<MAX_PRT_LEN && *s; y++) {

View File

@@ -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
View File

@@ -0,0 +1 @@
#define VERSION "@VERSION@"

17
tests/colors.rem Normal file
View 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 COLOR 129 0 0 Bright Red
REM 28 SPECIAL COLOR 0 129 0 Bright Green
REM 28 SPECIAL COLOR 0 0 129 Bright Blue
REM 28 SPECIAL COLOR 0 129 129 Bright Cyan
REM 28 SPECIAL COLOR 129 0 129 Bright Magenta
REM 28 SPECIAL COLOR 129 129 0 Bright Yellow
REM 28 SPECIAL COLOR 129 129 129 Bright White

1
tests/include_dir/01.rem Normal file
View File

@@ -0,0 +1 @@
REM 15 MSG 01

1
tests/include_dir/02.rem Normal file
View File

@@ -0,0 +1 @@
REM 15 MSG 02

View File

@@ -0,0 +1 @@
REM MSG IGNORE

View File

@@ -0,0 +1 @@
REM 15 MSG You can't read this file.

View File

@@ -0,0 +1 @@
REM MSG IGNORE

5
tests/include_test.rem Normal file
View File

@@ -0,0 +1,5 @@
INCLUDE include_dir
INCLUDE include_dir_no_rems
INCLUDE nonexistent_include_dir
REM 15 MSG Whee!!!!

3
tests/runinc.rem Normal file
View File

@@ -0,0 +1,3 @@
set s shell("echo 3")
run on
set s shell("echo 3")

6
tests/runtest.rem Normal file
View 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

View File

@@ -11,6 +11,14 @@
# Copyright (C) 1999-2000 Roaring Penguin Software Inc. # Copyright (C) 1999-2000 Roaring Penguin Software Inc.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
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 TEST_GETENV="foo bar baz" ; export TEST_GETENV
echo "Test 1" > ../tests/test.out echo "Test 1" > ../tests/test.out
echo "" >> ../tests/test.out echo "" >> ../tests/test.out
@@ -18,7 +26,7 @@ echo "" >> ../tests/test.out
echo "" >> ../tests/test.out echo "" >> ../tests/test.out
echo "Test 2" >> ../tests/test.out echo "Test 2" >> ../tests/test.out
echo "" >> ../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
echo "" >> ../tests/test.out echo "" >> ../tests/test.out
echo "Test 3" >> ../tests/test.out echo "Test 3" >> ../tests/test.out
echo "" >> ../tests/test.out echo "" >> ../tests/test.out
@@ -27,6 +35,39 @@ echo "" >> ../tests/test.out
echo "Test 4" >> ../tests/test.out echo "Test 4" >> ../tests/test.out
echo "" >> ../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
echo "Test 5" >> ../tests/test.out
echo "" >> ../tests/test.out
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
echo "Test 6" >> ../tests/test.out
echo "" >> ../tests/test.out
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
echo "Test 7" >> ../tests/test.out
echo "" >> ../tests/test.out
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
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
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 -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
cmp -s ../tests/test.out ../tests/test.cmp cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,10 @@
# #
# ./test-rem # From WITHIN Remind source directory! # ./test-rem # From WITHIN Remind source directory!
# Don't evaluate SATISFY expressions if reminder has expired
REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())] REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
fset _h(x, y) trigger(hebdate(x,y)) fset _h(x, y) trigger(hebdate(x,y))
@@ -128,7 +132,7 @@ CLEAR-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1 REM 1 Mar -1 MSG 1 mar -1
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 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 REM 28 Feb AFTER MSG 28 Feb AFTER
POP-OMIT-CONTEXT POP-OMIT-CONTEXT
@@ -140,7 +144,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 REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
# Test BACK # Test BACK
CLEAR-OMIT-CONTEXT CLEAR-OMIT-CONTEXT
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
@@ -159,6 +163,25 @@ REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
OMIT [trigger(trigdate())] OMIT [trigger(trigdate())]
REM Fri after MSG 16 Feb 1991 REM Fri after MSG 16 Feb 1991
CLEAR-OMIT-CONTEXT 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 a000 abs(1)
set a001 abs(-1) set a001 abs(-1)
set a002 asc("foo") set a002 asc("foo")
@@ -250,4 +273,9 @@ set a078 easterdate(today())
set a079 easterdate(1992) set a079 easterdate(1992)
set a080 easterdate(1995) set a080 easterdate(1995)
set a081 "" 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")
dump dump

View File

@@ -38,3 +38,6 @@ REM 22 AUG SPECIAL PostScript (cabbage) show
REM 23 AUG AT 16:44 SPECIAL blort snoo glup REM 23 AUG AT 16:44 SPECIAL blort snoo glup
REM 24 AUG SPECIAL blort gulp wookie 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
View 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

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
echo "Unconfiguring Remind..." echo "Unconfiguring Remind..."
echo rm -f config.cache config.log config.status src/Makefile src/config.h echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h
rm -f config.cache config.log config.status src/Makefile src/config.h rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h
exit 0 exit 0

View File

@@ -1,95 +0,0 @@
# Makefile for installing WWW server calendar scripts
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999 by Roaring Penguin Software Inc.
# The complete name of your www host. Example: www.mycompany.com
WWWHOST = magnesium.roaringpenguin.com
# WWWHOST = www.mycompany.com
# The complete path to where the scripts actually live, as seen by
# the UNIX operating system.
SCRIPTDIR = /var/www/cgi-bin
# SCRIPTDIR = /home/dfs/Remind/www/TEST
# Where the scripts live as seen by the web browser. If
# they live in WWWHOST/cgi-bin, supply /cgi-bin
CGIDIR = /cgi-bin
# The complete path to the directory containing the HTML file "calendar.html".
# This is a sample file containing links to all the scripts. This path
# should be the path as seen by the UNIX operating system
HTMLDIR = /var/www/html/remind
# Where you stick images, as seen by UNIX
IMAGEDIR = /var/www/html/remind
# Where images are, as seen by web browers
IMAGEBASE = /remind
# Location. Typically, the name of your city or town. Example: Ottawa
LOCATION = Ottawa
# LOCATION = New York
# Where do Remind and Rem2PS executables live?
REMIND = /usr/local/bin/remind
REM2PS = /usr/local/bin/rem2ps
# If your Web server requires CGI programs to have a .cgi suffix, use
# the next line. Otherwise, comment it out
CGISUFFIX=.cgi
# Don't change stuff below here.
# --------------------------------------------------------------------
# Construct a rotten mean nasty sed script to do the dirty work
SEDSCRIPT = -e 's/Ottawa/$(LOCATION)/g' \
-e 's@http://your.machine/your.dir@http://$(WWWHOST)$(CGIDIR)@g' \
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
-e 's@%REMIND%@$(REMIND)@g' \
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
-e 's@%REM2PS%@$(REM2PS)@g' \
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@g' \
-e 's@rem2html@rem2html$(CGISUFFIX)@g'
SEDSCRIPT2 = -e 's/Ottawa/$(LOCATION)/g' \
-e 's@http://your.machine/your.dir@http://$(WWWHOST)$(CGIDIR)@g' \
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
-e 's@%REMIND%@$(REMIND)@g' \
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
-e 's@%REM2PS%@$(REM2PS)@g'
all:
@echo "Edit the Makefile; then type 'make install' to install"
@echo "the www server scripts."
# OK, it's abominable. But it works...
install:
-mkdir $(SCRIPTDIR)
cp calps hebdate hebps hebhtml moon sunrise sunset $(SCRIPTDIR)
sed $(SEDSCRIPT) < cal_dispatch-DIST > $(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
sed $(SEDSCRIPT) < hebdate.rem-DIST > $(SCRIPTDIR)/hebdate.rem
sed $(SEDSCRIPT) < moon.rem-DIST > $(SCRIPTDIR)/moon.rem
sed $(SEDSCRIPT) < sunrise.rem-DIST > $(SCRIPTDIR)/sunrise.rem
sed $(SEDSCRIPT) < sunset.rem-DIST > $(SCRIPTDIR)/sunset.rem
sed $(SEDSCRIPT) < calendar.html-DIST > $(HTMLDIR)/calendar.html
sed $(SEDSCRIPT) < hebhtml > $(SCRIPTDIR)/hebhtml
sed $(SEDSCRIPT2) < rem2html > $(SCRIPTDIR)/rem2html$(CGISUFFIX)
chmod 644 $(SCRIPTDIR)/sunrise.rem
chmod 644 $(SCRIPTDIR)/moon.rem
chmod 644 $(SCRIPTDIR)/hebdate.rem
chmod 644 $(SCRIPTDIR)/sunset.rem
chmod 644 $(HTMLDIR)/calendar.html
chmod 755 $(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
chmod 755 $(SCRIPTDIR)/rem2html$(CGISUFFIX)
chmod 755 $(SCRIPTDIR)/calps $(SCRIPTDIR)/hebdate \
$(SCRIPTDIR)/hebps $(SCRIPTDIR)/moon $(SCRIPTDIR)/sunrise \
$(SCRIPTDIR)/sunset $(SCRIPTDIR)/hebhtml $(SCRIPTDIR)/rem2html$(CGISUFFIX)
-mkdir $(IMAGEDIR)
cp firstquarter.png fullmoon.png lastquarter.png newmoon.png $(IMAGEDIR)
chmod 644 $(IMAGEDIR)/firstquarter.png $(IMAGEDIR)/fullmoon.png $(IMAGEDIR)/lastquarter.png $(IMAGEDIR)/newmoon.png

100
www/Makefile.in Normal file
View File

@@ -0,0 +1,100 @@
# Makefile.in for installing WWW server calendar scripts
# This file is part of REMIND.
# Copyright (C) 1992-1997 by David F. Skoll
# Copyright (C) 1999-2007 by Roaring Penguin Software Inc.
# The complete path to where the scripts actually live, as seen by
# the UNIX operating system.
SCRIPTDIR = /var/www/cgi-bin
# Where the scripts live as seen by the web browser.
CGIDIR = /cgi-bin
# The complete path to the directory containing the HTML file "calendar.html".
# This is a sample file containing links to all the scripts. This path
# should be the path as seen by the UNIX operating system
HTMLDIR = /var/www/remind
# Where you stick images and CSS files, as seen by UNIX
IMAGEDIR = /var/www/remind/resources
# Where images are, as seen by web browers
IMAGEBASE = /remind/resources
# Set by configure - don't touch.
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
mandir=@mandir@
bindir=@bindir@
datadir=@datadir@
datarootdir=@datarootdir@
# Where do Remind and Rem2PS executables live?
REMIND = $(bindir)/remind
REM2PS = $(bindir)/rem2ps
# If your Web server requires CGI programs to have a .cgi suffix, use
# the next line. Otherwise, comment it out
CGISUFFIX=.cgi
# Don't change stuff below here.
# --------------------------------------------------------------------
# Construct a rotten mean nasty sed script to do the dirty work
SEDSCRIPT = -e 's@%CGIDIR%@$(CGIDIR)@g' \
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
-e 's@%REMIND%@$(REMIND)@g' \
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
-e 's@%REM2PS%@$(REM2PS)@g' \
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@g' \
-e 's@rem2html@rem2html$(CGISUFFIX)@g'
SEDSCRIPT2 = -e 's@%CGIDIR%@$(CGIDIR)@g' \
-e 's@%SCRIPTDIR%@$(SCRIPTDIR)@g' \
-e 's@%REMIND%@$(REMIND)@g' \
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
-e 's@%REM2PS%@$(REM2PS)@g'
all:
@echo "Edit the Makefile; then type 'make install' to install"
@echo "the www server scripts."
# OK, it's abominable. But it works...
install:
-mkdir -p $(DESTDIR)$(SCRIPTDIR)
-mkdir -p $(DESTDIR)$(HTMLDIR)
cp calps hebdate hebps hebhtml moon sunrise sunset $(DESTDIR)$(SCRIPTDIR)
sed $(SEDSCRIPT) < cal_dispatch-DIST > $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
sed $(SEDSCRIPT) < hebdate.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
sed $(SEDSCRIPT) < moon.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/moon.rem
sed $(SEDSCRIPT) < sunrise.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
sed $(SEDSCRIPT) < sunset.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunset.rem
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunset.rem
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
$(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
-mkdir -p $(DESTDIR)$(IMAGEDIR)
cp firstquarter.png fullmoon.png lastquarter.png newmoon.png rem-default.css $(DESTDIR)$(IMAGEDIR)
chmod 644 $(DESTDIR)$(IMAGEDIR)/firstquarter.png \
$(DESTDIR)$(IMAGEDIR)/fullmoon.png \
$(DESTDIR)$(IMAGEDIR)/lastquarter.png \
$(DESTDIR)$(IMAGEDIR)/newmoon.png \
$(DESTDIR)$(IMAGEDIR)/rem-default.css

View File

@@ -1,24 +1,13 @@
REM2HTML REM2HTML
--------
Rem2HTML is a Perl script which transforms the output of Rem2HTML is a Perl script that transforms the output of `remind -p
`remind -p ...' to an HTML table. Type `perl rem2html --help' for ...' to HTML. Type `perl rem2html --help' for usage information.
usage information.
Typical usage: remind -p ~/.reminders | rem2html > file.html Typical usage: remind -p ~/.reminders | rem2html > file.html
You may have to edit the "#!/bin/perl" line to reflect the location You may have to edit the "#!/usr/bin/perl" line to reflect the
of your Perl interpreter. location of your Perl interpreter.
If you make Remind output data for more than one month (for example,
remind -p3 ~/.reminders | rem2html > file.html), then rem2html
creates a _SINGLE_ file of concatenated HTML documents. It's up
to you to split them. In this case, you're probably better off
using the --tableonly option to rem2html and adding the appropriate
head and tail with another program.
Rem2HTML was contributed by Don Schwarz <darkowl@mcs.net>. It
produces HTML compatible with most modern browsers, but *not* with
browsers which don't support tables (like Lynx, as of this writing.)
-- --
David F. Skoll David F. Skoll

View File

@@ -6,10 +6,6 @@
# CAL_DISPATCH -- Shell script for CGI directory to dispatch calendar # CAL_DISPATCH -- Shell script for CGI directory to dispatch calendar
# commands. # commands.
#
# WARNING WARNING WARNING -- If your /bin/sh is really GNU's "bash",
# make sure you don't have a buggy version which treats char 0xFF as
# a command separator -- it is a security risk!
######################### #########################
# #

View File

@@ -1,28 +1,28 @@
<HTML> <HTML>
<!-- Sample HTML file with links to the calendar stuff --> <!-- Sample HTML file with links to the calendar stuff -->
<HEAD> <HEAD>
<TITLE>David Skoll's Calendar Server</TITLE> <TITLE>Remind Calendar Server</TITLE>
</HEAD> </HEAD>
<BODY> <BODY>
<H1>Roaring Penguin's Calendar Server</H1> <H1>Remind Calendar Server</H1>
<a HREF="http://your.machine/your.dir/cal_dispatch?sunrise"> <a HREF="%CGIDIR%/cal_dispatch?sunrise">
Sunrise Information</a><P> Sunrise Information</a><P>
<a HREF="http://your.machine/your.dir/cal_dispatch?sunset"> <a HREF="%CGIDIR%/cal_dispatch?sunset">
Sunset Information</a><P> Sunset Information</a><P>
<a HREF="http://your.machine/your.dir/cal_dispatch?moon"> <a HREF="%CGIDIR%/cal_dispatch?moon">
Moon Phase Information</a><P> Moon Phase Information</a><P>
<a HREF="http://your.machine/your.dir/cal_dispatch?calps"> <a HREF="%CGIDIR%/cal_dispatch?calps">
Blank PostScript Calendar</a> (Approximately 20kB)<P> Blank PostScript Calendar</a> (Approximately 20kB)<P>
<a HREF="http://your.machine/your.dir/cal_dispatch?hebdate"> <a HREF="%CGIDIR%/cal_dispatch?hebdate">
Today's Hebrew Date</a><P> Today's Hebrew Date</a><P>
<a HREF="http://your.machine/your.dir/cal_dispatch?hebps"> <a HREF="%CGIDIR%/cal_dispatch?hebps">
PostScript Calendar with Jewish Holidays</a> (Approximately 35 kB)<P> PostScript Calendar with Jewish Holidays</a> (Approximately 35 kB)<P>
<a HREF="http://your.machine/your.dir/cal_dispatch?hebhtml"> <a HREF="%CGIDIR%/cal_dispatch?hebhtml">
HTML Calendar with Jewish Holidays</a> (Your browser must support tables.)<P> HTML Calendar with Jewish Holidays</a>
<HR> <HR>
<a HREF="http://www.roaringpenguin.com/remind.html"> <a HREF="http://www.roaringpenguin.com/remind">
Get the Remind software</a> that provides this service.<P> Get the Remind software</a> that provides this service.<P>
</BODY> </BODY>

View File

@@ -8,5 +8,5 @@
echo "Content-type: application/postscript" echo "Content-type: application/postscript"
echo echo
$REMIND -p /dev/null | $REM2PS -e -c3 $REMIND -p /dev/null | $REM2PS -e -c3 -l
exit 0 exit 0

View File

@@ -65,7 +65,7 @@ IF !InIsrael
[_h(16, "Tishrey")] MSG %"Sukkot 2%" [_h(16, "Tishrey")] MSG %"Sukkot 2%"
ENDIF ENDIF
[_h(21, "Tishrey")] ++12 MSG %"Hashana Rabba%" is %b. [_h(21, "Tishrey")] ++12 MSG %"Hoshana Rabba%" is %b.
[_h(22, "Tishrey")] ++12 MSG %"Shemini Atzeret%" is %b. [_h(22, "Tishrey")] ++12 MSG %"Shemini Atzeret%" is %b.
IF InIsrael IF InIsrael
@@ -158,8 +158,8 @@ IF ostart <= TODAY() && (TODAY() - ostart < 49)
ENDIF ENDIF
IF !$PSCAL IF !$PSCAL
REM 20 ++40 msg Also available: <a HREF="http://your.machine/your.dir/cal_dispatch?hebps">a PostScript calendar</a> (about 35KB) for %m %y, complete with Hebrew dates, Jewish holidays, and moon phases for Ottawa. (This takes a few seconds to generate.) REM 20 ++40 msg Also available: <a HREF="%CGIDIR%/cal_dispatch?hebps">a PostScript calendar</a> (about 35KB) for %m %y, complete with Hebrew dates, Jewish holidays, and moon phases for [$Location].
REM 20 ++40 msg And: <a HREF="http://your.machine/your.dir/cal_dispatch?hebhtml">an HTML version</a> of the above. (Your browser must handle tables.) REM 20 ++40 msg And: <a HREF="%CGIDIR%/cal_dispatch?hebhtml">an HTML version</a> of the above.
ELSE ELSE
[trigger(moondate(0))] SPECIAL MOON 0 [trigger(moondate(0))] SPECIAL MOON 0
[trigger(moondate(1))] SPECIAL MOON 1 [trigger(moondate(1))] SPECIAL MOON 1

View File

@@ -12,7 +12,7 @@ echo ""
$REMIND - <<EOR $REMIND - <<EOR
BANNER % BANNER %
REM 20 ++40 RUN $REMIND -iHTML=0 -p $DIR/hebdate.rem %m %y | $REM2PS -e -c3 REM 20 ++40 RUN $REMIND -iHTML=0 -p $DIR/hebdate.rem %m %y | $REM2PS -e -c3 -l
EOR EOR
exit 0 exit 0

View File

@@ -9,11 +9,11 @@ set now now()
banner % banner %
MSG <HEAD>% MSG <HEAD>%
MSG <TITLE>Moon over Ottawa</TITLE>% MSG <TITLE>Moon over [$Location]</TITLE>%
MSG </HEAD>% MSG </HEAD>%
MSG <BODY> MSG <BODY>
MSG <H1>Moon over Ottawa</H1> MSG <H1>Moon over [$Location]</H1>
set ndate moondate(0) set ndate moondate(0)
set ntime moontime(0) set ntime moontime(0)
@@ -22,12 +22,12 @@ set ftime moontime(2)
fset t(x) wkday(x)+", "+day(x)+" "+mon(x)+", "+year(x) fset t(x) wkday(x)+", "+day(x)+" "+mon(x)+", "+year(x)
msg Today is %w, %d %m, %y.<P> msg Today is %w, %d %m, %y.<P>
msg The local time in Ottawa is [now].<P> msg The local time in [$Location] is [now].<P>
if ndate < fdate if ndate < fdate
msg The next new moon is on [t(ndate)] at [ntime], Ottawa time.<P> msg The next new moon is on [t(ndate)] at [ntime], [$Location] time.<P>
msg The next full moon is on [t(fdate)] at [ftime], Ottawa time.<P> msg The next full moon is on [t(fdate)] at [ftime], [$Location] time.<P>
else else
msg The next full moon is on [t(fdate)] at [ftime], Ottawa time.<P> msg The next full moon is on [t(fdate)] at [ftime], [$Location] time.<P>
msg The next new moon is on [t(ndate)] at [ntime], Ottawa time.<P> msg The next new moon is on [t(ndate)] at [ntime], [$Location] time.<P>
endif endif

69
www/rem-default.css Normal file
View File

@@ -0,0 +1,69 @@
table.rem-cal {
font-family: helvetica, arial, sans-serif;
font-size: 12pt;
}
table.rem-sc-table {
font-family: helvetica, arial, sans-serif;
font-size: 10pt;
width: 95%;
float: left;
}
caption.rem-cal-caption {
font-size: 14pt;
font-weight: bold;
}
th.rem-cal-hdr {
width: 14%;
border-style: solid;
border-width: 1px;
vertical-align: top;
}
td.rem-empty, td.rem-cell, td.rem-small-calendar {
width: 14%;
height: 7em;
border-style: solid;
border-width: 1px;
vertical-align: top;
}
td.rem-today {
width: 14%;
height: 7em;
border-style: solid;
border-width: 2px;
border-color: #EE3333;
vertical-align: top;
}
table.rem-cal {
width: 100%;
border-collapse: collapse;
}
div.rem-daynumber {
float: right;
text-align: right;
vertical-align: top;
font-size: 14pt;
}
div.rem-moon {
float: left;
text-align: left;
vertical-align: top;
}
th.rem-sc-hdr {
text-align: right;
}
td.rem-sc-empty-cell, td.rem-sc-cell {
text-align: right;
width: 14%;
}
caption.rem-sc-caption {
font-size: 12pt;
}

View File

@@ -1,102 +1,558 @@
#!/usr/bin/perl #!/usr/bin/perl
# rem2html use strict;
# use warnings;
# A script to convert from the output of "remind -p" to Hyper-Text Markup
# Language (HTML), the text format used in WWW documents. By default, it
# outputs a stand-alone file which can be fed directly into a web browser.
# The output uses nested <TABLE> blocks, so it will only work in a browser
# which supports tables (Netscape, MSIE, etc, NOT Lynx).
#
# This script works well on my computer (Linux 2.0.27) under Perl 5.003 and
# 5.004. It should work fine on other unices but I have no idea whether
# it will run under VMS, OS/2, Windows, etc.
#
# [Note from David: The REMIND license prohibits you from using REMIND
# under Windows.]
#
# Rem2html puts "normal" CAL or MSG-type reminders in a <P></P> pair,
# and escapes any special HTML characters.
#
# If you want to put actual HTML code in the calendar (hyper-links, for
# example), use the "SPECIAL HTML" type. For example:
#
# REM Wed SPECIAL HTML <P> Meeting at \
# <A HREF="http://www.linuxhq.com">Linux HQ</A> </P>
#
# This file is Copyright (C) 1997-8 by Don Schwarz <darkowl@mcs.net>
# and David F. Skoll
use Getopt::Long; use Getopt::Long;
@months = (January,February,March,April,May,June,July,August,September,October,November,December); my %Options;
$DefaultImageDir = "%IMAGEBASE%"; my $rem2html_version = '2.0';
if ($DefaultImageDir =~ m@/$@) {
chop $DefaultImageDir;
}
$rem2html_version = "1.0"; my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
&parse_options(); my $TIDY_PROGNAME = $0;
$TIDY_PROGNAME =~ s|^.*/||;
# Backgound color -- unfortunately, most Web browsers (as of 14 October 1999) # rem2html -- convert the output of "remind -p" to HTML
# do not correctly handle transparency in PNG images, so I had to make the
# moon image background white.
$Options{'bgcolor'} ||= "BGCOLOR=\"#FFFFFF\"";
if (-t STDIN) { =head1 NAME
print STDERR "(Rem2HTML: Input should not come from a terminal.)\n";
$Options{'help'} = 1;
}
if ($Options{'help'}) { rem2html - Convert the output of "remind -p" to HTML
&show_usage();
} elsif ($Options{'version'}) {
print "Rem2HTML Version $rem2html_version.\n";
} else {
$successes = 0;
while(1) {
last if (!parse_input());
$successes++;
&output_header();
&output_data();
&output_footer();
}
print STDERR "Rem2HTML: Couldn't find any calendar data.\n" if (!$successes);
}
exit(0); =head1 SYNOPSIS
sub show_usage { remind -p ... | rem2html [options]
print STDERR <<EndOfUsage;
Rem2HTML: Produce a HTML calendar from the output of Remind.
Usage: rem2html [options] =head1 OPTIONS
=over 4
=item --help, -h
Print usage information
=item --version
Print version
=item --backurl I<url>
When producing the small calendar for the previous month, make the
month name a link to I<url>.
=item --forwurl I<url>
When producing the small calendar for the next month, make the
month name a link to I<url>.
=item --imgbase I<url>
When creating URLs for images and the stylesheet, use
I<url> as the base URL.
=item --stylesheet I<url.css>
Use I<url.css> as the stylesheet. If this option is used,
I<url.css> is I<not> interpreted relative to B<imgbase>.
=item --nostyle
Produce basic HTML that does not use a CSS stylesheet.
=item --tableonly
Output results as a E<lt>tableE<gt> ... E<lt>/tableE<gt> sequence only
without any E<lt>htmlE<gt> or E<lt>bodyE<gt> tags.
=item --title I<title>
Use I<title> as the content between E<lt>titleE<gt> and E<lt>/titleE<gt>
tags.
=item --prologue I<html_text>
Insert I<html_text> right after the E<lt>bodyE<gt> tag.
=item --epilogue I<html_text>
Insert I<html_text> right before the E<lt>/bodyE<gt> tag.
=back
=head1 AUTHOR
rem2html was written by David F. Skoll with much inspiration from an
earlier version by Don Schwarz.
=cut
sub usage
{
my ($exit_status) = @_;
if (!defined($exit_status)) {
$exit_status = 1;
}
print STDERR <<"EOM";
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -p"
Usage: remind -p ... | rem2html [options]
Options: Options:
--help, -h Print this information --help, -h Print usage information
--version Version information --man Show man page (requires "perldoc")
-p file Prepend the specified HTML file to the beginning of the --version Print version
output --backurl url Make the title on the previous month's small calendar
-a file Append the specified HTML file to the end of the output entry a link to <url>
-f[shted] font Set font for small cal, hdr, title, cal entries,day numbers --forwurl url Same as --backurl, but for the next month's small calendar
-s[hted] size Set size for header, title, calendar entries and/or day --imgbase url Base URL of images and default stylesheet file
numbers --stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
--backurl url Make the title on the previous month's small calendar entry prepended to url.css
a hyperlink to <url> --nostyle Produce basic HTML that does not use a CSS stylesheet
--forwurl url Same as --backurl, but with the next month's small calendar --tableonly Output results as a <table> only, no <html>, <body>, etc.
--tableonly Output the results as a <TABLE> block only, no <HTML>, etc. --title string What to put in <title>...</title> tags
--border,-b size Set the border thickness of the table --prologue html_text Text to insert at the top of the body
--cellspace,-t size Set the line thickness of the table --epilogue html_text Text to insert at the end of the body
--bgcolor,-g color Set the background color for the day entries EOM
exit($exit_status);
EndOfUsage
} }
sub escape_html { sub parse_options
{
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
if (!GetOptions(\%Options, "help|h",
"man",
"version",
"stylesheet=s",
"nostyle",
"backurl=s",
"forwurl=s",
"title=s",
"prologue=s",
"epilogue=s",
"imgbase=s",
"tableonly")) {
usage(1);
}
$Options{'title'} ||= 'HTML Calendar';
# Fix up imgbase
my $imgbase = '%IMAGEBASE%';
if ($imgbase ne '%' . 'IMAGEBASE' . '%') {
$Options{'imgbase'} ||= $imgbase;
} else {
$Options{'imgbase'} ||= '';
}
$Options{'imgbase'} =~ s|/+$||;
my $stylesheet = $Options{'imgbase'};
$stylesheet .= '/' if ($stylesheet ne '');
$stylesheet .= 'rem-default.css';
$Options{'stylesheet'} ||= $stylesheet;
}
sub start_output
{
return if ($Options{'tableonly'});
print("<html>\n<head>\n<title>" . $Options{'title'} . "</title>\n");
if (!$Options{'nostyle'}) {
if ($Options{'stylesheet'}) {
print('<link rel="stylesheet" type="text/css" href="' .
$Options{'stylesheet'} . '">' . "\n");
}
}
print("</head>\n<body>\n");
if ($Options{'prologue'}) {
print $Options{'prologue'} . "\n";
}
}
sub end_output
{
return if ($Options{'tableonly'});
if ($Options{'epilogue'}) {
print $Options{'epilogue'} . "\n";
}
print("</body>\n</html>\n");
}
sub parse_input
{
undef $days;
undef $shades;
undef $moons;
undef $classes;
undef $weeks;
my $found_data = 0;
while(<STDIN>) {
chomp;
last if /^\# rem2ps begin$/;
}
my $line;
# Month Year numdays firstday monday_first_flag
$line = <STDIN>;
return 0 unless $line;
chomp($line);
($Month, $Year, $Numdays, $Firstwkday, $Mondayfirst) = split(' ', $line);
# Day names
$line = <STDIN>;
return 0 unless $line;
chomp($line);
@Daynames = split(' ', $line);
# Prevmon prevlen
$line = <STDIN>;
return 0 unless $line;
chomp($line);
($Prevmon, $Prevlen) = split(' ', $line);
# Nextmon nextlen
$line = <STDIN>;
return 0 unless $line;
chomp($line);
($Nextmon, $Nextlen) = split(' ', $line);
$found_data = 1;
my $class;
if ($Options{'nostyle'}) {
$class = '';
} else {
$class = ' class="rem-entry"';
}
while(<STDIN>) {
chomp;
last if /^\# rem2ps end$/;
next if /^\#/;
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
my ($y, $m, $d, $special, $tag, $duration, $time, $body) =
($1, $2, $3, $4, $5, $6, $7, $8);
my $d1 = $d;
$d1 =~ s/^0+//;
if ($special eq 'HTML') {
push(@{$days->[$d]}, $body);
} elsif ($special eq 'HTMLCLASS') {
$classes->[$d] = $body;
} elsif ($special eq 'WEEK') {
$body =~ s/^\s+//;
$body =~ s/\s+$//;
$weeks->{$d1} = $body;
} elsif ($special eq 'MOON') {
if ($body =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
my ($phase, $moonsize, $fontsize, $msg) = ($1, $2, $3, $4);
$moons->[$d]->{'phase'} = $phase;
$moons->[$d]->{'msg'} = $msg;
} elsif ($body =~ /(\S+)/) {
$moons->[$d]->{'phase'} = $1;
$moons->[$d]->{'msg'} = '';
}
} elsif ($special eq 'SHADE') {
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)/) {
$shades->[$d] = sprintf("#%02X%02X%02X",
($1 % 256), ($2 % 256), ($3 % 256));
}
} elsif ($special eq 'COLOR') {
if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {
my($r, $g, $b, $text) = ($1, $2, $3, $4);
my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
$r % 256, $g % 256, $b % 256);
push(@{$days->[$d]}, "<p$class $color>" . escape_html($text) . '</p>');
}
} elsif ($special eq '*') {
push(@{$days->[$d]}, "<p$class>" . escape_html($body) . '</p>');
}
}
return $found_data;
}
sub small_calendar
{
my($month, $monlen, $url, $first_col) = @_;
if ($Mondayfirst) {
$first_col--;
if ($first_col < 0) {
$first_col = 6;
}
}
if ($Options{'nostyle'}) {
print "<td width=\"14%\">\n";
print "<table border=\"0\">\n";
print "<caption>";
} else {
print "<td class=\"rem-small-calendar\">\n";
print "<table class=\"rem-sc-table\">\n";
print "<caption class=\"rem-sc-caption\">";
}
print "<a href=\"$url\">" if ($url);
print $month;
print "</a>" if ($url);
print "</caption>\n";
my $class;
if ($Options{'nostyle'}) {
print '<tr>';
$class = ' align="right"';
} else {
print '<tr class="rem-sc-hdr-row">';
$class = ' class="rem-sc-hdr"';
}
if (!$Mondayfirst) {
print "<th$class>" . substr($Daynames[0], 0, 1) . '</th>';
}
for (my $i=1; $i<7; $i++) {
print "<th$class>" . substr($Daynames[$i], 0, 1) . '</th>';
}
if ($Mondayfirst) {
print "<th$class>" . substr($Daynames[0], 0, 1) . '</th>';
}
print("</tr>\n");
my $col = 0;
for (; $col<$first_col; $col++) {
if ($col == 0) {
print("<tr>\n");
}
if ($Options{'nostyle'}) {
print("<td align=\"right\" width=\"14%\">&nbsp;</td>");
} else {
print("<td class=\"rem-sc-empty-cell\">&nbsp;</td>");
}
}
for (my $day=1; $day <= $monlen; $day++) {
if ($col == 0) {
print("<tr>\n");
}
$col++;
if ($Options{'nostyle'}) {
print("<td align=\"right\" width=\"14%\">$day</td>");
} else {
print("<td class=\"rem-sc-cell\">$day</td>");
}
if ($col == 7) {
print("</tr>\n");
$col = 0;
}
}
if ($col) {
while ($col < 7) {
if ($Options{'nostyle'}) {
print("<td align=\"right\" width=\"14%\">&nbsp;</td>");
} else {
print("<td class=\"rem-sc-empty-cell\">&nbsp;</td>");
}
$col++;
}
print("</tr>\n");
}
print("</table>\n");
print "</td>\n";
}
sub output_calendar
{
# Which column is 1st of month in?
my $first_col = $Firstwkday;
if ($Mondayfirst) {
$first_col--;
if ($first_col < 0) {
$first_col = 6;
}
}
# Last column
my $last_col = ($first_col + $Numdays - 1) % 7;
# Start the table
my $class;
if ($Options{'nostyle'}) {
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
$Month . ' ' . $Year . '</caption>' . "\n";
print '<tr>';
$class = ' width="14%"';
} else {
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
$Month . ' ' . $Year . '</caption>' . "\n";
print '<tr class="rem-cal-hdr-row">';
$class = ' class="rem-cal-hdr"';
}
if (!$Mondayfirst) {
print "<th$class>" . $Daynames[0] . '</th>';
}
for (my $i=1; $i<7; $i++) {
print "<th$class>" . $Daynames[$i] . '</th>';
}
if ($Mondayfirst) {
print "<th$class>" . $Daynames[0] . '</th>';
}
print "</tr>\n";
# Start the calendar rows
my $col = 0;
if ($Options{'nostyle'}) {
print "<tr>\n";
} else {
print "<tr class=\"rem-cal-row\">\n";
}
if ($first_col > 0) {
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
($Firstwkday - $Prevlen + 35) % 7);
$col++;
}
if ($last_col == 6 && $first_col > 0) {
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
($Firstwkday + $Numdays) % 7);
$col++;
}
if ($Options{'nostyle'}) {
$class = ' width="14%"';
} else {
$class = ' class="rem-empty"';
}
while ($col < $first_col) {
print("<td$class>&nbsp;</td>\n");
$col++;
}
for (my $day=1; $day<=$Numdays; $day++) {
draw_day_cell($day);
$col++;
if ($col == 7) {
$col = 0;
print "</tr>\n";
if ($day < $Numdays) {
if ($Options{'nostyle'}) {
print "<tr>\n";
} else {
print "<tr class=\"rem-cal-row\">\n";
}
}
}
}
if ($col) {
while ($col < 7) {
if ($col == 5) {
if ($first_col == 0) {
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
($Firstwkday - $Prevlen + 35) % 7);
} else {
print("<td$class>&nbsp;</td>\n");
}
} elsif ($col == 6) {
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
($Firstwkday + $Numdays) % 7);
} else {
print("<td$class>&nbsp;</td>\n");
}
$col++;
}
print "</tr>\n";
}
# Add a row for small calendars if they were not yet done!
if ($first_col == 0 && $last_col == 6) {
if ($Options{'nostyle'}) {
print "<tr>\n";
} else {
print "<tr class=\"rem-cal-row\">\n";
}
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
($Firstwkday - $Prevlen + 35) % 7);
for (my $i=0; $i<5; $i++) {
print("<td$class>&nbsp;</td>\n");
}
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
($Firstwkday + $Numdays) % 7);
print("</tr>\n");
}
# End the table
print "</table>\n";
}
sub draw_day_cell
{
my($day) = @_;
my $shade = $shades->[$day];
my $week = '';
if (exists($weeks->{$day})) {
$week = ' ' . $weeks->{$day};
}
my $class;
if ($Options{'nostyle'}) {
$class = $classes->[$day] || '';
} else {
$class = $classes->[$day] || "rem-cell";
}
if ($shade) {
$shade = " style=\"background: $shade;\"";
} else {
$shade = "";
}
if ($class ne '') {
print "<td class=\"$class\"$shade>\n";
} else {
print "<td valign=\"top\" $shade>\n";
}
if ($moons->[$day]) {
my $phase = $moons->[$day]->{'phase'};
my $msg = $moons->[$day]->{'msg'};
$msg ||= '';
if ($msg ne '') {
$msg = '&nbsp;' . escape_html($msg);
}
my $img;
my $alt;
my $title;
if ($phase == 0) {
$img = 'newmoon.png';
$title = 'New Moon';
$alt = 'new';
} elsif ($phase == 1) {
$img = 'firstquarter.png';
$title = 'First Quarter';
$alt = '1st';
} elsif ($phase == 2) {
$img = 'fullmoon.png';
$alt = 'full';
$title = 'Full Moon';
} else {
$img = 'lastquarter.png';
$alt = 'last';
$title = 'Last Quarter';
}
if ($Options{'imgbase'}) {
$img = $Options{'imgbase'} . '/' . $img;
}
if ($Options{'nostyle'}) {
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
} else {
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
}
}
if ($Options{'nostyle'}) {
print "<div style=\"float: right\">$day$week</div>\n";
print "<p>&nbsp;</p>\n";
} else {
print "<div class=\"rem-daynumber\">$day$week</div>\n";
}
if ($days->[$day]) {
print(join("\n", @{$days->[$day]}));
}
print "</td>\n";
}
sub escape_html
{
my($in) = @_; my($in) = @_;
$in =~ s/\&/\&amp;/g; $in =~ s/\&/\&amp;/g;
$in =~ s/\</\&lt;/g; $in =~ s/\</\&lt;/g;
@@ -104,313 +560,35 @@ sub escape_html {
return $in; return $in;
} }
sub parse_options { parse_options();
%Options = (); if ($Options{'help'}) {
usage(0);
GetOptions (\%Options, "help|h", exit(0);
"version", } elsif ($Options{'man'}) {
"border|b=i", system("perldoc $0");
"cellspace|t=i", exit(0);
"backurl|bu:s", "forwurl|fu:s", } elsif ($Options{'version'}) {
"tableonly|to", print "rem2html version $rem2html_version.\n";
"prologue|p=s", exit(0);
"append|a=s",
"bgcolor|g=s",
"fs=s", "fh=s", "ft=s", "fe=s", "fd=s",
"sh=i", "st=i", "se=i", "sd=i",
);
$Options{'border'} = "BORDER=" . ($Options{'border'} || 1);
$Options{'cellspace'} &&= "CELLSPACING=$Options{'cellspace'}";
$Options{'bgcolor'} &&= "BGCOLOR=$Options{'bgcolor'}";
} }
sub parse_input { if (-t STDIN) {
local $where = 0; print STDERR "$TIDY_PROGNAME: Input should not come from a terminal.\n\n";
local $msg; usage(1);
local $type;
local $day;
@days = ();
@shades = ();
@moons = ();
while (<>) {
chomp($_);
if (/rem2(html|ps) begin/) {
} elsif (!$where) {
next;
} elsif ($where == 1) {
local ($month, $year);
($month, $year, $month_length, $firstday, $mfirst) = split(" ");
$caption = "$month, $year";
for $i ( 1 .. $month_length) { push(@days, ""); }
} elsif ($where == 2) {
@DayNames = split(" ");
} elsif ($where == 3) {
@prevsc = split(" ");
} elsif ($where == 4) {
@nextsc = split(" ");
} else {
return 1 if /rem2(html|ps) end/;
next if /^\#/;
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
$type = $4;
$msg = $8;
$day = $3;
if ($type eq "HTML") {
$days[$day] .= "$msg ";
} elsif ($type eq "MOON") {
my($phase, $text);
if ($msg =~ /^\s*(\d+)\s+\S+\s+\S+\s+(.*)$/) {
$phase = $1;
$text = $2;
} elsif ($msg =~ /^\s*(\d+)/) {
$phase = $1;
$text = "";
} else {
next;
}
next if ($phase > 3);
if ($phase == 0) {
$text = "<IMAGE SRC=\"$DefaultImageDir/newmoon.png\" ALT=\"New Moon\"" .
"WIDTH=16 HEIGHT=16> <FONT SIZE=\"-2\">" . escape_html($text);
} elsif ($phase == 1) {
$text = "<IMAGE SRC=\"$DefaultImageDir/firstquarter.png\" ALT=\"First Quarter\"" .
"WIDTH=16 HEIGHT=16> <FONT SIZE=\"-2\">" . escape_html($text);
} elsif ($phase == 2) {
$text = "<IMAGE SRC=\"$DefaultImageDir/fullmoon.png\" ALT=\"Full Moon\"" .
"WIDTH=16 HEIGHT=16> <FONT SIZE=\"-2\">" . escape_html($text);
} else {
$text = "<IMAGE SRC=\"$DefaultImageDir/lastquarter.png\" ALT=\"Last Quarter\"" .
"WIDTH=16 HEIGHT=16> <FONT SIZE=\"-2\">" . escape_html($text);
}
$moons[$day] = $text . "</FONT> ";
} elsif ($type eq "SHADE") {
my($red, $green, $blue);
if ($msg =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s*$/) {
$red = $1;
$green = $2;
$blue = $3;
} elsif ($msg =~ /^\s*(\d+)\s*$/) {
$red = $1;
$green = $1;
$blue = $1;
} else {
next;
}
next if ($red > 255 || $green > 255 || $blue > 255);
$shades[$day] = sprintf(" BGCOLOR=\"#%02X%02X%02X\"",
$red, $green, $blue);
} elsif ($type eq "COLOR") {
my($red, $green, $blue, $stuff);
if ($msg =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$/) {
$red = $1;
$green = $2;
$blue = $3;
$stuff = $4;
next if ($red > 255 || $green > 255 || $blue > 255);
$days[$day] .=
sprintf("<P><font color=\"#%02x%02x%02x\">",
$red, $green, $blue) .
escape_html($stuff) . "</font></P>";
} else {
next;
}
} elsif ($type eq "*") {
$msg = &escape_html($msg);
$days[$day] .= "<P>$msg</P>";
}
}
$where++;
}
if ($where) {
return 1;
}
return 0;
} }
sub output_header { my $found_something = 0;
local ($title, $dayheader); while(1) {
last if (!parse_input());
if (!$Options{'tableonly'}) { start_output() unless $found_something;
print <<EndOfHTML; $found_something = 1;
<HTML> output_calendar();
<HEAD><TITLE>Reminders for $caption</TITLE></HEAD> }
<BODY> if ($found_something) {
EndOfHTML end_output();
} exit(0);
} else {
print <<EndOfHTML; print STDERR "$TIDY_PROGNAME: Could not find any calendar data on STDIN.\n";
<!-- This output was produced by Rem2HTML $rem2html_version (written by exit(1);
Don Schwarz <darkowl\@mcs.net>) and Remind (written by David F. Skoll). -->
EndOfHTML
if ($Options{'prologue'}) {
open(PROLOGUE, "< $Options{'prologue'}");
print while ( <PROLOGUE> );
close(PROLOGUE);
}
$caption = &format_font($caption, $Options{'ft'}, $Options{'st'} || "+1");
print <<EndOfHTML;
<TABLE $Options{'border'} $Options{'cellspace'} $Options{'bgcolor'} WIDTH=100%>
<CAPTION><STRONG>$caption</STRONG></CAPTION>
<TR>
EndOfHTML
$mfirst || &print_day_header($DayNames[0]);
for($i=1; $i<7; $i++) {
&print_day_header($DayNames[$i]);
}
$mfirst && &print_day_header($DayNames[0]);
print " </TR>\n";
} }
sub output_footer {
print "</TABLE>\n";
if ($Options{'append'}) {
open(EPILOGUE, "< $Options{'append'}");
print while ( <EPILOGUE> );
close(EPILOGUE);
}
unless ($Options{'tableonly'}) {
print <<EndOfHTML;
</BODY>
</HTML>
EndOfHTML
}
}
sub output_data {
local ($endday, $prevday, $nextday, $week, $weekday);
local ($element, $day, $msg, $fday);
$firstday -= $mfirst;
if ($firstday < 0) { $firstday += 7; }
$endday = $firstday + $month_length;
$endweek = $endday + (6 - ($endday % 7));
$endday %= 7;
if ( $firstday > 1 ) {
$prevday = 0;
$nextday = 1;
} elsif ($endday ? ($endday < 5) : !$firstday) {
$prevday = $endweek - 1;
$nextday = $endweek;
} else {
$prevday = 0;
$nextday = $endweek;
}
for $week ( 0..5 ) {
print " <TR>\n";
for $weekday ( 0..6 ) {
$element = ($week * 7) + ($weekday * 1);
$day = $element - $firstday + 1;
$msg = $days[$day];
$msg = $msg ? &format_font($msg, $Options{'fe'}, $Options{'se'})
: " <BR> <BR> <BR> <BR>";
$fday = &format_font($day, $Options{'fd'}, $Options{'sd'} || -1);
if ($day > 0 && $day <= $month_length) {
print <<EndOfHTML;
<TD HEIGHT="120" VALIGN=TOP WIDTH=14%$shades[$day]>
<P ALIGN=RIGHT>$moons[$day]$fday</P>
$msg
</TD>
EndOfHTML
} elsif ($element == $prevday) {
&small_calendar(@prevsc, 1, $Options{'backurl'});
} elsif ($element == $nextday) {
&small_calendar(@nextsc, 2, $Options{'forwurl'});
} else {
print " <TD WIDTH=14%><BR></TD>";
}
}
print " </TR>\n";
last if $day >= $month_length && $element >= $nextday;
}
}
sub small_calendar {
local ($scname, $scn, $which, $url) = @_;
local ($scstart, $l, $week, $weekday, $tday);
$scname = "<A HREF=\"$url\">$scname</A>", if $url;
$scname = &format_font($scname, $Options{'fs'}, -2);
if ($which == 1) {
$scstart = $firstday - ($scn % 7);
if ($scstart < 0) { $scstart += 7; }
} else {
$scstart = $firstday + ($month_length % 7);
if ($scstart > 6) { $scstart -= 7; }
}
print <<EndOfHTML;
<TD WIDTH=14% VALIGN=TOP>
<TABLE WIDTH=100%>
<CAPTION><STRONG>$scname</STRONG></CAPTION>
<TR>
EndOfHTML
$mfirst || &print_day_header(substr($DayNames[0], 0, 1), 1);
for ($i=1; $i<7; $i++) {
&print_day_header(substr($DayNames[$i], 0, 1), 1);
}
$mfirst && &print_day_header(substr($DayNames[0], 0, 1), 1);
print "</TR>\n";
for $week ( 0..5 ) {
print " <TR>\n";
for $weekday ( 0..6 ) {
$tday = ($week * 7) + ($weekday * 1) - $scstart + 1;
$tday = "", if $tday <= 0 || $tday > $scn;
print " <TD WIDTH=14%><FONT SIZE=-2>$tday</FONT></TD>\n";
}
print " </TR>\n";
last if $tday >= $scn;
}
print <<EndOfHTML;
</TABLE>
</TD>
EndOfHTML
}
sub format_font {
local ($text, $font, $size) = @_;
if (!$text) {
return "";
} elsif ($font && $size) {
return "<FONT FACE=$font SIZE=$size>$text</FONT>";
} elsif ($font) {
return "<FONT FACE=$font>$text</FONT>";
} elsif ($size) {
return "<FONT SIZE=$size>$text</FONT>";
} else {
return $text;
}
}
sub print_day_header {
local ($dheader, $small) = @_;
if ($small) {
$dheader = &format_font($dheader, $Options{'fs'}, -2);
} else {
$dheader = &format_font($dheader, $Options{'fh'}, $Options{'sh'});
}
print " <TH WIDTH=14%>$dheader</TH>\n";
}

View File

@@ -8,11 +8,11 @@ set now now()
banner % banner %
MSG <HEAD>% MSG <HEAD>%
MSG <TITLE>Sunrise in Ottawa</TITLE>% MSG <TITLE>Sunrise in [$Location]</TITLE>%
MSG </HEAD>% MSG </HEAD>%
MSG <BODY> MSG <BODY>
MSG <H1>Sunrise in Ottawa</H1> MSG <H1>Sunrise in [$Location]</H1>
set tod sunrise(today()) set tod sunrise(today())
set tom sunrise(today()+1) set tom sunrise(today()+1)
@@ -34,7 +34,7 @@ set fn iif(diff==0, "now", diff <0, "ago", "from now")
set iw iif(diff<0, "was", "is") set iw iif(diff<0, "was", "is")
set aw iif(tod==tom, " as well.", ".") set aw iif(tod==tom, " as well.", ".")
msg Today is %w, %d %m, %y.<P> msg Today is %w, %d %m, %y.<P>
msg The local time in Ottawa is [now].<P> msg The local time in [$Location] is [now].<P>
msg Sunrise today [iw] at [tod]; in other words, [hstr][astr][mstr] [fn].<P> msg Sunrise today [iw] at [tod]; in other words, [hstr][astr][mstr] [fn].<P>
msg Sunrise tomorrow is at [tom][aw]<P> msg Sunrise tomorrow is at [tom][aw]<P>
msg The daylight portion of tomorrow will be [slen] today.<P> msg The daylight portion of tomorrow will be [slen] today.<P>

View File

@@ -9,11 +9,11 @@ set now now()
banner % banner %
MSG <HEAD>% MSG <HEAD>%
MSG <TITLE>Sunset in Ottawa</TITLE>% MSG <TITLE>Sunset in [$Location]</TITLE>%
MSG </HEAD>% MSG </HEAD>%
MSG <BODY> MSG <BODY>
MSG <H1>Sunset in Ottawa</H1> MSG <H1>Sunset in [$Location]</H1>
set tod sunset(today()) set tod sunset(today())
set tom sunset(today()+1) set tom sunset(today()+1)
@@ -35,7 +35,7 @@ set fn iif(diff==0, "now", diff <0, "ago", "from now")
set iw iif(diff<0, "was", "is") set iw iif(diff<0, "was", "is")
set aw iif(tod==tom, " as well.", ".") set aw iif(tod==tom, " as well.", ".")
msg Today is %w, %d %m, %y.<P> msg Today is %w, %d %m, %y.<P>
msg The local time in Ottawa is [now].<P> msg The local time in [$Location] is [now].<P>
msg Sunset today [iw] at [tod]; in other words, [hstr][astr][mstr] [fn].<P> msg Sunset today [iw] at [tod]; in other words, [hstr][astr][mstr] [fn].<P>
msg Sunset tomorrow is at [tom][aw]<P> msg Sunset tomorrow is at [tom][aw]<P>
msg The daylight portion of tomorrow will be [slen] today.<P> msg The daylight portion of tomorrow will be [slen] today.<P>