mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 23:08:40 +02:00
Compare commits
155 Commits
03.03.01-B
...
03.03.09
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3297fe751 | ||
|
|
58ca741a1c | ||
|
|
14dbbc7bb4 | ||
|
|
df55c4032b | ||
|
|
3768155a20 | ||
|
|
2f3b9cadf4 | ||
|
|
2c79a6531a | ||
|
|
be5c856f4b | ||
|
|
712a333f08 | ||
|
|
b753e84c8c | ||
|
|
4b4acaadbb | ||
|
|
8a52f9b67d | ||
|
|
e372606281 | ||
|
|
c443d0a9da | ||
|
|
42c9ae9ea8 | ||
|
|
dac9bb4187 | ||
|
|
812d926f66 | ||
|
|
45831ea69f | ||
|
|
354e1d236b | ||
|
|
ac478039cf | ||
|
|
96f5799e6f | ||
|
|
e21479f696 | ||
|
|
25dc883e15 | ||
|
|
bfb1374ee3 | ||
|
|
cacd8f9792 | ||
|
|
3e9053a3c6 | ||
|
|
5fa357fec2 | ||
|
|
f109c3d696 | ||
|
|
b097ce7279 | ||
|
|
1297854935 | ||
|
|
0a1d0011f6 | ||
|
|
20db1be0a0 | ||
|
|
143f1d6144 | ||
|
|
358f6c9497 | ||
|
|
ca26544be8 | ||
|
|
5ceffddd5b | ||
|
|
8e3ddb96b3 | ||
|
|
377de36b35 | ||
|
|
4395e2f7ed | ||
|
|
1d0cc31b10 | ||
|
|
4b4b2ddcd4 | ||
|
|
3c9b5b786e | ||
|
|
08f1bea6ce | ||
|
|
a2cc5943e0 | ||
|
|
895ac6f0f7 | ||
|
|
759ca0253e | ||
|
|
0ca368c8d9 | ||
|
|
a467cc1b84 | ||
|
|
c65fd826a5 | ||
|
|
bd6f4e1b43 | ||
|
|
169520914f | ||
|
|
a163a0c446 | ||
|
|
295aeb0ed8 | ||
|
|
9b2fdad56c | ||
|
|
7a1184d3c5 | ||
|
|
b036244316 | ||
|
|
5ad5366e8a | ||
|
|
244677e524 | ||
|
|
f5a094a973 | ||
|
|
5681ebdb12 | ||
|
|
664fa5f08f | ||
|
|
14edec5eae | ||
|
|
6adfd2e739 | ||
|
|
34409f7a7d | ||
|
|
7e13d1052c | ||
|
|
eb1998c888 | ||
|
|
543252cbaf | ||
|
|
6df7c59876 | ||
|
|
f780e0afc3 | ||
|
|
310e8d3287 | ||
|
|
ba51bdf258 | ||
|
|
ef88b844fb | ||
|
|
67b96b0a26 | ||
|
|
562da30fb5 | ||
|
|
21175e8cf6 | ||
|
|
80d01f7158 | ||
|
|
90cac447e4 | ||
|
|
04bf5b0a8b | ||
|
|
d667c15b25 | ||
|
|
2123bf4b18 | ||
|
|
429a64f29e | ||
|
|
f39381dd6c | ||
|
|
0a9eb07f6f | ||
|
|
9c287e3fd7 | ||
|
|
cce4b2cb14 | ||
|
|
e49d9f8ab6 | ||
|
|
48cbeb28f4 | ||
|
|
57d5c54559 | ||
|
|
3b2260f67e | ||
|
|
d423a62327 | ||
|
|
ac8da00030 | ||
|
|
77eb7fb99d | ||
|
|
a751149dd3 | ||
|
|
69d45618c6 | ||
|
|
22fa1a28e5 | ||
|
|
f4cc233009 | ||
|
|
1d6e4edd0f | ||
|
|
daffa8cba0 | ||
|
|
2e161a1bc1 | ||
|
|
204bb00060 | ||
|
|
d6029a54aa | ||
|
|
f99b5c5a66 | ||
|
|
2df4119c1a | ||
|
|
d06b4e5dcd | ||
|
|
bf8a25137d | ||
|
|
0f302ad0fc | ||
|
|
e3d6b283c5 | ||
|
|
2e3ed09039 | ||
|
|
37971a3f07 | ||
|
|
2a1960f257 | ||
|
|
350564c304 | ||
|
|
9e2a9fea37 | ||
|
|
3592b43629 | ||
|
|
becf1fc459 | ||
|
|
2bccd058ed | ||
|
|
12c6621051 | ||
|
|
504bc6a875 | ||
|
|
9cfdd0b53f | ||
|
|
d59024f399 | ||
|
|
24e0178d1a | ||
|
|
1ede5775f2 | ||
|
|
a5c9b07052 | ||
|
|
22353d4833 | ||
|
|
7499ada891 | ||
|
|
3f0a4e5c39 | ||
|
|
b8d6472974 | ||
|
|
6358297724 | ||
|
|
4f6dcde980 | ||
|
|
8a7985c48e | ||
|
|
4ddbe54e55 | ||
|
|
ef0bf73a29 | ||
|
|
beda9014d8 | ||
|
|
498a429b2c | ||
|
|
6aa2aa0fb3 | ||
|
|
1bef88fccd | ||
|
|
8308068067 | ||
|
|
8385c7f1b0 | ||
|
|
0537d02fef | ||
|
|
c33a1a3b0b | ||
|
|
fd39999128 | ||
|
|
0aa40094fa | ||
|
|
e3bbbe07be | ||
|
|
5633798d33 | ||
|
|
0e7e1b1b75 | ||
|
|
4d3790bc1a | ||
|
|
2002c7f1f8 | ||
|
|
1be14e99a2 | ||
|
|
78efdaf85f | ||
|
|
0e98a1c656 | ||
|
|
7aa483e201 | ||
|
|
a6dbf05af4 | ||
|
|
8ab78fd8be | ||
|
|
4f119031a4 | ||
|
|
19bdd6c2db | ||
|
|
f1557b8243 |
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,16 +1,17 @@
|
|||||||
*.bak
|
*.bak
|
||||||
|
*.o
|
||||||
|
*~
|
||||||
|
.gitignore
|
||||||
|
TAGS
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
src/Makefile
|
rem2html/Makefile
|
||||||
www/Makefile
|
|
||||||
*.o
|
|
||||||
src/config.h
|
|
||||||
src/remind
|
|
||||||
src/*.tar.gz*
|
src/*.tar.gz*
|
||||||
tests/test.out
|
src/Makefile
|
||||||
.gitignore
|
src/config.h
|
||||||
*~
|
|
||||||
src/rem2ps
|
src/rem2ps
|
||||||
|
src/remind
|
||||||
src/version.h
|
src/version.h
|
||||||
TAGS
|
tests/test.out
|
||||||
|
www/Makefile
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
|||||||
1. REMIND refers to the entire set of files and documentation in the
|
1. REMIND refers to the entire set of files and documentation in the
|
||||||
REMIND package.
|
REMIND package.
|
||||||
|
|
||||||
2. REMIND is Copyright 1992-2020 Dianne Skoll, except where noted in
|
2. REMIND is Copyright 1992-2021 Dianne Skoll, except where noted in
|
||||||
individual files.
|
individual files.
|
||||||
|
|
||||||
3. DISTRIBUTION AND USE
|
3. DISTRIBUTION AND USE
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -18,7 +18,8 @@ install:
|
|||||||
@echo "* *"
|
@echo "* *"
|
||||||
@echo "*********************"
|
@echo "*********************"
|
||||||
@echo ""
|
@echo ""
|
||||||
@cd src && $(MAKE) install
|
@$(MAKE) -C src install
|
||||||
|
@$(MAKE) -C rem2html install
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name '*~' -exec rm {} \;
|
find . -name '*~' -exec rm {} \;
|
||||||
|
|||||||
49
configure
vendored
49
configure
vendored
@@ -626,6 +626,7 @@ VERSION
|
|||||||
EGREP
|
EGREP
|
||||||
GREP
|
GREP
|
||||||
CPP
|
CPP
|
||||||
|
PERL
|
||||||
SET_MAKE
|
SET_MAKE
|
||||||
LN_S
|
LN_S
|
||||||
INSTALL_DATA
|
INSTALL_DATA
|
||||||
@@ -3274,6 +3275,46 @@ $as_echo "no" >&6; }
|
|||||||
SET_MAKE="MAKE=${MAKE-make}"
|
SET_MAKE="MAKE=${MAKE-make}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Extract the first word of "perl", so it can be a program name with args.
|
||||||
|
set dummy perl; ac_word=$2
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||||
|
$as_echo_n "checking for $ac_word... " >&6; }
|
||||||
|
if ${ac_cv_path_PERL+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
case $PERL in
|
||||||
|
[\\/]* | ?:[\\/]*)
|
||||||
|
ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||||
|
for as_dir in $PATH
|
||||||
|
do
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
test -z "$as_dir" && as_dir=.
|
||||||
|
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||||
|
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||||
|
ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
PERL=$ac_cv_path_PERL
|
||||||
|
if test -n "$PERL"; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
|
||||||
|
$as_echo "$PERL" >&6; }
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3820,7 +3861,7 @@ _ACEOF
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_header in sys/file.h glob.h wctype.h locale.h
|
for ac_header in sys/types.h sys/file.h glob.h wctype.h locale.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
@@ -3991,9 +4032,10 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
VERSION=03.03.01
|
VERSION=03.03.09
|
||||||
|
|
||||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
|
||||||
|
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile"
|
||||||
|
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
# This file is a shell script that caches the results of configure
|
# This file is a shell script that caches the results of configure
|
||||||
@@ -4689,6 +4731,7 @@ do
|
|||||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||||
"www/Makefile") CONFIG_FILES="$CONFIG_FILES www/Makefile" ;;
|
"www/Makefile") CONFIG_FILES="$CONFIG_FILES www/Makefile" ;;
|
||||||
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
|
"src/version.h") CONFIG_FILES="$CONFIG_FILES src/version.h" ;;
|
||||||
|
"rem2html/Makefile") CONFIG_FILES="$CONFIG_FILES rem2html/Makefile" ;;
|
||||||
|
|
||||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ AC_PROG_CC
|
|||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_LN_S
|
AC_PROG_LN_S
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PATH_PROG([PERL], [perl])
|
||||||
|
|
||||||
dnl Checks for libraries.
|
dnl Checks for libraries.
|
||||||
dnl Replace `main' with a function in -lm:
|
dnl Replace `main' with a function in -lm:
|
||||||
@@ -61,7 +62,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 glob.h wctype.h locale.h)
|
AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
@@ -75,6 +76,7 @@ if test "$GCC" = yes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||||
VERSION=03.03.01
|
VERSION=03.03.09
|
||||||
AC_SUBST(VERSION)
|
AC_SUBST(VERSION)
|
||||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
AC_SUBST(PERL)
|
||||||
|
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile)
|
||||||
|
|||||||
154
docs/WHATSNEW
154
docs/WHATSNEW
@@ -1,16 +1,154 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
* VERSION 3.3 Patch 1 - 2020-XX-XX
|
* VERSION 3.3 Patch 9 - 2021-10-14
|
||||||
|
|
||||||
|
- NEW FEATURE: Add "-+username" option to tell Remind to trust files owned by
|
||||||
|
"username" and allow RUN directives in them. Idea courtesy of Ian! D. Allen
|
||||||
|
|
||||||
|
- NEW FEATURE: Add "-u+username" variant to tell Remind to switch users to
|
||||||
|
"username" without disabling RUN directices. Idea courtesy of Ian! D. Allen
|
||||||
|
|
||||||
|
- CHANGE: rem2html: rem2html has been moved out of the www/ directory into
|
||||||
|
its own rem2html/ directory. If your system has the prerequisites
|
||||||
|
(namely Perl, Getopt::Long and JSON::Any) then rem2html will be installed
|
||||||
|
by "make install".
|
||||||
|
|
||||||
|
- CHANGE: Remove "cm2rem". It was about 20 years obsolete.
|
||||||
|
|
||||||
|
- CHANGE: rem2html: Use inline data: URL images for moon images by default,
|
||||||
|
thus producing a completely stand-alone HTML file.
|
||||||
|
|
||||||
|
- CHANGE: Remove unnecessary spaces from "remind -pp" JSON output.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Various man page fixes and tweaks.
|
||||||
|
|
||||||
|
- BUG FIX: rem2html: Tweak the default CSS stylesheet; more rational
|
||||||
|
handling of rem2html command-line options.
|
||||||
|
|
||||||
|
- BUG FIX: remind: "remind -c" would sometimes highlight *two* days as
|
||||||
|
"today"; this has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: Add a missing #ifdef...#endif and remove a C99-ism. This once again
|
||||||
|
allows Remind to be compiled with some very old C compilers.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 8 - 2021-09-13
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add INCLUDECMD command
|
||||||
|
|
||||||
|
- NEW FEATURE: remind: Add shellescape() built-in function
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: TkRemind would sometimes fill in incorrect initial
|
||||||
|
values for the reminder-editing form if you clicked on a TkRemind-created
|
||||||
|
reminder to edit it. This has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: Get back better error messages from Remind if you
|
||||||
|
try to create a reminder with an invalid date specification.
|
||||||
|
|
||||||
|
- BUG FIX: remind: Catch integer overflow if we try to evaluate $IntMin * -1
|
||||||
|
|
||||||
|
- DOC UPDATES: remind: Minor man page fixes
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 7 - 2021-05-10
|
||||||
|
|
||||||
|
- MINOR FIX: Refuse to run "make test" as root --- it would fail
|
||||||
|
anyway with an obscure message.
|
||||||
|
|
||||||
|
- BUG FIX: Remind would sometimes compute incorrect trigger date for:
|
||||||
|
REM Tue 29 Feb MSG ...
|
||||||
|
|
||||||
|
- BUG FIX: Remind would sometimes compute incorrect trigger date for
|
||||||
|
a date spec like: Tue 31 2021 MSG ...
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 6 - 2021-03-30
|
||||||
|
|
||||||
|
- test/test.rem: Change local to en_US.utf-8 only if current locale
|
||||||
|
is not a UTF-8 locale.
|
||||||
|
|
||||||
|
- MINOR CHANGE: Remind's arithemtic operators (+, -, *, /) give errors
|
||||||
|
on overflow rather than silently giving the wrong answer.
|
||||||
|
|
||||||
|
- MINOR CHANGE: Add $IntMin and $IntMax system variables.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Document that TkRemind now requires Tcl/Tk version
|
||||||
|
8.5 or newer.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 5 - 2021-01-21
|
||||||
|
|
||||||
|
- NEW FEATURE: tkremind: Add ability to change fonts and colors from
|
||||||
|
within TkRemind "Options" dialog.
|
||||||
|
|
||||||
|
- CHANGE: tkremind: TkRemind now requires Tcl/Tk 8.5 or newer.
|
||||||
|
|
||||||
|
- CHANGE: tkremind: You can specify the location of the options
|
||||||
|
file on the command-line if you want to use one other than ~/.tkremindrc
|
||||||
|
|
||||||
|
- CLEANUP: tkremind: Remove "Apply Options" from Options dialog; we only
|
||||||
|
need "Save Options".
|
||||||
|
|
||||||
|
- DOC FIX: Add missing release note in 3.3.4 notes regarding
|
||||||
|
setpagedevice patch
|
||||||
|
|
||||||
|
- DOC FIX: tkremind: Document shortcut keys.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 4 - 2021-01-12
|
||||||
|
|
||||||
|
- NEW FEATURE: If "inotifywait" is installed, TkRemind uses it to refresh
|
||||||
|
the calendar display right away when the reminders file/directory is updated.
|
||||||
|
This makes TkRemind react almost instantly if external tools are editing
|
||||||
|
or updating reminders.
|
||||||
|
|
||||||
|
- MINOR NEW FEATURE: rem2ps has a new '-x' option; this puts the day numbers
|
||||||
|
on the top-left of the day's box instead of the top-right.
|
||||||
|
|
||||||
|
- MINOR FIXES: A typo in remind.1 was fixed; additional comments regarding
|
||||||
|
UNTIL were added.
|
||||||
|
|
||||||
|
- BUG FIX: rem2ps: Call setpagedevice to set page size. Based on a patch
|
||||||
|
from Jonathan Kamens.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 3 - 2020-11-09
|
||||||
|
|
||||||
|
- BUG FIX: Fix startup crash in TkRemind if "Show Today's Reminders on
|
||||||
|
Startup" is enabled (which, unfortunately, is the default.) Bug reported
|
||||||
|
by Martin Ziemer.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 2 - 2020-11-08
|
||||||
|
|
||||||
|
- MINOR NEW FEATURE: Add MAYBE-UNCOMPUTABLE keyword; see the man page
|
||||||
|
and discussion at
|
||||||
|
https://dianne.skoll.ca/pipermail/remind-fans/2020/003745.html
|
||||||
|
|
||||||
|
- CHANGE: TkRemind always invokes Remind with the "-itkremind=1" option,
|
||||||
|
even when printing. NOTE INCOMPATIBILITY: This is a behavior change!
|
||||||
|
When you print from TkRemind, we also invoke Remind with "-itkprint=1"
|
||||||
|
so you can detect that PostScript is being generated.
|
||||||
|
|
||||||
|
- CHANGE: The maxmimum length of a variable name has been increased from
|
||||||
|
16 characters to 64 characters. Modern computers have plenty of memory.
|
||||||
|
|
||||||
|
- BUG FIXES: Minor documentation updates, typo fixes, clarifications, etc.
|
||||||
|
|
||||||
|
- BUG FIX: Fix calendar-drawing alignment errors when displaying UTF-8
|
||||||
|
strings with zero-width combining characters and strings with tabs.
|
||||||
|
|
||||||
|
- BUG FIX: TkRemind would mess up placement of the WEEK special if invoked
|
||||||
|
with the "-m" option. This has been fixed.
|
||||||
|
|
||||||
|
- BUG FIX: TkRemind would sometimes fail with an error message when editing
|
||||||
|
a reminder; this is because it was interpreting months 08 and 09 as
|
||||||
|
illegal octal numbers. This has been fixed.
|
||||||
|
|
||||||
|
* VERSION 3.3 Patch 1 - 2020-03-20
|
||||||
|
|
||||||
- CHANGE: For overlapping multi-day events, issue a reminder for the
|
- CHANGE: For overlapping multi-day events, issue a reminder for the
|
||||||
most *recent* event rather than the earliest event. NOTE INCOMPATIBILITY:
|
most *recent* event rather than the earliest event. NOTE
|
||||||
This is a behavior change!
|
INCOMPATIBILITY: This is a behavior change!
|
||||||
|
|
||||||
- CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to recognize
|
- CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to
|
||||||
years. NOTE INCOMPATIBILITY: This is a behavior change!
|
recognize years. NOTE INCOMPATIBILITY: This is a behavior change!
|
||||||
|
|
||||||
- CHANGE: Revert change to -y option that included filename and line number
|
- CHANGE: Revert change to -y option that included filename and line
|
||||||
in the hash.
|
number in the hash.
|
||||||
|
|
||||||
- CHANGE: Retain newlines (produced by %_) in JSON output.
|
- CHANGE: Retain newlines (produced by %_) in JSON output.
|
||||||
|
|
||||||
@@ -18,6 +156,8 @@ CHANGES TO REMIND
|
|||||||
|
|
||||||
- FIX: Highlight today's date in "remind -c" output
|
- FIX: Highlight today's date in "remind -c" output
|
||||||
|
|
||||||
|
- FIX: Eliminate compiler warnings on Ubuntu 18.04.
|
||||||
|
|
||||||
- IMPROVEMENT: Allow times to be specified either in 24-hour mode
|
- IMPROVEMENT: Allow times to be specified either in 24-hour mode
|
||||||
(HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.)
|
(HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.)
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ RUN OFF
|
|||||||
################################################
|
################################################
|
||||||
# Ensure required version of remind is used... #
|
# Ensure required version of remind is used... #
|
||||||
################################################
|
################################################
|
||||||
IF version() < "03.01.08"
|
IF version() < "03.01.09"
|
||||||
ERRMSG This file requires at least version 03.01.08 of Remind.%
|
ERRMSG This file requires at least version 03.01.09 of Remind.%
|
||||||
ERRMSG This version is version [version()].
|
ERRMSG This version is version [version()].
|
||||||
EXIT
|
EXIT
|
||||||
ENDIF
|
ENDIF
|
||||||
@@ -84,7 +84,6 @@ SET December 12
|
|||||||
###########################################################
|
###########################################################
|
||||||
# Other symbolic constants and functions for "pasting"... #
|
# Other symbolic constants and functions for "pasting"... #
|
||||||
###########################################################
|
###########################################################
|
||||||
|
|
||||||
SET Quote CHAR(34)
|
SET Quote CHAR(34)
|
||||||
|
|
||||||
# Handy constants/function for specifing week of month...
|
# Handy constants/function for specifing week of month...
|
||||||
@@ -95,29 +94,17 @@ SET Week_4 22
|
|||||||
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
|
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
|
||||||
|
|
||||||
# Handy function to provide SCANFROM dates...
|
# Handy function to provide SCANFROM dates...
|
||||||
FSET _back(days) TODAY()-days
|
FSET _back(days) $U-days
|
||||||
|
|
||||||
###########################################################
|
|
||||||
# Function which returns a string in "am/pm" format based #
|
|
||||||
# on the time. For example, set a am_pm(NOW())... #
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
FSET _am_pm(tm) IIF(tm<01:00, tm+12*60+"am", \
|
|
||||||
tm<12:00, tm+"am", \
|
|
||||||
tm<13:00, tm+"pm", \
|
|
||||||
tm-12*60+"pm")
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Function which removes a single leading zero from a string... #
|
# Function that removes a single leading zero from a string... #
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
||||||
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
|
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# Return the length of the daylight/night portion of a date, #
|
# Return the length of the daylight/night portion of a date, #
|
||||||
# in minutes. #
|
# in minutes. #
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
||||||
FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0)
|
FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0)
|
||||||
FSET _dark_len(date) 1440-_light_len(date)
|
FSET _dark_len(date) 1440-_light_len(date)
|
||||||
|
|
||||||
@@ -125,26 +112,12 @@ FSET _dark_len(date) 1440-_light_len(date)
|
|||||||
# Function to calculate number of years since a given year #
|
# Function to calculate number of years since a given year #
|
||||||
# or number of months since a given month and year... #
|
# or number of months since a given month and year... #
|
||||||
############################################################
|
############################################################
|
||||||
|
FSET _yr_num(yr) ORD($Ty - yr)
|
||||||
FSET _yr_num(yr) ORD(YEAR(TRIGDATE()) - yr)
|
FSET _mo_num(mo, yr) ORD(12 * ($Ty - yr) + $Tm - mo)
|
||||||
FSET _mo_num(mo, yr) ORD(12 * (YEAR(TRIGDATE()) - yr) + \
|
|
||||||
MONNUM(TRIGDATE()) - mo)
|
|
||||||
|
|
||||||
# Here's an example of how to use them:
|
# Here's an example of how to use them:
|
||||||
REM 1 Nov ++12 MSG %"Dean's [_yr_num(1984)] birthday%" is %b.
|
REM 1 Nov ++12 MSG %"John's [_yr_num(1984)] birthday%" is %b.
|
||||||
REM 1 MSG Dean's [_mo_num(11, 1984)] 'monthly' anniversary
|
REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
|
||||||
|
|
||||||
###########################################################
|
|
||||||
# Function to send mail via elm's "fastmail" (by GMS!)... #
|
|
||||||
###########################################################
|
|
||||||
|
|
||||||
#FSET _mail(from, subj) "mailx -s " + \
|
|
||||||
# Quote + from + " : " + subj + Quote \
|
|
||||||
# GETENV("LOGNAME") + " < /dev/null 1>&0"
|
|
||||||
FSET _mail(from, subj) "fastmail -f " + \
|
|
||||||
Quote + from + Quote + \
|
|
||||||
" -s " + Quote + subj + Quote + \
|
|
||||||
" /dev/null " + GETENV("LOGNAME")
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Here's a tricky problem: The 4th of July is a holiday in the U.S.
|
# Here's a tricky problem: The 4th of July is a holiday in the U.S.
|
||||||
@@ -158,29 +131,28 @@ FSET _mail(from, subj) "fastmail -f " + \
|
|||||||
# dependent upon the current date, it's tricky and results may not be
|
# dependent upon the current date, it's tricky and results may not be
|
||||||
# what you expect. You should try to make sure that the OMIT context
|
# what you expect. You should try to make sure that the OMIT context
|
||||||
# "near" any current reminders will not change during a calendar run.
|
# "near" any current reminders will not change during a calendar run.
|
||||||
# The SCANFROM clause should help make these OMITs very safe.
|
# The SCANFROM clause will make these OMITs safe.
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
# Calculate the weekday of the holiday.
|
# Calculate the weekday of the holiday.
|
||||||
REM 4 July SCANFROM [_back(7)] SATISFY 1
|
REM 4 July SCANFROM [_back(7)] SATISFY 1
|
||||||
|
|
||||||
IF WKDAYNUM(TRIGDATE()) == Sat
|
SET iday $T
|
||||||
REM [TRIGDATE()] MSG Independence day (actual)
|
IF WKDAYNUM(iday) == Sat
|
||||||
OMIT [TRIGDATE()-1] MSG Independence day (observed)
|
REM [iday] MSG Independence day (actual)
|
||||||
|
OMIT [iday-1] MSG Independence day (observed)
|
||||||
ELSE
|
ELSE
|
||||||
IF WKDAYNUM(TRIGDATE()) == Sun
|
IF WKDAYNUM(iday) == Sun
|
||||||
REM [TRIGDATE()] MSG Independence day (actual)
|
REM [iday] MSG Independence day (actual)
|
||||||
OMIT [TRIGDATE()+1] MSG Independence day (observed)
|
OMIT [iday+1] MSG Independence day (observed)
|
||||||
ELSE
|
ELSE
|
||||||
OMIT [TRIGDATE()] MSG Independence day
|
OMIT [iday] MSG Independence day
|
||||||
ENDIF
|
ENDIF
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
# #
|
|
||||||
# A meeting on the first Monday of every month which is moved to the #
|
# A meeting on the first Monday of every month which is moved to the #
|
||||||
# second Monday in the event of a holiday. #
|
# second Monday in the event of a holiday. #
|
||||||
# #
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
# First, the normal meeting. However, the SKIP keyword means this
|
# First, the normal meeting. However, the SKIP keyword means this
|
||||||
@@ -192,68 +164,21 @@ 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($T-7)
|
||||||
REM [TRIGDATE()] MSG Delayed meeting
|
REM [$T] MSG Delayed meeting
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
############################################################################
|
|
||||||
# #
|
|
||||||
# A very complicated reminder sent in by a Remind user. #
|
|
||||||
# This person gets paid every two weeks, starting from 8 January 1993. #
|
|
||||||
# If a pay date occurs before the twelfth of a month, then that #
|
|
||||||
# he pays his mortgage on that pay date. Otherwise, he pays the mortgage #
|
|
||||||
# on the previous pay date. Furthermore, he has to schedule his #
|
|
||||||
# mortgage payment six days before it is due. He wants to be reminded #
|
|
||||||
# a further four days before the scheduling deadline. He also #
|
|
||||||
# wants to be mailed a notice two weeks before the scheduling deadline. #
|
|
||||||
# #
|
|
||||||
# Here's the solution - if you can follow this, consider yourself a #
|
|
||||||
# Remind programmer extraordinaire! #
|
|
||||||
# #
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
# A function to determine whether or not a pay-date is a mortgage-date.
|
|
||||||
|
|
||||||
FSET _IsMortDate(x) DAY(x) < 12 || (DAY(x+14) >= 12 && DAY(x+14) <= 14)
|
|
||||||
|
|
||||||
# Paydays - for reference
|
|
||||||
|
|
||||||
REM 8 Jan 1993 *14 MSG Payday
|
|
||||||
|
|
||||||
# Calculate the mortgage payment six days ahead of time. Note that this
|
|
||||||
# is done "implicitly" by subtracting 6 from the starting date - we start
|
|
||||||
# on 2 Jan rather than 8 Jan. We add 6 to TRIGDATE() in _IsMortDate to
|
|
||||||
# compensate.
|
|
||||||
|
|
||||||
REM 2 Jan 1993 *14 ++4 SATISFY [_IsMortDate(TRIGDATE()+6)] \
|
|
||||||
MSG %"Schedule mortgage payment%" for %a.
|
|
||||||
|
|
||||||
# Now the mail reminder two weeks before the payment date - because two
|
|
||||||
# weeks before a payment date is also a payment date, no pre-compensation
|
|
||||||
# in the starting date of 8 Jan is necessary - convince yourself of this!
|
|
||||||
# This uses the _mail() function defined earlier.
|
|
||||||
|
|
||||||
REM ONCE 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE()+14)] \
|
|
||||||
RUN [_mail("Decatur Federal", \
|
|
||||||
"Pay mortgage by the " + ORD(DAY(TRIGDATE()+14)))]
|
|
||||||
|
|
||||||
# Make an entry on the calendar when the mortgage should be paid
|
|
||||||
|
|
||||||
REM 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE())] \
|
|
||||||
CAL Mortgage payment
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# #
|
# #
|
||||||
# On our UNIX system, I run a program which queries the university #
|
# On our UNIX system, I run a program that queries the university #
|
||||||
# library and creates a file called ".booksdue". This file is #
|
# library and creates a file called ".booksdue". This file is #
|
||||||
# a REMIND script to tell me when my library books are due. Here's #
|
# a REMIND script to tell me when my library books are due. Here's #
|
||||||
# an example from my reminder file - it shows the use of filedate(). #
|
# an example from my reminder file - it shows the use of filedate(). #
|
||||||
# When the .booksdue file is at least 7 days old, I create a new version #
|
# When the .booksdue file is at least 7 days old, I create a new version #
|
||||||
# by querying the library computer. Note the use of realtoday() rather #
|
# by querying the library computer. Note the use of realtoday() rather #
|
||||||
# than today. #
|
# than today(). #
|
||||||
# #
|
# #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
IF !$RunOff && !$CalMode && !$SimpleCal
|
IF !$RunOff && !$CalMode && !$SimpleCal
|
||||||
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
|
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
|
||||||
REM RUN /home/dfs/bilge/library/getbooks
|
REM RUN /home/dfs/bilge/library/getbooks
|
||||||
@@ -283,7 +208,7 @@ REM Sat Sun SPECIAL SHADE 220
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
SET SaveTrig $NumTrig
|
SET SaveTrig $NumTrig
|
||||||
SET easter EASTERDATE(YEAR(TODAY()))
|
SET easter EASTERDATE($Uy)
|
||||||
REM [easter-46] MSG %"Ash Wednesday%"
|
REM [easter-46] MSG %"Ash Wednesday%"
|
||||||
REM [easter-7] MSG %"Palm Sunday%"
|
REM [easter-7] MSG %"Palm Sunday%"
|
||||||
OMIT [easter-2] MSG %"Good Friday%"
|
OMIT [easter-2] MSG %"Good Friday%"
|
||||||
@@ -301,7 +226,7 @@ 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 [trigdate()] MSG %"President's Day%"
|
OMIT [$T] MSG %"President's Day%"
|
||||||
REM Mar 17 MSG %"St. Patrick's%" Day
|
REM Mar 17 MSG %"St. Patrick's%" Day
|
||||||
|
|
||||||
# The DST rules are accurate for most locations in
|
# The DST rules are accurate for most locations in
|
||||||
@@ -319,23 +244,23 @@ 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 [trigdate()] MSG %"Memorial Day%"
|
OMIT [$T] 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 [trigdate()] MSG %"Labor Day%"
|
OMIT [$T] 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 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 [($Ty % 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 [trigdate()] MSG %"Thanksgiving%" Day
|
OMIT [$T] 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 [trigdate()] MSG %"Thanksgiving%" (cont.)
|
OMIT [$T] 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
|
||||||
|
|
||||||
@@ -350,13 +275,6 @@ if $NumTrig > SaveTrig
|
|||||||
REM SPECIAL SHADE 220
|
REM SPECIAL SHADE 220
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Seasons (valid from 1992 to 2000)...
|
|
||||||
REM Mar 20 MSG %"Spring%" begins
|
|
||||||
REM Jun [IIF(YEAR(TODAY())%4, 21, 20)] MSG %"Summer%" begins
|
|
||||||
REM Sep [CHOOSE(YEAR(TODAY())-1991, 22,22,23,23,22,22,22,23,22)] \
|
|
||||||
MSG %"Fall%" begins
|
|
||||||
REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
|
|
||||||
|
|
||||||
#PSSTUFF2
|
#PSSTUFF2
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# #
|
# #
|
||||||
@@ -370,7 +288,7 @@ REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
|
|||||||
# example, I recommend that you use the -sd 10 option for Rem2PS.
|
# example, I recommend that you use the -sd 10 option for Rem2PS.
|
||||||
REM PS Border Border moveto \
|
REM PS Border Border moveto \
|
||||||
/DayFont findfont DaySize scalefont setfont \
|
/DayFont findfont DaySize scalefont setfont \
|
||||||
([hebday(today())] [hebmon(today())]) show
|
([hebday($U)] [hebmon($U)]) show
|
||||||
|
|
||||||
# Fill in the phases of the moon on the PostScript calendar
|
# Fill in the phases of the moon on the PostScript calendar
|
||||||
[moondate(0)] SPECIAL MOON 0
|
[moondate(0)] SPECIAL MOON 0
|
||||||
@@ -382,7 +300,7 @@ REM PS Border Border moveto \
|
|||||||
# calendar - the sizes are hard-coded, however, and work best in landscape.
|
# calendar - the sizes are hard-coded, however, and work best in landscape.
|
||||||
REM PS Border Border 5 sub moveto \
|
REM PS Border Border 5 sub moveto \
|
||||||
/SmallFont findfont 4 scalefont setfont \
|
/SmallFont findfont 4 scalefont setfont \
|
||||||
(Sunrise: [sunrise(trigdate())] Sunset: [sunset(trigdate())]) show
|
(Sunrise: [sunrise($T)] Sunset: [sunset($T)]) show
|
||||||
|
|
||||||
# The next one puts the day number (1-366) and days left in the year at the
|
# The next one puts the day number (1-366) and days left in the year at the
|
||||||
# bottom of the post-script calendar. Again, the hard-coded sizes work best
|
# bottom of the post-script calendar. Again, the hard-coded sizes work best
|
||||||
@@ -390,7 +308,7 @@ REM PS Border Border 5 sub moveto \
|
|||||||
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
|
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
|
||||||
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
|
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
|
||||||
/SmallFont findfont 4 scalefont setfont \
|
/SmallFont findfont 4 scalefont setfont \
|
||||||
([_DayOfYear(today())]([365+isleap(today())-_DayOfYear(today())])) show
|
([_DayOfYear($U)]([365+isleap($U)-_DayOfYear($U)])) show
|
||||||
|
|
||||||
#JHOLS
|
#JHOLS
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -430,7 +348,7 @@ SET Reform 0
|
|||||||
|
|
||||||
# Convenient function definition to save typing
|
# Convenient function definition to save typing
|
||||||
FSET _h(x, y) 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, $U-7)
|
||||||
FSET _PastSat(x, y) 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) 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) 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)
|
||||||
@@ -464,7 +382,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) HEBDATE(24, "Kislev", today()-9)+x
|
FSET _chan(x) HEBDATE(24, "Kislev", $U-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%"
|
||||||
@@ -553,9 +471,9 @@ ENDIF
|
|||||||
# Counting the omer - do the whole spiel, i.e:
|
# Counting the omer - do the whole spiel, i.e:
|
||||||
# "This is the xth day of the omer, being y weeks and z days of the omer."
|
# "This is the xth day of the omer, being y weeks and z days of the omer."
|
||||||
# Nice Remind programming example here!
|
# Nice Remind programming example here!
|
||||||
SET ostart HEBDATE(16, "Nisan", TODAY()-50)
|
SET ostart HEBDATE(16, "Nisan", $U-50)
|
||||||
IF ostart <= TODAY() && (TODAY() - ostart < 49)
|
IF ostart <= $U && ($U - ostart < 49)
|
||||||
SET odays TODAY()-ostart+1
|
SET odays $U-ostart+1
|
||||||
IF odays < 7
|
IF odays < 7
|
||||||
MSG %"%"Today is the [ORD(odays)] day of the Omer.
|
MSG %"%"Today is the [ORD(odays)] day of the Omer.
|
||||||
ELSE
|
ELSE
|
||||||
@@ -573,8 +491,8 @@ ENDIF
|
|||||||
### for Friday and Saturday. Note: You must set your latitude, longitude
|
### for Friday and Saturday. Note: You must set your latitude, longitude
|
||||||
### and possibly time zone for these to work properly!
|
### and possibly time zone for these to work properly!
|
||||||
|
|
||||||
REM Friday CAL Candle lighting at [sunset(trigdate())-18]
|
REM Friday CAL Candle lighting at [sunset($T)-18]
|
||||||
REM Saturday CAL Havdalah at [sunset(trigdate())+42]
|
REM Saturday CAL Havdalah at [sunset($T)+42]
|
||||||
|
|
||||||
#COLORS
|
#COLORS
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|||||||
25
man/cm2rem.1
25
man/cm2rem.1
@@ -1,25 +0,0 @@
|
|||||||
.TH CM2REM 1 "18 October 1999"
|
|
||||||
.UC 4
|
|
||||||
.SH NAME
|
|
||||||
cm2rem.tcl \- Convert Sun's "cm" input file to Remind format
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B cm2rem.tcl < cm_file > remind_file
|
|
||||||
.SH DESCRIPTION
|
|
||||||
\fBcm2rem.tcl\fR reads the Sun calendar manager data file and converts
|
|
||||||
it into a \fBRemind\fR script. Note that \fBcm2rem.tcl\fR can convert
|
|
||||||
\fIonly\fR version 3 calendar manager files. If you are using version 4
|
|
||||||
files, there should be a system utility to convert them to version 3 files.
|
|
||||||
.SH AUTHOR
|
|
||||||
\fBcm2rem.tcl\fR was written by Dianne Skoll <dianne@skoll.ca>.
|
|
||||||
.SH BUGS
|
|
||||||
Not all of the Sun calendar manager options are respected. In particular,
|
|
||||||
nothing is done for e-mail actions. Also, the resulting Remind script
|
|
||||||
is not editable with \fBTkRemind\fR; you can only edit it with a text
|
|
||||||
editor.
|
|
||||||
.PP
|
|
||||||
\fBcm2rem.tcl\fR requires Tcl/Tk version 8.0 or higher. The
|
|
||||||
\fBtclsh\fR interpreter must be on your \fBpath\fR.
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
|
||||||
\fBremind(1)\fR, \fBtkremind(1)\fR
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH REM 1 "1 January 2020"
|
.TH REM 1 "1 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rem \- Invoke Remind with a default filename
|
rem \- Invoke Remind with a default filename
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.TH REM2PS 1 "1 January 2020"
|
.TH REM2PS 1 "5 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
rem2ps \- draw a PostScript calendar from Remind output
|
rem2ps \- draw a PostScript calendar from Remind output
|
||||||
@@ -29,6 +29,11 @@ include any document structuring comments in your prologue.
|
|||||||
Produce the calendar in landscape mode rather than the default
|
Produce the calendar in landscape mode rather than the default
|
||||||
portrait mode.
|
portrait mode.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-x
|
||||||
|
When printing the calendar, place the day numbers in the top-left of each
|
||||||
|
day's box. If this option is omitted, the day numbers appear in the
|
||||||
|
top-right.
|
||||||
|
.TP
|
||||||
\fB\-c\fR[\fIn\fR]
|
\fB\-c\fR[\fIn\fR]
|
||||||
If \fIn\fR is omitted, disables the small calendars for next and previous
|
If \fIn\fR is omitted, disables the small calendars for next and previous
|
||||||
months which are normally generated. If \fIn\fR is supplied, it can range
|
months which are normally generated. If \fIn\fR is supplied, it can range
|
||||||
@@ -470,7 +475,7 @@ present and the value will be the type of SPECIAL (such as SHADE, COLOR,
|
|||||||
MOON, etc.)
|
MOON, etc.)
|
||||||
.TP
|
.TP
|
||||||
.B tags \fIdata\fR
|
.B tags \fIdata\fR
|
||||||
If any TAG clauses are present, the \fBtag\fR key will be present and consist
|
If any TAG clauses are present, the \fBtags\fR key will be present and consist
|
||||||
of a comma-separated list of tags.
|
of a comma-separated list of tags.
|
||||||
.TP
|
.TP
|
||||||
.B time \fIt\fR
|
.B time \fIt\fR
|
||||||
|
|||||||
189
man/remind.1
189
man/remind.1
@@ -1,4 +1,4 @@
|
|||||||
.TH REMIND 1 "1 January 2020"
|
.TH REMIND 1 "1 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
remind \- a sophisticated reminder service
|
remind \- a sophisticated reminder service
|
||||||
@@ -26,12 +26,13 @@ Anything after the __EOF__ marker is completely ignored.
|
|||||||
|
|
||||||
.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".
|
||||||
.TP
|
.TP
|
||||||
.B \-n
|
.B \-n
|
||||||
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
|
||||||
of each reminder in a simple calendar format. You can sort this by
|
of each reminder in a simple calendar format. You can sort this by
|
||||||
date by piping the output through \fBsort(1)\fR.
|
date by piping the output through \fBsort(1)\fR. Note that the \fB\-n\fR
|
||||||
|
option causes any \fB\-g\fR option to be \fIignored\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-j\fR[\fIn\fR]
|
.B \-j\fR[\fIn\fR]
|
||||||
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
Runs \fBRemind\fR in "purge" mode to get rid of expired reminders.
|
||||||
@@ -39,7 +40,7 @@ See the section PURGE MODE for details.
|
|||||||
.TP
|
.TP
|
||||||
.B \-r
|
.B \-r
|
||||||
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.
|
||||||
.TP
|
.TP
|
||||||
.B \-c\fI[flags]\fIn\fR
|
.B \-c\fI[flags]\fIn\fR
|
||||||
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
||||||
@@ -248,8 +249,9 @@ encountered in the reminder script. The \fB\-g\fR option cause
|
|||||||
\fBRemind\fR to sort reminders by date and time prior to issuing them.
|
\fBRemind\fR to sort reminders by date and time prior to issuing them.
|
||||||
The optional \fBa\fR and \fBd\fR characters specify the sort order
|
The optional \fBa\fR and \fBd\fR characters specify the sort order
|
||||||
(ascending or descending) for the date, time and priority fields. See
|
(ascending or descending) for the date, time and priority fields. See
|
||||||
the section "Sorting Reminders" for more information.
|
the section "SORTING REMINDERS" for more information.
|
||||||
|
|
||||||
|
Note that \fB\-g\fR is \fIignored\fR if you use the \fB\-n\fR option.
|
||||||
.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
|
||||||
@@ -308,7 +310,11 @@ and user name, respectively, of the specified user. LOGNAME is also
|
|||||||
set to the specified user name. This option is meant for
|
set to the specified user name. This option is meant for
|
||||||
use in shell scripts that mail reminders to all users. Note that
|
use in shell scripts that mail reminders to all users. Note that
|
||||||
as of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR -- the RUN
|
as of Remind 3.00.17, using \fB\-u\fR implies \fB\-r\fR -- the RUN
|
||||||
directive and shell() functions are disabled.
|
directive and shell() functions are disabled. However, if you prefix
|
||||||
|
\fIname\fR with a \fB+\fR-sign, then RUN and shell() are \fInot\fR
|
||||||
|
disabled. That is, \fB\-uwhatever\fR switches the user to \fBwhatever\fR
|
||||||
|
and disables RUN, whereas \fB\-u+whatever\fR switches the user to
|
||||||
|
\fBwhatever\fR but leaves RUN enabled.
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
Non-root users can also use the \fB\-u\fR option. However, in this
|
Non-root users can also use the \fB\-u\fR option. However, in this
|
||||||
@@ -316,6 +322,13 @@ case, it only changes the environment variables as described above.
|
|||||||
It does not change the effective uid or gid.
|
It does not change the effective uid or gid.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-+\fIusername\fR
|
||||||
|
Causes \fBRemind\fR to trust files owned by the user \fIusername\fR.
|
||||||
|
Normally, if \fBRemind\fR reads a file that you do not own, it disables
|
||||||
|
RUN and the shell() function. This option causes it to also trust files
|
||||||
|
owned by \fIusername\fR. You can supply multiple \fB\-+\fR options
|
||||||
|
to trust multiple users, up to a limit of 20 trusted users.
|
||||||
|
.TP
|
||||||
\fB-y\fR
|
\fB-y\fR
|
||||||
Causes \fBRemind\fR to synthesize a tag for any reminder that lacks a
|
Causes \fBRemind\fR to synthesize a tag for any reminder that lacks a
|
||||||
TAG clause.
|
TAG clause.
|
||||||
@@ -323,7 +336,7 @@ TAG clause.
|
|||||||
\fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
|
\fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
|
||||||
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
|
.TP
|
||||||
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
|
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
|
||||||
Allows you to define a function on the command line.
|
Allows you to define a function on the command line.
|
||||||
@@ -349,10 +362,10 @@ 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.
|
time on the command line as one argument: YYYY-MM-DD@HH:MM.
|
||||||
.PP
|
.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 *\fIrep\fR. This causes \fBRemind\fR to be run \fIrep\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
|
||||||
the parameter in quotes to avoid shell expansion. See the subsection
|
the parameter in quotes to avoid shell expansion. See the subsection
|
||||||
"Repeated Execution" in the section "Calendar Mode" for more
|
"Repeated Execution" in the section "CALENDAR MODE" for more
|
||||||
information.
|
information.
|
||||||
.SH REMINDER FILES
|
.SH REMINDER FILES
|
||||||
.PP
|
.PP
|
||||||
@@ -439,7 +452,7 @@ These keywords denote the \fItype\fR
|
|||||||
of the reminder. (\fBSATISFY\fR is more complicated and will be explained
|
of the reminder. (\fBSATISFY\fR is more complicated and will be explained
|
||||||
later.) A \fBMSG\fR-type reminder normally prints a message to the standard
|
later.) A \fBMSG\fR-type reminder normally prints a message to the standard
|
||||||
output, after passing the \fIbody\fR through a special substitution filter,
|
output, after passing the \fIbody\fR through a special substitution filter,
|
||||||
described in the section "The Substitution Filter." However, if you have
|
described in the section "THE SUBSTITUTION FILTER." However, if you have
|
||||||
used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
|
used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
|
||||||
passed to the appropriate program. Note that the options \fB\-c\fR,
|
passed to the appropriate program. Note that the options \fB\-c\fR,
|
||||||
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
|
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
|
||||||
@@ -457,7 +470,7 @@ The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
|
|||||||
except that the reminder is formatted to fit into a paragraph-like
|
except that the reminder is formatted to fit into a paragraph-like
|
||||||
format. Three system variables control the formatting of \fBMSF\fR-type
|
format. Three system variables control the formatting of \fBMSF\fR-type
|
||||||
reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and
|
reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and
|
||||||
\fB$FormWidth\fR. They are discussed in the section "System Variables."
|
\fB$FormWidth\fR. They are discussed in the section "SYSTEM VARIABLES."
|
||||||
The \fBMSF\fR keyword causes the spacing of your reminder to be altered -
|
The \fBMSF\fR keyword causes the spacing of your reminder to be altered -
|
||||||
extra spaces are discarded, and two spaces are placed after periods and
|
extra spaces are discarded, and two spaces are placed after periods and
|
||||||
other characters, as specified by the system variables \fB$EndSent\fR and
|
other characters, as specified by the system variables \fB$EndSent\fR and
|
||||||
@@ -618,7 +631,7 @@ present. Examples:
|
|||||||
.nf
|
.nf
|
||||||
REM Sat 1 MSG First Saturday of every month
|
REM Sat 1 MSG First Saturday of every month
|
||||||
REM Mon Tue Wed Thu Fri 15 \\
|
REM Mon Tue Wed Thu Fri 15 \\
|
||||||
MSG 1st working day after 15th of every month
|
MSG 1st working day on or after 15th of every month
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
11.
|
11.
|
||||||
@@ -815,7 +828,7 @@ the initial date, and does not affect the repetition period.
|
|||||||
.B SCANFROM \fRand\fB FROM
|
.B SCANFROM \fRand\fB FROM
|
||||||
.PP
|
.PP
|
||||||
The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers
|
The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers
|
||||||
only, and will be explained in the section "Details about Trigger Computation"
|
only, and will be explained in the section "DETAILS ABOUT TRIGGER COMPUTATION"
|
||||||
near the end of this manual. Note that \fBSCANFROM\fR is available only
|
near the end of this manual. Note that \fBSCANFROM\fR is available only
|
||||||
in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only
|
in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only
|
||||||
from 03.01.00 and later.
|
from 03.01.00 and later.
|
||||||
@@ -827,7 +840,7 @@ It is used in calendar mode and when sorting reminders. If two reminders
|
|||||||
have the same trigger date and time, then they are sorted by priority.
|
have the same trigger date and time, then they are sorted by priority.
|
||||||
If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000
|
If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000
|
||||||
is used. (This default can be changed by adjusting the system variable
|
is used. (This default can be changed by adjusting the system variable
|
||||||
\fB$DefaultPrio\fR. See the section "System Variables" for more
|
\fB$DefaultPrio\fR. See the section "SYSTEM VARIABLES" for more
|
||||||
information.)
|
information.)
|
||||||
.PP
|
.PP
|
||||||
.B EXPIRY DATES
|
.B EXPIRY DATES
|
||||||
@@ -860,6 +873,20 @@ As a special case, you can use the \fBTHROUGH\fR keyword instead of
|
|||||||
REM 1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty
|
REM 1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
|
If you have an expiry date via the use of \fBTHROUGH\fR or \fBUNTIL\fR,
|
||||||
|
then Remind will \fInever\fR trigger the reminder after the expiry
|
||||||
|
date. For example, if you have this:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
OMIT 2021-01-08
|
||||||
|
REM 2021-01-01 THROUGH 2021-01-08 AFTER MSG Test
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
the reminder will not be triggered on 2021-01-08, and nor will it be
|
||||||
|
triggered on 2021-01-09; even though the AFTER keyword would normally
|
||||||
|
move the 8th's reminder to the 9th, the expiry date of 2021-01-08
|
||||||
|
overrides that.
|
||||||
|
.PP
|
||||||
.B THE ONCE KEYWORD
|
.B THE ONCE KEYWORD
|
||||||
.PP
|
.PP
|
||||||
Sometimes, it is necessary to ensure that reminders are run only once
|
Sometimes, it is necessary to ensure that reminders are run only once
|
||||||
@@ -968,7 +995,7 @@ it terminates the search after the \fBSATISFY\fR iteration limit
|
|||||||
.PP
|
.PP
|
||||||
Timed reminders are those that have an \fBAT\fR keyword followed
|
Timed reminders are those that have an \fBAT\fR keyword followed
|
||||||
by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR
|
by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR
|
||||||
mau be specified in 24-hour format, with 0:00 representing midnight,
|
may be specified in 24-hour format, with 0:00 representing midnight,
|
||||||
12:00 representing noon, and 23:59 representing one minute to midnight.
|
12:00 representing noon, and 23:59 representing one minute to midnight.
|
||||||
Alternatively, it may be specified in common "AM/PM" format; in this case,
|
Alternatively, it may be specified in common "AM/PM" format; in this case,
|
||||||
the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm
|
the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm
|
||||||
@@ -1061,7 +1088,7 @@ of timed reminders, and the \fBWARN\fR keyword allows precise control
|
|||||||
over the advance triggering of all types of reminders.
|
over the advance triggering of all types of reminders.
|
||||||
However, discussion must be deferred until after
|
However, discussion must be deferred until after
|
||||||
expressions and user-defined functions are explained. See the subsection
|
expressions and user-defined functions are explained. See the subsection
|
||||||
"Precise Scheduling" further on.
|
"PRECISE SCHEDULING" further on.
|
||||||
.PP
|
.PP
|
||||||
.B TAG AND DURATION
|
.B TAG AND DURATION
|
||||||
.PP
|
.PP
|
||||||
@@ -1323,7 +1350,7 @@ is similar to \fB%3\fR but displays the current time.
|
|||||||
used by the substitution filter,
|
used by the substitution filter,
|
||||||
but is used to tell \fBRemind\fR which text to include in a calendar
|
but is used to tell \fBRemind\fR which text to include in a calendar
|
||||||
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
|
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
|
||||||
See "Calendar Mode"
|
See "CALENDAR MODE"
|
||||||
.PP
|
.PP
|
||||||
Notes:
|
Notes:
|
||||||
.TP
|
.TP
|
||||||
@@ -1565,6 +1592,53 @@ It will not run set-uid. If it reads a file you don't own, it will
|
|||||||
disable RUN and the shell() function. And if it is run as \fIroot\fR,
|
disable RUN and the shell() function. And if it is run as \fIroot\fR,
|
||||||
it will only read files owned by \fIroot\fR.
|
it will only read files owned by \fIroot\fR.
|
||||||
.PP
|
.PP
|
||||||
|
Note that if \fBRemind\fR reads standard input, it does \fInot\fR
|
||||||
|
attempt to check the ownership of standard input, even if it is
|
||||||
|
coming from a file, and hence does \fInot\fR disable RUN and shell()
|
||||||
|
in this situation.
|
||||||
|
|
||||||
|
.SH THE INCLUDECMD COMMAND
|
||||||
|
.PP
|
||||||
|
\fBRemind\fR allows you to execute a shell command and evaluate the
|
||||||
|
output of that command as if it were an included file. For example,
|
||||||
|
you could have scripts that extract reminders out of a database and print
|
||||||
|
them on stdout as REM commands. Here is an example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
INCLUDECMD extract_reminders_for dfs
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
We assume that the command "extract_reminders_for" extracts reminders out
|
||||||
|
of a central database for the named user. Another use-case of INCLUDECMD
|
||||||
|
is if you have your reminders stored in a file in some non-Remind format;
|
||||||
|
you can write a command that transforms them to Remind format and then
|
||||||
|
Remind can "include" the file with an appropriate INCLUDECMD command.
|
||||||
|
.PP
|
||||||
|
Note that if RUN is disabled, then INCLUDECMD will fail with the error
|
||||||
|
message "RUN disabled"
|
||||||
|
.PP
|
||||||
|
INCLUDECMD passes the rest of the line to \fBpopen\fR(3), meaning that
|
||||||
|
the command is executed by the shell. As such, shell metacharacters
|
||||||
|
may need escaping or arguments quoting, depending on what you're trying
|
||||||
|
to do. Remind itself does not perform any modification of the command
|
||||||
|
line (apart from the normal [expr] expression-pasting mechanism).
|
||||||
|
.PP
|
||||||
|
If the command passed to INCLUDECMD begins with an exclamation mark "!",
|
||||||
|
then Remind disables \fBRUN\fR for the output of the command. If you are
|
||||||
|
running a command whose output you don't quite trust, you should
|
||||||
|
prefix it with "!" so that any RUN commands it emits fail.
|
||||||
|
.PP
|
||||||
|
An \fBINCLUDECMD\fR command counts towards the INCLUDE nesting depth.
|
||||||
|
For any given Remind run, a given INCLUDECMD command is only executed
|
||||||
|
once and the results are cached. For example, if you generate a
|
||||||
|
calendar, each unique INCLUDECMD command is run just once, not once
|
||||||
|
for each day of the produced calendar. "Uniqueness" is determined by
|
||||||
|
looking at the command that will be passed to the shell, so if (for example)
|
||||||
|
your INCLUDECMD uses expression-pasting that results in differences depending
|
||||||
|
on the value of \fBtoday()\fR, then each \fIunique\fR version of the
|
||||||
|
command will be executed once.
|
||||||
|
.PP
|
||||||
|
|
||||||
.SH THE BANNER COMMAND
|
.SH THE BANNER COMMAND
|
||||||
.PP
|
.PP
|
||||||
When \fBRemind\fR first issues a reminder, it prints a message like this:
|
When \fBRemind\fR first issues a reminder, it prints a message like this:
|
||||||
@@ -1854,6 +1928,11 @@ otherwise.
|
|||||||
.PP
|
.PP
|
||||||
.B NOTES
|
.B NOTES
|
||||||
.PP
|
.PP
|
||||||
|
If the result of an addition, subtraction or multiplication operation
|
||||||
|
would not fit in a C "int" type, \fBRemind\fR issues a "Number too
|
||||||
|
high" error. Unlike C, integer operations will not simply give the
|
||||||
|
wrong answer in case of overflow.
|
||||||
|
.PP
|
||||||
Operators of equal precedence are \fIalways\fR evaluated from left
|
Operators of equal precedence are \fIalways\fR evaluated from left
|
||||||
to right, except where parentheses dictate otherwise. This is important,
|
to right, except where parentheses dictate otherwise. This is important,
|
||||||
because the enhanced "+" operator is not necessarily associative.
|
because the enhanced "+" operator is not necessarily associative.
|
||||||
@@ -1900,6 +1979,9 @@ variable. Examples:
|
|||||||
Note that variables themselves have no type. They take on the type of
|
Note that variables themselves have no type. They take on the type of
|
||||||
whatever you store in them.
|
whatever you store in them.
|
||||||
.PP
|
.PP
|
||||||
|
Variables set with SET or on the command-line with \fB\-i\fR\fIvar\fB=\fR\fIexpr\fR
|
||||||
|
have global scope.
|
||||||
|
.PP
|
||||||
To delete a variable, use the \fBUNSET\fR command:
|
To delete a variable, use the \fBUNSET\fR command:
|
||||||
.PP
|
.PP
|
||||||
\fBUNSET\fR \fIvar\fR [\fIvar\fR...]
|
\fBUNSET\fR \fIvar\fR [\fIvar\fR...]
|
||||||
@@ -2043,6 +2125,14 @@ then \fBONCE\fR directives will be ignored.
|
|||||||
.B $InfDelta (read-only)
|
.B $InfDelta (read-only)
|
||||||
If non-zero, then the \fB\-t\fR option was supplied on the command line.
|
If non-zero, then the \fB\-t\fR option was supplied on the command line.
|
||||||
.TP
|
.TP
|
||||||
|
.B $IntMax (read-only)
|
||||||
|
The largest representable \fBINT\fR. On a machine with 32-bit signed integers
|
||||||
|
using twos-complement representation, this will be 2147483647.
|
||||||
|
.TP
|
||||||
|
.B $IntMin (read-only)
|
||||||
|
The smallest representable \fBINT\fR. On a machine with 32-bit signed integers
|
||||||
|
using twos-complement representation, this will be -2147483648.
|
||||||
|
.TP
|
||||||
.B $LatDeg, $LatMin, $LatSec
|
.B $LatDeg, $LatMin, $LatSec
|
||||||
These specify the latitude of your location. \fB$LatDeg\fR can
|
These specify the latitude of your location. \fB$LatDeg\fR can
|
||||||
range from \-90 to 90, and the others from \-59 to 59. Northern latitudes
|
range from \-90 to 90, and the others from \-59 to 59. Northern latitudes
|
||||||
@@ -2059,8 +2149,13 @@ the latitude and longitude system variables.
|
|||||||
These specify the longitude of your location. \fB$LongDeg\fR can
|
These specify the longitude of your location. \fB$LongDeg\fR can
|
||||||
range from \-180 to 180. Western longitudes are positive; eastern
|
range from \-180 to 180. Western longitudes are positive; eastern
|
||||||
ones are negative. Note that all three components should have the
|
ones are negative. Note that all three components should have the
|
||||||
same sign: All positive for Western longitudes and all negative
|
same sign: All positive for Western longitudes and all negative for
|
||||||
for Eastern longitudes.
|
Eastern longitudes. Note that for historical reasons, the sign for
|
||||||
|
longitude is \fIdifferent\fR from the usual convention! If you find
|
||||||
|
the longitude of your location from a search engine, you will most
|
||||||
|
likely \fIneed to invert the sign to have it work correctly with
|
||||||
|
Remind.\fR
|
||||||
|
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
The latitude and longitude information is required for the functions
|
The latitude and longitude information is required for the functions
|
||||||
@@ -2486,16 +2581,16 @@ variables are generally case-sensitive; thus, getenv("HOME") is not
|
|||||||
the same as getenv("home").
|
the same as getenv("home").
|
||||||
.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"
|
||||||
.TP
|
.TP
|
||||||
.B hebday(dq_date)
|
.B hebday(dq_date)
|
||||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
|
||||||
.TP
|
.TP
|
||||||
.B hebmon(dq_date)
|
.B hebmon(dq_date)
|
||||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
|
||||||
.TP
|
.TP
|
||||||
.B hebyear(dq_date)
|
.B hebyear(dq_date)
|
||||||
Support for Hebrew dates - see the section "The Hebrew Calendar"
|
Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
|
||||||
.TP
|
.TP
|
||||||
.B hour(tq_time)
|
.B hour(tq_time)
|
||||||
Returns the hour component of \fItime\fR.
|
Returns the hour component of \fItime\fR.
|
||||||
@@ -2816,6 +2911,23 @@ If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
|
|||||||
\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
|
.RE
|
||||||
|
.TP
|
||||||
|
.B shellescape(s_str)
|
||||||
|
Returns \fIstr\fR with all shell metacharacters such as " ", "*", etc
|
||||||
|
escaped with a backslash. For example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
SET a shellescape("a b*? c&d$e")
|
||||||
|
.fi
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
will set \fBa\fR to:
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
"a\\ b\\*\\?\\ c\\&d\\$e"
|
||||||
|
.fi
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B slide(d_start, i_amt [,s_wkday...])
|
.B slide(d_start, i_amt [,s_wkday...])
|
||||||
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR
|
||||||
@@ -3624,7 +3736,7 @@ However, when \fBRemind\fR gets around to calculating the trigger
|
|||||||
for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
|
for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
|
||||||
omitting Labour Day for 1993, and the "Mon AFTER" command
|
omitting Labour Day for 1993, and the "Mon AFTER" command
|
||||||
will not be triggered. (But see the description of \fBSCANFROM\fR
|
will not be triggered. (But see the description of \fBSCANFROM\fR
|
||||||
in the section "Details about Trigger Computation.")
|
in the section "DETAILS ABOUT TRIGGER COMPUTATION.")
|
||||||
.PP
|
.PP
|
||||||
It is probably best to stay away from computing \fBOMIT\fR
|
It is probably best to stay away from computing \fBOMIT\fR
|
||||||
trigger dates unless you keep these pitfalls in mind.
|
trigger dates unless you keep these pitfalls in mind.
|
||||||
@@ -3660,6 +3772,35 @@ 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
|
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
|
||||||
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
|
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
|
||||||
.PP
|
.PP
|
||||||
|
.SH POSSIBLY-UNCOMPUTABLE TRIGGERS
|
||||||
|
.PP
|
||||||
|
Occasionally, you may wish to suppress the "Can't compute trigger" warnings
|
||||||
|
for reminders for which a trigger date cannot be computed. For example,
|
||||||
|
the following reminder is triggered on a Monday that is not a holiday
|
||||||
|
if the following Tuesday is a holiday:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
However, if there are no Mondays after today's date that satisfy the
|
||||||
|
condition, Remind will print the "Can't compute trigger" error. To
|
||||||
|
suppress this, use the \fBMAYBE-UNCOMPUTABLE\fR keyword:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
It's almost never appropriate to use \fBMAYBE-UNCOMPUTABLE\fR, but it is
|
||||||
|
provided for those rare occasions when it makes sense. If you use
|
||||||
|
\fBMAYBE-UNCOMPUTABLE\fR inside the \fBevaltrig()\fR function, then
|
||||||
|
untriggerable triggers return -1. For example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT Mon")
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
will set a to -1.
|
||||||
.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
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
.TH TKREMIND 1 "1 January 2020"
|
.TH TKREMIND 1 "15 January 2021"
|
||||||
.UC 4
|
.UC 4
|
||||||
.SH NAME
|
.SH NAME
|
||||||
tkremind \- graphical front-end to Remind calendar program
|
tkremind \- graphical front-end to Remind calendar program
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B tkremind \fR[\fIoptions\fR] [\fIread_file\fR] [\fIwrite_file\fR]
|
.B tkremind \fR[\fIoptions\fR] [\fIread_file\fR] [\fIwrite_file\fR] [\fIconfig_file\fR]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBTkRemind\fR is a graphical front-end to the \fBRemind\fR program.
|
\fBTkRemind\fR is a graphical front-end to the \fBRemind\fR program.
|
||||||
It provides a friendly graphical interface which allows you to view
|
It provides a friendly graphical interface which allows you to view
|
||||||
@@ -13,8 +13,10 @@ Although not all of \fBRemind\fR's features are available with \fBTkRemind\fR,
|
|||||||
it creates. This allows you to learn \fBRemind\fR's syntax and then add
|
it creates. This allows you to learn \fBRemind\fR's syntax and then add
|
||||||
extra features as you become a more sophisticated \fBRemind\fR programmer.
|
extra features as you become a more sophisticated \fBRemind\fR programmer.
|
||||||
|
|
||||||
\fBTkRemind\fR is written in Tcl, and requires version 8.0
|
\fBTkRemind\fR is written in Tcl, and requires version 8.5 (or higher)
|
||||||
(or higher). It also requires a \fBwish\fR binary.
|
as well as the tcllib extension. It also requires a \fBwish\fR
|
||||||
|
binary. If you are using Tcl/Tk 8.5, you may also need either the Img
|
||||||
|
or the tkpng extension to handle PNG images.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
\fBTkRemind\fR itself has no options. However, it passes certain options
|
\fBTkRemind\fR itself has no options. However, it passes certain options
|
||||||
@@ -41,6 +43,9 @@ include the line:
|
|||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
|
\fIConfig_file\fR is the file in which \fBTkRemind\fR stores
|
||||||
|
its options. If it is omitted, it defaults to \fI$HOME/.tkremindrt\fR.
|
||||||
|
|
||||||
.SH THE CALENDAR WINDOW
|
.SH THE CALENDAR WINDOW
|
||||||
When you start \fBTkRemind\fR, it displays a calendar for the current
|
When you start \fBTkRemind\fR, it displays a calendar for the current
|
||||||
month, with today's date highlighted. Reminders are filled into each
|
month, with today's date highlighted. Reminders are filled into each
|
||||||
@@ -51,11 +56,14 @@ notice that the box appears completely full.
|
|||||||
|
|
||||||
.SH NAVIGATING
|
.SH NAVIGATING
|
||||||
To change to the previous or next month, click the \fB<\-\fR
|
To change to the previous or next month, click the \fB<\-\fR
|
||||||
or \fB\->\fR button, respectively. To change back to
|
or \fB\->\fR button, respectively. You can also use the left/right arrow
|
||||||
the current month, click \fBToday\fR. To go to a specific month,
|
keys or PageUp/PageDown to navigate.
|
||||||
click \fBGo To Date...\fR. This pops up a dialog box which allows you
|
|
||||||
to select a month and enter a year. Once you've done this, click
|
To change back to the current month, click \fBToday\fR or press the
|
||||||
\fBGo\fR to go to the date, or \fBCancel\fR to cancel.
|
Home key. To go to a specific month, click \fBGo To Date...\fR. This
|
||||||
|
pops up a dialog box which allows you to select a month and enter a
|
||||||
|
year. Once you've done this, click \fBGo\fR to go to the date, or
|
||||||
|
\fBCancel\fR to cancel.
|
||||||
|
|
||||||
To exit \fBTkRemind\fR, click \fBQuit\fR.
|
To exit \fBTkRemind\fR, click \fBQuit\fR.
|
||||||
|
|
||||||
@@ -125,10 +133,11 @@ Select the appropriate paper size and orientation. Activate
|
|||||||
be the normal case unless you have many reminders in a particular
|
be the normal case unless you have many reminders in a particular
|
||||||
day. (See the \fBRem2PS\fR documentation.)
|
day. (See the \fBRem2PS\fR documentation.)
|
||||||
|
|
||||||
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel.
|
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Note
|
||||||
Note that during printing, \fBRemind\fR is \fInot\fR called with
|
that during printing, \fBRemind\fR is called with the
|
||||||
the \fB-itkremind=1\fR option, because it is operated in normal
|
\fB-itkremind=1\fR option and also an additional \fB-itkprint=1\fR
|
||||||
PostScript-producing mode.
|
option.
|
||||||
|
|
||||||
|
|
||||||
.SH EDITING REMINDERS
|
.SH EDITING REMINDERS
|
||||||
|
|
||||||
@@ -210,7 +219,8 @@ background reminder pops up.
|
|||||||
.TP
|
.TP
|
||||||
.B Feed popped-up reminder to command's standard input
|
.B Feed popped-up reminder to command's standard input
|
||||||
If selected, feeds the text of the reminder to the command described
|
If selected, feeds the text of the reminder to the command described
|
||||||
above.
|
above. The text of the reminder is prefixed by "HH:MM ", where HH:MM
|
||||||
|
is the time of the reminder.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B E-mail reminders here if popup not dismissed
|
.B E-mail reminders here if popup not dismissed
|
||||||
@@ -231,6 +241,22 @@ The characters "%d" are replaced with the lined number of the file
|
|||||||
containing the reminder, and "%s" are replaced with the file name.
|
containing the reminder, and "%s" are replaced with the file name.
|
||||||
Useful strings might be "emacs +%d %s" or "gvim +%d %s"
|
Useful strings might be "emacs +%d %s" or "gvim +%d %s"
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B Extra Argument for Remind
|
||||||
|
This specifies any extra arguments that should be passed to Remind
|
||||||
|
when \BTkRemind\fR invokes \fBremind\fR. Unless you know what
|
||||||
|
you are doing, leave this blank.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B Change entry font...
|
||||||
|
This button pops up a font selection dialog that lets you change the
|
||||||
|
font used to draw calendar items in the calendar boxes.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B Change heading font...
|
||||||
|
Similar to Change entry font, but applies to calendar heading
|
||||||
|
(the month and day names and the day numbers.)
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
Once you've configured the options the way you like them,
|
Once you've configured the options the way you like them,
|
||||||
press \fBApply Options\fR to put them into effect, \fBSave Options\fR
|
press \fBApply Options\fR to put them into effect, \fBSave Options\fR
|
||||||
|
|||||||
29
rem2html/Makefile.in
Normal file
29
rem2html/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Set by configure - don't touch.
|
||||||
|
srcdir=@srcdir@
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
mandir=@mandir@
|
||||||
|
bindir=@bindir@
|
||||||
|
datadir=@datadir@
|
||||||
|
datarootdir=@datarootdir@
|
||||||
|
PERL=@PERL@
|
||||||
|
PERLMODS_NEEDED=JSON::Any Getopt::Long
|
||||||
|
all:
|
||||||
|
true
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if test "$(PERL)" = "" ; then \
|
||||||
|
echo "Not installing rem2html; Perl is required"; exit 0; fi; \
|
||||||
|
for m in $(PERLMODS_NEEDED) ; \
|
||||||
|
do \
|
||||||
|
perl -M$$m -e 1 > /dev/null 2>&1; \
|
||||||
|
if test $$? != 0 ; then echo "Not installing rem2html; missing $$m"; exit 0; fi; \
|
||||||
|
done; \
|
||||||
|
echo "Installing rem2html in $(DESTDIR)$(bindir)"; \
|
||||||
|
mkdir -p $(DESTDIR)$(bindir) && sed -e 's|^#!perl|#!$(PERL)|' < rem2html > $(DESTDIR)$(bindir)/rem2html && chmod 755 $(DESTDIR)$(bindir)/rem2html && exit 0; \
|
||||||
|
exit 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
12
rem2html/README.rem2html
Normal file
12
rem2html/README.rem2html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
REM2HTML
|
||||||
|
--------
|
||||||
|
|
||||||
|
rem2html is a Perl script that transforms the output of `remind -pp
|
||||||
|
...' to HTML. Type `perl rem2html --help' for usage information.
|
||||||
|
|
||||||
|
rem2html requires the Perl modules `JSON::Any' and `Getopt::Long'. It
|
||||||
|
will not be installed unless you have those modules as well as Perl
|
||||||
|
itself.
|
||||||
|
|
||||||
|
--
|
||||||
|
Dianne Skoll
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/perl
|
#!perl
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
@@ -16,15 +16,20 @@ my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mond
|
|||||||
my $TIDY_PROGNAME = $0;
|
my $TIDY_PROGNAME = $0;
|
||||||
$TIDY_PROGNAME =~ s|^.*/||;
|
$TIDY_PROGNAME =~ s|^.*/||;
|
||||||
|
|
||||||
# rem2html -- convert the output of "remind -p" to HTML
|
# rem2html -- convert the output of "remind -pp" to HTML
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
rem2html - Convert the output of "remind -p" to HTML
|
rem2html - Convert the output of "remind -pp" to HTML
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
remind -p ... | rem2html [options]
|
remind -pp ... | rem2html [options]
|
||||||
|
|
||||||
|
You can also use the old interchange format as below, but the -pp
|
||||||
|
version is preferred.
|
||||||
|
|
||||||
|
remind -p ... | rem2html [options]
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
|
|
||||||
@@ -50,13 +55,21 @@ month name a link to I<url>.
|
|||||||
|
|
||||||
=item --imgbase I<url>
|
=item --imgbase I<url>
|
||||||
|
|
||||||
When creating URLs for images and the stylesheet, use
|
When creating URLs for the stylesheet or external images, use I<url>
|
||||||
I<url> as the base URL.
|
as the base URL.
|
||||||
|
|
||||||
|
=item --pngs
|
||||||
|
|
||||||
|
Normally, rem2html uses inline "data:" URLs for the moon phase images,
|
||||||
|
yielding a standalone HTML file. The C<--pngs> option makes it use
|
||||||
|
external images named firstquarter.png, fullmoon.png, lastquarter.png
|
||||||
|
and newmoon.png, which are expected to live in C<--imgbase>.
|
||||||
|
|
||||||
=item --stylesheet I<url.css>
|
=item --stylesheet I<url.css>
|
||||||
|
|
||||||
Use I<url.css> as the stylesheet. If this option is used,
|
Use I<url.css> as the stylesheet. If this option is used,
|
||||||
I<url.css> is I<not> interpreted relative to B<imgbase>.
|
I<url.css> is interpreted relative to B<imgbase> I<unless> it start
|
||||||
|
with a "/".
|
||||||
|
|
||||||
=item --nostyle
|
=item --nostyle
|
||||||
|
|
||||||
@@ -97,9 +110,9 @@ sub usage
|
|||||||
$exit_status = 1;
|
$exit_status = 1;
|
||||||
}
|
}
|
||||||
print STDERR <<"EOM";
|
print STDERR <<"EOM";
|
||||||
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -p"
|
$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
|
||||||
|
|
||||||
Usage: remind -p ... | rem2html [options]
|
Usage: remind -pp ... | rem2html [options]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
@@ -110,6 +123,8 @@ Options:
|
|||||||
entry a link to <url>
|
entry a link to <url>
|
||||||
--forwurl url Same as --backurl, but for the next month's small calendar
|
--forwurl url Same as --backurl, but for the next month's small calendar
|
||||||
--imgbase url Base URL of images and default stylesheet file
|
--imgbase url Base URL of images and default stylesheet file
|
||||||
|
--pngs Use external .PNG images for moon phases rater than
|
||||||
|
inline data: URLs
|
||||||
--stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
|
--stylesheet url.css URL of CSS stylesheet. If specified, imgbase is NOT
|
||||||
prepended to url.css
|
prepended to url.css
|
||||||
--nostyle Produce basic HTML that does not use a CSS stylesheet
|
--nostyle Produce basic HTML that does not use a CSS stylesheet
|
||||||
@@ -121,11 +136,31 @@ EOM
|
|||||||
exit($exit_status);
|
exit($exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub smoosh
|
||||||
|
{
|
||||||
|
my ($first, $second) = @_;
|
||||||
|
return $second unless defined ($first);
|
||||||
|
return $second if $first eq '';
|
||||||
|
return $second if ($second =~ m|^/|); # Absolute path given for second
|
||||||
|
|
||||||
|
# Squash multiple slashes
|
||||||
|
$first =~ s|/+|/|g;
|
||||||
|
|
||||||
|
# Special case
|
||||||
|
return "/$second" if ($first eq '/');
|
||||||
|
|
||||||
|
# Delete trailing slash
|
||||||
|
$first =~ s|/$||;
|
||||||
|
|
||||||
|
return "$first/$second";
|
||||||
|
}
|
||||||
|
|
||||||
sub parse_options
|
sub parse_options
|
||||||
{
|
{
|
||||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||||
if (!GetOptions(\%Options, "help|h",
|
if (!GetOptions(\%Options, "help|h",
|
||||||
"man",
|
"man",
|
||||||
|
"pngs",
|
||||||
"version",
|
"version",
|
||||||
"stylesheet=s",
|
"stylesheet=s",
|
||||||
"nostyle",
|
"nostyle",
|
||||||
@@ -138,45 +173,40 @@ sub parse_options
|
|||||||
"tableonly")) {
|
"tableonly")) {
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
$Options{'title'} ||= 'HTML Calendar';
|
$Options{title} ||= 'HTML Calendar';
|
||||||
|
|
||||||
# Fix up imgbase
|
my $stylesheet = $Options{stylesheet};
|
||||||
my $imgbase = '%IMAGEBASE%';
|
if ($stylesheet) {
|
||||||
if ($imgbase ne '%' . 'IMAGEBASE' . '%') {
|
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||||
$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
|
sub start_output
|
||||||
{
|
{
|
||||||
return if ($Options{'tableonly'});
|
return if ($Options{tableonly});
|
||||||
|
|
||||||
print("<html>\n<head>\n<title>" . $Options{'title'} . "</title>\n");
|
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
||||||
if (!$Options{'nostyle'}) {
|
if (!$Options{nostyle}) {
|
||||||
if ($Options{'stylesheet'}) {
|
if ($Options{stylesheet}) {
|
||||||
print('<link rel="stylesheet" type="text/css" href="' .
|
print('<link rel="stylesheet" type="text/css" href="' .
|
||||||
$Options{'stylesheet'} . '">' . "\n");
|
$Options{stylesheet} . '">' . "\n");
|
||||||
}
|
} else {
|
||||||
|
print("<style>\n");
|
||||||
|
print default_stylesheet();
|
||||||
|
print("</style>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
print("</head>\n<body>\n");
|
print("</head>\n<body>\n");
|
||||||
if ($Options{'prologue'}) {
|
if ($Options{prologue}) {
|
||||||
print $Options{'prologue'} . "\n";
|
print $Options{prologue} . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub end_output
|
sub end_output
|
||||||
{
|
{
|
||||||
return if ($Options{'tableonly'});
|
return if ($Options{tableonly});
|
||||||
if ($Options{'epilogue'}) {
|
if ($Options{epilogue}) {
|
||||||
print $Options{'epilogue'} . "\n";
|
print $Options{epilogue} . "\n";
|
||||||
}
|
}
|
||||||
print("</body>\n</html>\n");
|
print("</body>\n</html>\n");
|
||||||
}
|
}
|
||||||
@@ -222,7 +252,7 @@ sub parse_input
|
|||||||
|
|
||||||
$found_data = 1;
|
$found_data = 1;
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
$class = '';
|
$class = '';
|
||||||
} else {
|
} else {
|
||||||
$class = ' class="rem-entry"';
|
$class = ' class="rem-entry"';
|
||||||
@@ -301,7 +331,7 @@ sub small_calendar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<td width=\"14%\">\n";
|
print "<td width=\"14%\">\n";
|
||||||
print "<table border=\"0\">\n";
|
print "<table border=\"0\">\n";
|
||||||
print "<caption>";
|
print "<caption>";
|
||||||
@@ -316,7 +346,7 @@ sub small_calendar
|
|||||||
print "</caption>\n";
|
print "</caption>\n";
|
||||||
|
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
$class = ' align="right"';
|
$class = ' align="right"';
|
||||||
} else {
|
} else {
|
||||||
@@ -338,7 +368,7 @@ sub small_calendar
|
|||||||
if ($col == 0) {
|
if ($col == 0) {
|
||||||
print("<tr>\n");
|
print("<tr>\n");
|
||||||
}
|
}
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||||
@@ -350,7 +380,7 @@ sub small_calendar
|
|||||||
print("<tr>\n");
|
print("<tr>\n");
|
||||||
}
|
}
|
||||||
$col++;
|
$col++;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\">$day</td>");
|
print("<td align=\"right\" width=\"14%\">$day</td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-cell\">$day</td>");
|
print("<td class=\"rem-sc-cell\">$day</td>");
|
||||||
@@ -362,7 +392,7 @@ sub small_calendar
|
|||||||
}
|
}
|
||||||
if ($col) {
|
if ($col) {
|
||||||
while ($col < 7) {
|
while ($col < 7) {
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print("<td align=\"right\" width=\"14%\"> </td>");
|
print("<td align=\"right\" width=\"14%\"> </td>");
|
||||||
} else {
|
} else {
|
||||||
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
print("<td class=\"rem-sc-empty-cell\"> </td>");
|
||||||
@@ -391,7 +421,7 @@ sub output_calendar
|
|||||||
|
|
||||||
# Start the table
|
# Start the table
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
||||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
@@ -415,23 +445,23 @@ sub output_calendar
|
|||||||
|
|
||||||
# Start the calendar rows
|
# Start the calendar rows
|
||||||
my $col = 0;
|
my $col = 0;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
}
|
}
|
||||||
if ($first_col > 0) {
|
if ($first_col > 0) {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
$col++;
|
$col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($last_col == 6 && $first_col > 0) {
|
if ($last_col == 6 && $first_col > 0) {
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
$col++;
|
$col++;
|
||||||
}
|
}
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
$class = ' width="14%"';
|
$class = ' width="14%"';
|
||||||
} else {
|
} else {
|
||||||
$class = ' class="rem-empty"';
|
$class = ' class="rem-empty"';
|
||||||
@@ -448,7 +478,7 @@ sub output_calendar
|
|||||||
$col = 0;
|
$col = 0;
|
||||||
print "</tr>\n";
|
print "</tr>\n";
|
||||||
if ($day < $Numdays) {
|
if ($day < $Numdays) {
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
@@ -461,13 +491,13 @@ sub output_calendar
|
|||||||
while ($col < 7) {
|
while ($col < 7) {
|
||||||
if ($col == 5) {
|
if ($col == 5) {
|
||||||
if ($first_col == 0) {
|
if ($first_col == 0) {
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
} else {
|
} else {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
}
|
}
|
||||||
} elsif ($col == 6) {
|
} elsif ($col == 6) {
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
} else {
|
} else {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
@@ -479,17 +509,17 @@ sub output_calendar
|
|||||||
|
|
||||||
# Add a row for small calendars if they were not yet done!
|
# Add a row for small calendars if they were not yet done!
|
||||||
if ($first_col == 0 && $last_col == 6) {
|
if ($first_col == 0 && $last_col == 6) {
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<tr>\n";
|
print "<tr>\n";
|
||||||
} else {
|
} else {
|
||||||
print "<tr class=\"rem-cal-row\">\n";
|
print "<tr class=\"rem-cal-row\">\n";
|
||||||
}
|
}
|
||||||
small_calendar($Prevmon, $Prevlen, $Options{'backurl'},
|
small_calendar($Prevmon, $Prevlen, $Options{backurl},
|
||||||
($Firstwkday - $Prevlen + 35) % 7);
|
($Firstwkday - $Prevlen + 35) % 7);
|
||||||
for (my $i=0; $i<5; $i++) {
|
for (my $i=0; $i<5; $i++) {
|
||||||
print("<td$class> </td>\n");
|
print("<td$class> </td>\n");
|
||||||
}
|
}
|
||||||
small_calendar($Nextmon, $Nextlen, $Options{'forwurl'},
|
small_calendar($Nextmon, $Nextlen, $Options{forwurl},
|
||||||
($Firstwkday + $Numdays) % 7);
|
($Firstwkday + $Numdays) % 7);
|
||||||
print("</tr>\n");
|
print("</tr>\n");
|
||||||
}
|
}
|
||||||
@@ -506,7 +536,7 @@ sub draw_day_cell
|
|||||||
$week = ' ' . $weeks->{$day};
|
$week = ' ' . $weeks->{$day};
|
||||||
}
|
}
|
||||||
my $class;
|
my $class;
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
$class = $classes->[$day] || '';
|
$class = $classes->[$day] || '';
|
||||||
} else {
|
} else {
|
||||||
$class = $classes->[$day] || "rem-cell";
|
$class = $classes->[$day] || "rem-cell";
|
||||||
@@ -532,33 +562,46 @@ sub draw_day_cell
|
|||||||
my $alt;
|
my $alt;
|
||||||
my $title;
|
my $title;
|
||||||
if ($phase == 0) {
|
if ($phase == 0) {
|
||||||
$img = 'newmoon.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'newmoon.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII=';
|
||||||
|
}
|
||||||
$title = 'New Moon';
|
$title = 'New Moon';
|
||||||
$alt = 'new';
|
$alt = 'new';
|
||||||
} elsif ($phase == 1) {
|
} elsif ($phase == 1) {
|
||||||
$img = 'firstquarter.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'firstquarter.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC';
|
||||||
|
}
|
||||||
$title = 'First Quarter';
|
$title = 'First Quarter';
|
||||||
$alt = '1st';
|
$alt = '1st';
|
||||||
} elsif ($phase == 2) {
|
} elsif ($phase == 2) {
|
||||||
$img = 'fullmoon.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'fullmoon.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC';
|
||||||
|
}
|
||||||
$alt = 'full';
|
$alt = 'full';
|
||||||
$title = 'Full Moon';
|
$title = 'Full Moon';
|
||||||
} else {
|
} else {
|
||||||
$img = 'lastquarter.png';
|
if ($Options{pngs}) {
|
||||||
|
$img = smoosh($Options{imgbase}, 'lastquarter.png');
|
||||||
|
} else {
|
||||||
|
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg==';
|
||||||
|
}
|
||||||
$alt = 'last';
|
$alt = 'last';
|
||||||
$title = 'Last Quarter';
|
$title = 'Last Quarter';
|
||||||
}
|
}
|
||||||
if ($Options{'imgbase'}) {
|
if ($Options{nostyle}) {
|
||||||
$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>");
|
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||||
} else {
|
} else {
|
||||||
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Options{'nostyle'}) {
|
if ($Options{nostyle}) {
|
||||||
print "<div style=\"float: right\">$day$week</div>\n";
|
print "<div style=\"float: right\">$day$week</div>\n";
|
||||||
print "<p> </p>\n";
|
print "<p> </p>\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -581,13 +624,13 @@ sub escape_html
|
|||||||
}
|
}
|
||||||
|
|
||||||
parse_options();
|
parse_options();
|
||||||
if ($Options{'help'}) {
|
if ($Options{help}) {
|
||||||
usage(0);
|
usage(0);
|
||||||
exit(0);
|
exit(0);
|
||||||
} elsif ($Options{'man'}) {
|
} elsif ($Options{man}) {
|
||||||
system("perldoc $0");
|
system("perldoc $0");
|
||||||
exit(0);
|
exit(0);
|
||||||
} elsif ($Options{'version'}) {
|
} elsif ($Options{version}) {
|
||||||
print "rem2html version $rem2html_version.\n";
|
print "rem2html version $rem2html_version.\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -612,3 +655,81 @@ if ($found_something) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub default_stylesheet
|
||||||
|
{
|
||||||
|
return <<'EOF';
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rem-entry {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
Files in this directory:
|
Files in this directory:
|
||||||
|
|
||||||
tkremind -- Tcl/Tk graphical calendar using Remind as engine
|
tkremind -- Tcl/Tk graphical calendar using Remind as engine
|
||||||
cm2rem.tcl -- Convert Sun's "cm" calendar manager files to Remind.
|
|
||||||
|
|||||||
@@ -1,358 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# -*-Mode: TCL;-*-
|
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
# cm2rem.tcl
|
|
||||||
#
|
|
||||||
# A cheesy Tcl script to convert Sun's "cm" calendar manager
|
|
||||||
# files (version 3 only) to Remind format.
|
|
||||||
#
|
|
||||||
# This file is part of REMIND.
|
|
||||||
# Copyright (C) 1992-2018 by Dianne Skoll
|
|
||||||
#
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
|
|
||||||
# the next line restarts using tclsh \
|
|
||||||
exec tclsh "$0" "$@"
|
|
||||||
|
|
||||||
set i 0
|
|
||||||
foreach month {January February March April May June
|
|
||||||
July August September October November December} {
|
|
||||||
incr i
|
|
||||||
set MonthNum($month) $i
|
|
||||||
set FullMonth([string range $month 0 2]) $month
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertParens
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# line -- a line read from a cm file
|
|
||||||
# %RETURNS:
|
|
||||||
# A new line with all ( and ) outside quotes converted to { and }.
|
|
||||||
# This cheap trick allows us to use Tcl's built-in list manipulation
|
|
||||||
# functions to munge the line.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertParens { line } {
|
|
||||||
# Convert all ( and ) to { and } unless they are inside a quoted
|
|
||||||
# string
|
|
||||||
set out ""
|
|
||||||
set len [string length $line]
|
|
||||||
set inQuotes 0
|
|
||||||
for {set i 0} {$i < $len} {incr i} {
|
|
||||||
set char [string range $line $i $i]
|
|
||||||
if {$char == "\\" && $inQuotes} {
|
|
||||||
append out $char
|
|
||||||
incr i
|
|
||||||
set char [string range $line $i $i]
|
|
||||||
append out $char
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == "(" && !$inQuotes} {
|
|
||||||
set char \{
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == ")" && !$inQuotes} {
|
|
||||||
set char \}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$char == "\""} {
|
|
||||||
set inQuotes [expr !$inQuotes]
|
|
||||||
}
|
|
||||||
|
|
||||||
append out $char
|
|
||||||
}
|
|
||||||
return $out
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: processLine
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# line -- a line read from a cm file
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Processes a single line from the file, possibly writing a reminder
|
|
||||||
# in Remind format to stdout
|
|
||||||
#***********************************************************************
|
|
||||||
proc processLine { line } {
|
|
||||||
global Attributes
|
|
||||||
global FullMonth
|
|
||||||
|
|
||||||
catch {unset Attributes}
|
|
||||||
|
|
||||||
# Only convert lines which start with "(add"
|
|
||||||
if {[string range $line 0 3] != "(add"} {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set line [convertParens $line]
|
|
||||||
# Convert it to a list. CAREFUL: Potential security problem if
|
|
||||||
# $line contains something nasty.
|
|
||||||
|
|
||||||
eval set line $line
|
|
||||||
|
|
||||||
set Attributes(body) ""
|
|
||||||
foreach {key val} $line {
|
|
||||||
switch -exact -- $key {
|
|
||||||
"add" {
|
|
||||||
set Attributes(date) $val
|
|
||||||
}
|
|
||||||
"what:" {
|
|
||||||
append Attributes(body) $val
|
|
||||||
}
|
|
||||||
"details:" {
|
|
||||||
append Attributes(body) $val
|
|
||||||
}
|
|
||||||
"duration:" {
|
|
||||||
set Attributes(duration) $val
|
|
||||||
}
|
|
||||||
"period:" {
|
|
||||||
set Attributes(period) $val
|
|
||||||
}
|
|
||||||
"ntimes:" {
|
|
||||||
set Attributes(ntimes) $val
|
|
||||||
}
|
|
||||||
"attributes:" {
|
|
||||||
set Attributes(action) $val
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[info exists Attributes(action)]} {
|
|
||||||
# Nuke quotes and commas in action
|
|
||||||
regsub -all {[,\"]} $Attributes(action) { } Attributes(action)
|
|
||||||
|
|
||||||
# Add spaces to pairs
|
|
||||||
regsub -all \}\{ $Attributes(action) \}\ \{ Attributes(action)
|
|
||||||
|
|
||||||
# Add another pair of brackets to make a proper list
|
|
||||||
set Attributes(action) "{$Attributes(action)}"
|
|
||||||
|
|
||||||
# Convert to a real Tcl list
|
|
||||||
eval set Attributes(action) $Attributes(action)
|
|
||||||
}
|
|
||||||
# Split out date into month, day, year, time parts
|
|
||||||
scan $Attributes(date) "%s%s%s%s%s" wkday month day time year
|
|
||||||
set time [string range $time 0 4]
|
|
||||||
set Attributes(wkday) $wkday
|
|
||||||
set Attributes(month) $FullMonth($month)
|
|
||||||
set Attributes(day) $day
|
|
||||||
set Attributes(time) $time
|
|
||||||
set Attributes(year) $year
|
|
||||||
|
|
||||||
# Convert newlines in body to spaces
|
|
||||||
set body $Attributes(body)
|
|
||||||
regsub -all "\n" $body " " body
|
|
||||||
|
|
||||||
# TODO: Escape BODY to get rid of [] chars.
|
|
||||||
set Attributes(body) $body
|
|
||||||
|
|
||||||
# Convert to Reminder format
|
|
||||||
convertReminder
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertReminder {} {
|
|
||||||
global Attributes
|
|
||||||
switch -exact $Attributes(period) {
|
|
||||||
single { convertSingleReminder }
|
|
||||||
daily { convertDailyReminder }
|
|
||||||
weekly { convertWeeklyReminder }
|
|
||||||
monthly { convertMonthlyReminder }
|
|
||||||
yearly { convertYearlyReminder }
|
|
||||||
default {
|
|
||||||
puts "\# Unable to convert reminder with period $Attributes(period)"
|
|
||||||
puts "\# Body is: $Attributes(body)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertSingleReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "single" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertSingleReminder {} {
|
|
||||||
global Attributes
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) [at][duration]MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertDailyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "daily" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertDailyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) $ntimes]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *1 [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertWeeklyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "daily" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertWeeklyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 7]]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) $Attributes(year) *7 [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertMonthlyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "monthly" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertMonthlyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
set ntimes [expr $Attributes(ntimes) - 1]
|
|
||||||
if {$ntimes <= 1} {
|
|
||||||
convertSingleReminder
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# If repetition > 1000, it's infinite
|
|
||||||
if {$ntimes > 1000} {
|
|
||||||
puts "REM $Attributes(day) [at][duration]MSG $Attributes(body)"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
### UNTIL date is fudged!
|
|
||||||
set until [getUntilDate $Attributes(day) $Attributes(month) $Attributes(year) [expr $ntimes * 30]]
|
|
||||||
|
|
||||||
puts "REM $Attributes(day) [at][duration]UNTIL $until MSG $Attributes(body)"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: convertYearlyReminder
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses global Attributes variable which must be filled in
|
|
||||||
# %RETURNS:
|
|
||||||
# Nothing
|
|
||||||
# %DESCRIPTION:
|
|
||||||
# Converts a reminder with "yearly" period to Remind format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc convertYearlyReminder {} {
|
|
||||||
global Attributes
|
|
||||||
|
|
||||||
# No special handling of ntimes et al.
|
|
||||||
puts "REM $Attributes(day) $Attributes(month) [at][duration]MSG $Attributes(body)"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: at
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses Attributes global variable
|
|
||||||
# %RETURNS:
|
|
||||||
# A string providing the correct AT clause for a timed reminder.
|
|
||||||
#***********************************************************************
|
|
||||||
proc at {} {
|
|
||||||
global Attributes
|
|
||||||
if {![info exists Attributes(time)]} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if {"$Attributes(time)" == ""} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return "AT $Attributes(time) "
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: duration
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# None -- uses Attributes global variable
|
|
||||||
# %RETURNS:
|
|
||||||
# A string providing the correct DURATION clause for a timed reminder.
|
|
||||||
#***********************************************************************
|
|
||||||
proc duration {} {
|
|
||||||
global Attributes
|
|
||||||
if {![info exists Attributes(duration)]} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if {"$Attributes(duration)" == ""} {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
set h [expr $Attributes(duration) / 3600]
|
|
||||||
set remainder [expr $Attributes(duration) - $h*3600]
|
|
||||||
set m [expr $remainder / 60]
|
|
||||||
return "DURATION [format "%d:%02d " $h $m]"
|
|
||||||
}
|
|
||||||
|
|
||||||
#***********************************************************************
|
|
||||||
# %PROCEDURE: getUntilDate
|
|
||||||
# %ARGUMENTS:
|
|
||||||
# day, month, year -- a date
|
|
||||||
# days -- number of days to add to date
|
|
||||||
# %RETURNS:
|
|
||||||
# The date which is "days" later than supplied date in a correct UNTIL
|
|
||||||
# format.
|
|
||||||
#***********************************************************************
|
|
||||||
proc getUntilDate { day month year days } {
|
|
||||||
global RemindPipe
|
|
||||||
global MonthNum
|
|
||||||
set date "'$year/$MonthNum($month)/$day'"
|
|
||||||
puts $RemindPipe "MSG \[trigger($date + $days)\]%"
|
|
||||||
puts $RemindPipe "flush"
|
|
||||||
flush $RemindPipe
|
|
||||||
gets $RemindPipe line
|
|
||||||
return $line
|
|
||||||
}
|
|
||||||
|
|
||||||
catch {wm withdraw .}
|
|
||||||
# Start a Remind process to issue reminders
|
|
||||||
if {[catch {set RemindPipe [open "|remind -" "r+"]} err]} {
|
|
||||||
puts stderr "Error: Cannot run Remind: $err"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
puts $RemindPipe "banner %"
|
|
||||||
flush $RemindPipe
|
|
||||||
|
|
||||||
# Write some blurb
|
|
||||||
puts "\# Reminder file converted from \"cm\" data by cm2rem.tcl"
|
|
||||||
puts ""
|
|
||||||
|
|
||||||
while {[gets stdin line] >= 0} {
|
|
||||||
processLine $line
|
|
||||||
}
|
|
||||||
exit 0
|
|
||||||
390
scripts/tkremind
390
scripts/tkremind
@@ -7,13 +7,31 @@
|
|||||||
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2020 Dianne Skoll
|
# Copyright (C) 1992-2021 Dianne Skoll
|
||||||
#
|
#
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
# the next line restarts using wish \
|
# the next line restarts using wish \
|
||||||
exec wish "$0" "$@"
|
exec wish "$0" "$@"
|
||||||
|
|
||||||
|
# We need at least version 8.5 because of {*} list expansion operator
|
||||||
|
if {[catch {package require Tcl 8.5}]} {
|
||||||
|
puts stderr "This program requires Tcl 8.5 or higher."
|
||||||
|
puts stderr "You have version [info tclversion]"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# If it's 8.5, try using the Img or the TkPNG package to
|
||||||
|
# get PNG support
|
||||||
|
if {[info tclversion] == 8.5} {
|
||||||
|
if {[catch {package require Img}]} {
|
||||||
|
if {[catch {package require tkpng}]} {
|
||||||
|
puts stderr "Tcl/Tk version 8.5 might require either the Img or tkpng"
|
||||||
|
puts stderr "package to handle PNG images correctly. TkRemind may"
|
||||||
|
puts stderr "crash because neither of these packages was found."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
wm withdraw .
|
wm withdraw .
|
||||||
|
|
||||||
set Hostname [exec hostname]
|
set Hostname [exec hostname]
|
||||||
@@ -106,13 +124,6 @@ if {[catch {package require json}]} {
|
|||||||
missing_tcllib json
|
missing_tcllib json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Check that we have the right version of wish
|
|
||||||
if {$tcl_version < 8.0} {
|
|
||||||
tk_dialog .error Error "You need wish version 8.0 or higher to run TkRemind; you have $tcl_version" error 0 OK
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$tcl_platform(platform) == "windows"} {
|
if {$tcl_platform(platform) == "windows"} {
|
||||||
tk_dialog .error Error "Please do not port Remind to Windows" error 0 OK
|
tk_dialog .error Error "Please do not port Remind to Windows" error 0 OK
|
||||||
exit 1
|
exit 1
|
||||||
@@ -155,6 +166,26 @@ set OptDescr(SMTPServer) "(String) IP address or host name of SMTP server to use
|
|||||||
set Option(ExtraRemindArgs) ""
|
set Option(ExtraRemindArgs) ""
|
||||||
set OptDescr(ExtraRemindArgs) "(String) Extra arguments when invoking remind"
|
set OptDescr(ExtraRemindArgs) "(String) Extra arguments when invoking remind"
|
||||||
|
|
||||||
|
set Option(CalboxFont) [font actual TkFixedFont]
|
||||||
|
set OptDescr(CalboxFont) "Font to use in calendar boxes in Tk font format"
|
||||||
|
|
||||||
|
set Option(HeadingFont) [font actual TkDefaultFont]
|
||||||
|
set OptDescr(HeadingFont) "Font to use in calendar headings in Tk font format"
|
||||||
|
|
||||||
|
set Option(BackgroundColor) "#d9d9d9"
|
||||||
|
set OptDescr(BackgroundColor) "Default background color of calendar boxes"
|
||||||
|
|
||||||
|
set Option(TextColor) "#000000"
|
||||||
|
set OptDescr(TextColor) "Default text color in calendar boxes"
|
||||||
|
|
||||||
|
set Option(LabelColor) "#000000"
|
||||||
|
set OptDescr(LabelColor) "Default label color for headings"
|
||||||
|
|
||||||
|
set Option(WinBackground) "#d9d9d9"
|
||||||
|
set OptDescr(WinBackground) "Background color of calendar window"
|
||||||
|
|
||||||
|
set TimerUpdateForChanges ""
|
||||||
|
|
||||||
# Remind program to execute -- supply full path if you want
|
# Remind program to execute -- supply full path if you want
|
||||||
set Remind "remind"
|
set Remind "remind"
|
||||||
#set Remind "/home/dfs/Remind/src/remind"
|
#set Remind "/home/dfs/Remind/src/remind"
|
||||||
@@ -166,8 +197,14 @@ set Rem2PS "rem2ps"
|
|||||||
set ReminderFile {NOSUCHFILE}
|
set ReminderFile {NOSUCHFILE}
|
||||||
set ReminderFile [file nativename "~/.reminders"]
|
set ReminderFile [file nativename "~/.reminders"]
|
||||||
|
|
||||||
|
# Default options file
|
||||||
|
set ConfigFile ~/.tkremindrc
|
||||||
|
|
||||||
set EditorPid -1
|
set EditorPid -1
|
||||||
|
|
||||||
|
# Inotify file
|
||||||
|
set InotifyFP ""
|
||||||
|
|
||||||
# Reminder file to append to -- default
|
# Reminder file to append to -- default
|
||||||
set AppendFile {NOSUCHFILE}
|
set AppendFile {NOSUCHFILE}
|
||||||
catch {set AppendFile $ReminderFile}
|
catch {set AppendFile $ReminderFile}
|
||||||
@@ -218,6 +255,7 @@ set PrintDest file
|
|||||||
set PrintSize letter
|
set PrintSize letter
|
||||||
set PrintOrient landscape
|
set PrintOrient landscape
|
||||||
set PrintFill 1
|
set PrintFill 1
|
||||||
|
set PrintDaysRight 1
|
||||||
set PrintEncoding 0
|
set PrintEncoding 0
|
||||||
set PrintMargins 36pt
|
set PrintMargins 36pt
|
||||||
set PrintSmallCalendars 1
|
set PrintSmallCalendars 1
|
||||||
@@ -263,9 +301,9 @@ proc Initialize {} {
|
|||||||
|
|
||||||
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
|
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
|
||||||
global MondayFirst TwentyFourHourMode ReminderFileModTime
|
global MondayFirst TwentyFourHourMode ReminderFileModTime
|
||||||
global Option
|
global Option ConfigFile
|
||||||
set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA"
|
set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA"
|
||||||
set PSCmd "$Remind -pp -l EXTRA"
|
set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp -l EXTRA"
|
||||||
set i 0
|
set i 0
|
||||||
while {$i < $argc} {
|
while {$i < $argc} {
|
||||||
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
|
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
|
||||||
@@ -289,6 +327,10 @@ proc Initialize {} {
|
|||||||
if {$i < $argc} {
|
if {$i < $argc} {
|
||||||
set AppendFile [lindex $argv $i]
|
set AppendFile [lindex $argv $i]
|
||||||
incr i
|
incr i
|
||||||
|
if {$i < $argc} {
|
||||||
|
set ConfigFile [lindex $argv $i]
|
||||||
|
incr i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,8 +417,7 @@ proc MonitorReminderFile {} {
|
|||||||
# Redraw calendar and restart daemon if needed
|
# Redraw calendar and restart daemon if needed
|
||||||
if {$ReminderFileModTime < $mtime} {
|
if {$ReminderFileModTime < $mtime} {
|
||||||
set ReminderFileModTime $mtime
|
set ReminderFileModTime $mtime
|
||||||
FillCalWindow
|
ScheduleUpdateForChanges
|
||||||
RestartBackgroundRemindDaemon
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -447,6 +488,7 @@ 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
|
global SetFontsWorked
|
||||||
|
global Option
|
||||||
set h [winfo screenheight .]
|
set h [winfo screenheight .]
|
||||||
if {$h <= 480} {
|
if {$h <= 480} {
|
||||||
if {$SetFontsWorked} {
|
if {$SetFontsWorked} {
|
||||||
@@ -461,7 +503,7 @@ proc CreateCalFrame { w dayNames } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
global MondayFirst
|
global MondayFirst
|
||||||
frame $w
|
frame $w -background $Option(WinBackground)
|
||||||
for {set i 0} {$i < 7} {incr i} {
|
for {set i 0} {$i < 7} {incr i} {
|
||||||
if {$MondayFirst} {
|
if {$MondayFirst} {
|
||||||
set index [expr ($i+1)%7]
|
set index [expr ($i+1)%7]
|
||||||
@@ -469,7 +511,7 @@ proc CreateCalFrame { w dayNames } {
|
|||||||
set index $i
|
set index $i
|
||||||
}
|
}
|
||||||
|
|
||||||
label $w.day$i -border 1 -text [lindex $dayNames $index] -justify center
|
label $w.day$i -border 1 -text [lindex $dayNames $index] -justify center -font HeadingFont -foreground $Option(LabelColor) -background $Option(WinBackground)
|
||||||
grid configure $w.day$i -row 0 -column $i -sticky ew
|
grid configure $w.day$i -row 0 -column $i -sticky ew
|
||||||
}
|
}
|
||||||
for {set i 0} {$i < 6} {incr i} {
|
for {set i 0} {$i < 6} {incr i} {
|
||||||
@@ -477,9 +519,9 @@ proc CreateCalFrame { w dayNames } {
|
|||||||
for {set j 0} {$j < 7} {incr j} {
|
for {set j 0} {$j < 7} {incr j} {
|
||||||
set f [expr $n+$j]
|
set f [expr $n+$j]
|
||||||
button $w.l$f -text "" -justify center -command "" \
|
button $w.l$f -text "" -justify center -command "" \
|
||||||
-state disabled -relief flat -border 0 -padx 0 -pady 0
|
-state disabled -relief flat -border 0 -padx 0 -pady 0 -font HeadingFont
|
||||||
text $w.t$f -width 12 -height $h -border 1 -spacing3 3 -wrap word -relief flat \
|
text $w.t$f -width 12 -height $h -border 1 -spacing3 3 -wrap word -relief flat \
|
||||||
-state disabled -takefocus 0 -cursor {}
|
-state disabled -takefocus 0 -cursor {} -font CalboxFont -foreground $Option(TextColor) -background $Option(BackgroundColor)
|
||||||
$w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
|
$w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
|
||||||
$w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f"
|
$w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f"
|
||||||
|
|
||||||
@@ -509,18 +551,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
|
global tk_version Option
|
||||||
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]
|
||||||
|
|
||||||
set bg [lindex [. 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 normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground)
|
||||||
|
$w.l$i configure -state disabled
|
||||||
balloon_add_help $w.l$i ""
|
balloon_add_help $w.l$i ""
|
||||||
$w.t$i configure -relief flat -takefocus 0 -state normal
|
$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
|
||||||
$w.t$i delete 1.0 end
|
$w.t$i delete 1.0 end
|
||||||
foreach t [$w.t$i tag names] {
|
foreach t [$w.t$i tag names] {
|
||||||
$w.t$i tag delete $t
|
$w.t$i tag delete $t
|
||||||
@@ -528,16 +569,14 @@ 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 $bg
|
|
||||||
$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
|
||||||
set d [expr $i-$first+1]
|
set d [expr $i-$first+1]
|
||||||
$w.l$i configure -text $d -state normal -relief flat \
|
$w.l$i configure -text $d -state normal -relief flat \
|
||||||
-command "ModifyDay $d $firstDay"
|
-command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground)
|
||||||
balloon_add_help $w.l$i "Add a reminder..."
|
balloon_add_help $w.l$i "Add a reminder..."
|
||||||
$w.t$i configure -relief sunken -takefocus 1 -state normal
|
$w.t$i configure -relief sunken -takefocus 1 -state normal -foreground $Option(TextColor) -background $Option(BackgroundColor)
|
||||||
$w.t$i delete 1.0 end
|
$w.t$i delete 1.0 end
|
||||||
foreach t [$w.t$i tag names] {
|
foreach t [$w.t$i tag names] {
|
||||||
$w.t$i tag delete $t
|
$w.t$i tag delete $t
|
||||||
@@ -545,8 +584,6 @@ 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 $bg
|
|
||||||
$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} {
|
||||||
@@ -559,11 +596,13 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
|||||||
grid rowconfigure $w $row -weight 0
|
grid rowconfigure $w $row -weight 0
|
||||||
grid rowconfigure $w [expr $row+1] -weight 0
|
grid rowconfigure $w [expr $row+1] -weight 0
|
||||||
} else {
|
} else {
|
||||||
|
grid $w.l$i $w.t$i
|
||||||
grid rowconfigure $w [expr $row+1] -weight 1
|
grid rowconfigure $w [expr $row+1] -weight 1
|
||||||
}
|
}
|
||||||
$w.l$i configure -text "" -command "" -state disabled -relief flat
|
$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground)
|
||||||
|
$w.l$i configure -state disabled
|
||||||
balloon_add_help $w.l$i ""
|
balloon_add_help $w.l$i ""
|
||||||
$w.t$i configure -relief flat -takefocus 0 -state normal
|
$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
|
||||||
$w.t$i delete 1.0 end
|
$w.t$i delete 1.0 end
|
||||||
foreach t [$w.t$i tag names] {
|
foreach t [$w.t$i tag names] {
|
||||||
$w.t$i tag delete $t
|
$w.t$i tag delete $t
|
||||||
@@ -571,8 +610,6 @@ 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 $bg
|
|
||||||
$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]
|
||||||
@@ -593,14 +630,14 @@ proc DoQueue {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc CreateCalWindow { dayNames } {
|
proc CreateCalWindow { dayNames } {
|
||||||
global Option
|
global Option
|
||||||
frame .h
|
frame .h -background $Option(WinBackground);
|
||||||
label .h.title -text "" -justify center -pady 1 -border 1 -relief raised
|
label .h.title -text "" -justify center -pady 1 -border 1 -relief raised -font HeadingFont -background $Option(WinBackground) -foreground $Option(LabelColor)
|
||||||
pack .h.title -side top -fill x
|
pack .h.title -side top -fill x
|
||||||
pack .h -side top -expand 0 -fill x
|
pack .h -side top -expand 0 -fill x
|
||||||
|
|
||||||
CreateCalFrame .cal $dayNames
|
CreateCalFrame .cal $dayNames
|
||||||
|
|
||||||
frame .b
|
frame .b -background $Option(WinBackground);
|
||||||
button .b.prev -image leftarrow -width 24 -command {MoveMonth -1} -border 1
|
button .b.prev -image leftarrow -width 24 -command {MoveMonth -1} -border 1
|
||||||
balloon_add_help .b.prev "Go to previous month"
|
balloon_add_help .b.prev "Go to previous month"
|
||||||
button .b.this -text {Today} -command {ThisMonth} -border 1
|
button .b.this -text {Today} -command {ThisMonth} -border 1
|
||||||
@@ -635,6 +672,7 @@ proc CreateCalWindow { dayNames } {
|
|||||||
bind . <KeyPress-Next> ".b.next flash; .b.next invoke"
|
bind . <KeyPress-Next> ".b.next flash; .b.next invoke"
|
||||||
bind . <KeyPress-Home> ".b.this flash; .b.this invoke"
|
bind . <KeyPress-Home> ".b.this flash; .b.this invoke"
|
||||||
|
|
||||||
|
. configure -background $Option(WinBackground)
|
||||||
if {$Option(StartIconified)} {
|
if {$Option(StartIconified)} {
|
||||||
wm iconify .
|
wm iconify .
|
||||||
}
|
}
|
||||||
@@ -736,6 +774,30 @@ proc EditOptions {} {
|
|||||||
pack $w.extraargs -in $w.eaf -side left -expand 1 -fill x
|
pack $w.extraargs -in $w.eaf -side left -expand 1 -fill x
|
||||||
$w.extraargs insert 0 $tmpOpt(ExtraRemindArgs)
|
$w.extraargs insert 0 $tmpOpt(ExtraRemindArgs)
|
||||||
|
|
||||||
|
# Fonts
|
||||||
|
frame $w.fframe
|
||||||
|
button $w.font -text "Change entry font..." -command "ChooseCalboxFont"
|
||||||
|
button $w.hfont -text "Change heading font..." -command "ChooseHeadingFont"
|
||||||
|
pack $w.font $w.hfont -in $w.fframe -side left -expand 1 -fill x
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
frame $w.colors1
|
||||||
|
label $w.textcolor -text "Text Color:"
|
||||||
|
button $w.btextcolor -background $Option(TextColor) -command [list PickColor TextColor $w.btextcolor] -text ...
|
||||||
|
label $w.bgcolor -text " Background color:"
|
||||||
|
button $w.bbgcolor -background $Option(BackgroundColor) -command [list PickColor BackgroundColor $w.bbgcolor] -text ...
|
||||||
|
|
||||||
|
grid $w.textcolor $w.btextcolor $w.bgcolor $w.bbgcolor -in $w.colors1
|
||||||
|
grid $w.bgcolor $w.bbgcolor -in $w.colors1
|
||||||
|
|
||||||
|
label $w.headcolor -text "Heading Color:"
|
||||||
|
button $w.bheadcolor -background $Option(LabelColor) -command [list PickColor LabelColor $w.bheadcolor] -text ...
|
||||||
|
label $w.wincolor -text " Window color:"
|
||||||
|
button $w.bwincolor -background $Option(WinBackground) -command [list PickColor WinBackground $w.bwincolor] -text ...
|
||||||
|
grid $w.headcolor $w.bheadcolor $w.wincolor $w.bwincolor -in $w.colors1
|
||||||
|
|
||||||
|
grid columnconfigure $w.colors1 0 -weight 1
|
||||||
|
grid columnconfigure $w.colors1 2 -weight 1
|
||||||
frame $w.sep1 -border 1 -relief sunken
|
frame $w.sep1 -border 1 -relief sunken
|
||||||
frame $w.sep2 -border 1 -relief sunken
|
frame $w.sep2 -border 1 -relief sunken
|
||||||
|
|
||||||
@@ -757,16 +819,23 @@ proc EditOptions {} {
|
|||||||
pack $w.fsmtp -in $w.f -side top -expand 0 -fill x
|
pack $w.fsmtp -in $w.f -side top -expand 0 -fill x
|
||||||
pack $w.ef -in $w.f -side top -expand 0 -fill x
|
pack $w.ef -in $w.f -side top -expand 0 -fill x
|
||||||
pack $w.eaf -in $w.f -side top -expand 0 -fill x
|
pack $w.eaf -in $w.f -side top -expand 0 -fill x
|
||||||
|
pack $w.fframe -in $w.f -side top -expand 0 -fill x
|
||||||
|
pack $w.colors1 -in $w.f -side top -expand 0 -fill x
|
||||||
pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1
|
pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1
|
||||||
|
|
||||||
button $w.apply -text "Apply Options" -command "ApplyOptions $w; destroy $w"
|
|
||||||
button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w"
|
button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w"
|
||||||
button $w.cancel -text "Cancel" -command "destroy $w"
|
button $w.cancel -text "Cancel" -command "CancelOptions; destroy $w"
|
||||||
|
wm protocol $w WM_DELETE_WINDOW "CancelOptions; destroy $w"
|
||||||
pack $w.apply $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
|
pack $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
|
||||||
CenterWindow $w .
|
CenterWindow $w .
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc CancelOptions { } {
|
||||||
|
global Option
|
||||||
|
font configure CalboxFont {*}$Option(CalboxFont)
|
||||||
|
font configure HeadingFont {*}$Option(HeadingFont)
|
||||||
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# %PROCEDURE: ApplyOptions
|
# %PROCEDURE: ApplyOptions
|
||||||
# %ARGUMENTS:
|
# %ARGUMENTS:
|
||||||
@@ -807,15 +876,15 @@ proc ApplyOptions { w } {
|
|||||||
# %RETURNS:
|
# %RETURNS:
|
||||||
# Nothing
|
# Nothing
|
||||||
# %DESCRIPTION:
|
# %DESCRIPTION:
|
||||||
# Saves options in $HOME/.tkremindrc
|
# Saves options in specified config file
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc SaveOptions { w } {
|
proc SaveOptions { w } {
|
||||||
global Option OptDescr
|
global Option OptDescr ConfigFile
|
||||||
ApplyOptions $w
|
ApplyOptions $w
|
||||||
|
|
||||||
set problem [catch {set f [open ~/.tkremindrc "w"]} err]
|
set problem [catch {set f [open $ConfigFile "w"]} err]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "Can't write ~/.tkremindrc: $err" 0 OK
|
tk_dialog .error Error "Can't write $ConfigFile: $err" 0 OK
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,6 +900,11 @@ proc SaveOptions { w } {
|
|||||||
}
|
}
|
||||||
puts $f ""
|
puts $f ""
|
||||||
close $f
|
close $f
|
||||||
|
FillCalWindow
|
||||||
|
.h.title configure -background $Option(WinBackground) -foreground $Option(LabelColor)
|
||||||
|
for {set i 0} {$i < 7} {incr i} {
|
||||||
|
.cal.day$i configure -foreground $Option(LabelColor) -background $Option(WinBackground)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
@@ -840,25 +914,31 @@ proc SaveOptions { w } {
|
|||||||
# %RETURNS:
|
# %RETURNS:
|
||||||
# Nothing
|
# Nothing
|
||||||
# %DESCRIPTION:
|
# %DESCRIPTION:
|
||||||
# Loads options from ~/.tkremindrc
|
# Loads options from $ConfigFile
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc LoadOptions {} {
|
proc LoadOptions {} {
|
||||||
global Option
|
global Option ConfigFile
|
||||||
set problem [catch {set f [open "~/.tkremindrc" "r"]}]
|
set problem [catch {set f [open "$ConfigFile" "r"]}]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
while {[gets $f line] >= 0} {
|
while {[gets $f line] >= 0} {
|
||||||
if {[string match "#*" $line]} { continue }
|
if {[string match "#*" $line]} {
|
||||||
if {$line == ""} { continue }
|
continue
|
||||||
foreach {key val} $line {}
|
}
|
||||||
if {![info exists Option($key)]} {
|
if {$line == ""} {
|
||||||
puts "Unknown option in ~/.tkremindrc: $key"
|
continue
|
||||||
continue
|
}
|
||||||
}
|
foreach {key val} $line {}
|
||||||
set Option($key) $val
|
if {![info exists Option($key)]} {
|
||||||
|
puts stderr "Unknown option in $ConfigFile: $key"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
set Option($key) $val
|
||||||
}
|
}
|
||||||
close $f
|
close $f
|
||||||
|
font configure CalboxFont {*}$Option(CalboxFont)
|
||||||
|
font configure HeadingFont {*}$Option(HeadingFont)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -925,8 +1005,8 @@ proc FillCalWindow {} {
|
|||||||
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
ConfigureCalWindow $monthName $year $firstWkday $daysInMonth
|
||||||
set offset [CalEntryOffset $firstWkday]
|
set offset [CalEntryOffset $firstWkday]
|
||||||
|
|
||||||
set fntag "x"
|
|
||||||
while { [gets $file line] >= 0 } {
|
while { [gets $file line] >= 0 } {
|
||||||
|
set fntag "x"
|
||||||
# Ignore unless begins with left brace
|
# Ignore unless begins with left brace
|
||||||
if { ! [string match "\{*" $line]} {
|
if { ! [string match "\{*" $line]} {
|
||||||
continue
|
continue
|
||||||
@@ -937,7 +1017,11 @@ proc FillCalWindow {} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if {[dict exists $obj filename]} {
|
if {[dict exists $obj filename]} {
|
||||||
set fntag [string cat "FILE_" [dict get $obj lineno] "_" [dict get $obj filename]]
|
set fname [dict get $obj filename]
|
||||||
|
# Don't make INCLUDECMD output editable
|
||||||
|
if {![string match "*|" $fname]} {
|
||||||
|
set fntag [string cat "FILE_" [dict get $obj lineno] "_" $fname]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set date [dict get $obj date]
|
set date [dict get $obj date]
|
||||||
@@ -962,7 +1046,8 @@ proc FillCalWindow {} {
|
|||||||
"WEEK" {
|
"WEEK" {
|
||||||
set stuff [string trimleft $stuff]
|
set stuff [string trimleft $stuff]
|
||||||
set stuff [string trimright $stuff]
|
set stuff [string trimright $stuff]
|
||||||
set label [expr $firstWkday + $day - 1]
|
set offset [CalEntryOffset $firstWkday]
|
||||||
|
set label [expr $offset + $day]
|
||||||
.cal.l$label configure -text "$day $stuff"
|
.cal.l$label configure -text "$day $stuff"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1006,13 +1091,17 @@ proc FillCalWindow {} {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
.cal.t$n configure -state normal
|
.cal.t$n configure -state normal
|
||||||
if {[regexp {TKTAG([0-9]+)} $tag all tagno]} {
|
if {[regexp {TKTAG([0-9]+)} $tag all tagno] && "$fntag" != "x"} {
|
||||||
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
.cal.t$n insert end [string trim $stuff] [list REM TAGGED "TKTAG$tagno" "date_$date" $extratags $fntag]
|
||||||
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
.cal.t$n tag bind "TKTAG$tagno" <Enter> "TaggedEnter .cal.t$n"
|
||||||
.cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
|
.cal.t$n tag bind "TKTAG$tagno" <Leave> "TaggedLeave .cal.t$n"
|
||||||
set TagToObj(TKTAG$tagno) $obj
|
set TagToObj(TKTAG$tagno) $obj
|
||||||
} else {
|
} else {
|
||||||
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
if {"$fntag" == "x" } {
|
||||||
|
.cal.t$n insert end [string trim $stuff] [list REM $extratags]
|
||||||
|
} else {
|
||||||
|
.cal.t$n insert end [string trim $stuff] [list REM $extratags $fntag]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.cal.t$n insert end "\n"
|
.cal.t$n insert end "\n"
|
||||||
.cal.t$n configure -state disabled
|
.cal.t$n configure -state disabled
|
||||||
@@ -1077,7 +1166,7 @@ proc Status { stuff } {
|
|||||||
# None
|
# None
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc DoPrint {} {
|
proc DoPrint {} {
|
||||||
global PrintDest PrintSize PrintMargins PrintOrient PrintFill PrintEncoding PrintSmallCalendars PrintStatus Rem2PS PSCmd Option
|
global PrintDest PrintSize PrintMargins PrintOrient PrintFill PrintDaysRight PrintEncoding PrintSmallCalendars PrintStatus Rem2PS PSCmd Option
|
||||||
global CurMonth CurYear MonthNames
|
global CurMonth CurYear MonthNames
|
||||||
catch {destroy .p}
|
catch {destroy .p}
|
||||||
toplevel .p
|
toplevel .p
|
||||||
@@ -1113,6 +1202,7 @@ proc DoPrint {} {
|
|||||||
radiobutton .p.portrait -text "Portrait" -variable PrintOrient -value portrait
|
radiobutton .p.portrait -text "Portrait" -variable PrintOrient -value portrait
|
||||||
|
|
||||||
checkbutton .p.fill -text "Fill page" -variable PrintFill
|
checkbutton .p.fill -text "Fill page" -variable PrintFill
|
||||||
|
checkbutton .p.right -text "Day numbers at top-right" -variable PrintDaysRight
|
||||||
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable PrintEncoding
|
checkbutton .p.encoding -text "ISO 8859-1 PostScript encoding" -variable PrintEncoding
|
||||||
checkbutton .p.calendars -text "Print small calendars" -variable PrintSmallCalendars
|
checkbutton .p.calendars -text "Print small calendars" -variable PrintSmallCalendars
|
||||||
|
|
||||||
@@ -1121,7 +1211,7 @@ proc DoPrint {} {
|
|||||||
|
|
||||||
pack .p.f1 .p.f2 .p.f2a .p.f3 .p.f3a \
|
pack .p.f1 .p.f2 .p.f2a .p.f3 .p.f3a \
|
||||||
-side top -fill both -expand 1 -anchor w
|
-side top -fill both -expand 1 -anchor w
|
||||||
pack .p.fill .p.encoding .p.calendars -in .p.f3a \
|
pack .p.fill .p.right .p.encoding .p.calendars -in .p.f3a \
|
||||||
-side top -anchor w -fill none -expand 0
|
-side top -anchor w -fill none -expand 0
|
||||||
pack .p.f4 -side top -fill both -expand 1 -anchor w
|
pack .p.f4 -side top -fill both -expand 1 -anchor w
|
||||||
pack .p.f11 .p.f12 -in .p.f1 -side top -fill none -expand 0 -anchor w
|
pack .p.f11 .p.f12 -in .p.f1 -side top -fill none -expand 0 -anchor w
|
||||||
@@ -1193,6 +1283,9 @@ proc DoPrint {} {
|
|||||||
append cmd " -e"
|
append cmd " -e"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if {!$PrintDaysRight} {
|
||||||
|
append cmd " -x"
|
||||||
|
}
|
||||||
if {$PrintEncoding} {
|
if {$PrintEncoding} {
|
||||||
append cmd " -i"
|
append cmd " -i"
|
||||||
}
|
}
|
||||||
@@ -1295,15 +1388,20 @@ proc DoGoto {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc Quit {} {
|
proc Quit {} {
|
||||||
global Option
|
global Option
|
||||||
|
global InotifyFP
|
||||||
if { !$Option(ConfirmQuit) } {
|
if { !$Option(ConfirmQuit) } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
exit
|
catch { exec kill [pid $InotifyFP] }
|
||||||
|
catch { close $InotifyFP }
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
exit
|
catch { exec kill [pid $InotifyFP] }
|
||||||
|
catch { close $InotifyFP }
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1747,6 +1845,7 @@ proc ModifyDay {d firstDay} {
|
|||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
while {1} {
|
while {1} {
|
||||||
grab .mod
|
grab .mod
|
||||||
|
raise .mod
|
||||||
focus .mod.entry
|
focus .mod.entry
|
||||||
set ModifyDialogResult -1
|
set ModifyDialogResult -1
|
||||||
tkwait variable ModifyDialogResult
|
tkwait variable ModifyDialogResult
|
||||||
@@ -1776,8 +1875,7 @@ proc ModifyDay {d firstDay} {
|
|||||||
WriteReminder $f TKTAG$HighestTagSoFar $rem $opts
|
WriteReminder $f TKTAG$HighestTagSoFar $rem $opts
|
||||||
close $f
|
close $f
|
||||||
|
|
||||||
FillCalWindow
|
ScheduleUpdateForChanges
|
||||||
RestartBackgroundRemindDaemon
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1894,7 +1992,7 @@ proc CreateReminder {w} {
|
|||||||
|
|
||||||
# Check it out!
|
# Check it out!
|
||||||
global Remind
|
global Remind
|
||||||
set f [open "|$Remind -arq -e -" r+]
|
set f [open "|$Remind -arq -e - 2>&1" r+]
|
||||||
puts $f "BANNER %"
|
puts $f "BANNER %"
|
||||||
puts $f "$rem MSG %"
|
puts $f "$rem MSG %"
|
||||||
puts $f "MSG %_%_%_%_"
|
puts $f "MSG %_%_%_%_"
|
||||||
@@ -1912,13 +2010,17 @@ proc CreateReminder {w} {
|
|||||||
return $rem
|
return $rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# We used to return YYYY-MM-DD, but reverted to
|
||||||
|
# day monthname year because this lets Remind produce
|
||||||
|
# much better error messages.
|
||||||
proc consolidate {y m d} {
|
proc consolidate {y m d} {
|
||||||
global MonthNames
|
global MonthNames
|
||||||
if {![regexp {^[0-9]+$} $m]} {
|
if {![regexp {^[0-9]+$} $m]} {
|
||||||
set m [lsearch -exact $MonthNames $m]
|
set m [lsearch -exact $MonthNames $m]
|
||||||
incr m
|
incr m
|
||||||
}
|
}
|
||||||
return [format "%04d-%02d-%02d" $y $m $d]
|
set mname [lindex $MonthNames [expr $m-1]]
|
||||||
|
return "$d $mname $y"
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -2340,8 +2442,12 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
# Starts a background Remind daemon to handle timed reminders
|
# Starts a background Remind daemon to handle timed reminders
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc StartBackgroundRemindDaemon {} {
|
proc StartBackgroundRemindDaemon {} {
|
||||||
global Remind DaemonFile ReminderFile Option
|
global Remind DaemonFile ReminderFile Option TwentyFourHourMode
|
||||||
set problem [catch { set DaemonFile [open "|$Remind -z0 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
if {$TwentyFourHourMode} {
|
||||||
|
set problem [catch { set DaemonFile [open "|$Remind -b1 -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||||
|
} else {
|
||||||
|
set problem [catch { set DaemonFile [open "|$Remind -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||||
|
}
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
|
||||||
} else {
|
} else {
|
||||||
@@ -2480,7 +2586,7 @@ proc DaemonReadable { file } {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
puts "Unknown message from daemon: $line\n"
|
puts stderr "Unknown message from daemon: $line\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2559,7 +2665,7 @@ proc IssueBackgroundReminder { file time now tag } {
|
|||||||
}
|
}
|
||||||
if {$Option(RunCmd) != ""} {
|
if {$Option(RunCmd) != ""} {
|
||||||
if {$Option(FeedReminder)} {
|
if {$Option(FeedReminder)} {
|
||||||
FeedReminderToCommand $Option(RunCmd) $msg
|
FeedReminderToCommand $Option(RunCmd) "$time: $msg"
|
||||||
} else {
|
} else {
|
||||||
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
||||||
}
|
}
|
||||||
@@ -2608,27 +2714,33 @@ proc CommandWritable { f msg } {
|
|||||||
|
|
||||||
|
|
||||||
proc main {} {
|
proc main {} {
|
||||||
# If no ~/.tkremindrc file, create an empty one
|
global ConfigFile
|
||||||
if {![file exists ~/.tkremindrc]} {
|
|
||||||
catch {
|
font create CalboxFont {*}[font actual TkFixedFont]
|
||||||
set f [open ~/.tkremindrc "w"]
|
font create HeadingFont {*}[font actual TkDefaultFont]
|
||||||
close $f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global AppendFile HighestTagSoFar DayNames
|
global AppendFile HighestTagSoFar DayNames
|
||||||
catch {
|
catch {
|
||||||
puts "\nTkRemind Copyright (C) 1996-2020 Dianne Skoll"
|
puts "\nTkRemind Copyright (C) 1996-2021 Dianne Skoll"
|
||||||
}
|
}
|
||||||
catch { SetFonts }
|
catch { SetFonts }
|
||||||
|
Initialize
|
||||||
|
|
||||||
|
# If no $ConfigFile file, create an empty one
|
||||||
|
if {![file exists $ConfigFile]} {
|
||||||
|
catch {
|
||||||
|
set f [open $ConfigFile "w"]
|
||||||
|
close $f
|
||||||
|
}
|
||||||
|
}
|
||||||
LoadOptions
|
LoadOptions
|
||||||
CreateMoonImages
|
CreateMoonImages
|
||||||
Initialize
|
|
||||||
ShowTodaysReminders
|
ShowTodaysReminders
|
||||||
ScanForTags $AppendFile
|
ScanForTags $AppendFile
|
||||||
CreateCalWindow $DayNames
|
CreateCalWindow $DayNames
|
||||||
FillCalWindow
|
FillCalWindow
|
||||||
StartBackgroundRemindDaemon
|
StartBackgroundRemindDaemon
|
||||||
|
SetupInotify
|
||||||
DisplayTimeContinuously
|
DisplayTimeContinuously
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2705,9 +2817,11 @@ proc ReadTaggedOptions { tag date } {
|
|||||||
lappend ans -text-day2 $d
|
lappend ans -text-day2 $d
|
||||||
}
|
}
|
||||||
if {[dict exists $obj m]} {
|
if {[dict exists $obj m]} {
|
||||||
lappend ans -text-mon1 [lindex $MonthNames [expr [dict get $obj m] -1]]
|
set m [dict get $obj m]
|
||||||
lappend ans -text-mon2 [lindex $MonthNames [expr [dict get $obj m] -1]]
|
set mm [string trimleft $m 0]
|
||||||
lappend ans -text-mon3 [lindex $MonthNames [expr [dict get $obj m] -1]]
|
lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
|
||||||
|
lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
|
||||||
|
lappend ans -text-mon3 [lindex $MonthNames [expr $mm -1]]
|
||||||
} else {
|
} else {
|
||||||
lappend ans -text-mon1 {every month}
|
lappend ans -text-mon1 {every month}
|
||||||
lappend ans -text-mon2 {every month}
|
lappend ans -text-mon2 {every month}
|
||||||
@@ -2746,7 +2860,8 @@ proc ReadTaggedOptions { tag date } {
|
|||||||
lappend ans -text-ordinal Last
|
lappend ans -text-ordinal Last
|
||||||
# Adjust month down and possibly year?
|
# Adjust month down and possibly year?
|
||||||
if {[dict exists $obj m]} {
|
if {[dict exists $obj m]} {
|
||||||
set idx [expr [dict get $obj m] -1]
|
set mm [string trimleft [dict get $obj m] 0]
|
||||||
|
set idx [expr $mm -1]
|
||||||
if {$idx <= 0} {
|
if {$idx <= 0} {
|
||||||
set idx 12
|
set idx 12
|
||||||
}
|
}
|
||||||
@@ -2792,15 +2907,18 @@ proc ReadTaggedOptions { tag date } {
|
|||||||
if {[dict exists $obj until]} {
|
if {[dict exists $obj until]} {
|
||||||
set u [dict get $obj until]
|
set u [dict get $obj until]
|
||||||
regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $u all yu mu du
|
regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $u all yu mu du
|
||||||
|
# Trim leading zeros, or Tcl complains
|
||||||
|
set mu [string trimleft $mu 0]
|
||||||
lappend ans -global-expbut 1
|
lappend ans -global-expbut 1
|
||||||
lappend ans -text-expday $du
|
lappend ans -text-expday $du
|
||||||
lappend ans -text-expmon [lindex $MonthNames [expr $mu-1]]
|
lappend ans -text-expmon [lindex $MonthNames [expr $mu-1]]
|
||||||
lappend ans -text-expyear $yu
|
lappend ans -text-expyear $yu
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
set mm [string trimleft $m 0]
|
||||||
lappend ans -global-expbut 0
|
lappend ans -global-expbut 0
|
||||||
lappend ans -text-expday $d
|
lappend ans -text-expday $d
|
||||||
lappend ans -text-expmon [lindex $MonthNames [expr $m-1]]
|
lappend ans -text-expmon [lindex $MonthNames [expr $mm-1]]
|
||||||
lappend ans -text-expyear $y
|
lappend ans -text-expyear $y
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3037,12 +3155,13 @@ proc TaggedEnter { w } {
|
|||||||
# Removes highlight from an "editable" reminder as mouse leaves it
|
# Removes highlight from an "editable" reminder as mouse leaves it
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc TaggedLeave { w } {
|
proc TaggedLeave { w } {
|
||||||
|
global Option
|
||||||
set tag [GetCurrentReminder $w]
|
set tag [GetCurrentReminder $w]
|
||||||
if {$tag != ""} {
|
if {$tag != ""} {
|
||||||
set tags [$w tag names current]
|
set tags [$w tag names current]
|
||||||
set index [lsearch -glob $tags "clr*"]
|
set index [lsearch -glob $tags "clr*"]
|
||||||
if {$index < 0} {
|
if {$index < 0} {
|
||||||
set fg "#000000"
|
set fg $Option(TextColor)
|
||||||
} else {
|
} else {
|
||||||
set fg [string range [lindex $tags $index] 3 end]
|
set fg [string range [lindex $tags $index] 3 end]
|
||||||
set fg "#$fg"
|
set fg "#$fg"
|
||||||
@@ -3088,6 +3207,7 @@ proc EditTaggedReminder { w } {
|
|||||||
tkwait visibility .mod
|
tkwait visibility .mod
|
||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
while {1} {
|
while {1} {
|
||||||
|
raise .mod
|
||||||
grab .mod
|
grab .mod
|
||||||
focus .mod.entry
|
focus .mod.entry
|
||||||
set ModifyDialogResult -1
|
set ModifyDialogResult -1
|
||||||
@@ -3123,12 +3243,38 @@ proc EditTaggedReminder { w } {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
FillCalWindow
|
ScheduleUpdateForChanges
|
||||||
RestartBackgroundRemindDaemon
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#***********************************************************************
|
||||||
|
# %PROCEDURE: UpdateForChanges
|
||||||
|
# Updates the calendar window and restarts background daemon because
|
||||||
|
# something has changed.
|
||||||
|
# %ARGUMENTS:
|
||||||
|
# None
|
||||||
|
# %RETURNS:
|
||||||
|
# Nothing
|
||||||
|
#***********************************************************************
|
||||||
|
proc UpdateForChanges {} {
|
||||||
|
global TimerUpdateForChanges
|
||||||
|
catch { after cancel $TimerUpdateForChanges }
|
||||||
|
FillCalWindow
|
||||||
|
RestartBackgroundRemindDaemon
|
||||||
|
}
|
||||||
|
|
||||||
|
# Schedule an update for 100ms in the future.
|
||||||
|
# That way, if we get a rapid succession of
|
||||||
|
# change notifications, we (probably) only
|
||||||
|
# end up doing one call to UpdateForChanges
|
||||||
|
proc ScheduleUpdateForChanges {} {
|
||||||
|
global TimerUpdateForChanges
|
||||||
|
catch { after cancel $TimerUpdateForChanges }
|
||||||
|
set TimerUpdateForChanges [after 100 UpdateForChanges]
|
||||||
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# %PROCEDURE: UniqueFileName
|
# %PROCEDURE: UniqueFileName
|
||||||
# %ARGUMENTS:
|
# %ARGUMENTS:
|
||||||
@@ -3407,6 +3553,7 @@ proc ShowTodaysReminders {} {
|
|||||||
global Option
|
global Option
|
||||||
global Remind
|
global Remind
|
||||||
global ReminderFile
|
global ReminderFile
|
||||||
|
global TwentyFourHourMode
|
||||||
if {!$Option(ShowTodaysReminders)} {
|
if {!$Option(ShowTodaysReminders)} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -3428,7 +3575,10 @@ proc ShowTodaysReminders {} {
|
|||||||
|
|
||||||
# Grab the reminders
|
# Grab the reminders
|
||||||
set stuff ""
|
set stuff ""
|
||||||
set cmdline "|$Remind -g -q -r "
|
set cmdline "|$Remind -itkremind=1 -g -q -r "
|
||||||
|
if {$TwentyFourHourMode} {
|
||||||
|
append cmdline "-b1 "
|
||||||
|
}
|
||||||
append cmdline $Option(ExtraRemindArgs);
|
append cmdline $Option(ExtraRemindArgs);
|
||||||
append cmdline " $ReminderFile 2>/dev/null"
|
append cmdline " $ReminderFile 2>/dev/null"
|
||||||
set f [open $cmdline r]
|
set f [open $cmdline r]
|
||||||
@@ -3453,8 +3603,7 @@ proc InteractiveDeleteReminder { tag } {
|
|||||||
set ans [tk_dialog .error "Really Delete" "Really delete reminder?" warning 0 No Yes]
|
set ans [tk_dialog .error "Really Delete" "Really delete reminder?" warning 0 No Yes]
|
||||||
if {$ans == 1} {
|
if {$ans == 1} {
|
||||||
DeleteTaggedReminder $tag
|
DeleteTaggedReminder $tag
|
||||||
FillCalWindow
|
ScheduleUpdateForChanges
|
||||||
RestartBackgroundRemindDaemon
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3507,10 +3656,35 @@ proc SetFonts {} {
|
|||||||
set SetFontsWorked 1
|
set SetFontsWorked 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set up inotify to watch for changes to reminder file/directory
|
||||||
|
proc SetupInotify {} {
|
||||||
|
global InotifyFP
|
||||||
|
global ReminderFile
|
||||||
|
set failed [catch {set InotifyFP [open "|inotifywait -q -m -e close_write -e move -e create -e delete $ReminderFile" "r"] } ]
|
||||||
|
if {$failed} {
|
||||||
|
# inotifywait probably not available... meh.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileevent $InotifyFP readable [list InotifyReadable $InotifyFP]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Called when inotifywait reports an event. Schedule a calendar update
|
||||||
|
# and daemon reload.
|
||||||
|
proc InotifyReadable { fp } {
|
||||||
|
catch { set num [gets $fp line] }
|
||||||
|
if {$num < 0} {
|
||||||
|
catch { exec kill [pid $fp] }
|
||||||
|
close $fp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ScheduleUpdateForChanges
|
||||||
|
}
|
||||||
|
|
||||||
### Balloon help
|
### Balloon help
|
||||||
set Balloon(HelpTime) 400
|
set Balloon(HelpTime) 400
|
||||||
set Balloon(StayTime) 3500
|
set Balloon(StayTime) 3500
|
||||||
set Balloon(Font) fixed
|
set Balloon(Font) fixed
|
||||||
|
set Balloon(MustLeave) 0
|
||||||
|
|
||||||
proc balloon_reset_timer { w } {
|
proc balloon_reset_timer { w } {
|
||||||
balloon_destroy_help_window
|
balloon_destroy_help_window
|
||||||
@@ -3624,4 +3798,40 @@ proc balloon_calculate_geometry { w } {
|
|||||||
return "+$tx+$ty"
|
return "+$tx+$ty"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc ChooseCalboxFont {} {
|
||||||
|
tk fontchooser show
|
||||||
|
tk fontchooser configure -font [font actual CalboxFont]
|
||||||
|
tk fontchooser configure -command SetCalboxFont
|
||||||
|
}
|
||||||
|
|
||||||
|
proc SetCalboxFont {font} {
|
||||||
|
global tmpOpt
|
||||||
|
font configure CalboxFont {*}[font actual $font]
|
||||||
|
set tmpOpt(CalboxFont) [font actual $font]
|
||||||
|
raise .opt
|
||||||
|
}
|
||||||
|
|
||||||
|
proc ChooseHeadingFont {} {
|
||||||
|
tk fontchooser show
|
||||||
|
tk fontchooser configure -font [font actual HeadingFont]
|
||||||
|
tk fontchooser configure -command SetHeadingFont
|
||||||
|
}
|
||||||
|
|
||||||
|
proc SetHeadingFont {font} {
|
||||||
|
global tmpOpt
|
||||||
|
font configure HeadingFont {*}[font actual $font]
|
||||||
|
set tmpOpt(HeadingFont) [font actual $font]
|
||||||
|
raise .opt
|
||||||
|
}
|
||||||
|
|
||||||
|
proc PickColor {index button} {
|
||||||
|
global tmpOpt
|
||||||
|
set x [tk_chooseColor -initialcolor $tmpOpt($index)]
|
||||||
|
if {"$x" != ""} {
|
||||||
|
set tmpOpt($index) $x
|
||||||
|
$button configure -background $x
|
||||||
|
}
|
||||||
|
raise .opt
|
||||||
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
|||||||
INSTALL_DATA=@INSTALL_DATA@
|
INSTALL_DATA=@INSTALL_DATA@
|
||||||
|
|
||||||
PROGS= remind rem2ps
|
PROGS= remind rem2ps
|
||||||
SCRIPTS= $(srcdir)/../scripts/tkremind $(srcdir)/../scripts/cm2rem.tcl
|
SCRIPTS= $(srcdir)/../scripts/tkremind
|
||||||
|
|
||||||
MANS= $(srcdir)/../man/rem2ps.1 $(srcdir)/../man/remind.1 \
|
MANS= $(srcdir)/../man/rem2ps.1 $(srcdir)/../man/remind.1 \
|
||||||
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/cm2rem.1 \
|
$(srcdir)/../man/tkremind.1 $(srcdir)/../man/rem.1
|
||||||
$(srcdir)/../man/rem.1
|
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
|
|||||||
117
src/calendar.c
117
src/calendar.c
@@ -5,10 +5,11 @@
|
|||||||
/* The code for generating a calendar. */
|
/* The code for generating a calendar. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
#define _XOPEN_SOURCE
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
|
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
#include <wchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@@ -266,7 +268,7 @@ void PrintJSONKeyPairInt(char const *name, int val)
|
|||||||
{
|
{
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":%d, ", val);
|
printf("\":%d,", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintJSONKeyPairString(char const *name, char const *val)
|
void PrintJSONKeyPairString(char const *name, char const *val)
|
||||||
@@ -280,7 +282,7 @@ void PrintJSONKeyPairString(char const *name, char const *val)
|
|||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"");
|
printf("\":\"");
|
||||||
PrintJSONString(val);
|
PrintJSONString(val);
|
||||||
printf("\", ");
|
printf("\",");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintJSONKeyPairDate(char const *name, int jul)
|
void PrintJSONKeyPairDate(char const *name, int jul)
|
||||||
@@ -293,7 +295,7 @@ void PrintJSONKeyPairDate(char const *name, int jul)
|
|||||||
FromJulian(jul, &y, &m, &d);
|
FromJulian(jul, &y, &m, &d);
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
printf("\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +313,7 @@ void PrintJSONKeyPairDateTime(char const *name, int dt)
|
|||||||
i = k % 60;
|
i = k % 60;
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%04d-%02d-%02dT%02d:%02d\", ", y, m+1, d, h, i);
|
printf("\":\"%04d-%02d-%02dT%02d:%02d\",", y, m+1, d, h, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +328,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
|
|||||||
i = t % 60;
|
i = t % 60;
|
||||||
printf("\"");
|
printf("\"");
|
||||||
PrintJSONString(name);
|
PrintJSONString(name);
|
||||||
printf("\":\"%02d:%02d\", ", h, i);
|
printf("\":\"%02d:%02d\",", h, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +358,7 @@ static int make_wchar_versions(CalEntry *e)
|
|||||||
if (!buf) return 0;
|
if (!buf) return 0;
|
||||||
|
|
||||||
(void) mbstowcs(buf, e->text, len+1);
|
(void) mbstowcs(buf, e->text, len+1);
|
||||||
|
buf[len] = 0;
|
||||||
e->wc_text = buf;
|
e->wc_text = buf;
|
||||||
e->wc_pos = buf;
|
e->wc_pos = buf;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -794,7 +797,7 @@ static int WriteCalendarRow(void)
|
|||||||
PrintLeft("", ColSpaces, ' ');
|
PrintLeft("", ColSpaces, ' ');
|
||||||
else {
|
else {
|
||||||
sprintf(buf, "%d ", d+i-wd);
|
sprintf(buf, "%d ", d+i-wd);
|
||||||
if (OrigJul+i == RealToday) {
|
if (Julian(y, m, d+i-wd) == RealToday) {
|
||||||
PrintLeft(buf, ColSpaces-1, '*');
|
PrintLeft(buf, ColSpaces-1, '*');
|
||||||
PutChar(' ');
|
PutChar(' ');
|
||||||
} else {
|
} else {
|
||||||
@@ -881,11 +884,21 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
|
|
||||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||||
for (i=0; i<width; i++) {
|
for (i=0; i<width; i++) {
|
||||||
if (*s) PutChar(*s++); else break;
|
if (*s) {
|
||||||
|
if (isspace(*s)) {
|
||||||
|
PutChar(' ');
|
||||||
|
s++;
|
||||||
|
} else {
|
||||||
|
PutChar(*s++);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||||
#else
|
#else
|
||||||
size_t len = mbstowcs(NULL, s, 0);
|
size_t len = mbstowcs(NULL, s, 0);
|
||||||
|
int display_len;
|
||||||
int i;
|
int i;
|
||||||
wchar_t static_buf[128];
|
wchar_t static_buf[128];
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
@@ -909,11 +922,25 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) mbstowcs(buf, s, len+1);
|
(void) mbstowcs(buf, s, len+1);
|
||||||
d = (width - len) / 2;
|
display_len = wcswidth(buf, len+1);
|
||||||
|
d = (width - display_len) / 2;
|
||||||
|
if (d < 0) d = 0;
|
||||||
ws = buf;
|
ws = buf;
|
||||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||||
for (i=0; i<width; i++) {
|
for (i=0; i<width; i++) {
|
||||||
if (*ws) PutWideChar(*ws++); else break;
|
if (*ws) {
|
||||||
|
PutWideChar(*ws++);
|
||||||
|
if (wcwidth(*ws) == 0) {
|
||||||
|
/* Don't count this character... it's zero-width */
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Mop up any potential combining characters */
|
||||||
|
while (*ws && wcwidth(*ws) == 0) {
|
||||||
|
PutWideChar(*ws++);
|
||||||
}
|
}
|
||||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||||
if (buf != static_buf) free(buf);
|
if (buf != static_buf) free(buf);
|
||||||
@@ -967,6 +994,7 @@ static int WriteOneColLine(int col)
|
|||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
wchar_t const *ws;
|
wchar_t const *ws;
|
||||||
wchar_t const *wspace;
|
wchar_t const *wspace;
|
||||||
|
int width;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int numwritten = 0;
|
int numwritten = 0;
|
||||||
@@ -991,9 +1019,18 @@ static int WriteOneColLine(int col)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find the last space char within the column. */
|
/* Find the last space char within the column. */
|
||||||
while (ws - e->wc_pos <= ColSpaces) {
|
width = 0;
|
||||||
if (!*ws) {wspace = ws; break;}
|
while (width <= ColSpaces) {
|
||||||
if (iswspace(*ws)) wspace = ws;
|
if (!*ws) {
|
||||||
|
wspace = ws;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (iswspace(*ws)) {
|
||||||
|
wspace = ws;
|
||||||
|
}
|
||||||
|
if (wcwidth(*ws)) {
|
||||||
|
width++;
|
||||||
|
}
|
||||||
ws++;
|
ws++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,16 +1043,30 @@ static int WriteOneColLine(int col)
|
|||||||
if (!wspace) {
|
if (!wspace) {
|
||||||
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) {
|
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) {
|
||||||
if (!*ws) break;
|
if (!*ws) break;
|
||||||
numwritten++;
|
if (iswspace(*ws)) {
|
||||||
PutWideChar(*ws);
|
PutChar(' ');
|
||||||
|
numwritten++;
|
||||||
|
} else {
|
||||||
|
if (wcwidth(*ws) > 0) {
|
||||||
|
numwritten += wcwidth(*ws);
|
||||||
|
}
|
||||||
|
PutWideChar(*ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e->wc_pos = ws;
|
e->wc_pos = ws;
|
||||||
} else {
|
} else {
|
||||||
/* We found a space - print everything before it. */
|
/* We found a space - print everything before it. */
|
||||||
for (ws = e->wc_pos; ws<wspace; ws++) {
|
for (ws = e->wc_pos; ws<wspace; ws++) {
|
||||||
if (!*ws) break;
|
if (!*ws) break;
|
||||||
numwritten++;
|
if (iswspace(*ws)) {
|
||||||
PutWideChar(*ws);
|
PutChar(' ');
|
||||||
|
numwritten++;
|
||||||
|
} else {
|
||||||
|
if (wcwidth(*ws) > 0) {
|
||||||
|
numwritten += wcwidth(*ws);
|
||||||
|
}
|
||||||
|
PutWideChar(*ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1116,7 @@ static int WriteOneColLine(int col)
|
|||||||
/* Find the last space char within the column. */
|
/* Find the last space char within the column. */
|
||||||
while (s - e->pos <= ColSpaces) {
|
while (s - e->pos <= ColSpaces) {
|
||||||
if (!*s) {space = s; break;}
|
if (!*s) {space = s; break;}
|
||||||
if (*s == ' ') space = s;
|
if (isspace(*s)) space = s;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,7 +1130,11 @@ static int WriteOneColLine(int col)
|
|||||||
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
||||||
if (!*s) break;
|
if (!*s) break;
|
||||||
numwritten++;
|
numwritten++;
|
||||||
PutChar(*s);
|
if (isspace(*s)) {
|
||||||
|
PutChar(' ');
|
||||||
|
} else {
|
||||||
|
PutChar(*s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e->pos = s;
|
e->pos = s;
|
||||||
} else {
|
} else {
|
||||||
@@ -1087,7 +1142,11 @@ static int WriteOneColLine(int col)
|
|||||||
for (s = e->pos; s<space; s++) {
|
for (s = e->pos; s<space; s++) {
|
||||||
if (!*s) break;
|
if (!*s) break;
|
||||||
numwritten++;
|
numwritten++;
|
||||||
PutChar(*s);
|
if (isspace(*s)) {
|
||||||
|
PutChar(' ');
|
||||||
|
} else {
|
||||||
|
PutChar(*s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1100,7 +1159,7 @@ static int WriteOneColLine(int col)
|
|||||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||||
|
|
||||||
/* Skip any spaces before next word */
|
/* Skip any spaces before next word */
|
||||||
while (*s == ' ') s++;
|
while (isspace(*s)) s++;
|
||||||
|
|
||||||
/* If done, free memory if no next entry. */
|
/* If done, free memory if no next entry. */
|
||||||
if (!*s && !e->next) {
|
if (!*s && !e->next) {
|
||||||
@@ -1180,6 +1239,7 @@ static void GenerateCalEntries(int col)
|
|||||||
case T_Else: r=DoElse(&p); break;
|
case T_Else: r=DoElse(&p); break;
|
||||||
case T_EndIf: r=DoEndif(&p); break;
|
case T_EndIf: r=DoEndif(&p); break;
|
||||||
case T_Include: r=DoInclude(&p); break;
|
case T_Include: r=DoInclude(&p); break;
|
||||||
|
case T_IncludeCmd: r=DoIncludeCmd(&p); break;
|
||||||
case T_Exit: DoExit(&p); break;
|
case T_Exit: DoExit(&p); break;
|
||||||
case T_Set: r=DoSet(&p); break;
|
case T_Set: r=DoSet(&p); break;
|
||||||
case T_Fset: r=DoFset(&p); break;
|
case T_Fset: r=DoFset(&p); break;
|
||||||
@@ -1325,6 +1385,9 @@ 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) {
|
if (r) {
|
||||||
|
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||||
|
r = OK;
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
if (r == E_EXPIRED) return OK;
|
if (r == E_EXPIRED) return OK;
|
||||||
return r;
|
return r;
|
||||||
@@ -1369,6 +1432,9 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
/* Calculate the trigger date */
|
/* Calculate the trigger date */
|
||||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||||
|
r = OK;
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1599,6 +1665,9 @@ static int DoCalRem(ParsePtr p, int col)
|
|||||||
if(!e->filename) {
|
if(!e->filename) {
|
||||||
if (e->text) free(e->text);
|
if (e->text) free(e->text);
|
||||||
if (e->raw_text) free(e->raw_text);
|
if (e->raw_text) free(e->raw_text);
|
||||||
|
#ifdef REM_USE_WCHAR
|
||||||
|
if (e->wc_text) free(e->wc_text);
|
||||||
|
#endif
|
||||||
free(e);
|
free(e);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
@@ -1687,7 +1756,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
|||||||
printf("\"%s\"", EnglishDayName[i]);
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("], ");
|
printf("],");
|
||||||
}
|
}
|
||||||
if (e->trig.d != NO_DAY) {
|
if (e->trig.d != NO_DAY) {
|
||||||
PrintJSONKeyPairInt("d", e->trig.d);
|
PrintJSONKeyPairInt("d", e->trig.d);
|
||||||
@@ -1740,7 +1809,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
|||||||
printf("\"%s\"", EnglishDayName[i]);
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("], ");
|
printf("],");
|
||||||
}
|
}
|
||||||
PrintJSONKeyPairDate("until", e->trig.until);
|
PrintJSONKeyPairDate("until", e->trig.until);
|
||||||
if (e->trig.once != NO_ONCE) {
|
if (e->trig.once != NO_ONCE) {
|
||||||
@@ -1809,7 +1878,7 @@ static void WriteSimpleEntries(int col, int jul)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DidADay = 1;
|
DidADay = 1;
|
||||||
printf("{\"date\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
printf("{\"date\":\"%04d-%02d-%02d\",", y, m+1, d);
|
||||||
WriteSimpleEntryProtocol2(e, jul);
|
WriteSimpleEntryProtocol2(e, jul);
|
||||||
printf("}");
|
printf("}");
|
||||||
if (PsCal != PSCAL_LEVEL3) {
|
if (PsCal != PSCAL_LEVEL3) {
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
/* 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 <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
/* Define if you have the <glob.h> header file */
|
/* Define if you have the <glob.h> header file */
|
||||||
#undef HAVE_GLOB_H
|
#undef HAVE_GLOB_H
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
|
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
|
||||||
/* any less than 12. */
|
/* any less than 12. */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define VAR_NAME_LEN 16
|
#define VAR_NAME_LEN 64
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* MAX_PRT_LEN: The maximum number of characters to print when */
|
/* MAX_PRT_LEN: The maximum number of characters to print when */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
|
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
|
||||||
/* any less than 12. */
|
/* any less than 12. */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define VAR_NAME_LEN 16
|
#define VAR_NAME_LEN 64
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* MAX_PRT_LEN: The maximum number of characters to print when */
|
/* MAX_PRT_LEN: The maximum number of characters to print when */
|
||||||
|
|||||||
39
src/dorem.c
39
src/dorem.c
@@ -7,7 +7,7 @@
|
|||||||
/* commands. */
|
/* commands. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -24,10 +24,6 @@
|
|||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
/* Define the shell characters not to escape */
|
|
||||||
static char const DontEscapeMe[] =
|
|
||||||
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
|
|
||||||
|
|
||||||
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
|
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);
|
||||||
@@ -81,6 +77,9 @@ int DoRem(ParsePtr p)
|
|||||||
PurgeEchoLine("%s\n", CurLine);
|
PurgeEchoLine("%s\n", CurLine);
|
||||||
r=DoSatRemind(&trig, &tim, p);
|
r=DoSatRemind(&trig, &tim, p);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||||
|
r = OK;
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
if (r == E_EXPIRED) return OK;
|
if (r == E_EXPIRED) return OK;
|
||||||
return r;
|
return r;
|
||||||
@@ -134,6 +133,9 @@ int DoRem(ParsePtr p)
|
|||||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||||
PurgeEchoLine("%s\n", CurLine);
|
PurgeEchoLine("%s\n", CurLine);
|
||||||
}
|
}
|
||||||
|
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||||
|
r = OK;
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -219,6 +221,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
trig->duration_days = 0;
|
trig->duration_days = 0;
|
||||||
trig->eventstart = NO_TIME;
|
trig->eventstart = NO_TIME;
|
||||||
trig->eventduration = NO_TIME;
|
trig->eventduration = NO_TIME;
|
||||||
|
trig->maybe_uncomputable = 0;
|
||||||
DBufInit(&(trig->tags));
|
DBufInit(&(trig->tags));
|
||||||
trig->passthru[0] = 0;
|
trig->passthru[0] = 0;
|
||||||
tim->ttime = NO_TIME;
|
tim->ttime = NO_TIME;
|
||||||
@@ -276,6 +279,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
|||||||
trig->m = tok.val;
|
trig->m = tok.val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_MaybeUncomputable:
|
||||||
|
trig->maybe_uncomputable = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case T_Skip:
|
case T_Skip:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
if (trig->skip != NO_SKIP) return E_SKIP_ERR;
|
if (trig->skip != NO_SKIP) return E_SKIP_ERR;
|
||||||
@@ -987,7 +994,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
system(DBufValue(&buf));
|
System(DBufValue(&buf));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* Unknown/illegal type? */
|
default: /* Unknown/illegal type? */
|
||||||
@@ -1219,24 +1226,16 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
|||||||
DynamicBuffer execBuffer;
|
DynamicBuffer execBuffer;
|
||||||
|
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
char const *s;
|
|
||||||
|
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
DBufInit(&execBuffer);
|
DBufInit(&execBuffer);
|
||||||
|
|
||||||
/* Escape shell characters in msg INCLUDING WHITESPACE! */
|
/* Escape shell characters in msg */
|
||||||
for (s=msg; *s; s++) {
|
if (ShellEscape(msg, &buf) != OK) {
|
||||||
if (isspace(*s) || !strchr(DontEscapeMe, *s)) {
|
r = E_NO_MEM;
|
||||||
if (DBufPutc(&buf, '\\') != OK) {
|
goto finished;
|
||||||
r = E_NO_MEM;
|
|
||||||
goto finished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DBufPutc(&buf, *s) != OK) {
|
|
||||||
r = E_NO_MEM;
|
|
||||||
goto finished;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = DBufValue(&buf);
|
msg = DBufValue(&buf);
|
||||||
|
|
||||||
/* Do "%s" substitution */
|
/* Do "%s" substitution */
|
||||||
@@ -1257,7 +1256,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
|||||||
}
|
}
|
||||||
r = OK;
|
r = OK;
|
||||||
|
|
||||||
system(DBufValue(&execBuffer));
|
System(DBufValue(&execBuffer));
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* reminders are triggered. */
|
/* reminders are triggered. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* buffers. */
|
/* buffers. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -150,7 +150,9 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
|
|||||||
we can usually save some unnecessary copying */
|
we can usually save some unnecessary copying */
|
||||||
|
|
||||||
*(dbuf->buffer) = 0;
|
*(dbuf->buffer) = 0;
|
||||||
fgets(dbuf->buffer, dbuf->allocatedLen, fp);
|
if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
if (!*(dbuf->buffer)) return OK;
|
if (!*(dbuf->buffer)) return OK;
|
||||||
dbuf->len = strlen(dbuf->buffer);
|
dbuf->len = strlen(dbuf->buffer);
|
||||||
l = dbuf->len - 1;
|
l = dbuf->len - 1;
|
||||||
@@ -162,7 +164,7 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
|
|||||||
|
|
||||||
while(busy) {
|
while(busy) {
|
||||||
*tmp = 0;
|
*tmp = 0;
|
||||||
fgets(tmp, 256, fp);
|
if (fgets(tmp, 256, fp) == NULL) return OK;
|
||||||
if (!*tmp) return OK;
|
if (!*tmp) return OK;
|
||||||
l = strlen(tmp) - 1;
|
l = strlen(tmp) - 1;
|
||||||
if (tmp[l] == '\n') {
|
if (tmp[l] == '\n') {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Declaration of functions for manipulating dynamic buffers */
|
/* Declaration of functions for manipulating dynamic buffers */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Error definitions. */
|
/* Error definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
51
src/expr.c
51
src/expr.c
@@ -5,7 +5,7 @@
|
|||||||
/* This file contains routines to parse and evaluate */
|
/* This file contains routines to parse and evaluate */
|
||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* Copyright 1992-2020 by Dianne Skoll */
|
/* Copyright 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -493,6 +494,7 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
|||||||
int len;
|
int len;
|
||||||
int h, m, r;
|
int h, m, r;
|
||||||
int ampm = 0;
|
int ampm = 0;
|
||||||
|
int prev_val;
|
||||||
|
|
||||||
if (*s == '\"') { /* It's a literal string "*/
|
if (*s == '\"') { /* It's a literal string "*/
|
||||||
len = strlen(s)-1;
|
len = strlen(s)-1;
|
||||||
@@ -519,9 +521,15 @@ static int MakeValue(char const *s, Value *v, Var *locals, ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
} else if (isdigit(*s)) { /* It's a number - use len to hold it.*/
|
||||||
len = 0;
|
len = 0;
|
||||||
|
prev_val = 0;
|
||||||
while (*s && isdigit(*s)) {
|
while (*s && isdigit(*s)) {
|
||||||
len *= 10;
|
len *= 10;
|
||||||
len += (*s++ - '0');
|
len += (*s++ - '0');
|
||||||
|
if (len < prev_val) {
|
||||||
|
/* We overflowed */
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
prev_val = len;
|
||||||
}
|
}
|
||||||
if (*s == ':' || *s == '.' || *s == TimeSep) { /* Must be a literal time */
|
if (*s == ':' || *s == '.' || *s == TimeSep) { /* Must be a literal time */
|
||||||
s++;
|
s++;
|
||||||
@@ -758,15 +766,22 @@ static int Add(void)
|
|||||||
|
|
||||||
/* If both are ints, just add 'em */
|
/* If both are ints, just add 'em */
|
||||||
if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
|
if (v2.type == INT_TYPE && v1.type == INT_TYPE) {
|
||||||
v2.v.val += v1.v.val;
|
int old = v1.v.val;
|
||||||
PushValStack(v2);
|
v1.v.val += v2.v.val;
|
||||||
|
/* Check for overflow */
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's a date plus an int, add 'em */
|
/* If it's a date plus an int, add 'em */
|
||||||
if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
|
if ((v1.type == DATE_TYPE && v2.type == INT_TYPE) ||
|
||||||
(v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
|
(v1.type == INT_TYPE && v2.type == DATE_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val += v2.v.val;
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
v1.type = DATE_TYPE;
|
v1.type = DATE_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -776,7 +791,9 @@ static int Add(void)
|
|||||||
/* If it's a datetime plus an int or a time, add 'em */
|
/* If it's a datetime plus an int or a time, add 'em */
|
||||||
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
||||||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val += v2.v.val;
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
v1.type = DATETIME_TYPE;
|
v1.type = DATETIME_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -788,7 +805,10 @@ static int Add(void)
|
|||||||
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
||||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
||||||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
||||||
v1.v.val = (v1.v.val + v2.v.val) % MINUTES_PER_DAY;
|
int old = v1.v.val;
|
||||||
|
v1.v.val += v2.v.val;
|
||||||
|
if (_private_add_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
|
v1.v.val = v1.v.val % MINUTES_PER_DAY;
|
||||||
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
||||||
v1.type = TIME_TYPE;
|
v1.type = TIME_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
@@ -848,14 +868,18 @@ static int Subtract(void)
|
|||||||
|
|
||||||
/* If they're both INTs, do subtraction */
|
/* If they're both INTs, do subtraction */
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_2HIGH;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it's a date minus an int, do subtraction, checking for underflow */
|
/* If it's a date minus an int, do subtraction, checking for underflow */
|
||||||
if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == DATE_TYPE && v2.type == INT_TYPE) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -864,7 +888,9 @@ static int Subtract(void)
|
|||||||
/* If it's a datetime minus an int or a time, do subtraction,
|
/* If it's a datetime minus an int or a time, do subtraction,
|
||||||
* checking for underflow */
|
* checking for underflow */
|
||||||
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
if (v1.v.val < 0) return E_DATE_OVER;
|
if (v1.v.val < 0) return E_DATE_OVER;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -882,7 +908,9 @@ static int Subtract(void)
|
|||||||
if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) ||
|
if ((v1.type == TIME_TYPE && v2.type == TIME_TYPE) ||
|
||||||
(v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) ||
|
(v1.type == DATETIME_TYPE && v2.type == DATETIME_TYPE) ||
|
||||||
(v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
|
(v1.type == DATE_TYPE && v2.type == DATE_TYPE)) {
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val -= v2.v.val;
|
v1.v.val -= v2.v.val;
|
||||||
|
if (_private_sub_overflow(v1.v.val, v2.v.val, old)) return E_DATE_OVER;
|
||||||
v1.type = INT_TYPE;
|
v1.type = INT_TYPE;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -912,7 +940,16 @@ static int Multiply(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
|
/* Prevent floating-point exception */
|
||||||
|
if ((v2.v.val == -1 && v1.v.val == INT_MIN) ||
|
||||||
|
(v1.v.val == -1 && v2.v.val == INT_MIN)) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
|
int old = v1.v.val;
|
||||||
v1.v.val *= v2.v.val;
|
v1.v.val *= v2.v.val;
|
||||||
|
if (v2.v.val != 0) {
|
||||||
|
if (_private_div(v1.v.val, v2.v.val) != old) return E_2HIGH;
|
||||||
|
}
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -940,6 +977,10 @@ static int Divide(void)
|
|||||||
|
|
||||||
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
if (v1.type == INT_TYPE && v2.type == INT_TYPE) {
|
||||||
if (v2.v.val == 0) return E_DIV_ZERO;
|
if (v2.v.val == 0) return E_DIV_ZERO;
|
||||||
|
/* This is the only way it can overflow */
|
||||||
|
if (v2.v.val == -1 && v1.v.val == INT_MIN) {
|
||||||
|
return E_2HIGH;
|
||||||
|
}
|
||||||
v1.v.val /= v2.v.val;
|
v1.v.val /= v2.v.val;
|
||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -1114,7 +1155,9 @@ static int UnMinus(void)
|
|||||||
{
|
{
|
||||||
Value *v = &ValStack[ValStackPtr-1];
|
Value *v = &ValStack[ValStackPtr-1];
|
||||||
if (v->type != INT_TYPE) return E_BAD_TYPE;
|
if (v->type != INT_TYPE) return E_BAD_TYPE;
|
||||||
|
int old = v->v.val;
|
||||||
v->v.val = -v->v.val;
|
v->v.val = -v->v.val;
|
||||||
|
if (_private_unminus_overflow(old, v->v.val)) return E_2HIGH;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/expr.h
11
src/expr.h
@@ -5,7 +5,7 @@
|
|||||||
/* Contains a few definitions used by expression evaluator. */
|
/* Contains a few definitions used by expression evaluator. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -53,3 +53,12 @@ if (ValStackPtr <= 0) \
|
|||||||
return E_VA_STK_UNDER; \
|
return E_VA_STK_UNDER; \
|
||||||
else \
|
else \
|
||||||
(val) = ValStack[--ValStackPtr]
|
(val) = ValStack[--ValStackPtr]
|
||||||
|
|
||||||
|
/* These functions are in utils.c and are used to detect overflow
|
||||||
|
in various arithmetic operators. They have to be in separate
|
||||||
|
functions with extern linkage to defeat compiler optimizations
|
||||||
|
that would otherwise break the overflow checks. */
|
||||||
|
extern int _private_div(int a, int b);
|
||||||
|
extern int _private_add_overflow(int result, int b, int old);
|
||||||
|
extern int _private_sub_overflow(int result, int b, int old);
|
||||||
|
extern int _private_unminus_overflow(int a, int b);
|
||||||
|
|||||||
287
src/files.c
287
src/files.c
@@ -7,7 +7,7 @@
|
|||||||
/* files. */
|
/* files. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -40,8 +40,9 @@
|
|||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
|
||||||
|
|
||||||
/* Convenient macro for closing files */
|
/* Convenient macros for closing files */
|
||||||
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
|
#define PCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
|
|
||||||
/* Define the structures needed by the file caching system */
|
/* Define the structures needed by the file caching system */
|
||||||
typedef struct cache {
|
typedef struct cache {
|
||||||
@@ -91,12 +92,12 @@ static FILE *fp;
|
|||||||
static IncludeStruct IStack[INCLUDE_NEST];
|
static IncludeStruct IStack[INCLUDE_NEST];
|
||||||
static int IStackPtr = 0;
|
static int IStackPtr = 0;
|
||||||
|
|
||||||
static int ReadLineFromFile (void);
|
static int ReadLineFromFile (int use_pclose);
|
||||||
static int CacheFile (char const *fname);
|
static int CacheFile (char const *fname, int use_pclose);
|
||||||
static void DestroyCache (CachedFile *cf);
|
static void DestroyCache (CachedFile *cf);
|
||||||
static int CheckSafety (void);
|
static int CheckSafety (void);
|
||||||
static int PopFile (void);
|
static int PopFile (void);
|
||||||
|
static int IncludeCmd(char const *);
|
||||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||||
{
|
{
|
||||||
DynamicBuffer fname_buf;
|
DynamicBuffer fname_buf;
|
||||||
@@ -167,7 +168,7 @@ int ReadLine(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Not cached. Read from the file. */
|
/* Not cached. Read from the file. */
|
||||||
return ReadLineFromFile();
|
return ReadLineFromFile(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -177,7 +178,7 @@ int ReadLine(void)
|
|||||||
/* Read a line from the file pointed to by fp. */
|
/* Read a line from the file pointed to by fp. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int ReadLineFromFile(void)
|
static int ReadLineFromFile(int use_pclose)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
char copy_buffer[4096];
|
char copy_buffer[4096];
|
||||||
@@ -200,7 +201,11 @@ static int ReadLineFromFile(void)
|
|||||||
return E_IO_ERR;
|
return E_IO_ERR;
|
||||||
}
|
}
|
||||||
if (feof(fp)) {
|
if (feof(fp)) {
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
if ((DBufLen(&buf) == 0) &&
|
if ((DBufLen(&buf) == 0) &&
|
||||||
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
(DBufLen(&LineBuffer) == 0) && PurgeMode) {
|
||||||
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
if (PurgeFP != NULL && PurgeFP != stdout) fclose(PurgeFP);
|
||||||
@@ -248,7 +253,11 @@ static int ReadLineFromFile(void)
|
|||||||
if (PurgeFP != stdout) fclose(PurgeFP);
|
if (PurgeFP != stdout) fclose(PurgeFP);
|
||||||
PurgeFP = NULL;
|
PurgeFP = NULL;
|
||||||
}
|
}
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
CurLine = DBufValue(&LineBuffer);
|
CurLine = DBufValue(&LineBuffer);
|
||||||
}
|
}
|
||||||
@@ -282,9 +291,6 @@ int OpenFile(char const *fname)
|
|||||||
PurgeFP = NULL;
|
PurgeFP = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume we own the file for now */
|
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
|
||||||
|
|
||||||
/* If it's in the cache, get it from there. */
|
/* If it's in the cache, get it from there. */
|
||||||
|
|
||||||
while (h) {
|
while (h) {
|
||||||
@@ -297,7 +303,9 @@ int OpenFile(char const *fname)
|
|||||||
LineNo = 0;
|
LineNo = 0;
|
||||||
if (!h->ownedByMe) {
|
if (!h->ownedByMe) {
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
}
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
}
|
||||||
if (FileName) return OK; else return E_NO_MEM;
|
if (FileName) return OK; else return E_NO_MEM;
|
||||||
}
|
}
|
||||||
h = h->next;
|
h = h->next;
|
||||||
@@ -306,6 +314,7 @@ int OpenFile(char const *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;
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
if (PurgeMode) {
|
if (PurgeMode) {
|
||||||
PurgeFP = stdout;
|
PurgeFP = stdout;
|
||||||
}
|
}
|
||||||
@@ -325,7 +334,7 @@ int OpenFile(char const *fname)
|
|||||||
CLine = NULL;
|
CLine = NULL;
|
||||||
if (ShouldCache) {
|
if (ShouldCache) {
|
||||||
LineNo = 0;
|
LineNo = 0;
|
||||||
r = CacheFile(fname);
|
r = CacheFile(fname, 0);
|
||||||
if (r == OK) {
|
if (r == OK) {
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
CLine = CachedFiles->cache;
|
CLine = CachedFiles->cache;
|
||||||
@@ -353,7 +362,7 @@ int OpenFile(char const *fname)
|
|||||||
/* Returns an indication of success or failure. */
|
/* Returns an indication of success or failure. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int CacheFile(char const *fname)
|
static int CacheFile(char const *fname, int use_pclose)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
CachedFile *cf;
|
CachedFile *cf;
|
||||||
@@ -366,16 +375,24 @@ static int CacheFile(char const *fname)
|
|||||||
cl = NULL;
|
cl = NULL;
|
||||||
/* Create a file header */
|
/* Create a file header */
|
||||||
cf = NEW(CachedFile);
|
cf = NEW(CachedFile);
|
||||||
cf->cache = NULL;
|
|
||||||
if (!cf) {
|
if (!cf) {
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
cf->cache = NULL;
|
||||||
cf->filename = StrDup(fname);
|
cf->filename = StrDup(fname);
|
||||||
if (!cf->filename) {
|
if (!cf->filename) {
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
free(cf);
|
free(cf);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
@@ -388,11 +405,15 @@ static int CacheFile(char const *fname)
|
|||||||
|
|
||||||
/* Read the file */
|
/* Read the file */
|
||||||
while(fp) {
|
while(fp) {
|
||||||
r = ReadLineFromFile();
|
r = ReadLineFromFile(use_pclose);
|
||||||
if (r) {
|
if (r) {
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* Skip blank chars */
|
/* Skip blank chars */
|
||||||
@@ -406,7 +427,11 @@ static int CacheFile(char const *fname)
|
|||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
cl = cf->cache;
|
cl = cf->cache;
|
||||||
@@ -416,7 +441,11 @@ static int CacheFile(char const *fname)
|
|||||||
DBufFree(&LineBuffer);
|
DBufFree(&LineBuffer);
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
@@ -428,7 +457,11 @@ static int CacheFile(char const *fname)
|
|||||||
if (!cl->text) {
|
if (!cl->text) {
|
||||||
DestroyCache(cf);
|
DestroyCache(cf);
|
||||||
ShouldCache = 0;
|
ShouldCache = 0;
|
||||||
FCLOSE(fp);
|
if (use_pclose) {
|
||||||
|
PCLOSE(fp);
|
||||||
|
} else {
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,9 +504,6 @@ static int PopFile(void)
|
|||||||
{
|
{
|
||||||
IncludeStruct *i;
|
IncludeStruct *i;
|
||||||
|
|
||||||
/* Assume we own the file for now */
|
|
||||||
RunDisabled &= ~RUN_NOTOWNER;
|
|
||||||
|
|
||||||
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];
|
i = &IStack[IStackPtr-1];
|
||||||
@@ -500,8 +530,10 @@ static int PopFile(void)
|
|||||||
STRSET(FileName, i->filename);
|
STRSET(FileName, i->filename);
|
||||||
if (!i->ownedByMe) {
|
if (!i->ownedByMe) {
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
}
|
}
|
||||||
if (!CLine && (i->offset != -1L)) {
|
if (!CLine && (i->offset != -1L || !strcmp(i->filename, "-"))) {
|
||||||
/* We must open the file, then seek to specified position */
|
/* We must open the file, then seek to specified position */
|
||||||
if (strcmp(i->filename, "-")) {
|
if (strcmp(i->filename, "-")) {
|
||||||
fp = fopen(i->filename, "r");
|
fp = fopen(i->filename, "r");
|
||||||
@@ -544,6 +576,64 @@ int DoInclude(ParsePtr p)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* DoIncludeCmd */
|
||||||
|
/* */
|
||||||
|
/* The INCLUDECMD command. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int DoIncludeCmd(ParsePtr p)
|
||||||
|
{
|
||||||
|
DynamicBuffer buf;
|
||||||
|
int r;
|
||||||
|
int ch;
|
||||||
|
char append_buf[2];
|
||||||
|
int seen_nonspace = 0;
|
||||||
|
|
||||||
|
append_buf[1] = 0;
|
||||||
|
|
||||||
|
DBufInit(&buf);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
ch = ParseChar(p, &r, 0);
|
||||||
|
if (r) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (!ch) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isspace(ch) && !seen_nonspace) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
seen_nonspace = 1;
|
||||||
|
/* Convert \n to ' ' to better handle line continuation */
|
||||||
|
if (ch == '\n') {
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
|
append_buf[0] = (char) ch;
|
||||||
|
if (DBufPuts(&buf, append_buf) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RunDisabled) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_RUN_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (r=IncludeCmd(DBufValue(&buf))) ) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
DBufFree(&buf);
|
||||||
|
NumIfs = 0;
|
||||||
|
IfFlags = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GLOB
|
#ifdef HAVE_GLOB
|
||||||
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||||
{
|
{
|
||||||
@@ -664,6 +754,127 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* IncludeCmd */
|
||||||
|
/* */
|
||||||
|
/* Process the INCLUDECMD command - actually do the command */
|
||||||
|
/* inclusion. */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static int IncludeCmd(char const *cmd)
|
||||||
|
{
|
||||||
|
IncludeStruct *i;
|
||||||
|
DynamicBuffer buf;
|
||||||
|
FILE *fp2;
|
||||||
|
int r;
|
||||||
|
CachedFile *h;
|
||||||
|
char const *fname;
|
||||||
|
int old_flag;
|
||||||
|
|
||||||
|
FreshLine = 1;
|
||||||
|
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
|
||||||
|
i = &IStack[IStackPtr];
|
||||||
|
|
||||||
|
/* Use "cmd|" as the filename */
|
||||||
|
DBufInit(&buf);
|
||||||
|
if (DBufPuts(&buf, cmd) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
if (DBufPuts(&buf, "|") != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
fname = DBufValue(&buf);
|
||||||
|
|
||||||
|
if (FileName) {
|
||||||
|
i->filename = StrDup(FileName);
|
||||||
|
if (!i->filename) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i->filename = NULL;
|
||||||
|
}
|
||||||
|
i->ownedByMe = 1;
|
||||||
|
i->LineNo = LineNo;
|
||||||
|
i->NumIfs = NumIfs;
|
||||||
|
i->IfFlags = IfFlags;
|
||||||
|
i->CLine = CLine;
|
||||||
|
i->offset = -1L;
|
||||||
|
i->chain = NULL;
|
||||||
|
if (fp) {
|
||||||
|
i->offset = ftell(fp);
|
||||||
|
FCLOSE(fp);
|
||||||
|
}
|
||||||
|
IStackPtr++;
|
||||||
|
|
||||||
|
/* If the file is cached, use it */
|
||||||
|
h = CachedFiles;
|
||||||
|
while(h) {
|
||||||
|
if (!strcmp(fname, h->filename)) {
|
||||||
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
|
fprintf(ErrFp, "Reading command `%s': Found in cache\n", fname);
|
||||||
|
}
|
||||||
|
CLine = h->cache;
|
||||||
|
STRSET(FileName, fname);
|
||||||
|
DBufFree(&buf);
|
||||||
|
LineNo = 0;
|
||||||
|
if (!h->ownedByMe) {
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
}
|
||||||
|
if (FileName) return OK; else return E_NO_MEM;
|
||||||
|
}
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
|
fprintf(ErrFp, "Executing `%s' for INCLUDECMD and caching as `%s'\n",
|
||||||
|
cmd, fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found in cache */
|
||||||
|
|
||||||
|
/* If cmd starts with !, then disable RUN within the cmd output */
|
||||||
|
if (cmd[0] == '!') {
|
||||||
|
fp2 = popen(cmd+1, "r");
|
||||||
|
} else {
|
||||||
|
fp2 = popen(cmd, "r");
|
||||||
|
}
|
||||||
|
if (!fp2) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_CANT_OPEN;
|
||||||
|
}
|
||||||
|
fp = fp2;
|
||||||
|
LineNo = 0;
|
||||||
|
|
||||||
|
/* Temporarily turn of file tracing */
|
||||||
|
old_flag = DebugFlag;
|
||||||
|
DebugFlag &= (~DB_TRACE_FILES);
|
||||||
|
|
||||||
|
if (cmd[0] == '!') {
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
}
|
||||||
|
r = CacheFile(fname, 1);
|
||||||
|
|
||||||
|
DebugFlag = old_flag;
|
||||||
|
if (r == OK) {
|
||||||
|
fp = NULL;
|
||||||
|
CLine = CachedFiles->cache;
|
||||||
|
LineNo = 0;
|
||||||
|
STRSET(FileName, fname);
|
||||||
|
DBufFree(&buf);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
DBufFree(&buf);
|
||||||
|
/* We failed */
|
||||||
|
PopFile();
|
||||||
|
return E_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* IncludeFile */
|
/* IncludeFile */
|
||||||
@@ -828,7 +1039,8 @@ int TopLevel(void)
|
|||||||
/* root, we refuse to open files not owned by root. */
|
/* root, we refuse to open files not owned by root. */
|
||||||
/* We also reject world-writable files, no matter */
|
/* We also reject world-writable files, no matter */
|
||||||
/* who we're running as. */
|
/* who we're running as. */
|
||||||
/* As a side effect, if we don't own the file, we disable RUN */
|
/* As a side effect, if we don't own the file, or it's not */
|
||||||
|
/* owned by a trusted user, we disable RUN */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int CheckSafety(void)
|
static int CheckSafety(void)
|
||||||
{
|
{
|
||||||
@@ -866,9 +1078,22 @@ static int CheckSafety(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If file is not owned by me, disable RUN command */
|
/* If file is not owned by me or a trusted user, disable RUN command */
|
||||||
if (statbuf.st_uid != geteuid()) {
|
|
||||||
RunDisabled |= RUN_NOTOWNER;
|
/* Assume unsafe */
|
||||||
|
RunDisabled |= RUN_NOTOWNER;
|
||||||
|
if (statbuf.st_uid == geteuid()) {
|
||||||
|
/* Owned by me... safe */
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<NumTrustedUsers; i++) {
|
||||||
|
if (statbuf.st_uid == TrustedUsers[i]) {
|
||||||
|
/* Owned by a trusted user... safe */
|
||||||
|
RunDisabled &= ~RUN_NOTOWNER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
34
src/funcs.c
34
src/funcs.c
@@ -6,7 +6,7 @@
|
|||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -151,6 +151,7 @@ static int FWeekno (func_info *);
|
|||||||
static int FWkday (func_info *);
|
static int FWkday (func_info *);
|
||||||
static int FWkdaynum (func_info *);
|
static int FWkdaynum (func_info *);
|
||||||
static int FYear (func_info *);
|
static int FYear (func_info *);
|
||||||
|
static int FShellescape (func_info *);
|
||||||
|
|
||||||
static int CleanUpAfterFunc (func_info *);
|
static int CleanUpAfterFunc (func_info *);
|
||||||
static int CheckArgs (BuiltinFunc *f, int nargs);
|
static int CheckArgs (BuiltinFunc *f, int nargs);
|
||||||
@@ -267,6 +268,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "realtoday", 0, 0, 0, FRealtoday },
|
{ "realtoday", 0, 0, 0, FRealtoday },
|
||||||
{ "sgn", 1, 1, 1, FSgn },
|
{ "sgn", 1, 1, 1, FSgn },
|
||||||
{ "shell", 1, 2, 0, FShell },
|
{ "shell", 1, 2, 0, FShell },
|
||||||
|
{ "shellescape", 1, 1, 1, FShellescape },
|
||||||
{ "slide", 2, NO_MAX, 0, FSlide },
|
{ "slide", 2, NO_MAX, 0, FSlide },
|
||||||
{ "strlen", 1, 1, 1, FStrlen },
|
{ "strlen", 1, 1, 1, FStrlen },
|
||||||
{ "substr", 2, 3, 1, FSubstr },
|
{ "substr", 2, 3, 1, FSubstr },
|
||||||
@@ -866,12 +868,14 @@ static int FTime(func_info *info)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int FAbs(func_info *info)
|
static int FAbs(func_info *info)
|
||||||
{
|
{
|
||||||
int v;
|
volatile int v;
|
||||||
|
|
||||||
ASSERT_TYPE(0, INT_TYPE);
|
ASSERT_TYPE(0, INT_TYPE);
|
||||||
v = ARGV(0);
|
v = ARGV(0);
|
||||||
RetVal.type = INT_TYPE;
|
RetVal.type = INT_TYPE;
|
||||||
RETVAL = (v < 0) ? (-v) : v;
|
RETVAL = (v < 0) ? (-v) : v;
|
||||||
|
v = RETVAL;
|
||||||
|
if (v < 0) return E_2HIGH;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1070,6 +1074,28 @@ static int FOstype(func_info *info)
|
|||||||
return RetStrVal("UNIX", info);
|
return RetStrVal("UNIX", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* FShellescape - escape shell meta-characters */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static int FShellescape(func_info *info)
|
||||||
|
{
|
||||||
|
DynamicBuffer buf;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
ASSERT_TYPE(0, STR_TYPE);
|
||||||
|
DBufInit (&buf);
|
||||||
|
if (ShellEscape(ARG(0).v.str, &buf) != OK) {
|
||||||
|
DBufFree(&buf);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = RetStrVal(DBufValue(&buf), info);
|
||||||
|
DBufFree(&buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* FUpper - convert string to upper-case */
|
/* FUpper - convert string to upper-case */
|
||||||
@@ -2917,6 +2943,10 @@ FEvalTrig(func_info *info)
|
|||||||
}
|
}
|
||||||
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
||||||
}
|
}
|
||||||
|
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
|
||||||
|
r = 0;
|
||||||
|
jul = -1;
|
||||||
|
}
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
if (jul < 0) {
|
if (jul < 0) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* globals.h and err.h */
|
/* globals.h and err.h */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -21,6 +21,12 @@
|
|||||||
#define INIT(var, val) var
|
#define INIT(var, val) var
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_TRUSTED_USERS 20
|
||||||
|
|
||||||
#define MINUTES_PER_DAY 1440
|
#define MINUTES_PER_DAY 1440
|
||||||
|
|
||||||
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
|
||||||
@@ -36,6 +42,9 @@ EXTERN int CurMon;
|
|||||||
EXTERN int CurYear;
|
EXTERN int CurYear;
|
||||||
EXTERN int LineNo;
|
EXTERN int LineNo;
|
||||||
EXTERN int FreshLine;
|
EXTERN int FreshLine;
|
||||||
|
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||||
|
|
||||||
|
EXTERN INIT( int NumTrustedUsers, 0);
|
||||||
EXTERN INIT( char const *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);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the Hebrew calendar */
|
/* Support for the Hebrew calendar */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||||
/* 1985. */
|
/* 1985. */
|
||||||
|
|||||||
60
src/init.c
60
src/init.c
@@ -7,7 +7,7 @@
|
|||||||
/* in normal mode. */
|
/* in normal mode. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -89,6 +89,7 @@ static void ChgUser(char const *u);
|
|||||||
static void InitializeVar(char const *str);
|
static void InitializeVar(char const *str);
|
||||||
|
|
||||||
static char const *BadDate = "Illegal date on command line\n";
|
static char const *BadDate = "Illegal date on command line\n";
|
||||||
|
static void AddTrustedUser(char const *username);
|
||||||
|
|
||||||
static DynamicBuffer default_filename_buf;
|
static DynamicBuffer default_filename_buf;
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ static char const *DefaultFilename(void)
|
|||||||
s = getenv("HOME");
|
s = getenv("HOME");
|
||||||
if (!s) {
|
if (!s) {
|
||||||
fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n");
|
fprintf(stderr, "HOME environment variable not set. Unable to determine reminder file.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
DBufPuts(&default_filename_buf, s);
|
DBufPuts(&default_filename_buf, s);
|
||||||
DBufPuts(&default_filename_buf, "/.reminders");
|
DBufPuts(&default_filename_buf, "/.reminders");
|
||||||
@@ -172,7 +173,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
if (getgid() != getegid() ||
|
if (getgid() != getegid() ||
|
||||||
getuid() != geteuid()) {
|
getuid() != geteuid()) {
|
||||||
fprintf(ErrFp, "\nRemind should not be installed set-uid or set-gid.\nCHECK YOUR SYSTEM SECURITY.\n");
|
fprintf(ErrFp, "\nRemind should not be installed set-uid or set-gid.\nCHECK YOUR SYSTEM SECURITY.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
y = NO_YR;
|
y = NO_YR;
|
||||||
@@ -183,7 +184,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
|
||||||
if (RealToday < 0) {
|
if (RealToday < 0) {
|
||||||
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
JulianToday = RealToday;
|
JulianToday = RealToday;
|
||||||
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
|
||||||
@@ -217,6 +218,10 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
while (*arg) {
|
while (*arg) {
|
||||||
switch(*arg++) {
|
switch(*arg++) {
|
||||||
|
case '+':
|
||||||
|
AddTrustedUser(arg);
|
||||||
|
while(*arg) arg++;
|
||||||
|
break;
|
||||||
|
|
||||||
case '@':
|
case '@':
|
||||||
UseVTColors = 1;
|
UseVTColors = 1;
|
||||||
@@ -330,8 +335,12 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'U':
|
case 'U':
|
||||||
ChgUser(arg);
|
if (*arg == '+') {
|
||||||
RunDisabled = RUN_CMDLINE;
|
ChgUser(arg+1);
|
||||||
|
} else {
|
||||||
|
RunDisabled = RUN_CMDLINE;
|
||||||
|
ChgUser(arg);
|
||||||
|
}
|
||||||
while (*arg) arg++;
|
while (*arg) arg++;
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
@@ -535,7 +544,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
if (!InvokedAsRem) {
|
if (!InvokedAsRem) {
|
||||||
if (i >= argc) {
|
if (i >= argc) {
|
||||||
Usage();
|
Usage();
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
InitialFile = argv[i++];
|
InitialFile = argv[i++];
|
||||||
} else {
|
} else {
|
||||||
@@ -649,7 +658,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
#ifndef L_USAGE_OVERRIDE
|
#ifndef L_USAGE_OVERRIDE
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -682,7 +691,7 @@ void Usage(void)
|
|||||||
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");
|
||||||
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
fprintf(ErrFp, " -j[n] Run in 'purge' mode. [n = INCLUDE depth]\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
#endif /* L_USAGE_OVERRIDE */
|
#endif /* L_USAGE_OVERRIDE */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -711,23 +720,23 @@ static void ChgUser(char const *user)
|
|||||||
|
|
||||||
if (!pwent) {
|
if (!pwent) {
|
||||||
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
|
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!myuid && setgid(pwent->pw_gid)) {
|
if (!myuid && setgid(pwent->pw_gid)) {
|
||||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
|
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!myuid && setuid(pwent->pw_uid)) {
|
if (!myuid && setuid(pwent->pw_uid)) {
|
||||||
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
|
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
home = malloc(strlen(pwent->pw_dir) + 6);
|
home = malloc(strlen(pwent->pw_dir) + 6);
|
||||||
if (!home) {
|
if (!home) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(home, "HOME=%s", pwent->pw_dir);
|
sprintf(home, "HOME=%s", pwent->pw_dir);
|
||||||
putenv(home);
|
putenv(home);
|
||||||
@@ -735,7 +744,7 @@ static void ChgUser(char const *user)
|
|||||||
shell = malloc(strlen(pwent->pw_shell) + 7);
|
shell = malloc(strlen(pwent->pw_shell) + 7);
|
||||||
if (!shell) {
|
if (!shell) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
sprintf(shell, "SHELL=%s", pwent->pw_shell);
|
||||||
putenv(shell);
|
putenv(shell);
|
||||||
@@ -744,14 +753,14 @@ static void ChgUser(char const *user)
|
|||||||
username = malloc(strlen(pwent->pw_name) + 6);
|
username = malloc(strlen(pwent->pw_name) + 6);
|
||||||
if (!username) {
|
if (!username) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(username, "USER=%s", pwent->pw_name);
|
sprintf(username, "USER=%s", pwent->pw_name);
|
||||||
putenv(username);
|
putenv(username);
|
||||||
logname= malloc(strlen(pwent->pw_name) + 9);
|
logname= malloc(strlen(pwent->pw_name) + 9);
|
||||||
if (!logname) {
|
if (!logname) {
|
||||||
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
fprintf(ErrFp, "%s", ErrMsg[M_NOMEM_ENV]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
|
||||||
putenv(logname);
|
putenv(logname);
|
||||||
@@ -838,6 +847,25 @@ static void InitializeVar(char const *str)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddTrustedUser(char const *username)
|
||||||
|
{
|
||||||
|
struct passwd *pwent;
|
||||||
|
if (NumTrustedUsers >= MAX_TRUSTED_USERS) {
|
||||||
|
fprintf(stderr, "Too many trusted users (%d max)\n",
|
||||||
|
MAX_TRUSTED_USERS);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwent = getpwnam(username);
|
||||||
|
if (!pwent) {
|
||||||
|
fprintf(ErrFp, ErrMsg[M_BAD_USER], username);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
|
||||||
|
NumTrustedUsers++;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||||
static char const pmsg1[] = {
|
static char const pmsg1[] = {
|
||||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ static int new_value (json_state * state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define whitespace \
|
#define whitespace \
|
||||||
case '\n': ++ state.cur_line; state.cur_col = 0; \
|
case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
|
||||||
case ' ': case '\t': case '\r'
|
case ' ': case '\t': case '\r'
|
||||||
|
|
||||||
#define string_add(b) \
|
#define string_add(b) \
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Header file for language support for various languages. */
|
/* Header file for language support for various languages. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
/* Further corrections by Erik-Jan Vens */
|
/* Further corrections by Erik-Jan Vens */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the English language. */
|
/* Support for the English language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* */
|
/* */
|
||||||
@@ -359,7 +359,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* I don't speak German. */
|
/* I don't speak German. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Support for the Icelandic language. */
|
/* Support for the Icelandic language. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||||
/* */
|
/* */
|
||||||
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
|
/* Remind is copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||||
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Remind is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* Polish. */
|
/* Polish. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -397,7 +397,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* */
|
/* */
|
||||||
@@ -257,7 +257,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2021 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
30
src/main.c
30
src/main.c
@@ -6,7 +6,7 @@
|
|||||||
/* routines, etc. */
|
/* routines, etc. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -243,6 +243,15 @@ static void DoReminders(void)
|
|||||||
r=DoInclude(&p);
|
r=DoInclude(&p);
|
||||||
purge_handled = 1;
|
purge_handled = 1;
|
||||||
break;
|
break;
|
||||||
|
case T_IncludeCmd:
|
||||||
|
/* In purge mode, include closes file, so we
|
||||||
|
need to echo it here! */
|
||||||
|
if (PurgeMode) {
|
||||||
|
PurgeEchoLine("%s\n", CurLine);
|
||||||
|
}
|
||||||
|
r=DoIncludeCmd(&p);
|
||||||
|
purge_handled = 1;
|
||||||
|
break;
|
||||||
case T_Exit: DoExit(&p); break;
|
case T_Exit: DoExit(&p); break;
|
||||||
case T_Flush: r=DoFlush(&p); break;
|
case T_Flush: r=DoFlush(&p); break;
|
||||||
case T_Set: r=DoSet(&p); break;
|
case T_Set: r=DoSet(&p); break;
|
||||||
@@ -813,9 +822,11 @@ int DoIfTrig(ParsePtr p)
|
|||||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (!Hush || r != E_RUN_DISABLED) {
|
if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
|
||||||
Eprint("%s", ErrMsg[r]);
|
if (!Hush || r != E_RUN_DISABLED) {
|
||||||
}
|
Eprint("%s", ErrMsg[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1392,3 +1403,14 @@ SaveLastTimeTrig(TimeTrig const *t)
|
|||||||
{
|
{
|
||||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrapper to ignore warnings about ignoring return value of system() */
|
||||||
|
void
|
||||||
|
System(char const *cmd)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
r = system(cmd);
|
||||||
|
if (r == 0) {
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Calculations for figuring out moon phases. */
|
/* Calculations for figuring out moon phases. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* the data structures for OMITted dates. */
|
/* the data structures for OMITted dates. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ int CopyValue (Value *dest, const Value *src);
|
|||||||
int ReadLine (void);
|
int ReadLine (void);
|
||||||
int OpenFile (char const *fname);
|
int OpenFile (char const *fname);
|
||||||
int DoInclude (ParsePtr p);
|
int DoInclude (ParsePtr p);
|
||||||
|
int DoIncludeCmd (ParsePtr p);
|
||||||
int IncludeFile (char const *fname);
|
int IncludeFile (char const *fname);
|
||||||
int GetAccessDate (char const *file);
|
int GetAccessDate (char const *file);
|
||||||
int SetAccessDate (char const *fname, int jul);
|
int SetAccessDate (char const *fname, int jul);
|
||||||
@@ -160,3 +161,5 @@ void PrintJSONKeyPairString(char const *name, char const *val);
|
|||||||
void PrintJSONKeyPairDate(char const *name, int jul);
|
void PrintJSONKeyPairDate(char const *name, int jul);
|
||||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||||
void PrintJSONKeyPairTime(char const *name, int t);
|
void PrintJSONKeyPairTime(char const *name, int t);
|
||||||
|
void System(char const *cmd);
|
||||||
|
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Queue up reminders for subsequent execution. */
|
/* Queue up reminders for subsequent execution. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
118
src/rem2ps.c
118
src/rem2ps.c
@@ -5,7 +5,7 @@
|
|||||||
/* Print a PostScript calendar. */
|
/* Print a PostScript calendar. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -99,6 +99,7 @@ CalEntry *CurEntries = NULL;
|
|||||||
CalEntry *PsEntries[32];
|
CalEntry *PsEntries[32];
|
||||||
PageType *CurPage;
|
PageType *CurPage;
|
||||||
char PortraitMode;
|
char PortraitMode;
|
||||||
|
char DaynumRight;
|
||||||
char NoSmallCal;
|
char NoSmallCal;
|
||||||
char UseISO;
|
char UseISO;
|
||||||
|
|
||||||
@@ -140,6 +141,18 @@ void WriteOneEntry (CalEntry *c);
|
|||||||
void GetSmallLocations (void);
|
void GetSmallLocations (void);
|
||||||
char const *EatToken(char const *in, char *out, int maxlen);
|
char const *EatToken(char const *in, char *out, int maxlen);
|
||||||
|
|
||||||
|
static void
|
||||||
|
put_escaped_string(char const *s)
|
||||||
|
{
|
||||||
|
while(*s) {
|
||||||
|
if (*s == '\\' || *s == '(' || *s == ')') {
|
||||||
|
PutChar('\\');
|
||||||
|
}
|
||||||
|
PutChar(*s);
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* StrCmpi */
|
/* StrCmpi */
|
||||||
@@ -336,7 +349,7 @@ int main(int argc, char *argv[])
|
|||||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
|
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2021 by Dianne Skoll\n\n", VERSION);
|
||||||
fprintf(stderr, "Generating PostScript calendar\n");
|
fprintf(stderr, "Generating PostScript calendar\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,6 +600,12 @@ void WriteProlog(void)
|
|||||||
printf("%%%%Pages: (atend)\n");
|
printf("%%%%Pages: (atend)\n");
|
||||||
printf("%%%%Orientation: %s\n", PortraitMode ? "Portrait" : "Landscape");
|
printf("%%%%Orientation: %s\n", PortraitMode ? "Portrait" : "Landscape");
|
||||||
printf("%%%%EndComments\n");
|
printf("%%%%EndComments\n");
|
||||||
|
if (PortraitMode) {
|
||||||
|
printf("<< /PageSize [%d %d] >> setpagedevice\n", x, y);
|
||||||
|
} else {
|
||||||
|
/* They were swapped up above, so swap them back or we'll get rotated output */
|
||||||
|
printf("<< /PageSize [%d %d] >> setpagedevice\n", y, x);
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; PSProlog1[i]; i++) puts(PSProlog1[i]);
|
for (i=0; PSProlog1[i]; i++) puts(PSProlog1[i]);
|
||||||
if (!MondayFirst)
|
if (!MondayFirst)
|
||||||
@@ -679,7 +698,7 @@ void WriteCalEntry(void)
|
|||||||
printf("]\n");
|
printf("]\n");
|
||||||
|
|
||||||
/* Print the day number */
|
/* Print the day number */
|
||||||
printf("(%d)\n", CurDay);
|
printf("(%d) %d\n", CurDay, (int) DaynumRight);
|
||||||
/* Do it! */
|
/* Do it! */
|
||||||
printf("DoCalBox\n");
|
printf("DoCalBox\n");
|
||||||
|
|
||||||
@@ -819,6 +838,7 @@ void Init(int argc, char *argv[])
|
|||||||
FillPage = 0;
|
FillPage = 0;
|
||||||
MondayFirst = 0;
|
MondayFirst = 0;
|
||||||
SmallLocation = "bt";
|
SmallLocation = "bt";
|
||||||
|
DaynumRight = 1;
|
||||||
|
|
||||||
for(j=0; j<32; j++) PsEntries[i] = NULL;
|
for(j=0; j<32; j++) PsEntries[i] = NULL;
|
||||||
|
|
||||||
@@ -935,6 +955,7 @@ void Init(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'i': UseISO = 1; break;
|
case 'i': UseISO = 1; break;
|
||||||
|
|
||||||
|
case 'x': DaynumRight = 0; break;
|
||||||
case 'c': k=(*s);
|
case 'c': k=(*s);
|
||||||
if (!k) {
|
if (!k) {
|
||||||
SmallLocation = SmallCalLoc[0];
|
SmallLocation = SmallCalLoc[0];
|
||||||
@@ -979,6 +1000,7 @@ void Usage(char const *s)
|
|||||||
fprintf(stderr, "-b size Set border size for calendar entries\n");
|
fprintf(stderr, "-b size Set border size for calendar entries\n");
|
||||||
fprintf(stderr, "-t size Set line thickness\n");
|
fprintf(stderr, "-t size Set line thickness\n");
|
||||||
fprintf(stderr, "-e Make calendar fill entire page\n");
|
fprintf(stderr, "-e Make calendar fill entire page\n");
|
||||||
|
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
||||||
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -1054,10 +1076,10 @@ int DoQueuedPs(void)
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
int fnoff;
|
int fnoff;
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
char const *size, *extra;
|
char fbuffer[512];
|
||||||
|
char const *size, *fsize, *extra;
|
||||||
char const *s;
|
char const *s;
|
||||||
int num, r, g, b, phase, fontsize, moonsize;
|
int num, r, g, b, phase, fontsize, moonsize;
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
if (!MondayFirst) begin = CurDay - WkDayNum;
|
if (!MondayFirst) begin = CurDay - WkDayNum;
|
||||||
else begin = CurDay - (WkDayNum ? WkDayNum-1 : 6);
|
else begin = CurDay - (WkDayNum ? WkDayNum-1 : 6);
|
||||||
@@ -1129,19 +1151,28 @@ int DoQueuedPs(void)
|
|||||||
while(*s && isspace(*s)) {
|
while(*s && isspace(*s)) {
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
while(*s) {
|
put_escaped_string(s);
|
||||||
if (*s == '\\' || *s == '(' || *s == ')') {
|
|
||||||
PutChar('\\');
|
|
||||||
}
|
|
||||||
PutChar(*s);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
printf(") show grestore\n");
|
printf(") show grestore\n");
|
||||||
break;
|
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);
|
||||||
|
/* See if we have extra stuff */
|
||||||
|
extra = e->entry+fnoff;
|
||||||
|
|
||||||
|
/* Skip phase */
|
||||||
|
while(*extra && !isspace(*extra)) extra++;
|
||||||
|
while(*extra && isspace(*extra)) extra++;
|
||||||
|
|
||||||
|
/* Skip moon size */
|
||||||
|
while(*extra && !isspace(*extra)) extra++;
|
||||||
|
while(*extra && isspace(*extra)) extra++;
|
||||||
|
|
||||||
|
/* Skip font size */
|
||||||
|
while(*extra && !isspace(*extra)) extra++;
|
||||||
|
while(*extra && isspace(*extra)) extra++;
|
||||||
|
|
||||||
if (num == 1) {
|
if (num == 1) {
|
||||||
moonsize = -1;
|
moonsize = -1;
|
||||||
fontsize = -1;
|
fontsize = -1;
|
||||||
@@ -1163,7 +1194,27 @@ int DoQueuedPs(void)
|
|||||||
size = buffer;
|
size = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("gsave 0 setgray newpath Border %s add BoxHeight Border sub %s sub\n", size, size);
|
/* Store the starting X coordinate in "moonstartx" */
|
||||||
|
if (DaynumRight) {
|
||||||
|
printf("Border %s add /moonstartx exch def", size);
|
||||||
|
} else {
|
||||||
|
printf("xincr Border sub %s sub ", size);
|
||||||
|
if (*extra) {
|
||||||
|
if (fontsize < 0) {
|
||||||
|
fsize = "EntrySize";
|
||||||
|
} else {
|
||||||
|
sprintf(fbuffer, "%d", fontsize);
|
||||||
|
fsize = fbuffer;
|
||||||
|
}
|
||||||
|
printf("/EntryFont findfont %s scalefont setfont (",
|
||||||
|
fsize);
|
||||||
|
put_escaped_string(extra);
|
||||||
|
printf(") stringwidth pop sub Border sub ");
|
||||||
|
}
|
||||||
|
printf("/moonstartx exch def\n");
|
||||||
|
}
|
||||||
|
printf(" gsave 0 setgray newpath ");
|
||||||
|
printf("moonstartx BoxHeight Border sub %s sub\n", size);
|
||||||
printf(" %s 0 360 arc closepath\n", size);
|
printf(" %s 0 360 arc closepath\n", size);
|
||||||
switch(phase) {
|
switch(phase) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -1174,49 +1225,28 @@ int DoQueuedPs(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
printf("stroke\n");
|
printf("stroke\nnewpath ");
|
||||||
printf("newpath Border %s add BoxHeight Border sub %s sub\n",
|
printf("moonstartx BoxHeight Border sub %s sub\n", size);
|
||||||
size, size);
|
|
||||||
printf("%s 90 270 arc closepath fill\n", size);
|
printf("%s 90 270 arc closepath fill\n", size);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("stroke\n");
|
printf("stroke\nnewpath ");
|
||||||
printf("newpath Border %s add BoxHeight Border sub %s sub\n",
|
printf("moonstartx BoxHeight Border sub %s sub\n", size);
|
||||||
size, size);
|
|
||||||
printf("%s 270 90 arc closepath fill\n", size);
|
printf("%s 270 90 arc closepath fill\n", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* See if we have extra stuff */
|
|
||||||
extra = e->entry+fnoff;
|
|
||||||
|
|
||||||
/* Skip phase */
|
|
||||||
while(*extra && !isspace(*extra)) extra++;
|
|
||||||
while(*extra && isspace(*extra)) extra++;
|
|
||||||
|
|
||||||
/* Skip moon size */
|
|
||||||
while(*extra && !isspace(*extra)) extra++;
|
|
||||||
while(*extra && isspace(*extra)) extra++;
|
|
||||||
|
|
||||||
/* Skip font size */
|
|
||||||
while(*extra && !isspace(*extra)) extra++;
|
|
||||||
while(*extra && isspace(*extra)) extra++;
|
|
||||||
|
|
||||||
/* Anything left? */
|
/* Anything left? */
|
||||||
if (*extra) {
|
if (*extra) {
|
||||||
printf("Border %s add %s add Border add BoxHeight border sub %s sub %s sub moveto\n", size, size, size, size);
|
printf("moonstartx %s add Border add BoxHeight border sub %s sub %s sub moveto\n", size, size, size);
|
||||||
if (fontsize < 0) {
|
if (fontsize < 0) {
|
||||||
size = "EntrySize";
|
fsize = "EntrySize";
|
||||||
} else {
|
} else {
|
||||||
sprintf(buffer, "%d", fontsize);
|
sprintf(fbuffer, "%d", fontsize);
|
||||||
size = buffer;
|
fsize = fbuffer;
|
||||||
}
|
}
|
||||||
printf("/EntryFont findfont %s scalefont setfont (",
|
printf("/EntryFont findfont %s scalefont setfont (",
|
||||||
size);
|
fsize);
|
||||||
while(*extra) {
|
put_escaped_string(extra);
|
||||||
c = (unsigned char) *extra++;
|
|
||||||
if (c == '\\' || c == '(' || c == ')') PutChar('\\');
|
|
||||||
PutChar(c);
|
|
||||||
}
|
|
||||||
printf(") show\n");
|
printf(") show\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/rem2ps.h
13
src/rem2ps.h
@@ -5,7 +5,7 @@
|
|||||||
/* Define the PostScript prologue */
|
/* Define the PostScript prologue */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ char *PSProlog1[] =
|
|||||||
{
|
{
|
||||||
"% This file was produced by Remind and Rem2PS, written by",
|
"% This file was produced by Remind and Rem2PS, written by",
|
||||||
"% Dianne Skoll.",
|
"% Dianne Skoll.",
|
||||||
"% Remind and Rem2PS are Copyright 1992-2020 Dianne Skoll.",
|
"% Remind and Rem2PS are Copyright 1992-2021 Dianne Skoll.",
|
||||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||||
@@ -196,9 +196,10 @@ char *PSProlog2[] =
|
|||||||
"% Variables for calendar boxes:",
|
"% Variables for calendar boxes:",
|
||||||
"% ytop - current top position",
|
"% ytop - current top position",
|
||||||
"% ymin - minimum y reached for current row",
|
"% ymin - minimum y reached for current row",
|
||||||
"% border ytop xleft width textarray daynum DoCalBox ybot",
|
"% border ytop xleft width textarray daynum onright DoCalBox ybot",
|
||||||
"% Do the entries for one calendar box. Returns lowest Y-coordinate reached",
|
"% Do the entries for one calendar box. Returns lowest Y-coordinate reached",
|
||||||
"/DoCalBox {",
|
"/DoCalBox {",
|
||||||
|
" /onright exch def",
|
||||||
" /daynum exch def",
|
" /daynum exch def",
|
||||||
" /textarr exch def",
|
" /textarr exch def",
|
||||||
" /wid exch def",
|
" /wid exch def",
|
||||||
@@ -207,8 +208,10 @@ char *PSProlog2[] =
|
|||||||
" /border exch def",
|
" /border exch def",
|
||||||
"% Do the day number",
|
"% Do the day number",
|
||||||
" /DayFont findfont DaySize scalefont setfont",
|
" /DayFont findfont DaySize scalefont setfont",
|
||||||
" xl wid add border sub daynum stringwidth pop sub",
|
" onright 1 eq",
|
||||||
" yt border sub DaySize sub moveto daynum show",
|
" {xl wid add border sub daynum stringwidth pop sub yt border sub DaySize sub moveto daynum show}",
|
||||||
|
" {xl border add yt border sub DaySize sub moveto daynum show}",
|
||||||
|
" ifelse",
|
||||||
"% Do the text entries. Precharge the stack with current y pos.",
|
"% Do the text entries. Precharge the stack with current y pos.",
|
||||||
" /ycur yt border sub DaySize sub DaySize sub 2 add def",
|
" /ycur yt border sub DaySize sub DaySize sub 2 add def",
|
||||||
" /EntryFont findfont EntrySize scalefont setfont",
|
" /EntryFont findfont EntrySize scalefont setfont",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Routines for sorting reminders by trigger date */
|
/* Routines for sorting reminders by trigger date */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ void IssueSortedReminders(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
system(cur->text);
|
System(cur->text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/token.c
18
src/token.c
@@ -6,7 +6,7 @@
|
|||||||
/* classifying the tokens parsed. */
|
/* classifying the tokens parsed. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -62,11 +62,13 @@ Token TokArray[] = {
|
|||||||
{ "if", 2, T_If, 0 },
|
{ "if", 2, T_If, 0 },
|
||||||
{ "iftrig", 6, T_IfTrig, 0 },
|
{ "iftrig", 6, T_IfTrig, 0 },
|
||||||
{ "include", 3, T_Include, 0 },
|
{ "include", 3, T_Include, 0 },
|
||||||
|
{ "includecmd", 10, T_IncludeCmd, 0 },
|
||||||
{ "january", 3, T_Month, 0 },
|
{ "january", 3, T_Month, 0 },
|
||||||
{ "july", 3, T_Month, 6 },
|
{ "july", 3, T_Month, 6 },
|
||||||
{ "june", 3, T_Month, 5 },
|
{ "june", 3, T_Month, 5 },
|
||||||
{ "march", 3, T_Month, 2 },
|
{ "march", 3, T_Month, 2 },
|
||||||
{ "may", 3, T_Month, 4 },
|
{ "may", 3, T_Month, 4 },
|
||||||
|
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
|
||||||
{ "monday", 3, T_WkDay, 0 },
|
{ "monday", 3, T_WkDay, 0 },
|
||||||
{ "msf", 3, T_RemType, MSF_TYPE },
|
{ "msf", 3, T_RemType, MSF_TYPE },
|
||||||
{ "msg", 3, T_RemType, MSG_TYPE },
|
{ "msg", 3, T_RemType, MSG_TYPE },
|
||||||
@@ -171,6 +173,10 @@ void FindToken(char const *s, Token *tok)
|
|||||||
int top, bot, mid, r, max;
|
int top, bot, mid, r, max;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
|
#if LANG != ENGLISH
|
||||||
|
size_t i;
|
||||||
|
#endif
|
||||||
|
|
||||||
tok->type = T_Illegal;
|
tok->type = T_Illegal;
|
||||||
if (! *s) {
|
if (! *s) {
|
||||||
tok->type = T_Empty;
|
tok->type = T_Empty;
|
||||||
@@ -228,11 +234,11 @@ void FindToken(char const *s, Token *tok)
|
|||||||
/* If language is other than English, search the DayNames[] and MonthNames[]
|
/* If language is other than English, search the DayNames[] and MonthNames[]
|
||||||
array. */
|
array. */
|
||||||
#if LANG != ENGLISH
|
#if LANG != ENGLISH
|
||||||
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
|
for (i=0; i<(sizeof(NonEnglishToks) / sizeof(Token)); i++) {
|
||||||
if (l >= NonEnglishToks[x].MinLen &&
|
if (l >= NonEnglishToks[i].MinLen &&
|
||||||
!TokStrCmp(&NonEnglishToks[x], s)) {
|
!TokStrCmp(&NonEnglishToks[i], s)) {
|
||||||
tok->type = NonEnglishToks[x].type;
|
tok->type = NonEnglishToks[i].type;
|
||||||
tok->val = NonEnglishToks[x].val;
|
tok->val = NonEnglishToks[i].val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Routines for figuring out the trigger date of a reminder */
|
/* Routines for figuring out the trigger date of a reminder */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
#define GOT_YR 4
|
#define GOT_YR 4
|
||||||
#define GOT_WD 8
|
#define GOT_WD 8
|
||||||
|
|
||||||
|
#define ADVANCE_TO_WD(x, wd) while (! ((wd) & (1 << ((x)%7)))) (x)++
|
||||||
|
|
||||||
static int JYear(int jul);
|
static int JYear(int jul);
|
||||||
static int JMonth(int jul);
|
static int JMonth(int jul);
|
||||||
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
static int NextSimpleTrig(int startdate, Trigger *trig, int *err);
|
||||||
@@ -58,9 +60,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (trig->wd != NO_WD) typ |= GOT_WD;
|
if (trig->wd != NO_WD) typ |= GOT_WD;
|
||||||
switch(typ) {
|
switch(typ) {
|
||||||
case 0:
|
case 0:
|
||||||
|
return startdate;
|
||||||
|
|
||||||
case GOT_WD:
|
case GOT_WD:
|
||||||
if (trig->wd != NO_WD)
|
ADVANCE_TO_WD(startdate, trig->wd);
|
||||||
while(! (trig->wd & (1 << (startdate%7)))) startdate++;
|
|
||||||
return startdate;
|
return startdate;
|
||||||
|
|
||||||
case GOT_DAY:
|
case GOT_DAY:
|
||||||
@@ -83,12 +86,12 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
else return -1;
|
else return -1;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON:
|
case GOT_DAY+GOT_MON:
|
||||||
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
|
||||||
if (trig->d > MonthDays[trig->m]) {
|
if (trig->d > MonthDays[trig->m]) {
|
||||||
*err = E_BAD_DATE;
|
*err = E_BAD_DATE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
|
||||||
/* Take care of Feb. 29 */
|
/* Take care of Feb. 29 */
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
return Julian(y, trig->m, trig->d);
|
return Julian(y, trig->m, trig->d);
|
||||||
@@ -121,19 +124,19 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (y > trig->y) return -1;
|
if (y > trig->y) return -1;
|
||||||
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
if (y < trig->y) j = Julian(trig->y, 0, 1);
|
||||||
else j = startdate;
|
else j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JYear(j) > trig->y) return -1;
|
if (JYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_MON+GOT_WD:
|
case GOT_MON+GOT_WD:
|
||||||
if (m == trig->m) {
|
if (m == trig->m) {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (JMonth(j) == trig->m) return j;
|
if (JMonth(j) == trig->m) return j;
|
||||||
}
|
}
|
||||||
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
|
||||||
else j = Julian(y, trig->m, 1);
|
else j = Julian(y, trig->m, 1);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j; /* Guaranteed to be within the month */
|
return j; /* Guaranteed to be within the month */
|
||||||
|
|
||||||
case GOT_DAY+GOT_WD:
|
case GOT_DAY+GOT_WD:
|
||||||
@@ -144,7 +147,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
/* If there are fewer days in previous month, no match */
|
/* If there are fewer days in previous month, no match */
|
||||||
if (trig->d <= DaysInMonth(m2, y2)) {
|
if (trig->d <= DaysInMonth(m2, y2)) {
|
||||||
j = Julian(y2, m2, trig->d);
|
j = Julian(y2, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -153,7 +156,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, y)) {
|
if (trig->d <= DaysInMonth(m, y)) {
|
||||||
j = Julian(y, m, trig->d);
|
j = Julian(y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,18 +165,18 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
if (m2 > 11) { m2 = 0; y++; }
|
if (m2 > 11) { m2 = 0; y++; }
|
||||||
while (trig->d > DaysInMonth(m2, y)) m2++;
|
while (trig->d > DaysInMonth(m2, y)) m2++;
|
||||||
j = Julian(y, m2, trig->d);
|
j = Julian(y, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_YR+GOT_DAY:
|
case GOT_WD+GOT_YR+GOT_DAY:
|
||||||
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
|
||||||
if (y > trig->y) {
|
if (y > trig->y) {
|
||||||
j = Julian(trig->y, 11, trig->d);
|
j = Julian(trig->y, 11, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
} else if (y < trig->y) {
|
} else if (y < trig->y) {
|
||||||
j = Julian(trig->y, 0, trig->d);
|
j = Julian(trig->y, 0, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
/* Try last month */
|
/* Try last month */
|
||||||
@@ -181,14 +184,16 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m2 = m-1;
|
m2 = m-1;
|
||||||
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
|
||||||
j = Julian(trig->y, m2, trig->d);
|
j = Julian(trig->y, m2, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Try this month */
|
/* Try this month */
|
||||||
if (trig->d <= DaysInMonth(m, trig->y)) {
|
if (trig->d <= DaysInMonth(m, trig->y)) {
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = Julian(trig->y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +202,8 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m++;
|
m++;
|
||||||
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
while (trig->d > DaysInMonth(m, trig->d)) m++;
|
||||||
j = Julian(trig->y, m, trig->d);
|
j = Julian(trig->y, m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
|
if (JYear(j) > trig->y) return -1;
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_DAY+GOT_MON+GOT_WD:
|
case GOT_DAY+GOT_MON+GOT_WD:
|
||||||
@@ -215,31 +221,32 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
/* Try last year */
|
/* Try last year */
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Try this year */
|
/* Try this year */
|
||||||
y++;
|
y++;
|
||||||
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
if (j >= startdate) return j;
|
if (j >= startdate) return j;
|
||||||
|
|
||||||
/* Must be next year */
|
/* Must be next year */
|
||||||
y++;
|
y++;
|
||||||
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
while (trig->d > DaysInMonth(trig->m, y)) y++;
|
||||||
j = Julian(y, trig->m, trig->d);
|
j = Julian(y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
case GOT_WD+GOT_MON+GOT_YR:
|
case GOT_WD+GOT_MON+GOT_YR:
|
||||||
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
|
||||||
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
||||||
j = Julian(trig->y, trig->m, 1);
|
j = Julian(trig->y, trig->m, 1);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
} else {
|
} else {
|
||||||
j = startdate;
|
j = startdate;
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
FromJulian(j, &y2, &m2, &d2);
|
FromJulian(j, &y2, &m2, &d2);
|
||||||
if (m2 == trig->m) return j; else return -1;
|
if (m2 == trig->m) return j; else return -1;
|
||||||
}
|
}
|
||||||
@@ -250,7 +257,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
j = Julian(trig->y, trig->m, trig->d);
|
j = Julian(trig->y, trig->m, trig->d);
|
||||||
while(! (trig->wd & (1 << (j%7)))) j++;
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Type definitions all dumped here. */
|
/* Type definitions all dumped here. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -73,6 +73,7 @@ typedef struct {
|
|||||||
int duration_days; /* Duration converted to days to search */
|
int duration_days; /* Duration converted to days to search */
|
||||||
int eventstart; /* Original event start (datetime) */
|
int eventstart; /* Original event start (datetime) */
|
||||||
int eventduration; /* Original event duration (minutes) */
|
int eventduration; /* Original event duration (minutes) */
|
||||||
|
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
||||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||||
@@ -149,7 +150,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
|||||||
enum TokTypes
|
enum TokTypes
|
||||||
{ T_Illegal,
|
{ T_Illegal,
|
||||||
/* Commands first */
|
/* Commands first */
|
||||||
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_If, T_Else, T_EndIf,
|
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_IncludeCmd, T_If, T_Else, T_EndIf,
|
||||||
T_IfTrig, T_ErrMsg,
|
T_IfTrig, T_ErrMsg,
|
||||||
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
|
||||||
T_WkDay,
|
T_WkDay,
|
||||||
@@ -171,7 +172,8 @@ enum TokTypes
|
|||||||
T_Duration,
|
T_Duration,
|
||||||
T_LongTime,
|
T_LongTime,
|
||||||
T_OmitFunc,
|
T_OmitFunc,
|
||||||
T_Through
|
T_Through,
|
||||||
|
T_MaybeUncomputable
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The structure of a token */
|
/* The structure of a token */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* functions. */
|
/* functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
|||||||
41
src/utils.c
41
src/utils.c
@@ -5,11 +5,15 @@
|
|||||||
/* Useful utility functions. */
|
/* Useful utility functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
|
static char const DontEscapeMe[] =
|
||||||
|
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "err.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -123,3 +127,38 @@ int DateOK(int y, int m, int d)
|
|||||||
d > DaysInMonth(m, y) ) return 0;
|
d > DaysInMonth(m, y) ) return 0;
|
||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Functions designed to defeat gcc optimizer */
|
||||||
|
|
||||||
|
int _private_div(int a, int b) { return a/b; }
|
||||||
|
int _private_add_overflow(int result, int b, int old)
|
||||||
|
{
|
||||||
|
if (b > 0 && result < old) return 1;
|
||||||
|
if (b < 0 && result > old) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int _private_sub_overflow(int result, int b, int old)
|
||||||
|
{
|
||||||
|
if (b < 0 && result < old) return 1;
|
||||||
|
if (b > 0 && result > old) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _private_unminus_overflow(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > 0 && b > 0) return 1;
|
||||||
|
if (a < 0 && b < 0) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ShellEscape(char const *in, DynamicBuffer *out)
|
||||||
|
{
|
||||||
|
while(*in) {
|
||||||
|
if (!strchr(DontEscapeMe, *in)) {
|
||||||
|
if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
|
||||||
|
}
|
||||||
|
if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|||||||
20
src/var.c
20
src/var.c
@@ -6,7 +6,7 @@
|
|||||||
/* user- and system-defined variables. */
|
/* user- and system-defined variables. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
/* Copyright (C) 1992-2021 by Dianne Skoll */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
@@ -31,6 +32,9 @@
|
|||||||
#define VALUE ErrMsg[E_VAL]
|
#define VALUE ErrMsg[E_VAL]
|
||||||
#define UNDEF ErrMsg[E_UNDEF]
|
#define UNDEF ErrMsg[E_UNDEF]
|
||||||
|
|
||||||
|
static int IntMin = INT_MIN;
|
||||||
|
static int IntMax = INT_MAX;
|
||||||
|
|
||||||
static Var *VHashTbl[VAR_HASH_SIZE];
|
static Var *VHashTbl[VAR_HASH_SIZE];
|
||||||
|
|
||||||
typedef int (*SysVarFunc)(int, Value *);
|
typedef int (*SysVarFunc)(int, Value *);
|
||||||
@@ -475,17 +479,17 @@ int DoDump(ParsePtr p)
|
|||||||
DumpVarTable();
|
DumpVarTable();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
|
fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
|
||||||
while(1) {
|
while(1) {
|
||||||
if (*DBufValue(&buf) == '$') {
|
if (*DBufValue(&buf) == '$') {
|
||||||
DumpSysVarByName(DBufValue(&buf)+1);
|
DumpSysVarByName(DBufValue(&buf)+1);
|
||||||
} else {
|
} else {
|
||||||
v = FindVar(DBufValue(&buf), 0);
|
v = FindVar(DBufValue(&buf), 0);
|
||||||
DBufValue(&buf)[VAR_NAME_LEN] = 0;
|
DBufValue(&buf)[VAR_NAME_LEN] = 0;
|
||||||
if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN,
|
if (!v) fprintf(ErrFp, "%s %s\n",
|
||||||
DBufValue(&buf), UNDEF);
|
DBufValue(&buf), UNDEF);
|
||||||
else {
|
else {
|
||||||
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
|
fprintf(ErrFp, "%s ", v->name);
|
||||||
PrintValue(&(v->v), ErrFp);
|
PrintValue(&(v->v), ErrFp);
|
||||||
fprintf(ErrFp, "\n");
|
fprintf(ErrFp, "\n");
|
||||||
}
|
}
|
||||||
@@ -513,12 +517,12 @@ void DumpVarTable(void)
|
|||||||
register Var *v;
|
register Var *v;
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
|
fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
|
||||||
|
|
||||||
for (i=0; i<VAR_HASH_SIZE; i++) {
|
for (i=0; i<VAR_HASH_SIZE; i++) {
|
||||||
v = VHashTbl[i];
|
v = VHashTbl[i];
|
||||||
while(v) {
|
while(v) {
|
||||||
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
|
fprintf(ErrFp, "%s ", v->name);
|
||||||
PrintValue(&(v->v), ErrFp);
|
PrintValue(&(v->v), ErrFp);
|
||||||
fprintf(ErrFp, "\n");
|
fprintf(ErrFp, "\n");
|
||||||
v = v->next;
|
v = v->next;
|
||||||
@@ -661,6 +665,8 @@ static SysVar SysVarArr[] = {
|
|||||||
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
{"HushMode", 0, INT_TYPE, &Hush, 0, 0 },
|
||||||
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
{"IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
|
||||||
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
{"InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
|
||||||
|
{"IntMax", 0, INT_TYPE, &IntMax, 0, 0 },
|
||||||
|
{"IntMin", 0, INT_TYPE, &IntMin, 0, 0 },
|
||||||
{"LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
{"LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
|
||||||
{"LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
{"LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
|
||||||
{"LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
{"LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
|
||||||
@@ -835,7 +841,7 @@ static void DumpSysVar(char const *name, const SysVar *v)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
||||||
fprintf(ErrFp, "%*s ", VAR_NAME_LEN+1, buffer);
|
fprintf(ErrFp, "%16s ", buffer);
|
||||||
if (v) {
|
if (v) {
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == SPECIAL_TYPE) {
|
||||||
Value val;
|
Value val;
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd /home/dfs/Software/Remind.git || exit 1
|
|
||||||
|
|
||||||
rm -f .git/COMMIT_EDITMSG .git/*~
|
|
||||||
|
|
||||||
git update-server-info && cd .git && rsync --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
|
|
||||||
exit $?
|
|
||||||
|
|
||||||
27
tests/test-for-backends.rem
Normal file
27
tests/test-for-backends.rem
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This file is designed for testing how back-ends
|
||||||
|
# handle SPECIALs, including SPECIALS they don't understand
|
||||||
|
# If you're writing a back-end, test it by feeding it the output
|
||||||
|
# of: remind -pp test-for-backends.rem
|
||||||
|
|
||||||
|
# Color and shade
|
||||||
|
REM 1 SPECIAL COLOR 128 0 0 Red
|
||||||
|
REM 2 SPECIAL COLOUR 0 128 0 British Green
|
||||||
|
REM 3 SPECIAL SHADE 192 192 255
|
||||||
|
|
||||||
|
# Moon
|
||||||
|
REM [moondate(0)] SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||||
|
REM [moondate(1)] SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||||
|
REM [moondate(2)] SPECIAL MOON 2 -1 -1 [moontime(2)]
|
||||||
|
REM [moondate(3)] SPECIAL MOON 3 -1 -1 [moontime(3)]
|
||||||
|
|
||||||
|
# Week
|
||||||
|
REM Monday SPECIAL WEEK (W[weekno()])
|
||||||
|
|
||||||
|
# PostScript
|
||||||
|
REM Wed PS Border Border 2 div moveto /Helvetica-Oblique findfont 6 scalefont setfont (oof!) show
|
||||||
|
|
||||||
|
# A SPECIAL that should be ignored
|
||||||
|
REM 15 SPECIAL RANDOM-STUFF ignore me and be happy
|
||||||
|
|
||||||
|
# A normal reminder
|
||||||
|
REM 16 MSG A normal reminder
|
||||||
@@ -7,13 +7,22 @@
|
|||||||
# in the build directory.
|
# in the build directory.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2018 Dianne Skoll
|
# Copyright (C) 1992-2021 Dianne Skoll
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
DIR=`dirname $0`
|
DIR=`dirname $0`
|
||||||
cd $DIR
|
cd $DIR
|
||||||
if test $? != 0 ; then
|
if test $? != 0 ; then
|
||||||
|
echo ""
|
||||||
echo "Unable to cd $DIR" >&2
|
echo "Unable to cd $DIR" >&2
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test `id -u` = 0 ; then
|
||||||
|
echo ""
|
||||||
|
echo "*** Please do not run the test suite as root; it will fail."
|
||||||
|
echo ""
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -56,6 +65,14 @@ echo "" >> ../tests/test.out
|
|||||||
|
|
||||||
chmod 644 include_dir/04cantread.rem
|
chmod 644 include_dir/04cantread.rem
|
||||||
|
|
||||||
|
# Feb 29 bug
|
||||||
|
echo "Feb 29 Bug Test" >> ../tests/test.out
|
||||||
|
echo 'REM Sun 29 Feb MSG [$T]' | ../src/remind -dt - 1 feb 2021 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Day Weekday Year out-of-year bug
|
||||||
|
echo "Mon 31 Dec Bug Test" >> ../tests/test.out
|
||||||
|
echo 'REM Mon 31 2021 MSG [$T]' | ../src/remind -dt - 31 dec 2021 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
echo "Color Test" >> ../tests/test.out
|
echo "Color Test" >> ../tests/test.out
|
||||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
@@ -289,6 +306,25 @@ rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
|||||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# If we're already in a utf-8 locale, do
|
||||||
|
# nothing; otherwise, set LC_ALL
|
||||||
|
OK=0
|
||||||
|
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||||
|
OK=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -z "$LC_ALL" ; then
|
||||||
|
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||||
|
export LC_ALL="$LANG"
|
||||||
|
OK=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$OK" = 0 ; then
|
||||||
|
export LC_ALL=en_US.utf-8
|
||||||
|
fi
|
||||||
|
|
||||||
|
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
|
||||||
cmp -s ../tests/test.out ../tests/test.cmp
|
cmp -s ../tests/test.out ../tests/test.cmp
|
||||||
if [ "$?" = "0" ]; then
|
if [ "$?" = "0" ]; then
|
||||||
echo "Remind: Acceptance test PASSED"
|
echo "Remind: Acceptance test PASSED"
|
||||||
|
|||||||
2434
tests/test.cmp
2434
tests/test.cmp
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,40 @@ REM Wed UNTIL 15 Feb 1991 SATISFY [trigdate() > '1990-01-01'] MSG wookie
|
|||||||
# bad AT
|
# bad AT
|
||||||
REM AT 0:00 0:01 0:02 MSG foo
|
REM AT 0:00 0:01 0:02 MSG foo
|
||||||
|
|
||||||
|
# Includecmd
|
||||||
|
INCLUDECMD echo REM 16 Feb 1991 MSG Blork
|
||||||
|
INCLUDECMD echo REM 18 Feb 1991 MSG Blork
|
||||||
|
|
||||||
|
# Includecmd with continuation line
|
||||||
|
INCLUDECMD echo REM 18 Feb 1991 MSG This line is \
|
||||||
|
continued so there
|
||||||
|
|
||||||
|
# This should work
|
||||||
|
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||||
|
|
||||||
|
# This should fail
|
||||||
|
INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo INCLUDECMD echo MSG Yippee
|
||||||
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))
|
||||||
|
|
||||||
|
# Test case from Remind mailing list
|
||||||
|
set mltest "a b"
|
||||||
|
INCLUDECMD printf 'REM %s\n' [mltest]
|
||||||
|
|
||||||
|
# Disabling RUN in an !includecmd
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||||
|
INCLUDECMD !echo INCLUDECMD echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
INCLUDECMD !echo MSG foo
|
||||||
|
|
||||||
|
# INCLUDECMD with RUN disabled
|
||||||
|
RUN OFF
|
||||||
|
INCLUDECMD echo MSG foo
|
||||||
|
RUN ON
|
||||||
|
INCLUDECMD echo MSG foo
|
||||||
|
|
||||||
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
[_h(1, "Tishrey")] MSG Rosh Hashana 1
|
||||||
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
[_h(2, "Tishrey")] MSG Rosh Hashana 2
|
||||||
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
[_h(3, "Tishrey")] MSG Tzom Gedalia
|
||||||
@@ -376,6 +407,14 @@ set a133 trigduration()
|
|||||||
set a134 trigeventstart()
|
set a134 trigeventstart()
|
||||||
set a135 trigeventduration()
|
set a135 trigeventduration()
|
||||||
|
|
||||||
|
# These will issue errors
|
||||||
|
REM Mon OMIT Mon SKIP MSG Never ever ever...
|
||||||
|
REM Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
|
||||||
|
|
||||||
|
# These will just silently not trigger
|
||||||
|
REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
|
||||||
|
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
|
||||||
|
|
||||||
dump
|
dump
|
||||||
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||||
@@ -525,6 +564,33 @@ set x coerce("DATETIME", "2020-05-05@12:45am")
|
|||||||
set x coerce("DATETIME", "2020-05-05@12:45")
|
set x coerce("DATETIME", "2020-05-05@12:45")
|
||||||
set x coerce("DATETIME", "2020-05-05@1:45pm")
|
set x coerce("DATETIME", "2020-05-05@1:45pm")
|
||||||
|
|
||||||
|
# Overflow - these tests only work on machines with 32-bit
|
||||||
|
# twos-complement signed integers. You may get test failures on
|
||||||
|
# machines with different architectures.
|
||||||
|
set a $IntMin - 1
|
||||||
|
set a $IntMin - $IntMax
|
||||||
|
set a $IntMax - $IntMin
|
||||||
|
set a $IntMax - (-1)
|
||||||
|
set a $IntMax + 1
|
||||||
|
set a $IntMax + $IntMax
|
||||||
|
set a $IntMin + (-1)
|
||||||
|
set a $IntMin + $IntMin
|
||||||
|
set a $IntMax * 2
|
||||||
|
set a $IntMax * $IntMax
|
||||||
|
set a $IntMax * $IntMin
|
||||||
|
set a $IntMin * 2
|
||||||
|
set a $IntMin * $IntMin
|
||||||
|
set a $IntMin * $IntMax
|
||||||
|
set a $IntMin / (-1)
|
||||||
|
set a $IntMin * (-1)
|
||||||
|
set a (-1) * $IntMin
|
||||||
|
set a abs($IntMin)
|
||||||
|
|
||||||
|
# Shellescape
|
||||||
|
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
|
||||||
|
|
||||||
|
msg [a]
|
||||||
|
|
||||||
# Don't want Remind to queue reminders
|
# Don't want Remind to queue reminders
|
||||||
EXIT
|
EXIT
|
||||||
|
|
||||||
|
|||||||
4
tests/utf-8.rem
Normal file
4
tests/utf-8.rem
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
|
||||||
|
MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
|
||||||
|
|
||||||
|
Wed MSG With tabs and spaces
|
||||||
@@ -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 src/version.h www/Makefile
|
echo rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||||
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile
|
rm -f config.cache config.log config.status src/Makefile src/config.h src/version.h www/Makefile rem2html/Makefile
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# The complete path to where the scripts actually live, as seen by
|
# The complete path to where the scripts actually live, as seen by
|
||||||
# the UNIX operating system.
|
# the UNIX operating system.
|
||||||
SCRIPTDIR = /var/www/cgi-bin
|
SCRIPTDIR = /usr/lib/cgi-bin
|
||||||
|
|
||||||
# Where the scripts live as seen by the web browser.
|
# Where the scripts live as seen by the web browser.
|
||||||
CGIDIR = /cgi-bin
|
CGIDIR = /cgi-bin
|
||||||
@@ -17,7 +17,7 @@ HTMLDIR = /var/www/remind
|
|||||||
# Where you stick images and CSS files, as seen by UNIX
|
# Where you stick images and CSS files, as seen by UNIX
|
||||||
IMAGEDIR = /var/www/remind/resources
|
IMAGEDIR = /var/www/remind/resources
|
||||||
|
|
||||||
# Where images are, as seen by web browers
|
# Where images and CSS fiels are, as seen by web browers
|
||||||
IMAGEBASE = /remind/resources
|
IMAGEBASE = /remind/resources
|
||||||
|
|
||||||
# Set by configure - don't touch.
|
# Set by configure - don't touch.
|
||||||
@@ -32,7 +32,7 @@ datarootdir=@datarootdir@
|
|||||||
# Where do Remind and Rem2PS executables live?
|
# Where do Remind and Rem2PS executables live?
|
||||||
REMIND = $(bindir)/remind
|
REMIND = $(bindir)/remind
|
||||||
REM2PS = $(bindir)/rem2ps
|
REM2PS = $(bindir)/rem2ps
|
||||||
|
REM2HTML = $(bindir)/rem2html
|
||||||
# If your Web server requires CGI programs to have a .cgi suffix, use
|
# If your Web server requires CGI programs to have a .cgi suffix, use
|
||||||
# the next line. Otherwise, comment it out
|
# the next line. Otherwise, comment it out
|
||||||
CGISUFFIX=.cgi
|
CGISUFFIX=.cgi
|
||||||
@@ -46,14 +46,8 @@ SEDSCRIPT = -e 's@%CGIDIR%@$(CGIDIR)@g' \
|
|||||||
-e 's@%REMIND%@$(REMIND)@g' \
|
-e 's@%REMIND%@$(REMIND)@g' \
|
||||||
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
-e 's@%IMAGEBASE%@$(IMAGEBASE)@g' \
|
||||||
-e 's@%REM2PS%@$(REM2PS)@g' \
|
-e 's@%REM2PS%@$(REM2PS)@g' \
|
||||||
|
-e 's@%REM2HTML%@$(REM2HTML)@g' \
|
||||||
-e 's@cal_dispatch@cal_dispatch$(CGISUFFIX)@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:
|
all:
|
||||||
@echo "Edit the Makefile; then type 'make install' to install"
|
@echo "Edit the Makefile; then type 'make install' to install"
|
||||||
@@ -72,7 +66,6 @@ install:
|
|||||||
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||||
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||||
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
||||||
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
||||||
@@ -80,20 +73,14 @@ install:
|
|||||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||||
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
|
chmod 755 $(DESTDIR)$(SCRIPTDIR)/calps $(DESTDIR)$(SCRIPTDIR)/hebdate \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
|
$(DESTDIR)$(SCRIPTDIR)/hebps $(DESTDIR)$(SCRIPTDIR)/moon \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
|
$(DESTDIR)$(SCRIPTDIR)/sunrise $(DESTDIR)$(SCRIPTDIR)/sunset \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
|
$(DESTDIR)$(SCRIPTDIR)/hebhtml \
|
||||||
$(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
|
||||||
|
|
||||||
-mkdir -p $(DESTDIR)$(IMAGEDIR)
|
-mkdir -p $(DESTDIR)$(IMAGEDIR)
|
||||||
cp firstquarter.png fullmoon.png lastquarter.png newmoon.png rem-default.css $(DESTDIR)$(IMAGEDIR)
|
cp rem-default.css *.png $(DESTDIR)$(IMAGEDIR)
|
||||||
chmod 644 $(DESTDIR)$(IMAGEDIR)/firstquarter.png \
|
chmod 644 $(DESTDIR)$(IMAGEDIR)/rem-default.css $(DESTDIR)$(IMAGEDIR)/*.png
|
||||||
$(DESTDIR)$(IMAGEDIR)/fullmoon.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/lastquarter.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/newmoon.png \
|
|
||||||
$(DESTDIR)$(IMAGEDIR)/rem-default.css
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ server:
|
|||||||
1) Edit the Makefile in this directory. See the comments in the Makefile
|
1) Edit the Makefile in this directory. See the comments in the Makefile
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
2) Edit the first line of "rem2html" to reflect the location of
|
2) Make sure "rem2html" is installed.
|
||||||
Perl on your system. (Oh yeah, you need Perl for the
|
|
||||||
HTML Hebrew calendar...)
|
|
||||||
|
|
||||||
3) Type "make install"
|
3) Type "make install"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
REM2HTML
|
|
||||||
--------
|
|
||||||
|
|
||||||
Rem2HTML is a Perl script that transforms the output of `remind -p
|
|
||||||
...' to HTML. Type `perl rem2html --help' for usage information.
|
|
||||||
|
|
||||||
Typical usage: remind -p ~/.reminders | rem2html > file.html
|
|
||||||
|
|
||||||
You may have to edit the "#!/usr/bin/perl" line to reflect the
|
|
||||||
location of your Perl interpreter.
|
|
||||||
|
|
||||||
--
|
|
||||||
Dianne Skoll
|
|
||||||
@@ -18,7 +18,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
|||||||
set nextmon mon(nextmon)
|
set nextmon mon(nextmon)
|
||||||
set lastmon mon(lastmon)
|
set lastmon mon(lastmon)
|
||||||
BANNER %
|
BANNER %
|
||||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||||
EOR
|
EOR
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -33,7 +33,7 @@ set lastyear iif(lastmon==12, thisyear-1, thisyear)
|
|||||||
set nextmon mon(nextmon)
|
set nextmon mon(nextmon)
|
||||||
set lastmon mon(lastmon)
|
set lastmon mon(lastmon)
|
||||||
BANNER %
|
BANNER %
|
||||||
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | $DIR/rem2html --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]"
|
REM RUN $REMIND -iHTML=1 -p $DIR/hebdate.rem %m %y | %REM2HTML% --forwurl "cal_dispatch?hebhtml+[nextmon]+[nextyear]" --backurl "cal_dispatch?hebhtml+[lastmon]+[lastyear]" --imgbase "%IMAGEBASE%" --stylesheet rem-default.css --pngs
|
||||||
EOR
|
EOR
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ div.rem-daynumber {
|
|||||||
font-size: 14pt;
|
font-size: 14pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.rem-entry {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
div.rem-moon {
|
div.rem-moon {
|
||||||
float: left;
|
float: left;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -66,4 +70,4 @@ td.rem-sc-empty-cell, td.rem-sc-cell {
|
|||||||
|
|
||||||
caption.rem-sc-caption {
|
caption.rem-sc-caption {
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user