mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-17 14:59:20 +02:00
Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb688850b1 | ||
|
|
5b1bad2650 | ||
|
|
e5ff132c5e | ||
|
|
a0830ad23c | ||
|
|
9290f53466 | ||
|
|
e5711032bd | ||
|
|
08e3c1d5a2 | ||
|
|
29c579a301 | ||
|
|
61f55bceee | ||
|
|
6586fae3eb | ||
|
|
d5a86f3e4f | ||
|
|
96551ccaa4 | ||
|
|
c83ee86d10 | ||
|
|
c913306cbd | ||
|
|
03d385df97 | ||
|
|
61fcc1b275 | ||
|
|
26977a4ac0 | ||
|
|
28acd05215 | ||
|
|
be4eed8b20 | ||
|
|
cdb0850373 | ||
|
|
0d55e04284 | ||
|
|
f4cce54b70 | ||
|
|
2dc6ca44f1 | ||
|
|
d1d833f0f3 | ||
|
|
1d44577ce9 | ||
|
|
1be7c2d6d7 | ||
|
|
b1f418ee42 | ||
|
|
72b0bf96fe | ||
|
|
3388849fa5 | ||
|
|
dc9650d5fa | ||
|
|
8eb40ae748 | ||
|
|
89184f1d0f | ||
|
|
e899c790b9 | ||
|
|
bd6d695020 | ||
|
|
20d4626a71 | ||
|
|
8ff94c5031 | ||
|
|
ee185a0eeb | ||
|
|
06f8932efd | ||
|
|
1dc627148c | ||
|
|
3cdde5351f | ||
|
|
6e93b8a73d | ||
|
|
267e8533cf | ||
|
|
d3bfb0a28f | ||
|
|
5a31bc7058 | ||
|
|
746bde71bd | ||
|
|
b274ac635c | ||
|
|
9e0a74e583 | ||
|
|
0f782f7697 | ||
|
|
8efde3e9af | ||
|
|
3bf3137dc4 | ||
|
|
63ec32d28d | ||
|
|
d2f4177cdb | ||
|
|
1d958fb7a8 | ||
|
|
fcd580d42e | ||
|
|
34dab68805 | ||
|
|
216dd03922 | ||
|
|
5eef9ac621 | ||
|
|
6b798d5f7c | ||
|
|
22ccce0934 | ||
|
|
fe2af14952 | ||
|
|
8e99ed27e7 | ||
|
|
bb12362cc8 | ||
|
|
1bfc630a64 | ||
|
|
987983f8ae | ||
|
|
657a6118aa | ||
|
|
43e7e6ec7f | ||
|
|
b8b3c19fbf | ||
|
|
69298c96a5 | ||
|
|
7356138872 | ||
|
|
616966f5df | ||
|
|
a59e277c21 | ||
|
|
740ae2c3e9 | ||
|
|
25b7a40f2b | ||
|
|
2beaab1a2f | ||
|
|
60793d53c6 | ||
|
|
4f869c8c81 | ||
|
|
8955180a35 | ||
|
|
a30cbf5797 | ||
|
|
b2bd6109dc | ||
|
|
9455ec48d7 | ||
|
|
f751f5defa | ||
|
|
994edbebbe | ||
|
|
70959b791c | ||
|
|
524ece5119 | ||
|
|
6334bd61b6 | ||
|
|
2e56edd557 | ||
|
|
8cae1d21cd | ||
|
|
1de6ed16eb | ||
|
|
860cb94f41 | ||
|
|
6b505704e9 | ||
|
|
167631451d | ||
|
|
fa5180b94d | ||
|
|
ae01d7be43 | ||
|
|
d5ce39ade1 | ||
|
|
a043dfe8b9 | ||
|
|
7cfb75e3b3 | ||
|
|
a18f0d982f | ||
|
|
0e2dc805c2 | ||
|
|
4c1e11df2c | ||
|
|
76776d054a | ||
|
|
45ebd05cb6 | ||
|
|
0203ce3979 | ||
|
|
72d10178bf | ||
|
|
96f4e26d53 | ||
|
|
4fd86f1b6a | ||
|
|
2f3ee0aec3 | ||
|
|
a5dde31160 | ||
|
|
b45428df05 | ||
|
|
d938763643 | ||
|
|
e4e2157622 | ||
|
|
04b349c6c7 | ||
|
|
7fe3eb7391 | ||
|
|
c1992b577a | ||
|
|
632283d47f | ||
|
|
1d9e46997c | ||
|
|
861ce34022 | ||
|
|
32e8db322d | ||
|
|
3df2b72175 | ||
|
|
e7ac4f95be | ||
|
|
e7ed69287b | ||
|
|
2e80417f53 | ||
|
|
ee435d2bb9 | ||
|
|
bb516946be | ||
|
|
81157e1cb5 | ||
|
|
51dfd707a2 | ||
|
|
7c3bf8601b | ||
|
|
714195efe5 | ||
|
|
eaeca2d09b | ||
|
|
ffa3b13437 | ||
|
|
2551e98d11 | ||
|
|
1bfd7761bc | ||
|
|
de9cb1d0a3 | ||
|
|
b2d32b514a | ||
|
|
6e53fd6924 | ||
|
|
8296d2b962 | ||
|
|
d6e66ee1e6 | ||
|
|
a49532b9c5 | ||
|
|
57d87f4caf | ||
|
|
ec9b30c616 | ||
|
|
27d8a62ab6 | ||
|
|
5077814c4a | ||
|
|
ca795a352a | ||
|
|
e59fc36458 | ||
|
|
39e3657539 | ||
|
|
6031f70701 | ||
|
|
3567c9e55f | ||
|
|
26de4e3fd3 | ||
|
|
cd65c6144d | ||
|
|
7b64623115 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,6 +16,7 @@ man/remind.1
|
|||||||
man/tkremind.1
|
man/tkremind.1
|
||||||
pm_to_blib
|
pm_to_blib
|
||||||
rem2html/Makefile
|
rem2html/Makefile
|
||||||
|
rem2html/rem2html
|
||||||
rem2html/rem2html.1
|
rem2html/rem2html.1
|
||||||
rem2pdf/Makefile.PL
|
rem2pdf/Makefile.PL
|
||||||
rem2pdf/Makefile.old
|
rem2pdf/Makefile.old
|
||||||
|
|||||||
@@ -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-2023 Dianne Skoll, except where noted in
|
2. REMIND is Copyright 1992-2024 Dianne Skoll, except where noted in
|
||||||
individual files.
|
individual files.
|
||||||
|
|
||||||
3. DISTRIBUTION AND USE
|
3. DISTRIBUTION AND USE
|
||||||
@@ -16,7 +16,7 @@ individual files.
|
|||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
675 Mass Ave, Cambridge, MA 02139, USA
|
51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -44,7 +44,7 @@ test:
|
|||||||
@$(MAKE) -C src -s test
|
@$(MAKE) -C src -s test
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile rem2pdf/Makefile.top rem2pdf/Makefile.old rem2pdf/Makefile rem2pdf/Makefile.PL rem2pdf/bin/rem2pdf
|
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile rem2pdf/Makefile.top rem2pdf/Makefile.old rem2pdf/Makefile rem2pdf/Makefile.PL rem2pdf/bin/rem2pdf rem2html/rem2html
|
||||||
|
|
||||||
src/Makefile: src/Makefile.in
|
src/Makefile: src/Makefile.in
|
||||||
./configure
|
./configure
|
||||||
|
|||||||
26
build.tk
Normal file → Executable file
26
build.tk
Normal file → Executable file
@@ -27,10 +27,10 @@ exec wish "$0" "$@"
|
|||||||
proc SetConfigDefaults {} {
|
proc SetConfigDefaults {} {
|
||||||
global Config
|
global Config
|
||||||
set Config(LAT_DEG) 45
|
set Config(LAT_DEG) 45
|
||||||
set Config(LAT_MIN) 24
|
set Config(LAT_MIN) 25
|
||||||
set Config(LAT_SEC) 14
|
set Config(LAT_SEC) 14
|
||||||
set Config(LON_DEG) 75
|
set Config(LON_DEG) 75
|
||||||
set Config(LON_MIN) 39
|
set Config(LON_MIN) 41
|
||||||
set Config(LON_SEC) 23
|
set Config(LON_SEC) 23
|
||||||
set Config(LOCATION) "Ottawa"
|
set Config(LOCATION) "Ottawa"
|
||||||
set Config(DEFAULT_PAGE) "Letter"
|
set Config(DEFAULT_PAGE) "Letter"
|
||||||
@@ -53,7 +53,7 @@ proc SetConfigDefaults {} {
|
|||||||
# Pops up an error dialog; then calls exit.
|
# Pops up an error dialog; then calls exit.
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc Bail { msg } {
|
proc Bail { msg } {
|
||||||
tk_dialog .err "Remind Configuration Error" $msg error 0 "Bummer"
|
tk_messageBox -message "Remind Build Error" -detail $msg -icon error -type ok
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +190,8 @@ proc CreateLocationDialog { w } {
|
|||||||
|
|
||||||
grid $w.north $w.west
|
grid $w.north $w.west
|
||||||
grid $w.south $w.east
|
grid $w.south $w.east
|
||||||
grid $w.loclab -sticky e
|
grid $w.loclab -sticky e
|
||||||
grid $w.location -sticky nsew -row 6 -column 1
|
grid $w.location -sticky nsew -row 8 -column 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
@@ -293,9 +293,9 @@ proc BuildRemind {} {
|
|||||||
|
|
||||||
.msgs insert end "\n>>> Creating src/custom.h...\n\n" green
|
.msgs insert end "\n>>> Creating src/custom.h...\n\n" green
|
||||||
CreateCustomH
|
CreateCustomH
|
||||||
.msgs insert end ">>> Calling `./configure'...\n\n" green
|
.msgs insert end "\n>>> Calling `./configure'...\n\n" green
|
||||||
CallConfigure
|
CallConfigure
|
||||||
.msgs insert end ">>> Calling `make'...\n\n" green
|
.msgs insert end "\n>>> Calling `make'...\n\n" green
|
||||||
CallMake
|
CallMake
|
||||||
.msgs insert end "\n----------------------------------------------\n\n"
|
.msgs insert end "\n----------------------------------------------\n\n"
|
||||||
.msgs insert end "Remind" red
|
.msgs insert end "Remind" red
|
||||||
@@ -447,12 +447,12 @@ proc CreateCustomH {} {
|
|||||||
"#define DEFAULT_LATITUDE *" {
|
"#define DEFAULT_LATITUDE *" {
|
||||||
set lat [expr $LAT_DEG + ($LAT_MIN/60.0) + ($LAT_SEC/3600.0)];
|
set lat [expr $LAT_DEG + ($LAT_MIN/60.0) + ($LAT_SEC/3600.0)];
|
||||||
puts $out "#define DEFAULT_LATITUDE $lat"
|
puts $out "#define DEFAULT_LATITUDE $lat"
|
||||||
.msgs insert end "#define DEFAULT_LATITUDE $lat"
|
.msgs insert end "#define DEFAULT_LATITUDE $lat\n"
|
||||||
}
|
}
|
||||||
"#define DEFAULT_LONGITUDE *" {
|
"#define DEFAULT_LONGITUDE *" {
|
||||||
set lon [expr -1.0 * ($LON_DEG + ($LON_MIN/60.0) + ($LON_SEC/3600.0))]
|
set lon [expr -1.0 * ($LON_DEG + ($LON_MIN/60.0) + ($LON_SEC/3600.0))]
|
||||||
puts $out "#define DEFAULT_LONGITUDE $lon"
|
puts $out "#define DEFAULT_LONGITUDE $lon"
|
||||||
.msgs insert end "#define DEFAULT_LONGITUDE $lon"
|
.msgs insert end "#define DEFAULT_LONGITUDE $lon\n"
|
||||||
}
|
}
|
||||||
"#define LOCATION *" {
|
"#define LOCATION *" {
|
||||||
puts $out "#define LOCATION \"$Config(LOCATION)\""
|
puts $out "#define LOCATION \"$Config(LOCATION)\""
|
||||||
@@ -506,7 +506,13 @@ proc CallMake {} {
|
|||||||
"Icelandic" { set lang ICELANDIC }
|
"Icelandic" { set lang ICELANDIC }
|
||||||
default { set lang ENGLISH }
|
default { set lang ENGLISH }
|
||||||
}
|
}
|
||||||
RunCommand "make \"LANGDEF=-DLANG=$lang\""
|
set nproc 0
|
||||||
|
catch { set nproc [exec nproc] }
|
||||||
|
if { $nproc != 0 } {
|
||||||
|
RunCommand "make -j $nproc \"LANGDEF=-DLANG=$lang\""
|
||||||
|
} else {
|
||||||
|
RunCommand "make \"LANGDEF=-DLANG=$lang\""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
configure
vendored
21
configure
vendored
@@ -4034,6 +4034,12 @@ then :
|
|||||||
printf "%s\n" "#define HAVE_LANGINFO_H 1" >>confdefs.h
|
printf "%s\n" "#define HAVE_LANGINFO_H 1" >>confdefs.h
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
ac_fn_c_check_header_compile "$LINENO" "sys/inotify.h" "ac_cv_header_sys_inotify_h" "$ac_includes_default"
|
||||||
|
if test "x$ac_cv_header_sys_inotify_h" = xyes
|
||||||
|
then :
|
||||||
|
printf "%s\n" "#define HAVE_SYS_INOTIFY_H 1" >>confdefs.h
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
|
||||||
@@ -4134,14 +4140,14 @@ if test "$GCC" = yes; then
|
|||||||
f=-flto=auto
|
f=-flto=auto
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||||
printf %s "checking whether $CC supports $f... " >&6; }
|
printf %s "checking whether $CC supports $f... " >&6; }
|
||||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
printf "%s\n" "yes" >&6; }
|
printf "%s\n" "yes" >&6; }
|
||||||
CFLAGS="$CFLAGS $f"
|
CFLAGS="$CFLAGS $f"
|
||||||
f=-ffat-lto-objects
|
f=-ffat-lto-objects
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||||
printf %s "checking whether $CC supports $f... " >&6; }
|
printf %s "checking whether $CC supports $f... " >&6; }
|
||||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
printf "%s\n" "yes" >&6; }
|
printf "%s\n" "yes" >&6; }
|
||||||
CFLAGS="$CFLAGS $f"
|
CFLAGS="$CFLAGS $f"
|
||||||
@@ -4211,14 +4217,20 @@ then :
|
|||||||
printf "%s\n" "#define HAVE_INITGROUPS 1" >>confdefs.h
|
printf "%s\n" "#define HAVE_INITGROUPS 1" >>confdefs.h
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
ac_fn_c_check_func "$LINENO" "inotify_init1" "ac_cv_func_inotify_init1"
|
||||||
|
if test "x$ac_cv_func_inotify_init1" = xyes
|
||||||
|
then :
|
||||||
|
printf "%s\n" "#define HAVE_INOTIFY_INIT1 1" >>confdefs.h
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
VERSION=04.02.07
|
VERSION=04.03.03
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1"
|
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2html/rem2html rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1"
|
||||||
|
|
||||||
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
|
||||||
@@ -4910,6 +4922,7 @@ do
|
|||||||
"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" ;;
|
"rem2html/Makefile") CONFIG_FILES="$CONFIG_FILES rem2html/Makefile" ;;
|
||||||
|
"rem2html/rem2html") CONFIG_FILES="$CONFIG_FILES rem2html/rem2html" ;;
|
||||||
"rem2pdf/Makefile.PL") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.PL" ;;
|
"rem2pdf/Makefile.PL") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.PL" ;;
|
||||||
"rem2pdf/Makefile.top") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.top" ;;
|
"rem2pdf/Makefile.top") CONFIG_FILES="$CONFIG_FILES rem2pdf/Makefile.top" ;;
|
||||||
"rem2pdf/bin/rem2pdf") CONFIG_FILES="$CONFIG_FILES rem2pdf/bin/rem2pdf" ;;
|
"rem2pdf/bin/rem2pdf") CONFIG_FILES="$CONFIG_FILES rem2pdf/bin/rem2pdf" ;;
|
||||||
|
|||||||
12
configure.in
12
configure.in
@@ -38,7 +38,7 @@ AC_CHECK_SIZEOF(unsigned long)
|
|||||||
AC_CHECK_SIZEOF(time_t)
|
AC_CHECK_SIZEOF(time_t)
|
||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_CHECK_HEADERS(sys/types.h glob.h wctype.h locale.h langinfo.h)
|
AC_CHECK_HEADERS(sys/types.h glob.h wctype.h locale.h langinfo.h sys/inotify.h)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
@@ -50,12 +50,12 @@ if test "$GCC" = yes; then
|
|||||||
# Check for link-time optimization support
|
# Check for link-time optimization support
|
||||||
f=-flto=auto
|
f=-flto=auto
|
||||||
AC_MSG_CHECKING([whether $CC supports $f])
|
AC_MSG_CHECKING([whether $CC supports $f])
|
||||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
CFLAGS="$CFLAGS $f"
|
CFLAGS="$CFLAGS $f"
|
||||||
f=-ffat-lto-objects
|
f=-ffat-lto-objects
|
||||||
AC_MSG_CHECKING([whether $CC supports $f])
|
AC_MSG_CHECKING([whether $CC supports $f])
|
||||||
if $CC -E $f /dev/null > /dev/null 2>&1 ; then
|
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
CFLAGS="$CFLAGS $f"
|
CFLAGS="$CFLAGS $f"
|
||||||
else
|
else
|
||||||
@@ -86,13 +86,13 @@ if test "$?" != 0 ; then
|
|||||||
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
|
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
|
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups inotify_init1)
|
||||||
|
|
||||||
VERSION=04.02.07
|
VERSION=04.03.03
|
||||||
AC_SUBST(VERSION)
|
AC_SUBST(VERSION)
|
||||||
AC_SUBST(PERL)
|
AC_SUBST(PERL)
|
||||||
AC_SUBST(PERLARTIFACTS)
|
AC_SUBST(PERLARTIFACTS)
|
||||||
AC_SUBST(RELEASE_DATE)
|
AC_SUBST(RELEASE_DATE)
|
||||||
AC_CONFIG_FILES([src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1])
|
AC_CONFIG_FILES([src/Makefile www/Makefile src/version.h rem2html/Makefile rem2html/rem2html rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf man/rem.1 man/rem2ps.1 man/remind.1 man/tkremind.1])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
chmod a+x rem2pdf/bin/rem2pdf
|
chmod a+x rem2pdf/bin/rem2pdf
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
|
|
||||||
;; You should have received a copy of the GNU General Public License
|
;; You should have received a copy of the GNU General Public License
|
||||||
;; along with this program; if not, write to the Free Software
|
;; along with this program; if not, write to the Free Software
|
||||||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
|
||||||
;; 02111-1307, USA.
|
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ Norman Walsh.
|
|||||||
#!/usr/local/bin/wish
|
#!/usr/local/bin/wish
|
||||||
wm withdraw .
|
wm withdraw .
|
||||||
after 15000 { destroy . ; exit }
|
after 15000 { destroy . ; exit }
|
||||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
tk_messageBox -message Message -detail $argv -icon info -type ok
|
||||||
destroy .
|
destroy .
|
||||||
exit
|
exit
|
||||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
||||||
|
|||||||
163
docs/WHATSNEW
163
docs/WHATSNEW
@@ -1,5 +1,168 @@
|
|||||||
CHANGES TO REMIND
|
CHANGES TO REMIND
|
||||||
|
|
||||||
|
* VERSION 4.3 Patch 3 - 2024-03-18
|
||||||
|
|
||||||
|
* IMPROVEMENT: tkremind: Update icon to include a white border so it shows
|
||||||
|
up better on dark backgrounds.
|
||||||
|
|
||||||
|
* IMPROVEMENT: C code: Fix a number of cppcheck static-analysis warnings.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: Update the "-zj" protocol to include a queue-id for
|
||||||
|
each queued reminder and add the DEL client command to delete a specific
|
||||||
|
item from the queue. Used by tkremind to implement "don't remind me about
|
||||||
|
this again today."
|
||||||
|
|
||||||
|
* MINOR NEW FEATURE: Add a "-ds" debugging flag to print out expression-parsing
|
||||||
|
stack high-water marks on exit. This esoteric feature is of no use to
|
||||||
|
anyone by the Remind author.
|
||||||
|
|
||||||
|
* IMPROVEMENT: tkremind: Stop using the deprecated tk_dialog command in favor
|
||||||
|
of the newer tk_messageBox command.
|
||||||
|
|
||||||
|
* IMPROVEMENT: remind: In server mode, try to minimize redraws by
|
||||||
|
consuming inotify events until at least 0.2s elapses without an
|
||||||
|
event appearing.
|
||||||
|
|
||||||
|
* BUG FIX: tkremind: The "Don't remind me about this again today" feature
|
||||||
|
was unreliable and only worked for reminders created with TkRemind itself.
|
||||||
|
It has been made more reliable and works with any reminder.
|
||||||
|
|
||||||
|
* BUG FIX: remind: Make it a syntax error if a local OMIT in a REM statement
|
||||||
|
is not followed by at least one weekday name.
|
||||||
|
|
||||||
|
* VERSION 4.3 Patch 2 - 2024-03-01
|
||||||
|
|
||||||
|
- BUG FIX: remind: Fix a logic error when implementing the RUN command in
|
||||||
|
server mode. As it turns out, the error is harmless, but it's best to do
|
||||||
|
things correctly.
|
||||||
|
|
||||||
|
- BUG FIX: The Makefile would install the tkremind.png and tkremind.desktop
|
||||||
|
files in the wrong location. This has been fixed.
|
||||||
|
|
||||||
|
* VERSION 4.3 Patch 1 - 2024-02-29
|
||||||
|
|
||||||
|
- BUG FIX: tests: "make test" could fail because of a bad test. This
|
||||||
|
has been fixed. There are no actual code changes to any of the programs
|
||||||
|
in Remind compared to 04.03.00.
|
||||||
|
|
||||||
|
* VERSION 4.3 Patch 0 - 2024-02-29
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: If Remind is compiled on a system that supports
|
||||||
|
inotify, then in server mode (-z0 or -zj) it monitors the reminders file
|
||||||
|
and restarts itself if it detects a change, and also notifies the client.
|
||||||
|
Moving inotify support directly into Remind means that tkremind no longer
|
||||||
|
has to invoke a separate inotifywait process.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: Set the CLOEXEC flag on files we open so we
|
||||||
|
don't leak file descriptors to programs that we run. While I don't
|
||||||
|
think there's a security issue here (any program you run can do
|
||||||
|
anything as your userid anyway) it's best to be clean and tidy.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: Add localization for the Catalan language, courtesy
|
||||||
|
of Eloi Torrents.
|
||||||
|
|
||||||
|
- IMPROVEMENT: tkremind: Add a .desktop file and icon so TkRemind can be
|
||||||
|
integrated into the desktop menu system, courtesy of Eloi Torrents.
|
||||||
|
|
||||||
|
- CHANGE: Add a new server mode with the "-zj" flag. This is just
|
||||||
|
like "-z0" except it uses JSON messages to communicate with the
|
||||||
|
client rather than an ad-hoc protocol. The "-z0" mode is still
|
||||||
|
supported, but is deprecated.
|
||||||
|
|
||||||
|
- CHANGE: In server mode (-z0 or -zj) any RUN-type reminders, or message
|
||||||
|
commands of the "-kcommand" type are run with standard input and standard
|
||||||
|
output connected to /dev/null. NOTE INCOMPATIBILITY: If you previously
|
||||||
|
relied on RUN-type reminders to pop up reminders in TkRemind, they no
|
||||||
|
longer do. If you want this, you'll have to get the command that you
|
||||||
|
run to pop up its own window with "xmessage" or something similar.
|
||||||
|
|
||||||
|
- IMPROVEMENT: tkremind: Make the "Go to date..." dialog non-modal.
|
||||||
|
|
||||||
|
- CHANGE: remind: Allow the argument to easterdate() and
|
||||||
|
orthodoxeaster() to be omitted, in which case it defaults to
|
||||||
|
today().
|
||||||
|
|
||||||
|
- BUG FIX: Miscellaneous man page fixes.
|
||||||
|
|
||||||
|
- BUG FIX: Fix a leap-year edge-case. The reminder: REM 29 MSG whatever
|
||||||
|
was not triggered on Feb 29 of leap years.
|
||||||
|
|
||||||
|
- BUG FIX: rem2html: Make the version of rem2html track the version of
|
||||||
|
Remind. Noted by Ian! D. Allen.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 9 - 2024-02-04
|
||||||
|
|
||||||
|
- CHANGE: remind: Do not attempt to guess terminal background color on
|
||||||
|
startup. Only obtain it as needed. This can prevent mojibake from
|
||||||
|
appearing on terminals that don't support the color query escape
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: Add new system variables $NumFullOmits,
|
||||||
|
$MaxFullOmits, $NumPartialOmits and $MaxPartialOmits.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: Issue a warning if someone OMITs every possible date.
|
||||||
|
|
||||||
|
- IMPROVEMENT: remind: In several error messages complaining about limits
|
||||||
|
being exceeded, include the actual limit in the error message. Clarify
|
||||||
|
the man page regarding limits on the number of OMITs.
|
||||||
|
|
||||||
|
- MINOR NEW FEATURE: remind: The expression STRING * INT or INT * STRING
|
||||||
|
is now accepted and yields a string that is INT concatenations of the
|
||||||
|
original STRING. In this case, INT must be non-negative and the total
|
||||||
|
string length can't exceed $MaxStringLen.
|
||||||
|
|
||||||
|
- DOCUMENTATION: Add "Astronomical Algorithms" by Jean Meeus to bibliography.
|
||||||
|
|
||||||
|
- DOCUMENTATION FIX: Update address of the Free Software Foundation in the
|
||||||
|
license file.
|
||||||
|
|
||||||
|
- DOCUMENTATION: Note that rem2ps is deprecated and will not received any
|
||||||
|
new features. Further development will happen on rem2pdf.
|
||||||
|
|
||||||
|
- BUG FIX: Preserve the filename() and priority context for queued reminders.
|
||||||
|
Previously, the filename information was lost and the priority was
|
||||||
|
coming from uninitialized memory (yikes!). bug found by Alexander
|
||||||
|
Möller.
|
||||||
|
|
||||||
|
- BUG FIX: build.tk: Various minor improvements.
|
||||||
|
|
||||||
|
- BUG FIX: remind: In server mode, if we de-queue a reminder without
|
||||||
|
triggering it, issue a "NOTE queued %d" message to update the
|
||||||
|
client's notion of the queue size.
|
||||||
|
|
||||||
|
- BUG FIX: tkremind: Fix typo found by Lorenzo Bazzanini.
|
||||||
|
|
||||||
|
* VERSION 4.2 Patch 8 - 2023-12-14
|
||||||
|
|
||||||
|
- NEW FEATURE: Add the $MaxLateMinutes system variable. This suppresses
|
||||||
|
a queued time reminder if the current time is more than $MaxLateMinutes
|
||||||
|
past the trigger time. (This typically only occurs if the computer
|
||||||
|
has been suspended/hibernated and then resumed.)
|
||||||
|
|
||||||
|
- IMPROVEMENT: tkremind: If an error occurs during printing, catch it
|
||||||
|
and change the Queue... button to Errors... (the same way errors in
|
||||||
|
reminder files are handled.)
|
||||||
|
|
||||||
|
- IMPROVEMENT: rem2html: add the --utf8 flag to set the HTML charset to
|
||||||
|
UTF-8.
|
||||||
|
|
||||||
|
- MINOR IMPROVEMENTS: Refactor some of the C code; use symbolic exit
|
||||||
|
statuses and file descriptors for stdin/stdout/stderr where possible.
|
||||||
|
|
||||||
|
- BUG FIX: configure.in: Use better option detection so we don't use the
|
||||||
|
unsupported option -ffat-lto-objects if compiling with clang instead of gcc.
|
||||||
|
|
||||||
|
- BUG FIXES: Many fixes to man pages, some by Jochen Sprickerhof
|
||||||
|
|
||||||
|
- MINOR BUG FIX: If Remind puts itself in the background, only close
|
||||||
|
stdout/stderr if they are not associated with a terminal. If
|
||||||
|
we close a descriptor, dup /dev/null onto it.
|
||||||
|
|
||||||
|
- MINOR BUG FIX: Catch SIGCONT when running in daemon/background mode.
|
||||||
|
This forces the select() call to be interrupted so we can update the
|
||||||
|
sleep time. This really only matters if the computer or the background
|
||||||
|
Remind process is suspended and then resumed.
|
||||||
|
|
||||||
* VERSION 4.2 Patch 7 - 2023-10-09
|
* VERSION 4.2 Patch 7 - 2023-10-09
|
||||||
|
|
||||||
- IMPROVEMENT: remind: On 32-bit systems, attempt to use a 64-bit time_t
|
- IMPROVEMENT: remind: On 32-bit systems, attempt to use a 64-bit time_t
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ FSET center(x) pad("", " ", (columns() - columns(x))/2) + x
|
|||||||
FSET right(x) pad("", " ", columns() - columns(x)) + x
|
FSET right(x) pad("", " ", columns() - columns(x)) + x
|
||||||
|
|
||||||
MSG This is left-aligned.
|
MSG This is left-aligned.
|
||||||
MSG [ansicolor(0,255,0)]This is also left-aligned.[ansicolor("")]
|
MSG [ansicolor(0,255,0)]🌕 🌕 🌕 🌕 This is also left-aligned.[ansicolor("")]
|
||||||
|
|
||||||
MSG [center("This is centered.")]
|
MSG [center("This is centered.")]
|
||||||
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
|
MSG [ansicolor(255,255,0) + center("🌕 🌕 🌕 🌕 This is also centered. ") + ansicolor("")]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# "#PSSTUFF" for nifty PostScript examples #
|
# "#PSSTUFF" for nifty PostScript examples #
|
||||||
# #
|
# #
|
||||||
# This file is part of REMIND. #
|
# This file is part of REMIND. #
|
||||||
# Copyright (C) 1992-2023 Dianne Skoll #
|
# Copyright (C) 1992-2024 Dianne Skoll #
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# #
|
# #
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Not all sequences are supported by all terminals.
|
# Not all sequences are supported by all terminals.
|
||||||
|
|
||||||
# This file is part of REMIND
|
# This file is part of REMIND
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
if !defined("ansi_bold")
|
if !defined("ansi_bold")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# US holidays
|
# US holidays
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2023 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
REM [easterdate($Uy)-46] MSG Ash Wednesday
|
REM [easterdate($Uy)-46] MSG Ash Wednesday
|
||||||
|
|||||||
53
include/lang/ca.rem
Normal file
53
include/lang/ca.rem
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Support for the Catalan language.
|
||||||
|
# This file is part of REMIND.
|
||||||
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
|
# This file was created by Eloi Torrents <eloitor@disroot.org>
|
||||||
|
|
||||||
|
SET $Monday "dilluns"
|
||||||
|
SET $Tuesday "dimarts"
|
||||||
|
SET $Wednesday "dimecres"
|
||||||
|
SET $Thursday "dijous"
|
||||||
|
SET $Friday "divendres"
|
||||||
|
SET $Saturday "dissabte"
|
||||||
|
SET $Sunday "diumenge"
|
||||||
|
|
||||||
|
SET $January "gener"
|
||||||
|
SET $February "febrer"
|
||||||
|
SET $March "març"
|
||||||
|
SET $April "abril"
|
||||||
|
SET $May "maig"
|
||||||
|
SET $June "juny"
|
||||||
|
SET $July "juliol"
|
||||||
|
SET $August "agost"
|
||||||
|
SET $September "setembre"
|
||||||
|
SET $October "octubre"
|
||||||
|
SET $November "novembre"
|
||||||
|
SET $December "desembre"
|
||||||
|
|
||||||
|
SET $Today "avui"
|
||||||
|
SET $Tomorrow "demà"
|
||||||
|
FSET subst_bx(a,d,t) iif(d==today()+2, "demà passat", "d'aquí " + (d-today()) + " dies")
|
||||||
|
|
||||||
|
# 1 d'abril vs 1 de maig.
|
||||||
|
FSET subst_sx(a,d,t) iif(isany(substr(mon(d), 1, 1), "a", "o") , "d'", "de")
|
||||||
|
FSET subst_ordinal(d) ""
|
||||||
|
|
||||||
|
BANNER Agenda pel %w, %d %s %m de %y%o:
|
||||||
|
|
||||||
|
SET $Am "am"
|
||||||
|
SET $Pm "pm"
|
||||||
|
|
||||||
|
SET $Ago "fa"
|
||||||
|
SET $Fromnow "des d'avui"
|
||||||
|
SET $On "el dia"
|
||||||
|
SET $Now "ara"
|
||||||
|
SET $At "a les"
|
||||||
|
|
||||||
|
SET $Minute "minut"
|
||||||
|
SET $Mplu "s"
|
||||||
|
SET $Hour "hora"
|
||||||
|
FSET subst_hours(h) iif(h==1, "1 hora", h + " hores")
|
||||||
|
|
||||||
|
SET $Is "és"
|
||||||
|
SET $Was "va ser"
|
||||||
|
SET $And "i"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Danish language.
|
# Support for the Danish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mogens Lynnerup.
|
# This file is derived from a translation by Mogens Lynnerup.
|
||||||
|
|
||||||
SET $Sunday "Søndag"
|
SET $Sunday "Søndag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the German language.
|
# Support for the German language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Wolfgang Thronicke
|
# This file is derived from a translation by Wolfgang Thronicke
|
||||||
|
|
||||||
# Day names
|
# Day names
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Support for the English language.
|
# Support for the English language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# Nothing to do for English since it is the default.
|
# Nothing to do for English since it is the default.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Spanish language.
|
# Support for the Spanish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
||||||
|
|
||||||
SET $Sunday "Domingo"
|
SET $Sunday "Domingo"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Finnish language.
|
# Support for the Finnish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Mikko Silvonen
|
# This file is derived from a translation by Mikko Silvonen
|
||||||
|
|
||||||
SET $Sunday "sunnuntai"
|
SET $Sunday "sunnuntai"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the French language.
|
# Support for the French language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Laurent Duperval
|
# This file is derived from a translation by Laurent Duperval
|
||||||
|
|
||||||
SET $Sunday "dimanche"
|
SET $Sunday "dimanche"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Hellenic (Greek) language.
|
# Support for the Hellenic (Greek) language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
||||||
|
|
||||||
SET $Sunday "Κυριακή"
|
SET $Sunday "Κυριακή"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Icelanding language.
|
# Support for the Icelanding language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
||||||
|
|
||||||
SET $Sunday "sunnudagur"
|
SET $Sunday "sunnudagur"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Italian language.
|
# Support for the Italian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Valerio Aimale
|
# This file is derived from a translation by Valerio Aimale
|
||||||
|
|
||||||
SET $Sunday "Domenica"
|
SET $Sunday "Domenica"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Dutch language.
|
# Support for the Dutch language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
||||||
|
|
||||||
SET $Sunday "zondag"
|
SET $Sunday "zondag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Norwegian language.
|
# Support for the Norwegian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Trygve Randen
|
# This file is derived from a translation by Trygve Randen
|
||||||
|
|
||||||
SET $Sunday "Søndag"
|
SET $Sunday "Søndag"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Polish language.
|
# Support for the Polish language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Jerzy Sobczyk
|
# This file is derived from a translation by Jerzy Sobczyk
|
||||||
|
|
||||||
SET $Sunday "Niedziela"
|
SET $Sunday "Niedziela"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the (Brazilian) Portuguese language.
|
# Support for the (Brazilian) Portuguese language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Marco Paganini
|
# This file is derived from a translation by Marco Paganini
|
||||||
|
|
||||||
SET $Sunday "domingo"
|
SET $Sunday "domingo"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Support for the Romanian language.
|
# Support for the Romanian language.
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# REMIND is Copyright (C) 1992-2023 by Dianne Skoll
|
# REMIND is Copyright (C) 1992-2024 by Dianne Skoll
|
||||||
# This file is derived from a translation by Liviu Daia
|
# This file is derived from a translation by Liviu Daia
|
||||||
|
|
||||||
SET $Sunday "Duminică"
|
SET $Sunday "Duminică"
|
||||||
|
|||||||
@@ -5,22 +5,25 @@ rem2ps \- draw a PostScript calendar from Remind output
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B rem2ps [\fIoptions\fR]
|
.B rem2ps [\fIoptions\fR]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBRem2ps\fR reads the standard input, which should be the results of
|
\fBrem2ps\fR reads the standard input, which should be the results of
|
||||||
running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
|
running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
|
||||||
emits PostScript code (which draws a calendar) to the standard output.
|
emits PostScript code (which draws a calendar) to the standard output.
|
||||||
.PP
|
.PP
|
||||||
See the section "Rem2PS Input Format" for details about the \fB\-p\fR
|
Although \fBrem2ps\fR will be maintained, no new features will be added
|
||||||
|
to it. Instead, all new development will continue on \fBrem2pdf\fR.
|
||||||
|
.PP
|
||||||
|
See the section "REM2PS INPUT FORMAT" for details about the \fB\-p\fR
|
||||||
data. This may be useful if you wish to create other \fBRemind\fR
|
data. This may be useful if you wish to create other \fBRemind\fR
|
||||||
back-ends.
|
back-ends.
|
||||||
.PP
|
.PP
|
||||||
Note that \fBRem2PS\fR does not handle UTF-8 input. If you need to
|
Note that \fBrem2ps\fR does not handle UTF-8 input. If you need to
|
||||||
render characters outside the ASCII character set, see
|
render characters outside the ASCII character set, see
|
||||||
\fBrem2pdf\fR instead.
|
\fBrem2pdf\fR instead.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Be more verbose. This causes \fBRem2ps\fR to print progress messages
|
Be more verbose. This causes \fBrem2ps\fR to print progress messages
|
||||||
to the standard error stream. Normally, it is silent.
|
to the standard error stream. Normally, it is silent.
|
||||||
.TP
|
.TP
|
||||||
.B \-p file
|
.B \-p file
|
||||||
@@ -133,7 +136,7 @@ numbers.
|
|||||||
|
|
||||||
.PP
|
.PP
|
||||||
Type "rem2ps \-m help" for a list of available media. Note that the media
|
Type "rem2ps \-m help" for a list of available media. Note that the media
|
||||||
type (and all \fBRem2ps\fR options) are case-sensitive. If you don't use
|
type (and all \fBrem2ps\fR options) are case-sensitive. If you don't use
|
||||||
the \fB\-m\fR option, the media defaults to a compiled-in default - this
|
the \fB\-m\fR option, the media defaults to a compiled-in default - this
|
||||||
is usually Letter for North America and A4 for Europe. The "\-m help"
|
is usually Letter for North America and A4 for Europe. The "\-m help"
|
||||||
option will display the compiled-in default.
|
option will display the compiled-in default.
|
||||||
@@ -193,8 +196,8 @@ for good output:
|
|||||||
rem2ps \-ol 72 \-sh 12
|
rem2ps \-ol 72 \-sh 12
|
||||||
.fi
|
.fi
|
||||||
.SH USAGE
|
.SH USAGE
|
||||||
To use \fBRem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
|
To use \fBrem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
|
||||||
option to \fBRem2ps\fR, and then send the result to a printer. This is most easily
|
option to \fBrem2ps\fR, and then send the result to a printer. This is most easily
|
||||||
illustrated with examples:
|
illustrated with examples:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
@@ -228,10 +231,10 @@ calendar entries. This border is normally blank space.
|
|||||||
.TP
|
.TP
|
||||||
BoxWidth and BoxHeight
|
BoxWidth and BoxHeight
|
||||||
The width and height of the calendar box, from center-to-center of the
|
The width and height of the calendar box, from center-to-center of the
|
||||||
black gridlines.
|
black grid lines.
|
||||||
.TP
|
.TP
|
||||||
InBoxHeight
|
InBoxHeight
|
||||||
The height from the center of the bottom black gridline to the top
|
The height from the center of the bottom black grid line to the top
|
||||||
of the regular calendar entry area. The space from here to the top
|
of the regular calendar entry area. The space from here to the top
|
||||||
of the box is used only to draw the day number.
|
of the box is used only to draw the day number.
|
||||||
.TP
|
.TP
|
||||||
@@ -260,7 +263,7 @@ PostScript files. Always test your PostScript thoroughly with a PostScript
|
|||||||
viewer before sending it to the printer. You should not use any document
|
viewer before sending it to the printer. You should not use any document
|
||||||
structuring comments in your PostScript code.
|
structuring comments in your PostScript code.
|
||||||
.PP
|
.PP
|
||||||
In addition, prior to drawing a calendar page, \fBRem2ps\fR emits
|
In addition, prior to drawing a calendar page, \fBrem2ps\fR emits
|
||||||
the following PostScript code:
|
the following PostScript code:
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
@@ -320,8 +323,8 @@ For an example, create a file called "myprolog" whose contents are:
|
|||||||
} bind def
|
} bind def
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
|
Use that file with the \fBrem2ps\fR \fB\-p\fR option to create calendars
|
||||||
with the year and month in large grey letters in the background of the
|
with the year and month in large gray letters in the background of the
|
||||||
calendar.
|
calendar.
|
||||||
.PP
|
.PP
|
||||||
.SH REM2PS INPUT FORMAT (-P OPTION)
|
.SH REM2PS INPUT FORMAT (-P OPTION)
|
||||||
@@ -380,7 +383,7 @@ been set to "-". The consistent use of "/" is designed to ease parsing.
|
|||||||
.PP
|
.PP
|
||||||
\fIspecial\fR is a string used
|
\fIspecial\fR is a string used
|
||||||
for "out-of-band" communication with back-ends. If the reminder
|
for "out-of-band" communication with back-ends. If the reminder
|
||||||
is a normal reminder, \fIspecial\fR is "*". The \fBRem2PS\fR
|
is a normal reminder, \fIspecial\fR is "*". The \fBrem2ps\fR
|
||||||
back-end understands the specials \fBPostScript\fR and \fBPSFile\fR.
|
back-end understands the specials \fBPostScript\fR and \fBPSFile\fR.
|
||||||
Other back-ends may understand other specials. A back end should
|
Other back-ends may understand other specials. A back end should
|
||||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
||||||
@@ -458,7 +461,7 @@ JSON object. The keys that may be present in the JSON object are as
|
|||||||
follows:
|
follows:
|
||||||
.TP
|
.TP
|
||||||
.B date \fIYYYY-MM-DD\fR
|
.B date \fIYYYY-MM-DD\fR
|
||||||
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
|
The \fBdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||||
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
||||||
.TP
|
.TP
|
||||||
.B filename \fIf\fR
|
.B filename \fIf\fR
|
||||||
@@ -674,17 +677,17 @@ is desired.
|
|||||||
|
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
|
rem2ps was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
All \fBRem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
|
All \fBrem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
|
||||||
Any time you supply
|
Any time you supply
|
||||||
a font name or size, line thickness, or border width, it is treated as a
|
a font name or size, line thickness, or border width, it is treated as a
|
||||||
string and sent straight to the PostScript interpreter. Thus, if you
|
string and sent straight to the PostScript interpreter. Thus, if you
|
||||||
supply invalid fonts or sizes, \fBRem2ps\fR will not complain, but the
|
supply invalid fonts or sizes, \fBrem2ps\fR will not complain, but the
|
||||||
resulting PostScript output will probably not work.
|
resulting PostScript output will probably not work.
|
||||||
.PP
|
.PP
|
||||||
You should ensure that the values you supply for margin widths are sensible.
|
You should ensure that the values you supply for margin widths are sensible.
|
||||||
If they are too big for the media size, \fBRem2ps\fR will not complain,
|
If they are too big for the media size, \fBrem2ps\fR will not complain,
|
||||||
but again, the PostScript output will probably not work.
|
but again, the PostScript output will probably not work.
|
||||||
.SH HOME PAGE
|
.SH HOME PAGE
|
||||||
https://dianne.skoll.ca/projects/remind/
|
https://dianne.skoll.ca/projects/remind/
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ causes \fBRemind\fR to display reminders on the calendar on the
|
|||||||
day they actually occur \fIas well as\fR on any preceding days
|
day they actually occur \fIas well as\fR on any preceding days
|
||||||
specified by the reminder's \fIdelta\fR. This \fIalso\fR causes
|
specified by the reminder's \fIdelta\fR. This \fIalso\fR causes
|
||||||
\fBRemind\fR to include text outside %"...%" sequences that would
|
\fBRemind\fR to include text outside %"...%" sequences that would
|
||||||
otherwise be removed (though the actual %" markers themselves are removed.)
|
otherwise be removed (though the actual %" markers themselves are removed.) \"" Add comment to avoid Emacs highlighting problems
|
||||||
.TP
|
.TP
|
||||||
.B 'l'
|
.B 'l'
|
||||||
causes \fBRemind\fR to use VT100 line-drawing characters to draw
|
causes \fBRemind\fR to use VT100 line-drawing characters to draw
|
||||||
@@ -300,6 +300,11 @@ Echo lines when displaying error messages
|
|||||||
.TP
|
.TP
|
||||||
.B f
|
.B f
|
||||||
Trace the reading of reminder files
|
Trace the reading of reminder files
|
||||||
|
.TP
|
||||||
|
.B s
|
||||||
|
Upon exit, print the high-water mark of the operator and value stacks
|
||||||
|
used for expression-parsing. This is unlikely to be useful unless
|
||||||
|
you're intimately familiar with Remind's source code.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
\fB\-g\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR[\fBa|d\fR]]]]
|
||||||
@@ -368,9 +373,12 @@ defaults to 1, and can range from 1 to 60. Note that the use of the
|
|||||||
\fB\-z\fR option also enables the \fB\-f\fR option.
|
\fB\-z\fR option also enables the \fB\-f\fR option.
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
If you supply the option \fB\-z0\fR, \fBRemind\fR runs in a
|
If you supply the option \fB\-zj\fR, \fBRemind\fR runs in a
|
||||||
special mode called \fBserver mode\fR. This is documented
|
special mode called \fBserver mode\fR. This is documented
|
||||||
in the tkremind man page; see tkremind(1).
|
in the tkremind man page; see tkremind(1). The older server mode
|
||||||
|
option \fB\-z0\fR still works, but is deprecated; it uses an ad-hoc
|
||||||
|
method to communicate with the client rather than using JSON to communicate
|
||||||
|
with the client.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
\fB\-u\fR\fIname\fR
|
\fB\-u\fR\fIname\fR
|
||||||
@@ -1138,7 +1146,7 @@ reminder is queued for later activation. When \fBRemind\fR has
|
|||||||
finished processing the reminder file, it puts itself in the
|
finished processing the reminder file, it puts itself in the
|
||||||
background, and activates timed reminders when the system time reached
|
background, and activates timed reminders when the system time reached
|
||||||
the specified time. Note that if you use the \fBNOQUEUE\fR modifier
|
the specified time. Note that if you use the \fBNOQUEUE\fR modifier
|
||||||
in the \fBREM\fR command, then this queueing and background activation
|
in the \fBREM\fR command, then this queuing and background activation
|
||||||
is \fInot\fR performed. \fBNOQUEUE\fR is useful if you want a time
|
is \fInot\fR performed. \fBNOQUEUE\fR is useful if you want a time
|
||||||
to be associated with a reminder (eg, in the calendar) but are not
|
to be associated with a reminder (eg, in the calendar) but are not
|
||||||
interested in a popup reminder happening at the specified time.
|
interested in a popup reminder happening at the specified time.
|
||||||
@@ -1210,7 +1218,9 @@ in the bodies of timed reminders, then when the timed reminders are
|
|||||||
activated, the variables and functions have the definitions that were
|
activated, the variables and functions have the definitions that were
|
||||||
in effect at the end of the reminder script. These definitions may
|
in effect at the end of the reminder script. These definitions may
|
||||||
\fInot\fR necessarily be those that were in effect at the time the reminder
|
\fInot\fR necessarily be those that were in effect at the time the reminder
|
||||||
was queued.
|
was queued. In addition, the OMIT context is whatever was in effect at
|
||||||
|
the end of the reminder script, which may not necessarily be the same
|
||||||
|
as when the \fBREM\fR command was first processed.
|
||||||
.PP
|
.PP
|
||||||
.B THE SCHED AND WARN KEYWORDS
|
.B THE SCHED AND WARN KEYWORDS
|
||||||
.PP
|
.PP
|
||||||
@@ -1704,6 +1714,11 @@ For example, the following sequences are equivalent:
|
|||||||
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
|
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
|
||||||
.fi
|
.fi
|
||||||
.PP
|
.PP
|
||||||
|
Note that \fBRemind\fR has a compiled-in limit to the number of full
|
||||||
|
OMITs. If you omit a range of \fIN\fR fully-specified (ie, year
|
||||||
|
included) days, then \fIN\fR full OMITs are used up. Trying to omit a
|
||||||
|
very large range may result in the error "Too many full OMITs"
|
||||||
|
.PP
|
||||||
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command as
|
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command as
|
||||||
long as both dates are fully specified
|
long as both dates are fully specified
|
||||||
.PP
|
.PP
|
||||||
@@ -2162,7 +2177,10 @@ Unary minus. Can be applied to an \fBINT\fR. Returns the negative
|
|||||||
of the operand.
|
of the operand.
|
||||||
.TP
|
.TP
|
||||||
.B *
|
.B *
|
||||||
Multiplication. Returns the product of two \fBINT\fRs.
|
Multiplication. Returns the product of two \fBINT\fRs. Alternatively, if
|
||||||
|
one argument is a \fBSTRING\fR and the other an \fBINT\fR, returns a
|
||||||
|
\fBSTRING\fR consisting of the INT number of repeats of the original STRING.
|
||||||
|
In this case, the INT argument cannot be negative.
|
||||||
.TP
|
.TP
|
||||||
.B /
|
.B /
|
||||||
Integer division. Returns the quotient of two \fBINT\fRs, discarding the
|
Integer division. Returns the quotient of two \fBINT\fRs, discarding the
|
||||||
@@ -2562,6 +2580,24 @@ updates \fB$LongDeg\fR, \fB$LongMin\fR and \fB$LongSec\fR. Similar
|
|||||||
rules apply to \fB$Latitude\fR, \fB$LatDeg\fR, \fB$LatMin\fR and \fB$LatSec\fR.
|
rules apply to \fB$Latitude\fR, \fB$LatDeg\fR, \fB$LatMin\fR and \fB$LatSec\fR.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
.B $MaxLateMinutes
|
||||||
|
This variable controls how \fBRemind\fR reacts to a computer being suspended
|
||||||
|
and then woken. Normally, if a timed reminder is queued and then the
|
||||||
|
computer suspended, and then the computer is woken \fIafter\fR the
|
||||||
|
timed reminder's trigger time, \fBRemind\fR will triger the timer anyway,
|
||||||
|
despite the fact that the trigger time has already passed.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
If you set \fB$MaxLateMinutes\fR to a non-zero integer between 1 and 1440,
|
||||||
|
then \fBRemind\fR will \fInot\fR trigger a timed reminder whose trigger
|
||||||
|
time is more than \fB$MaxLateMinutes\fR minutes in the past.
|
||||||
|
.PP
|
||||||
|
Note that \fBRemind\fR uses the value of \fB$MaxLateMinutes\fR that is in
|
||||||
|
effect when it has finished reading the reminder file and puts itself in
|
||||||
|
the background. Generally, you should set \fB$MaxLateMinutes\fR once
|
||||||
|
near the beginning of the file and not change it after that.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
.B $MaxSatIter
|
.B $MaxSatIter
|
||||||
The maximum number of iterations for the \fBSATISFY\fR clause
|
The maximum number of iterations for the \fBSATISFY\fR clause
|
||||||
(described later.) Must be at least 10.
|
(described later.) Must be at least 10.
|
||||||
@@ -2570,7 +2606,9 @@ The maximum number of iterations for the \fBSATISFY\fR clause
|
|||||||
A limit on the longest string that \fBRemind\fR will allow you
|
A limit on the longest string that \fBRemind\fR will allow you
|
||||||
to create. The default is 65535. If you set \fB$MaxStringLen\fR to 0
|
to create. The default is 65535. If you set \fB$MaxStringLen\fR to 0
|
||||||
or to -1, then \fBremind\fR will allow you to create arbitrarily-long
|
or to -1, then \fBremind\fR will allow you to create arbitrarily-long
|
||||||
strings, at least until it runs out of memory.
|
strings, at least until it runs out of memory. We do not recommend
|
||||||
|
setting \fB$MaxStringLen\fR to 0 or -1 because it is very easy to write
|
||||||
|
code that DOSes \fBRemind\fR in that case.
|
||||||
.TP
|
.TP
|
||||||
.B $MinsFromUTC
|
.B $MinsFromUTC
|
||||||
The number of minutes between Universal Time Coordinated and local time. If
|
The number of minutes between Universal Time Coordinated and local time. If
|
||||||
@@ -2585,6 +2623,18 @@ must also set \fB$CalcUTC\fR to 0 with the \fB\-i\fR option.
|
|||||||
.B $NextMode (read-only)
|
.B $NextMode (read-only)
|
||||||
If non-zero, then the \fB\-n\fR option was supplied on the command line.
|
If non-zero, then the \fB\-n\fR option was supplied on the command line.
|
||||||
.TP
|
.TP
|
||||||
|
.B $MaxFullOmits (read-only)
|
||||||
|
The maximum number of full OMITs allowed (a compiled-in constant.)
|
||||||
|
.TP
|
||||||
|
.B $MaxPartialOmits (read-only)
|
||||||
|
The maximum number of partial OMITs allowed (a compiled-in constant.)
|
||||||
|
.TP
|
||||||
|
.B $NumFullOmits (read-only)
|
||||||
|
The number of full OMITs in the current OMIT context.
|
||||||
|
.TP
|
||||||
|
.B $NumPartialOmits (read-only)
|
||||||
|
The number of partial OMITs in the current OMIT context.
|
||||||
|
.TP
|
||||||
.B $NumQueued (read-only)
|
.B $NumQueued (read-only)
|
||||||
Contains the number of reminders queued so far for background
|
Contains the number of reminders queued so far for background
|
||||||
timed triggering.
|
timed triggering.
|
||||||
@@ -3038,11 +3088,12 @@ will produce undefined results.
|
|||||||
Returns the time of "civil twilight" on the specified \fIdate\fR. If
|
Returns the time of "civil twilight" on the specified \fIdate\fR. If
|
||||||
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
|
\fIdate\fR is omitted, defaults to \fBtoday()\fR.
|
||||||
.TP
|
.TP
|
||||||
.B easterdate(dqi_arg)
|
.B easterdate([dqi_arg])
|
||||||
If \fIarg\fR is an \fBINT\fR, then returns the date of Easter Sunday
|
If \fIarg\fR is an \fBINT\fR, then returns the date of Easter Sunday
|
||||||
for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
||||||
\fBDATETIME\fR, then returns the date of the next Easter Sunday on or
|
\fBDATETIME\fR, then returns the date of the next Easter Sunday on or
|
||||||
after \fIarg\fR. (The time component of a datetime is ignored.)
|
after \fIarg\fR. (The time component of a datetime is ignored.) If \fIarg\fR
|
||||||
|
is omitted, then it defaults to \fBtoday()\fR.
|
||||||
.RS
|
.RS
|
||||||
.P
|
.P
|
||||||
Note that \fBeasterdate\fR computes the Western Easter. For the Orthodox
|
Note that \fBeasterdate\fR computes the Western Easter. For the Orthodox
|
||||||
@@ -3397,11 +3448,12 @@ the actual time, or a time supplied on the command line.
|
|||||||
Returns a string that is the ordinal number \fInum\fR. For example,
|
Returns a string that is the ordinal number \fInum\fR. For example,
|
||||||
\fBord(2)\fR returns "2nd", and \fBord(213)\fR returns "213th".
|
\fBord(2)\fR returns "2nd", and \fBord(213)\fR returns "213th".
|
||||||
.TP
|
.TP
|
||||||
.B orthodoxeaster(dqi_arg)
|
.B orthodoxeaster([dqi_arg])
|
||||||
If \fIarg\fR is an \fBINT\fR, then returns the date of Orthodox Easter Sunday
|
If \fIarg\fR is an \fBINT\fR, then returns the date of Orthodox Easter Sunday
|
||||||
for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
for the specified year. If \fIarg\fR is a \fBDATE\fR or
|
||||||
\fBDATETIME\fR, then returns the date of the next Orthodox Easter Sunday on or
|
\fBDATETIME\fR, then returns the date of the next Orthodox Easter Sunday on or
|
||||||
after \fIarg\fR. (The time component of a datetime is ignored.)
|
after \fIarg\fR. (The time component of a datetime is ignored.) If \fIarg\fR
|
||||||
|
is omitted, then it defaults to \fBtoday()\fR.
|
||||||
.RS
|
.RS
|
||||||
.P
|
.P
|
||||||
Note that \fBorthodoxeaster\fR computes the Orthodox Easter. For the Western
|
Note that \fBorthodoxeaster\fR computes the Orthodox Easter. For the Western
|
||||||
@@ -3622,7 +3674,7 @@ not supplied, then it defaults to \fBtoday()\fR.
|
|||||||
.PP
|
.PP
|
||||||
The return value of \fBsoleq()\fR is a \fBDATETIME\fR object specifying
|
The return value of \fBsoleq()\fR is a \fBDATETIME\fR object specifying
|
||||||
the date and time of the solstice or equinox in the local time zone. It
|
the date and time of the solstice or equinox in the local time zone. It
|
||||||
should be accurate to within 3 minues or so in the worst case.
|
should be accurate to within 3 minutes or so in the worst case.
|
||||||
.PP
|
.PP
|
||||||
See the included file \fB$SysInclude/seasons.rem\fR for examples of how
|
See the included file \fB$SysInclude/seasons.rem\fR for examples of how
|
||||||
to use \fBsoleq()\fR.
|
to use \fBsoleq()\fR.
|
||||||
@@ -5213,7 +5265,7 @@ A number of system variables let you translate various phrases
|
|||||||
to other languages. These system variables are:
|
to other languages. These system variables are:
|
||||||
.PP
|
.PP
|
||||||
.TP
|
.TP
|
||||||
.B $Monday, $Tuesday, $Wednesday, $Thursday, $Friday, $Saturday
|
.B $Monday, $Tuesday, $Wednesday, $Thursday, $Friday, $Saturday, $Sunday
|
||||||
Set each of these system variables to a string representing the corresponding
|
Set each of these system variables to a string representing the corresponding
|
||||||
day's name in your language. Strings must be valid UTF-8 strings.
|
day's name in your language. Strings must be valid UTF-8 strings.
|
||||||
.TP
|
.TP
|
||||||
@@ -5519,13 +5571,13 @@ the anniversary of a death is. The following rules are used:
|
|||||||
o
|
o
|
||||||
If the death occurred on 30 Heshvan, and Heshvan in the year after the
|
If the death occurred on 30 Heshvan, and Heshvan in the year after the
|
||||||
death is \fIchaser\fR, then the jahrzeit is observed on 29 Heshvan in years
|
death is \fIchaser\fR, then the jahrzeit is observed on 29 Heshvan in years
|
||||||
when Heshvan is \fIchaser\fR. Otherwise, the yahrzeit is observed on 1
|
when Heshvan is \fIchaser\fR. Otherwise, the jahrzeit is observed on 1
|
||||||
Kislev when Heshvan is \fIchaser\fR.
|
Kislev when Heshvan is \fIchaser\fR.
|
||||||
.TP
|
.TP
|
||||||
o
|
o
|
||||||
If the death occurred on 30 Kislev, and Kislev in the year after the
|
If the death occurred on 30 Kislev, and Kislev in the year after the
|
||||||
death is \fIchaser\fR, then the jahrzeit is observed on 29 Kislev in years
|
death is \fIchaser\fR, then the jahrzeit is observed on 29 Kislev in years
|
||||||
when Kislev is \fIchaser\fR. Otherwise, the yahrzeit is observed on 1
|
when Kislev is \fIchaser\fR. Otherwise, the jahrzeit is observed on 1
|
||||||
Tevet when Kislev is \fIchaser\fR.
|
Tevet when Kislev is \fIchaser\fR.
|
||||||
.TP
|
.TP
|
||||||
o
|
o
|
||||||
@@ -5932,6 +5984,9 @@ Almanac Office, USNO.
|
|||||||
.PP
|
.PP
|
||||||
Richard Siegel and Michael and Sharon Strassfeld, \fIThe First Jewish
|
Richard Siegel and Michael and Sharon Strassfeld, \fIThe First Jewish
|
||||||
Catalog\fR, Jewish Publication Society of America.
|
Catalog\fR, Jewish Publication Society of America.
|
||||||
|
.PP
|
||||||
|
Jean Meeus, \fIAstronomical Algorithms, Second Edition\fR, Willmann-Bell, Inc.
|
||||||
|
|
||||||
.SH HOME PAGE
|
.SH HOME PAGE
|
||||||
https://dianne.skoll.ca/projects/remind/
|
https://dianne.skoll.ca/projects/remind/
|
||||||
.SH MAILING LIST
|
.SH MAILING LIST
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ If you create "timed" reminders, \fBTkRemind\fR will queue them in
|
|||||||
the background and pop up boxes as they are triggered. Additionally,
|
the background and pop up boxes as they are triggered. Additionally,
|
||||||
if you created the reminder using \fBTkRemind\fR, you will be given the
|
if you created the reminder using \fBTkRemind\fR, you will be given the
|
||||||
option of "turning off" the reminder for the rest of the day.
|
option of "turning off" the reminder for the rest of the day.
|
||||||
\fBTkRemind\fR achieves queueing of background reminders by running
|
\fBTkRemind\fR achieves queuing of background reminders by running
|
||||||
\fBRemind\fR in \fIserver mode\fR, described later.
|
\fBRemind\fR in \fIserver mode\fR, described later.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
@@ -301,11 +301,11 @@ Today
|
|||||||
|
|
||||||
.SH IMMEDIATE UPDATES
|
.SH IMMEDIATE UPDATES
|
||||||
|
|
||||||
If you are running \fBTkRemind\fR on Linux and have the
|
If you are running \fBTkRemind\fR on Linux and \fBRemind\fR has been
|
||||||
\fBinotifywait\fR program installed (part of the \fBinotify-tools\fR
|
compiled with \fBinotify\fR(7) support, then \fBTkRemind\fR redraws
|
||||||
or similar package), then \fBTkRemind\fR redraws the calendar window
|
the calendar window \fIimmediately\fR if \fB$HOME/.reminders\fR
|
||||||
\fIimmediately\fR if \fB$HOME/.reminders\fR changes (or, if it is a
|
changes (or, if it is a directory, any files in that directory
|
||||||
directory, any files in that directory change.)
|
change.)
|
||||||
.PP
|
.PP
|
||||||
This lets \fBTkRemind\fR react immediately to hand-edited reminders or
|
This lets \fBTkRemind\fR react immediately to hand-edited reminders or
|
||||||
to reminder files that are imported from another calendar system (for example,
|
to reminder files that are imported from another calendar system (for example,
|
||||||
@@ -366,60 +366,110 @@ your hand-edited files in a separate \fB*.rem\fR file than \fBTkRemind\fR's
|
|||||||
|
|
||||||
\fBRemind\fR has a special mode for interacting with programs like
|
\fBRemind\fR has a special mode for interacting with programs like
|
||||||
\fBTkRemind\fR. This mode is called \fIserver mode\fR and is
|
\fBTkRemind\fR. This mode is called \fIserver mode\fR and is
|
||||||
selected by supplying the \fB\-z0\fR option to \fBRemind\fR.
|
selected by supplying the \fB\-zj\fR option to \fBRemind\fR.
|
||||||
|
|
||||||
In server mode, \fBRemind\fR operates similar to daemon mode, except
|
In server mode, \fBRemind\fR operates similar to daemon mode, except
|
||||||
it reads commands (one per line)
|
it reads commands (one per line) from standard input and writes status
|
||||||
from standard input and writes status lines to standard output.
|
lines to standard output. Each status line is a JSON object.
|
||||||
|
|
||||||
The commands accepted in server mode are:
|
The commands accepted in server mode are:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
EXIT
|
EXIT
|
||||||
Terminate the \fBRemind\fR process. EOF on standard input does the
|
Terminate the \fBRemind\fR process. EOF on standard input does the
|
||||||
same thing.
|
same thing. \fBRemind\fR exits immediately without printing
|
||||||
|
a JSON status line.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
STATUS
|
STATUS
|
||||||
Return the number of queued reminders.
|
Return the number of queued reminders. The JSON object looks
|
||||||
|
something like this:
|
||||||
|
.nf
|
||||||
|
|
||||||
|
{"response":"queued","nqueued":n,"command":"STATUS"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
where \fIn\fR is the number of reminders queued.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
QUEUE or JSONQUEUE
|
||||||
|
Returns the contents of the queue. The JSON object looks something
|
||||||
|
like this:
|
||||||
|
.nf
|
||||||
|
|
||||||
|
{"response":"queue","queue":[ ... ],"command":"QUEUE"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
The value of the \fBqueue\fR key is an array of JSON objects, each
|
||||||
|
representing a queued reminder.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
DEL \fIqid\fR
|
||||||
|
Delete the reminder with queue-id \fIqid\fR from the queue.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
REREAD
|
REREAD
|
||||||
Re-read the reminder file
|
Re-read the reminder file. Returns the following status line:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
|
||||||
|
{"response":"reread","command":"REREAD"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
The status lines written are as follows:
|
Additional status lines written are as follows:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
NOTE reminder \fItime\fR \fItag\fR
|
.nf
|
||||||
Signifies the beginning of a timed reminder whose trigger time is
|
|
||||||
\fItime\fR with tag \fItag\fR. If the reminder has no tag, an
|
|
||||||
asterisk is supplied for \fItag\fR. All lines following this line
|
|
||||||
are the body of the reminder, until the line \fBNOTE endreminder\fR
|
|
||||||
is transmitted.
|
|
||||||
|
|
||||||
|
{"response":"reminder","ttime":tt,"now":now,"tags":tags,"qid":qid,"body":body}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
In this line, \fItt\fR is the trigger time of the reminder (expressed
|
||||||
|
as a string), \fInow\fR is the current time, \fItags\fR (if present)
|
||||||
|
is the tag or tags associated with the reminder, and \fIbody\fR is the
|
||||||
|
body of the reminder. This response causes \fBTkRemind\fR to pop up a
|
||||||
|
reminder notification. \fIqid\fR is a unique identifier for this
|
||||||
|
reminder. You may delete it from the queue by sending a \fBDEL\fR
|
||||||
|
\fIqid\fR command to the server. Note that \fIqid\fRs are not stable
|
||||||
|
across re-reads; if \fBRemind\fR restarts itself to re-read the reminder
|
||||||
|
file, then the \fIqid\fR values are likely to change, and any reminder
|
||||||
|
deleted with a \fBDEL\fR \fIqid\fR command is likely to be re-queued.
|
||||||
.TP
|
.TP
|
||||||
NOTE newdate
|
.nf
|
||||||
|
|
||||||
|
{"response":"newdate"}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
|
||||||
This line is emitted whenever \fBRemind\fR has detected a rollover of
|
This line is emitted whenever \fBRemind\fR has detected a rollover of
|
||||||
the system date. The front-end program should redraw its calendar
|
the system date. The front-end program should redraw its calendar
|
||||||
or take whatever other action is needed.
|
or take whatever other action is needed.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
NOTE reread
|
.nf
|
||||||
This line is emitted whenever the number of reminders in \fBRemind\fR's
|
|
||||||
queue changes because of a date rollover or a \fBREREAD\fR command.
|
|
||||||
The front-end should issue a \fBSTATUS\fR command in response to this
|
|
||||||
message.
|
|
||||||
|
|
||||||
.TP
|
{"response":"reread","command":"inotify"}
|
||||||
NOTE queued \fIn\fR
|
|
||||||
This line is emitted in response to a \fBSTATUS\fR command. The number
|
.fi
|
||||||
\fIn\fR is the number of reminders in the queue.
|
|
||||||
|
If \fBRemind\fR was compiled with support for \fBinotify\fR(7), then
|
||||||
|
if it detects a change to the top-level reminder file or directory,
|
||||||
|
it issues the above response. The front-end should redraw its
|
||||||
|
calendar since this response indicates that a change has been made
|
||||||
|
to the reminder file or directory.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Please note that \fBRemind\fR can write a status message \fIat any time\fR
|
||||||
|
and not just in response to a command sent to its standard input. Therefore,
|
||||||
|
a program that runs \fBRemind\fR in server mode must be prepared to handle
|
||||||
|
asynchronous status messages.
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||||
|
|
||||||
\fBTkRemind\fR is Copyright 1996-2023 by Dianne Skoll.
|
\fBTkRemind\fR is Copyright 1996-2024 by Dianne Skoll.
|
||||||
|
|
||||||
.SH FILES
|
.SH FILES
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ use warnings;
|
|||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use JSON::MaybeXS;
|
use JSON::MaybeXS;
|
||||||
|
use Encode;
|
||||||
|
|
||||||
my %Options;
|
my %Options;
|
||||||
|
|
||||||
my $rem2html_version = '2.1';
|
my $rem2html_version = '@VERSION@';
|
||||||
|
|
||||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||||
@@ -44,6 +45,11 @@ Print usage information
|
|||||||
|
|
||||||
Print version
|
Print version
|
||||||
|
|
||||||
|
=item --utf8
|
||||||
|
|
||||||
|
Assume standard input is encoded in UTF-8; write UTF-8 data to standard
|
||||||
|
output.
|
||||||
|
|
||||||
=item --backurl I<url>
|
=item --backurl I<url>
|
||||||
|
|
||||||
When producing the small calendar for the previous month, make the
|
When producing the small calendar for the previous month, make the
|
||||||
@@ -154,6 +160,7 @@ Usage: remind -pp ... | rem2html [options]
|
|||||||
Options:
|
Options:
|
||||||
|
|
||||||
--help, -h Print usage information
|
--help, -h Print usage information
|
||||||
|
--utf8 Assume UTF-8 input and write UTF-8 output
|
||||||
--man Show man page (requires "perldoc")
|
--man Show man page (requires "perldoc")
|
||||||
--version Print version
|
--version Print version
|
||||||
--backurl url Make the title on the previous month's small calendar
|
--backurl url Make the title on the previous month's small calendar
|
||||||
@@ -197,6 +204,7 @@ sub parse_options
|
|||||||
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
|
||||||
if (!GetOptions(\%Options, "help|h",
|
if (!GetOptions(\%Options, "help|h",
|
||||||
"man",
|
"man",
|
||||||
|
"utf8",
|
||||||
"pngs",
|
"pngs",
|
||||||
"version",
|
"version",
|
||||||
"stylesheet=s",
|
"stylesheet=s",
|
||||||
@@ -216,13 +224,22 @@ sub parse_options
|
|||||||
if ($stylesheet) {
|
if ($stylesheet) {
|
||||||
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
$Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
|
||||||
}
|
}
|
||||||
|
if ($Options{utf8}) {
|
||||||
|
binmode(STDIN, ':encoding(UTF-8)');
|
||||||
|
binmode(STDOUT, ':encoding(UTF-8)');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub start_output
|
sub start_output
|
||||||
{
|
{
|
||||||
return if ($Options{tableonly});
|
return if ($Options{tableonly});
|
||||||
|
|
||||||
print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
|
print("<html>\n<head>\n");
|
||||||
|
if ($Options{utf8}) {
|
||||||
|
print '<meta charset="UTF-8">' . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print("<title>" . $Options{title} . "</title>\n");
|
||||||
if (!$Options{nostyle}) {
|
if (!$Options{nostyle}) {
|
||||||
if ($Options{stylesheet}) {
|
if ($Options{stylesheet}) {
|
||||||
print('<link rel="stylesheet" type="text/css" href="' .
|
print('<link rel="stylesheet" type="text/css" href="' .
|
||||||
@@ -310,7 +327,12 @@ sub parse_input
|
|||||||
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||||
} elsif (/\{/) {
|
} elsif (/\{/) {
|
||||||
my $obj = decode_json($_);
|
my $obj;
|
||||||
|
if ($Options{utf8}) {
|
||||||
|
$obj = decode_json(encode('UTF-8', $_, Encode::FB_DEFAULT));
|
||||||
|
} else {
|
||||||
|
$obj = decode_json($_);
|
||||||
|
}
|
||||||
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||||
$y = $1;
|
$y = $1;
|
||||||
$m = $2;
|
$m = $2;
|
||||||
15
resources/tkremind.desktop
Executable file
15
resources/tkremind.desktop
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Exec=tkremind
|
||||||
|
StartupNotify=true
|
||||||
|
Icon=tkremind
|
||||||
|
Terminal=false
|
||||||
|
Name=tkremind
|
||||||
|
Comment=TkRemind Calendar Program
|
||||||
|
Categories=Office;Calendar;
|
||||||
|
Keywords=Calendar;remind;
|
||||||
|
Keywords[ca]=Calendari;remind;
|
||||||
|
Keywords[de]=Kalender;remind;
|
||||||
|
Keywords[en_GB]=Calendar;remind;
|
||||||
|
Keywords[es]=Calendario;remind;
|
||||||
|
|
||||||
BIN
resources/tkremind.png
Normal file
BIN
resources/tkremind.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
523
scripts/tkremind
523
scripts/tkremind
@@ -8,7 +8,7 @@
|
|||||||
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
# A cheesy graphical front/back end for Remind using Tcl/Tk
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2023 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
#
|
#
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
@@ -29,69 +29,92 @@ set Hostname [exec hostname]
|
|||||||
# Our icon photo
|
# Our icon photo
|
||||||
catch {
|
catch {
|
||||||
image create photo rpicon -data {
|
image create photo rpicon -data {
|
||||||
iVBORw0KGgoAAAANSUhEUgAAAEAAAABbCAYAAADDeIOGAAAACXBIWXMAAAu6AAALugFBTNueAAAA
|
iVBORw0KGgoAAAANSUhEUgAAAEAAAABbCAYAAADDeIOGAAAACXBIWXMAAAtEAAALRAHk62/EAAAA
|
||||||
GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAADANJREFUeJzdnGtsFNcVx38Xr19r
|
GXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAD5RJREFUeJzdXHtQFNea/80DZ2SQ
|
||||||
4/BawjPGjcGY2MY8Q+1g05iXKwoihvAQoCJEQoiU0CofWgmpUhIJNVKpSGnUSGmKLEEihcZFQeBW
|
l8CMkEUQH0QQAUWXiKKiUVGjxmvFupqUGpMQU1nLSmpTtbkbTWW33GTzWG8iZbIxlUqMsLnxZkwG
|
||||||
gRJeKQkQisFAsWDxGsdAawjgGGF7Tz/MrrvGuzN3ZmchzV8aeT17zj3n/u+5d87cxyoR4fsMpVQx
|
klosFbM+koDGOL5AUECYAeU1w2Ngmv72j6GpRqZ7unsG2b2/qlMz5/T5zuN3Xt/5zulWERH+hhED
|
||||||
MBkYC+QDQ4DBQDtQ7XmEviUESqnBwAKgFHgaGAP0iRC5AWwDtojI1e8FAUqp4cBzwExgBpAVRexb
|
YAuAxQBSAUQDGA9AA4AF8Jvqb5CApwHsBJAOIBQA7ty5g8rKSrS0tMBut0OlUiE9PR3r1q2zg4j+
|
||||||
4E/AJhG52n1XRP4vL2Ag8DOgFmgDJMYVBPYCT0ct51FXJEbl+gLpMb77IbAZuGpS6fBVD6wys6W+
|
vzstEb1ARBVE5GZZls6dO0dvv/02bdy4kaZOnUparZYAEACaNWsWFRYWktvtJiJyj3Xh/XFbiegy
|
||||||
C4OgUiodeBGYC4zHaN1OoAU4CxzGaOVFwHR69ulo+Bb4HfCmiNw1lfwOtPY84AzWral7HQfKtO0/
|
ETEMw5DFYqGXX36ZkpOThyrLd8nJyfyKExG5iOg/xroS3twkIsonoj8S0Rwi0vOeRRLRYSLqcrvd
|
||||||
4sqvA+66VPFO4PeA15YPj7Dyz4VC1Y3KtwIvOvLjEVW+CPi3TuUyMzOtZC4DJY59eQSVTwL26VR+
|
ZLFY6KWXXqKpU6d6rTQACg8Pp9dee40cDsewig/2HIx1ZTlnJKLviaiLvOM+EV0lIra2tpb27dsn
|
||||||
48aNcu/ePXn++edjyVwAiuPy5xEQ8Gvdlr97966IiLz99tvRZPzA2Hj9sXqcuAql1CLgVR3Ze/fu
|
2NKcU6vVtHbtWrJarVwaLBEVEdE4ft7/FybBfwewp6KiQmOxWHD9+nW0t7cjJCQEcXFxyMrKwqpV
|
||||||
ce7cOUSE/fv39/oaeFVEzsft1ENs+TwggI3BbcSIEVJcXBztu39iEFkBpGra7xtN9qEkQqFE568Y
|
q3D+/HkcPXoUJSUl6OrqEk1w9uzZeOutt7B27Vou6CqAdQBqRkQe45Y/WVNTQ1u2bKGgoCDB1hw/
|
||||||
SYzbuAU0YHQJP0aGeBODKICRQAHQCPxCHqzwQ2r93+BeomM3NzgCVMXyLeERoJSaDewC0hJqyEAb
|
frxoa3NOp9PR7t27yel0cq3eQURPiZVhLCv/3z/99BMlJSVJqpwvl5SURKWlpfxhU0xEal/lGKvK
|
||||||
xpPhLHAa+LuInDBTSCgBSql+wCGMEEwULgN/AfYDB0Xkti3tBIf+H0hQeCulBKgG+n4nH4NKqXnA
|
/9ulS5coLi4uIJVfvHgx1dbWchV3EFGe1LKMReWT29vbB1JTUwNS+eeff576+vq4yl8momA55XnY
|
||||||
mkSUnZmZyaZNmxgyZMhgEbkTV2EJavlU4CQWrejz+SQjI0O71VNTU2XBggXyxRdfiIhIZWXlN0BK
|
lVcTkf3FF1+UNJ4PHTpEZrOZIiIiRjxXqVS0Z88eYlmWq/zHSsr0sAn4saioSHTC43drDkuXLh3x
|
||||||
PL4makpsIzDBSmjz5s3Mnz+fQ4cOceHCBQKBAM3Nzdy+fZs7d+6glGLAgAH4fD6Ki4uZNWsWeXl5
|
/NVXXyUe3lRapodZ+X+4ceMGmUwmSV07IyODGIah+vp6iomJGfZs5cqVxDAMV3k7Ef2JiBbRoHLz
|
||||||
3fqTJk3K2rt372xgt2NPE9D6+RhvZ6atmZubK/fv35d48MknnwiwOR5/EzEGvAn0txKqqqoiOTk5
|
gNMT0T8RUfpYEpDW3d098Nhjj8ka31lZWTRlypRhYRqNhl555RX69ttv6d69e+QFveSZCDsH/5PT
|
||||||
LkPPPvss/fv3/1E8ZbhKgFJqDjBfR7a0tDRue16vl/z8/LGhx60juEaAUkoBvwTrcSUzM5NnnnnG
|
6SSGYTpouFYJooejCKkBNBcUFER9/PHHAU1Yp9Nh6tSpSEhIwJQpUzB58mRERkYCADQaDe7evQur
|
||||||
Fbv5+flpQLlTfTcj4KdoOpKXl0f//pa9RAsFBQUAE53qu0KAUioF2KArP2DAADfMAvDkk0+CMZPs
|
1Ypp06bhzTffBIALALKHJfIQWv9oUVERaTSagMz6Up1Wq6Xc3Fw6fvw41zNYInr1YfeA3KamplML
|
||||||
CG5FwAsY01xaSE9Pd8ksFBUV4fF4xjrVj5sApVQSsNqOjsfjXvqRnZ3NsGHDRimlHPUpNyJgNTb7
|
FixQ3blzZzTzQXh4OGbOnImUlBTMnj0bubm5SE1N5R63A9gBwDxCcBRbXktEHZs3bx61VjYajbR7
|
||||||
YEtLiwtm/4fs7OxUYIoT3bgICI38tvN9v98fTppcwdChQwFynejGGwFVwDS7Si0tLWzdupWvv/46
|
926yWCzkcrm8zQWXyGMrGJNV4C+fffYZqVSqUan8jBkzyGaz8bt3PREdI6IC8uwuJZVT62/XE0Ca
|
||||||
TvMGfD4fwAgnuvESsNKJUjAY5JVXXmHMmDEsXLiQHTt2EAwGHTsxePBggKGOlOPI+Qsxdlm48n4/
|
zWbb+MYbbyDQQ0yr1WL79u0IDg5Gd3c3F/wGgH9RlOAotf7tnTt3+mzFtLQ0mjt3LoWEhPiMq9Pp
|
||||||
depU+fjjjx29E7zzzjsC1DqqRxwEbHGr8uHL4/HI+vXrpb293RYB27dvF+DUQyMAYweGzvq8o2vR
|
aM2aNWSxWIiIqKioiD766COuB1QqLetoTIIvl5eX/3nFihXo6+sTjWixWLB69Wo4nU78/PPPaGho
|
||||||
okXS0dGhTUBNTY0ATU7q4nQMWAYMc6hriZ07d/LGG29oy2dkZAD0VUrZTjCcEqD1xhcPtm7dyqVL
|
QFNTExwOB1iWBQBMnDgRCQkJyMnJwSOPPDIke//+fRQUFOCbb74BAAZAkKLSBrjl9QzDuLKzs322
|
||||||
l7RkQwRkAo/ZtWObAKVULhDXO7gOWltb2blzp5as1+sFoy62nwROImA54F4yH4GsrJ6buw4fPqyl
|
aHp6Ol+PV4T8/Hz+RujvlZRZrYg1YXzy4Ycf6s6fP+8z4rp166BSqfzKLCEhAWfOnOG8W5SkEUgC
|
||||||
16dPdzUG2bXpJCmf50DHEsOHD+f+/fs97ukmShEE2J5ishUBSqnxaEx2OsG4ceO4detWj3t37ujN
|
Ih0Oxx8PHjwoKfLcuXP9zjA1NRWVlZWcd5GSNAJJQPF7772nuXXrls+IBoMBCxYs8DvDtLQ0XLp0
|
||||||
eEcQoOzatdsFFuAsaizh8/no6Ojoca+wsFBLNyJykuzatUvATLsGdPH444/3ujdtmt5rRkSk2B7T
|
ifPOUJRIgMZ+UmNjI2s0GiWt4SkpKX6NfQ5ut5syMjL4QZLX/0DPAZ+9++67qubmZkmRDQZDQDLV
|
||||||
tBWUUqOBqXYN6CAjI4ORI0f2uJeWlkZlZaWWfnt7u2Pbdhj7McaKj+soKirq1f8rKysZN26cln4E
|
arXQarWor6/ngvLlphEIAiY1Nzcv/OqrryQL6HS6AGTrweTJk/Hbb79x3hy58oEg4PCBAwdULS0t
|
||||||
Affs2rZDQIndwnUxceJEmpqaetxbvHixtn4EAbZDQYuAUIqZMAImTJhAY2Njj3vNzc3a+q2treGP
|
kgV86QdykJCQAN68M0uuvL8EhLe1ta344osvZAnV1dUNKTr+Ij4+nk9Aglx5fwn4c2FhobqxsVGW
|
||||||
5ttio0A3AmbicMLBCklJSZSUlBAIBHrcf++997h586ZWGRHd5xu79nUJcGcVIwrGjx9PVlYWly9f
|
UEtLC27evOln1h7ExMTg9u3bnDdcrrxfBDAM84cjR47IliMi5OXlYevWrSguLsbAwIDiMsTExMBm
|
||||||
7nH//PnzvPbaa1plhIj6Frhu174uAZPsFBp6OdFCWVkZx44d65UFAmzbto13333XsoxQF7glIu6P
|
s3HeIMitkx9L367PP/88YFvb999/n6/WSkZtbS0ZjUa+Wj1dTj38IaBu5cqVAd3jZ2VlUWVlpSwC
|
||||||
AUqpZGxmf6E5Oi2Ul5dTX18f9btgMMgHH3xgWUYoZb5lJRcNOhEwA+idpZggNEenJTd37lzOnTsX
|
+vv7KSwsjG8bED0LDBQBMysrKyXZ9+W6iRMnUllZmSwSjEYjlZeXc969cuqidA741yNHjsDtdisU
|
||||||
UyY7O9uynKtXr4KxNc42dAiwFf4Ajz2m91peXl5OWloaZ86ciSnzYIL0IILBYPiJ8R8bLnZDh4Bi
|
F0ZrayuefvppVFVVSZYxGAzo7OzkvEY5+SkigGGYFSUlJUpEJcFut2Pv3r2S4xsMBr51KFJOXkoI
|
||||||
u4XqLn3NmDGDixcvmkbAE088YVpGY2NjeAxwtNqiQ8BTtgrs00dr8TM1NZXKykoOHDjQ6yUoEqNG
|
WHfs2LHxclpICcxmM+rq6iTF1ev1cDqdnDdCTj5KCHj9+++/VyAmDq1WC71eP+R3uVwoLS2VJKtS
|
||||||
jTItp66uLjyl7miRwZQApdQQYLSdAlNTU7UImDx5Mjk5OXz55ZcxZbxeLxMnmq+6RUybuU8Axgkt
|
qeBwODhvqJx85RKg7ujoyPjhhx9kivlGYmIi+vv7h4U1NDRIlufJytpoyCVgi9ls1ra1tckU8w2j
|
||||||
W/l/V1eX1mOwoqICwJSAwsJCBg0yn+SJyB+u6foYCSsCbIU/GNPsVk+B5ORkqqqqOH36tOkAOGmS
|
0ThCPeZNbKJQq9WeJW3QKydfuQQUnDhxQqaINEyaNGlE2IwZ0mwcLMvytUlZdjZZBLhcrjknT56U
|
||||||
9fgbigABHG2dtyIgz+L7Xujs7CQzM9NUpqSkhKKiInbv3k1nZ2dMueJi6/H34sWLYGSA/7LnqQEr
|
IyIZcXFxw/wqlQq5ubmSZHt7e/m9RyMnXzkEPG6xWHQ8vTtgMBqNiIqKGhaWmZmJ2bNnS5J3uVyK
|
||||||
An5gt0ARYeDAgabdYN48Y1px3759MWWSkpKYPt18d73f76ehoQHgiog4WlyMSYBSqg8OCAAjCmK9
|
85ZDwHPl5eWKMxLDnDlz0NTUNCxs8+bNkuV7e3v5K4gsNuQQsPDs2bNy0paM9PT0YWt+WFgYtm3b
|
||||||
y2dlZbF06VIaGxv5/PPPY5ZRUFDA2LHmGz+OHj0ajiC/Ez/BPALGYTMDDOPatWuMHx992878+fMZ
|
JkmWZVl0d3ePOgEh169fj7ly5YqctCUjIyMDd+/eHfI7HA5IzevevXtwOBx8M1uvnLylErDzxIkT
|
||||||
MWIENTU1pjM5s2bNsrQTMX40OHATMCcgHwezrGAMTLEIWLZsGQA1NTWmZcyePdvSTl1dXfjjBTv+
|
KoZh5KQtCQaDAdnZ2XzDJogI77zzDn9pE0RdXR0GBgb4PaBHTv5SCdgg5bRHCebNm4fa2lq0t7cP
|
||||||
9YDJAujPcbi4WVVVJUeOHOl1f/LkyRIMBuX48ePi8Xhi6o8ePVq6urpMF0SDwaCMGjVKME6HFzpZ
|
C//xxx+xf/9+n/Ktra0APMNmEPfl5C+VgFkVFRWSEw0LC4NGI201ys3NhdVq9fps//798DXxckpZ
|
||||||
GLVaHHW8+NnQ0MC0adN6bGwGWLVqFUopPvzwQ9PRv6KiInKuPyrq6+u5cuUKQBPG2WNnMImA7TiM
|
RMTQFqBJMLIXSCFAb7Vaw2tqRl60FoLJZJJs5lqyZAmuX7/u9VlXVxf/5McruNXDZDJxQXcFI3uB
|
||||||
gJSUFAkEAvLyyy9338vJyZG2tjbp6OiQ3NxcU/29e/daLom///77Yfm/OW19qwhwtuUEY6HiwIED
|
FAI2nTt3TiXHihsTEyMp3vTp07Fw4ULcuHFDME58fLxoGo2NjRg3bhz/6Fz6BgLSCNhw8eJFOWki
|
||||||
PQaylStX4vV6qa6uDj+6omLChAnMmTPH0kbEABjf2UGTCDhHHJscNmzYIB0dHZKdnS3Dhg2T69ev
|
ODhYUrzc3FwwDIPff/9dMM706dNF02hqaoLJZEJISAgXdFliMQFIIyD98mVZaUo++Vm0aBFOnjwJ
|
||||||
i4hIeXm5qd7rr79u2foiImVlZWGd9fFEQNRlrtAskOMIAOMZ7fF4mDlzJkOHDsXn81FbW8uhQ4di
|
oSO1yMhIJCcni6bR2NjIb30CIMtG75MAl8sVK9ZFvSE2NtZnnNDQUKxevRq//PKLYJz4+HhotcLX
|
||||||
6ni9XpYuXWpZ9vXr1zlxovsw2Nl4/IzV+k/hwn6furo6qa2tlRs3boiIyOLFi011Fi5cqNX61dXV
|
mIgId+7c4RMgawkEfBMQdfbsWV1HR4esRI1Go88D0JycHERERODXX38VjMO75+cV1dXVsNlsfALa
|
||||||
YZ2baJ4cjRnpMQj4SbwEAPLWW291O338+HFJS0szla+pqdEiYN26dWGdA/FU3oyAF9wgoKKiotvp
|
xeJ7gy8C/nDt2jW5aUKlUg1dWRXC6tWr4XK5RHtAZmamaBpXr14FEfF3kvKOqOCbgMVCS5QYWJbF
|
||||||
JUuWmMpOmTJFgsGgFgFFRUVhvd8mioBfuUFAcnKynDx5Ug4fPiwpKSmmslu2bNGqfH19vSQlJYX1
|
xIkTBZ9HRUVh8+bNsFgsguMf8GySxMAdifF6wG3ByALwRcCjUm58PIjOzk7+ujwC+fn5iIyMhJht
|
||||||
VsZLQKy1fsdHUCLR0dHBRx99xNmzZ6PO+4cxcuRIVq/W23D+6aef0tXVBXAf41RqXIhFQLRfYnKE
|
ITY21uctEk6B4i2Vsjcrvgj4OzkKEIfW1lbR8fvkk0+CZVmIWZcyMzN9apNWqxV6vZ6fl3R1dRCi
|
||||||
6upqy93hK1asoG/fvlrlHT16NPyxXkT8cTkHMbvATlzoAjpXv379xO/3a4V/V1dXOP8X4I/xhr+Y
|
BNjt9lA5hkkOra2tSEtL8/psxowZWLt2LU6dOoXq6mrBNJYuXSqah8PhwI0bNxAfH8/XAYQnFAGI
|
||||||
ZIKuRYAVli9frrX4AcYEit/vD/970g37sQiwveHQCdLT03nppZe05ffs2RP+KMA/XHEiRheIKw3W
|
ERB38eJFjZLTn/r6emRnZ3tdwtavXw+1Wg2zeeTFbQ46nQ5r1qwRzePMmTNwOp18PaEfgLzlCuIE
|
||||||
vZYvX64V+mEUFhaGdS8ROvof7xWLgOZEVz4pKUk+++wz7cofPHgwfGRegB1uVD7qGKCUSuUhdIG5
|
5PK3qHJw+/ZtmEwmJCUlDQsPCgrCU089hb6+Pnz33XeC8vPnz8e0adNE87h69SoA8AmwKymrGAFp
|
||||||
c+dSVlamLb9nz55w44Bb4U/0McBHgrbCRmLt2rW25CNmkIPAQdcciQj7EmATxs9RJDT8S0tLtdNe
|
fCOFHPT09KCiomLEXcAVK1YgIyMDX3/9NcTIzcvL85kHZzDhESB/uYI4AdPtdkWkAvAUcNmyZcPC
|
||||||
EZFTp05FTqHVuxX+IoJHKTUIeBtYgsuHqWNh7dq1GAfO9LBr167IKbTYc+kO8WceUtIDSEFBga3T
|
tm/fDgCi3T8oKAjr16/3mT7XA3iG0/9RVFCRo+NfV61apfiYe9u2bdTe3j70zt+8efOIZVmqqqoi
|
||||||
ICIi06dPjyzjBVcjANiKsQBiex+AE6xZsybmydG2tja++uorrly5QlNTE4FAgEAgwLFjx8IiHRg/
|
g8EgKLds2TKfx+EtLS2k1+vJZDLx3x5LU3LUL9YDTP6YwC9evIjw8HAsWbIEALBr1y6oVCocOnSI
|
||||||
xOYalIiEDz+vBVZgbIdNSFfIyclh9+7dNDU1dVcw8q/f76etrc2siBMiMtlNn3r9jpBSqhSYjTEo
|
f5I7Ahs2bPCZ9unTp+FyuZCcnMwtlSwA4S2lGISYYVnW+eD7enKcVqslq9VKhYWFlJmZSQzDUFtb
|
||||||
5mNMjztaIHkQKSkpdHZ2Wp0RvI2x2NkS+tsc+nsNqBMRV8cA0x9SCh2NHYtxRnA0MBwYgJEnhC+z
|
G8XGxgrKREdHU1tbm88esGfPHgJABQUFXNA9Ja1PJPLGiM1mG3//vizz2jAwDIPS0lJs3boVBoMB
|
||||||
17h2jP27d0Kf2zH2893G2NNzM3S1YvzAYgDj9Ffsd2eX8V/DpporbFKohAAAAABJRU5ErkJggg== }
|
Go0Ghw8fHmH/5+OJJ57gm7YEwdkneROgfG2NgwAzIWVlZX5fd1m1atVQq/X19VFKSopojzl//rzP
|
||||||
|
1m9oaCC9Xk8A+NdiPlDaA4QeLPnyyy/9JmDChAnU2NhIREQHDhwQjZufn++z8kREn376KQGeN8Z4
|
||||||
|
H0TJUkqA0CSYKvXisxicTieKi4vR09ODQ4cOicaVehJ04cIFAJ69wqCmyQAQNir4gNAcEPegnV4p
|
||||||
|
zGYzGIYRtPwCnm3vxo0bJaXHjX+erUCZtjYIIQJipF5O8IVz587B147ymWeegVrt2zx5+fLlISJ5
|
||||||
|
BFzwp3xCuUYFioCBgQHRmX/y5MnYsWOHpLROnToFlmVhMBj4dweO+VM+IQIiA0WAL2zZsoW/nRXF
|
||||||
|
6dOnAXhelRm0OBEA4V2VBAgREMa7dTVqCAsLwwsvvCApbnt7+9AxGa/7t8KzDVYMIQJCHgYBmzZt
|
||||||
|
8nnyw8FsNoOzTvMIUKb+8iBIwGgPAZ1Oh127dkmOX1ZWBgAYN24c31r0V78L4kU5mE5EvdHR0QG/
|
||||||
|
CM13mzZtkqT4EBH19PQQ90ZaVlYW/1GIUgXImyK0HB67+s2uri79aA4BlUqF5557TnL848ePD5nP
|
||||||
|
582bxwXfByD+UTEJ4PSAvW63e98nn3yCkpIS3Lx5M6AvNj2IvLw8LF++XHJ8vvU4O3voEyCyDaBe
|
||||||
|
QURzmpub2UWLFo1ql+e74uJiyd2fYRhKTEwkABQcHEx2u517tNXf7k+Dm6H7e/fufWiVnzNnDg0M
|
||||||
|
DEiqPMuydPTo0SHZnJycoUfk/ZtBiuwBf9q3b99HRqNR88EHH4ja6gOBHTt2DFN7+/v7UVVVhdra
|
||||||
|
WtTX16OhoWHYL/+NtPnz53N/bfBsgvzHIBPJRGTv6uqigwcP0uOPP07BwcEBb/0JEybQ66+/Ts8+
|
||||||
|
+ywtX76cHn30UVH7IOdCQ0Np2rRpQ1+PIKL/CkTrE438gsRLAP4ZgNFms6GsrAzXrl3DrVu3UF1d
|
||||||
|
jZqaGlF7nhyo1WpEREQgIiICkZGRiIiIQFRUFKKiohAbG4vo6GiYTCYkJiYiKSkJQUHDPhCxBkBA
|
||||||
|
XlkR+oRGGoB/BLAEgAmDClN3dzeuXLkCh8OBjo4OdHZ2orOzc8Q9fz5CQ0Oh1+sxfvx4GAwGhIaG
|
||||||
|
Ijg4GImJiTAaRV/vGYDnwkMHgHsA6uExfd0E8J/yq+odUr8hkgTPm9nZAGbC84amAZ6vNI+D8LYa
|
||||||
|
8HTjAQBueMatG57bnF3wrOX34DnVqYOngjXwfAPULx1fKv4X5zAnLNolSeQAAAAASUVORK5CYII=}
|
||||||
wm iconphoto . -default rpicon
|
wm iconphoto . -default rpicon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc die_with_error { msg } {
|
||||||
|
tk_messageBox -message "Fatal Error" -detail $msg -icon error -type ok
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
proc show_error { msg } {
|
||||||
|
tk_messageBox -message "Error" -detail $msg -icon error -type ok
|
||||||
|
}
|
||||||
proc missing_tcllib { pkg } {
|
proc missing_tcllib { pkg } {
|
||||||
catch { puts stderr "Could not find the '$pkg' package -- you must install tcllib.\nPlease see http://tcllib.sourceforge.net/" }
|
catch { puts stderr "Could not find the '$pkg' package -- you must install tcllib.\nPlease see http://tcllib.sourceforge.net/" }
|
||||||
tk_dialog .err "Error: tcllib not installed" "Could not find the '$pkg' package -- you must install tcllib. Please see http://tcllib.sourceforge.net/" error 0 OK
|
tk_messageBox -message "Error: tcllib not installed" -detail "Could not find the '$pkg' package -- you must install tcllib. Please see http://tcllib.sourceforge.net/" -icon error -type ok
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if {[catch {package require mime}]} {
|
if {[catch {package require mime}]} {
|
||||||
@@ -106,10 +129,23 @@ if {[catch {package require json}]} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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_messageBox -message "Please do not port Remind to Windows" -icon error -type ok
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# GetRemindVersion
|
||||||
|
# Arguments:
|
||||||
|
# none
|
||||||
|
# Returns:
|
||||||
|
# The version of Remind
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
proc GetRemindVersion {} {
|
||||||
|
global Remind
|
||||||
|
set ver [exec sh -c "(echo \"banner %\"; echo \"msg \[version()\]%\") | $Remind -"]
|
||||||
|
return $ver
|
||||||
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# GLOBAL VARIABLES
|
# GLOBAL VARIABLES
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -203,9 +239,6 @@ set ConfigFile ""
|
|||||||
|
|
||||||
set EditorPid -1
|
set EditorPid -1
|
||||||
|
|
||||||
# Inotify file
|
|
||||||
set InotifyFP ""
|
|
||||||
|
|
||||||
# Errors from last remind run
|
# Errors from last remind run
|
||||||
set RemindErrors ""
|
set RemindErrors ""
|
||||||
|
|
||||||
@@ -289,11 +322,19 @@ set Option(PrintSmallCalendars) 1
|
|||||||
set OptDescr(PrintFormat) "Print format: pdf or ps"
|
set OptDescr(PrintFormat) "Print format: pdf or ps"
|
||||||
set Option(PrintFormat) ps
|
set Option(PrintFormat) ps
|
||||||
|
|
||||||
set WarningHeaders [list "# Lines staring with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
set WarningHeaders [list "# Lines starting with REM TAG TKTAGnnn ... were created by tkremind" "# Do not edit them by hand or results may be unpredictable."]
|
||||||
|
|
||||||
# Highest tag seen so far. Array of tags is stored in ReminderTags()
|
# Highest tag seen so far.
|
||||||
set HighestTagSoFar 0
|
set HighestTagSoFar 0
|
||||||
|
|
||||||
|
# Check Remind version
|
||||||
|
set ver [GetRemindVersion]
|
||||||
|
|
||||||
|
if {"$ver" < "04.03.03"} {
|
||||||
|
tk_messageBox -message "This version of TkRemind requires Remind version 04.03.03 or newer; you have version $ver" -icon error -type ok
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
proc get_weekday { yyyymmdd } {
|
proc get_weekday { yyyymmdd } {
|
||||||
global EnglishDayNames
|
global EnglishDayNames
|
||||||
return [lindex $EnglishDayNames [clock format [clock scan $yyyymmdd] -format %w -locale C]]
|
return [lindex $EnglishDayNames [clock format [clock scan $yyyymmdd] -format %w -locale C]]
|
||||||
@@ -312,10 +353,29 @@ proc is_warning_header { line } {
|
|||||||
if {"$line" == "$h"} {
|
if {"$line" == "$h"} {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
# Ignore prior typo line too
|
||||||
|
if {"$line" == "# Lines staring with REM TAG TKTAGnnn ... were created by tkremind"} {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc extract_tag { regex tag } {
|
||||||
|
if {[regexp $regex $tag extracted]} {
|
||||||
|
return $extracted
|
||||||
|
}
|
||||||
|
return "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
proc extract_tktag { tag } {
|
||||||
|
extract_tag {TKTAG[0-9]+} $tag
|
||||||
|
}
|
||||||
|
|
||||||
|
proc extract_syntag { tag } {
|
||||||
|
extract_tag {__syn__[0-9a-f]+} $tag
|
||||||
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# %PROCEDURE: Initialize
|
# %PROCEDURE: Initialize
|
||||||
# %ARGUMENTS:
|
# %ARGUMENTS:
|
||||||
@@ -382,8 +442,8 @@ proc Initialize {} {
|
|||||||
|
|
||||||
# Check system sanity
|
# Check system sanity
|
||||||
if {! [file readable $ReminderFile]} {
|
if {! [file readable $ReminderFile]} {
|
||||||
set ans [tk_dialog .error "TkRemind: Warning" "Can't read reminder file `$ReminderFile'" warning 0 "Create it and continue" "Exit"]
|
set ans [tk_messageBox -message "Can't read reminder file `$ReminderFile'. Create it and continue?" -type yesno -icon question]
|
||||||
if {$ans != 0} {
|
if {$ans != "yes"} {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -394,7 +454,7 @@ proc Initialize {} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if {! [file readable $ReminderFile]} {
|
if {! [file readable $ReminderFile]} {
|
||||||
tk_dialog .error "TkRemind: Error" "Could not create reminder file `$ReminderFile'" error 0 "Exit"
|
die_with_error "Could not create reminder file `$ReminderFile'"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,12 +464,12 @@ proc Initialize {} {
|
|||||||
write_warning_headers $out
|
write_warning_headers $out
|
||||||
puts $out ""
|
puts $out ""
|
||||||
close $out}]} {
|
close $out}]} {
|
||||||
tk_dialog .error "Created File" "Created blank file `$AppendFile'" info 0 "OK"
|
tk_messageBox -message "Created File" -detail "Created blank file `$AppendFile'" -icon info -type ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if {! [file writable $AppendFile]} {
|
if {! [file writable $AppendFile]} {
|
||||||
tk_dialog .error Error "Can't write reminder file `$AppendFile'" error 0 Ok
|
die_with_error "Can't write reminder file `$AppendFile'"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,7 +1020,7 @@ proc WriteOptionsToFile {} {
|
|||||||
global Option OptDescr
|
global Option OptDescr
|
||||||
set problem [catch {set f [open "$ConfigFile.tmp" "w"]} err]
|
set problem [catch {set f [open "$ConfigFile.tmp" "w"]} err]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "Can't write $ConfigFile.tmp: $err" 0 OK
|
show_error "Can't write $ConfigFile.tmp: $err"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1280,7 +1340,7 @@ proc Status { stuff } {
|
|||||||
# None
|
# None
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc DoPrint {} {
|
proc DoPrint {} {
|
||||||
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus
|
global Rem2PS Rem2PDF HaveRem2PDF PSCmd Option PrintStatus RemindErrors
|
||||||
global CurMonth CurYear MonthNames
|
global CurMonth CurYear MonthNames
|
||||||
|
|
||||||
catch {destroy .p}
|
catch {destroy .p}
|
||||||
@@ -1374,16 +1434,16 @@ proc DoPrint {} {
|
|||||||
WriteOptionsToFile
|
WriteOptionsToFile
|
||||||
if {$Option(PrintDest) == "file"} {
|
if {$Option(PrintDest) == "file"} {
|
||||||
if {$fname == ""} {
|
if {$fname == ""} {
|
||||||
tk_dialog .error Error "No filename specified" error 0 Ok
|
show_error "No filename specified"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if {[file isdirectory $fname]} {
|
if {[file isdirectory $fname]} {
|
||||||
tk_dialog .error Error "$fname is a directory" error 0 Ok
|
show_error "$fname is a directory"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if {[file readable $fname]} {
|
if {[file readable $fname]} {
|
||||||
set ans [tk_dialog .error Overwrite? "Overwrite $fname?" question 0 No Yes]
|
set ans [tk_messageBox -message "Overwrite?" -detail "Overwrite $fname?" -icon question -type yesno]
|
||||||
if {$ans == 0} {
|
if {$ans == no} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1466,7 +1526,8 @@ proc DoPrint {} {
|
|||||||
append cmd " $fname"
|
append cmd " $fname"
|
||||||
Status "Printing..."
|
Status "Printing..."
|
||||||
if {[catch {eval "exec $cmd"} err]} {
|
if {[catch {eval "exec $cmd"} err]} {
|
||||||
tk_dialog .error Error "Error during printing: $err" error 0 Ok
|
set RemindErrors [unique_lines $err]
|
||||||
|
set_button_to_errors
|
||||||
}
|
}
|
||||||
DisplayTime
|
DisplayTime
|
||||||
}
|
}
|
||||||
@@ -1523,9 +1584,7 @@ proc GotoDialog {} {
|
|||||||
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
bind .g <KeyPress-Escape> ".g.b.cancel flash; .g.b.cancel invoke"
|
||||||
CenterWindow .g .
|
CenterWindow .g .
|
||||||
set oldFocus [focus]
|
set oldFocus [focus]
|
||||||
grab .g
|
|
||||||
focus .g.y.e
|
focus .g.y.e
|
||||||
tkwait window .g
|
|
||||||
catch {focus $oldFocus}
|
catch {focus $oldFocus}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1536,17 +1595,17 @@ proc DoGoto {} {
|
|||||||
global CurYear CurMonth MonthNames
|
global CurYear CurMonth MonthNames
|
||||||
set year [.g.y.e get]
|
set year [.g.y.e get]
|
||||||
if { ! [regexp {^[0-9]+$} $year] } {
|
if { ! [regexp {^[0-9]+$} $year] } {
|
||||||
tk_dialog .error Error {Illegal year specified (1990-5990)} error 0 Ok
|
show_error {Illegal year specified (1990-5990)}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if { $year < 1990 || $year > 5990 } {
|
if { $year < 1990 || $year > 5990 } {
|
||||||
tk_dialog .error Error {Illegal year specified (1990-5990)} error 0 Ok
|
show_error {Illegal year specified (1990-5990)}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set month [lsearch -exact $MonthNames [.g.mon cget -text]]
|
set month [lsearch -exact $MonthNames [.g.mon cget -text]]
|
||||||
set CurMonth $month
|
set CurMonth $month
|
||||||
set CurYear $year
|
set CurYear $year
|
||||||
destroy .g
|
catch { destroy .g }
|
||||||
FillCalWindow
|
FillCalWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1555,19 +1614,15 @@ proc DoGoto {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc Quit {} {
|
proc Quit {} {
|
||||||
global Option
|
global Option
|
||||||
global InotifyFP
|
|
||||||
if { !$Option(ConfirmQuit) } {
|
if { !$Option(ConfirmQuit) } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
catch { exec kill [pid $InotifyFP] }
|
|
||||||
catch { close $InotifyFP }
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
if { [tk_dialog .question "Confirm..." {Really quit?} question 0 No Yes] } {
|
set ans [tk_messageBox -message "Really quit?" -icon question -type yesno]
|
||||||
|
if { $ans == "yes" } {
|
||||||
destroy .
|
destroy .
|
||||||
StopBackgroundRemindDaemon
|
StopBackgroundRemindDaemon
|
||||||
catch { exec kill [pid $InotifyFP] }
|
|
||||||
catch { close $InotifyFP }
|
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2002,7 +2057,7 @@ proc CreateYearMenu {w {every 1}} {
|
|||||||
# firstDay -- first weekday in month (0-6)
|
# firstDay -- first weekday in month (0-6)
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc ModifyDay {d firstDay} {
|
proc ModifyDay {d firstDay} {
|
||||||
global ModifyDialogResult AppendFile HighestTagSoFar ReminderTags
|
global ModifyDialogResult AppendFile HighestTagSoFar
|
||||||
catch {destroy .mod}
|
catch {destroy .mod}
|
||||||
toplevel .mod
|
toplevel .mod
|
||||||
CreateModifyDialog .mod $d $firstDay "Cancel" "Add to reminder file" "Preview reminder"
|
CreateModifyDialog .mod $d $firstDay "Cancel" "Add to reminder file" "Preview reminder"
|
||||||
@@ -2023,7 +2078,7 @@ proc ModifyDay {d firstDay} {
|
|||||||
}
|
}
|
||||||
set problem [catch {set rem [CreateReminder .mod]} err]
|
set problem [catch {set rem [CreateReminder .mod]} err]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "$err" error 0 Ok
|
show_error $err
|
||||||
} else {
|
} else {
|
||||||
if {$ModifyDialogResult == 3} {
|
if {$ModifyDialogResult == 3} {
|
||||||
set rem [EditReminder $rem Cancel "Add reminder"]
|
set rem [EditReminder $rem Cancel "Add reminder"]
|
||||||
@@ -2037,7 +2092,6 @@ proc ModifyDay {d firstDay} {
|
|||||||
Status "Writing reminder..."
|
Status "Writing reminder..."
|
||||||
set f [open $AppendFile a]
|
set f [open $AppendFile a]
|
||||||
incr HighestTagSoFar
|
incr HighestTagSoFar
|
||||||
set ReminderTags($HighestTagSoFar) 1
|
|
||||||
|
|
||||||
WriteReminder $f TKTAG$HighestTagSoFar $rem $opts
|
WriteReminder $f TKTAG$HighestTagSoFar $rem $opts
|
||||||
close $f
|
close $f
|
||||||
@@ -2050,7 +2104,6 @@ proc ModifyDay {d firstDay} {
|
|||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# CenterWindow -- center a window on the screen or over a parent.
|
# CenterWindow -- center a window on the screen or over a parent.
|
||||||
# Stolen from tk_dialog code
|
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# w -- window to center
|
# w -- window to center
|
||||||
# parent -- window over which to center. Defaults to screen if not supplied.
|
# parent -- window over which to center. Defaults to screen if not supplied.
|
||||||
@@ -2566,7 +2619,7 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
set dir [$w.cwd cget -text]
|
set dir [$w.cwd cget -text]
|
||||||
}
|
}
|
||||||
if {[catch "cd $dir" err]} {
|
if {[catch "cd $dir" err]} {
|
||||||
tk_dialog .error Error "$err" error 0 Ok
|
show_error "$err"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$w.cwd configure -text [pwd]
|
$w.cwd configure -text [pwd]
|
||||||
@@ -2598,7 +2651,6 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
cd $cwd
|
cd $cwd
|
||||||
$w.entry delete 0 end
|
$w.entry delete 0 end
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# StartBackgroundRemindDaemon
|
# StartBackgroundRemindDaemon
|
||||||
# Arguments:
|
# Arguments:
|
||||||
@@ -2611,12 +2663,12 @@ proc BrowseForFileRead {w {dir ""}} {
|
|||||||
proc StartBackgroundRemindDaemon {} {
|
proc StartBackgroundRemindDaemon {} {
|
||||||
global Remind DaemonFile ReminderFile Option TwentyFourHourMode
|
global Remind DaemonFile ReminderFile Option TwentyFourHourMode
|
||||||
if {$TwentyFourHourMode} {
|
if {$TwentyFourHourMode} {
|
||||||
set problem [catch { set DaemonFile [open "|$Remind -b1 -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
set problem [catch { set DaemonFile [open "|$Remind -b1 -zj -y -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
||||||
} else {
|
} else {
|
||||||
set problem [catch { set DaemonFile [open "|$Remind -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
|
set problem [catch { set DaemonFile [open "|$Remind -zj -y -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
|
show_error "Can't start Remind daemon in background: $err"
|
||||||
} else {
|
} else {
|
||||||
fileevent $DaemonFile readable "DaemonReadable $DaemonFile"
|
fileevent $DaemonFile readable "DaemonReadable $DaemonFile"
|
||||||
puts $DaemonFile "STATUS"
|
puts $DaemonFile "STATUS"
|
||||||
@@ -2669,19 +2721,19 @@ proc RestartBackgroundRemindDaemon {} {
|
|||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# ShowQueue
|
# ShowQueue
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# file -- file channel that is readable
|
# queue - the queue
|
||||||
# Returns:
|
# Returns:
|
||||||
# nothing
|
# nothing
|
||||||
# Description:
|
# Description:
|
||||||
# Dumps the debugging queue listing
|
# Dumps the debugging queue listing
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc ShowQueue { file } {
|
proc ShowQueue { queue } {
|
||||||
set w .queuedbg
|
set w .queuedbg
|
||||||
catch { destroy $w }
|
catch { destroy $w }
|
||||||
toplevel $w
|
toplevel $w
|
||||||
wm title $w "Queue (Debugging Output)"
|
wm title $w "Queue (Debugging Output)"
|
||||||
wm iconname $w "Queue Dbg"
|
wm iconname $w "Queue Dbg"
|
||||||
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
text $w.t -fg black -bg white -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
|
||||||
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
scrollbar $w.sb -orient vertical -command "$w.text yview"
|
||||||
button $w.ok -text "OK" -command "destroy $w"
|
button $w.ok -text "OK" -command "destroy $w"
|
||||||
grid $w.t -row 0 -column 0 -sticky nsew
|
grid $w.t -row 0 -column 0 -sticky nsew
|
||||||
@@ -2692,26 +2744,34 @@ proc ShowQueue { file } {
|
|||||||
grid rowconfigure $w 0 -weight 1
|
grid rowconfigure $w 0 -weight 1
|
||||||
grid rowconfigure $w 1 -weight 0
|
grid rowconfigure $w 1 -weight 0
|
||||||
CenterWindow $w .
|
CenterWindow $w .
|
||||||
while (1) {
|
set obj [lsort -command sort_q $queue]
|
||||||
# We should only get one line
|
set did 0
|
||||||
gets $file line
|
$w.t tag configure grey -background "#DDDDDD" -selectbackground "#999999"
|
||||||
if {$line == "NOTE ENDJSONQUEUE"} {
|
set toggle 0
|
||||||
break
|
foreach q $obj {
|
||||||
}
|
if { $did > 0 } {
|
||||||
if {[catch {set obj [::json::json2dict $line]}]} {
|
$w.t insert end "\n"
|
||||||
continue;
|
}
|
||||||
}
|
foreach r $q {
|
||||||
set obj [lsort -command sort_q $obj]
|
if { $toggle != 0 } {
|
||||||
foreach q $obj {
|
$w.t insert end "$r " grey
|
||||||
$w.t insert end "$q\n"
|
} else {
|
||||||
}
|
$w.t insert end "$r "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$w.t insert end "\n"
|
||||||
|
set toggle [expr 1 - $toggle]
|
||||||
|
set did 1
|
||||||
|
}
|
||||||
|
if { $did == 0 } {
|
||||||
|
$w.t insert end "(Queue is empty)\n"
|
||||||
}
|
}
|
||||||
$w.t configure -state disabled
|
$w.t configure -state disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
proc sort_q { a b } {
|
proc sort_q { a b } {
|
||||||
set a_ttime [dict get $a nextttime]
|
set a_ttime [dict get $a nexttime]
|
||||||
set b_ttime [dict get $b nextttime]
|
set b_ttime [dict get $b nexttime]
|
||||||
if {$a_ttime < $b_ttime} {
|
if {$a_ttime < $b_ttime} {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@@ -2738,77 +2798,97 @@ proc DaemonReadable { file } {
|
|||||||
catch { close $file }
|
catch { close $file }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch -glob -- $line {
|
if {[catch {set obj [::json::json2dict $line]}]} {
|
||||||
"NOTE reminder*" {
|
return;
|
||||||
scan $line "NOTE reminder %s %s %s" time now tag
|
}
|
||||||
IssueBackgroundReminder $file $time $now $tag
|
if {![dict exists $obj response]} {
|
||||||
}
|
return;
|
||||||
"NOTE JSONQUEUE" {
|
}
|
||||||
ShowQueue $file
|
set response [dict get $obj response]
|
||||||
}
|
switch -- $response {
|
||||||
"NOTE newdate" {
|
"queued" {
|
||||||
# Date has rolled over -- clear "ignore" list
|
set n [dict get $obj nqueued]
|
||||||
catch { unset Ignore}
|
|
||||||
Initialize
|
|
||||||
FillCalWindow
|
|
||||||
ShowTodaysReminders
|
|
||||||
}
|
|
||||||
"NOTE reread" {
|
|
||||||
puts $file "STATUS"
|
|
||||||
flush $file
|
|
||||||
}
|
|
||||||
"NOTE queued*" {
|
|
||||||
scan $line "NOTE queued %d" n
|
|
||||||
if {$n == 1} {
|
if {$n == 1} {
|
||||||
.b.nqueued configure -text "1 reminder queued"
|
.b.nqueued configure -text "1 reminder queued"
|
||||||
} else {
|
} else {
|
||||||
.b.nqueued configure -text "$n reminders queued"
|
.b.nqueued configure -text "$n reminders queued"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default {
|
"reminder" {
|
||||||
puts stderr "Unknown message from daemon: $line\n"
|
set time [dict get $obj ttime]
|
||||||
}
|
set now [dict get $obj now]
|
||||||
|
set tag "*"
|
||||||
|
if {[dict exists $obj tags]} {
|
||||||
|
set tag [dict get $obj tags]
|
||||||
|
}
|
||||||
|
set body [dict get $obj body]
|
||||||
|
set qid "*"
|
||||||
|
if {[dict exists $obj qid]} {
|
||||||
|
set qid [dict get $obj qid]
|
||||||
|
}
|
||||||
|
IssueBackgroundReminder $body $time $now $tag $qid
|
||||||
|
}
|
||||||
|
"queue" {
|
||||||
|
set queue [dict get $obj queue]
|
||||||
|
ShowQueue $queue
|
||||||
|
}
|
||||||
|
"newdate" {
|
||||||
|
# Date has rolled over -- clear "ignore" list
|
||||||
|
catch { unset Ignore }
|
||||||
|
Initialize
|
||||||
|
FillCalWindow
|
||||||
|
ShowTodaysReminders
|
||||||
|
}
|
||||||
|
"reread" {
|
||||||
|
if {[dict exists $obj command]} {
|
||||||
|
set cmd [dict get $obj command]
|
||||||
|
if {"$cmd" == "inotify"} {
|
||||||
|
FillCalWindow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts $file "STATUS"
|
||||||
|
flush $file
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
puts stderr "Unknown message from daemon: $line\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# IssueBackgroundReminder
|
# IssueBackgroundReminder
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# file -- file channel that is readable
|
# body -- body of reminder
|
||||||
# time -- time of reminder
|
# time -- time of reminder
|
||||||
# now -- current time according to Remind daemon
|
# now -- current time according to Remind daemon
|
||||||
# tag -- tag for reminder, or "*" if no tag
|
# tag -- tag for reminder, or "*" if no tag
|
||||||
|
# qid -- Queue-ID for reminder, or "*" if no qid
|
||||||
# Returns:
|
# Returns:
|
||||||
# nothing
|
# nothing
|
||||||
# Description:
|
# Description:
|
||||||
# Reads a background reminder from daemon and pops up window.
|
# Reads a background reminder from daemon and pops up window.
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
proc IssueBackgroundReminder { file time now tag } {
|
proc IssueBackgroundReminder { body time now tag qid } {
|
||||||
global BgCounter Option Ignore
|
global BgCounter Option Ignore DaemonFile
|
||||||
if {$Option(Deiconify)} {
|
if {$Option(Deiconify)} {
|
||||||
wm deiconify .
|
wm deiconify .
|
||||||
}
|
}
|
||||||
|
|
||||||
set msg ""
|
|
||||||
set line ""
|
|
||||||
while (1) {
|
|
||||||
gets $file line
|
|
||||||
if {$line == "NOTE endreminder"} {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if {$msg != ""} {
|
|
||||||
append msg "\n";
|
|
||||||
}
|
|
||||||
append msg $line
|
|
||||||
}
|
|
||||||
# Do nothing if it's blank -- was probably a RUN-type reminder.
|
# Do nothing if it's blank -- was probably a RUN-type reminder.
|
||||||
if {$msg == ""} {
|
if {$body == ""} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
# Do nothing if user told us to ignore this reminder
|
# If we're ignoring it because of tag, ignore and delete
|
||||||
if {[info exists Ignore($tag)]} {
|
set syntag [extract_syntag $tag]
|
||||||
return
|
if {$syntag != "*"} {
|
||||||
|
if {[info exists Ignore($syntag)]} {
|
||||||
|
if {$qid != "*"} {
|
||||||
|
puts $DaemonFile "DEL $qid"
|
||||||
|
flush $DaemonFile
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
incr BgCounter
|
incr BgCounter
|
||||||
@@ -2817,24 +2897,30 @@ proc IssueBackgroundReminder { file time now tag } {
|
|||||||
wm iconname $w "Reminder"
|
wm iconname $w "Reminder"
|
||||||
wm title $w "Timed reminder ($time)"
|
wm title $w "Timed reminder ($time)"
|
||||||
label $w.l -text "Reminder for $time issued at $now"
|
label $w.l -text "Reminder for $time issued at $now"
|
||||||
message $w.msg -width 6i -text $msg
|
message $w.msg -width 6i -text $body
|
||||||
frame $w.b
|
frame $w.b
|
||||||
|
|
||||||
# Automatically shut down window after a minute if option says so
|
# Automatically shut down window after a minute if option says so
|
||||||
set after_token [after 60000 [list ClosePopup $w "" $Option(MailAddr) $Option(AutoClose) "" $tag $msg $time]]
|
set after_token [after 60000 [list ClosePopup $w "" $Option(MailAddr) $Option(AutoClose) "" $tag $body $time $qid]]
|
||||||
|
|
||||||
wm protocol $w WM_DELETE_WINDOW [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
|
wm protocol $w WM_DELETE_WINDOW [list ClosePopup $w $after_token "" 1 "" $tag $body $time $qid]
|
||||||
button $w.ok -text "OK" -command [list ClosePopup $w $after_token "" 1 "" $tag $msg $time]
|
button $w.ok -text "OK" -command [list ClosePopup $w $after_token "" 1 "" $tag $body $time $qid]
|
||||||
if {$tag != "*"} {
|
set tktag [extract_tktag $tag]
|
||||||
button $w.nomore -text "Don't remind me again today" -command [list ClosePopup $w $after_token "" 1 "ignore" $tag $msg $time]
|
if {$tktag != "*"} {
|
||||||
button $w.kill -text "Delete this reminder completely" -command [list ClosePopup $w $after_token "" 1 "kill" $tag $msg $time]
|
button $w.kill -text "Delete this reminder completely" -command [list ClosePopup $w $after_token "" 1 "kill" $tag $body $time $qid]
|
||||||
|
}
|
||||||
|
if {$qid != "*"} {
|
||||||
|
button $w.nomore -text "Don't remind me again today" -command [list ClosePopup $w $after_token "" 1 "ignore" $tag $body $time $qid]
|
||||||
}
|
}
|
||||||
pack $w.l -side top
|
pack $w.l -side top
|
||||||
pack $w.msg -side top -expand 1 -fill both
|
pack $w.msg -side top -expand 1 -fill both
|
||||||
pack $w.b -side top
|
pack $w.b -side top
|
||||||
pack $w.ok -in $w.b -side left
|
pack $w.ok -in $w.b -side left
|
||||||
if {$tag != "*"} {
|
if {$qid != "*"} {
|
||||||
pack $w.nomore $w.kill -in $w.b -side left
|
pack $w.nomore -in $w.b -side left
|
||||||
|
}
|
||||||
|
if {$tktag != "*"} {
|
||||||
|
pack $w.kill -in $w.b -side left
|
||||||
}
|
}
|
||||||
|
|
||||||
CenterWindow $w .
|
CenterWindow $w .
|
||||||
@@ -2845,17 +2931,11 @@ proc IssueBackgroundReminder { file time now tag } {
|
|||||||
}
|
}
|
||||||
if {$Option(RunCmd) != ""} {
|
if {$Option(RunCmd) != ""} {
|
||||||
if {$Option(FeedReminder)} {
|
if {$Option(FeedReminder)} {
|
||||||
FeedReminderToCommand $Option(RunCmd) "$time: $msg"
|
FeedReminderToCommand $Option(RunCmd) "$time: $body"
|
||||||
} else {
|
} else {
|
||||||
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
exec "/bin/sh" "-c" $Option(RunCmd) "&"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# reread status
|
|
||||||
if {$file != "stdin"} {
|
|
||||||
puts $file "STATUS"
|
|
||||||
flush $file
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
@@ -2901,7 +2981,7 @@ proc main {} {
|
|||||||
|
|
||||||
global AppendFile HighestTagSoFar DayNames
|
global AppendFile HighestTagSoFar DayNames
|
||||||
catch {
|
catch {
|
||||||
puts "\nTkRemind Copyright (C) 1996-2021 Dianne Skoll"
|
puts "\nTkRemind Copyright (C) 1996-2024 Dianne Skoll"
|
||||||
}
|
}
|
||||||
catch { SetFonts }
|
catch { SetFonts }
|
||||||
Initialize
|
Initialize
|
||||||
@@ -2920,7 +3000,6 @@ proc main {} {
|
|||||||
CreateCalWindow $DayNames
|
CreateCalWindow $DayNames
|
||||||
FillCalWindow
|
FillCalWindow
|
||||||
StartBackgroundRemindDaemon
|
StartBackgroundRemindDaemon
|
||||||
SetupInotify
|
|
||||||
DisplayTimeContinuously
|
DisplayTimeContinuously
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2935,7 +3014,7 @@ proc main {} {
|
|||||||
# the tag array. Also adjusts HighestTagSoFar
|
# the tag array. Also adjusts HighestTagSoFar
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc ScanForTags { fname } {
|
proc ScanForTags { fname } {
|
||||||
global HighestTagSoFar ReminderTags
|
global HighestTagSoFar
|
||||||
if {[catch { set f [open $fname "r"]}]} {
|
if {[catch { set f [open $fname "r"]}]} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2946,7 +3025,6 @@ proc ScanForTags { fname } {
|
|||||||
if {$tagno > $HighestTagSoFar} {
|
if {$tagno > $HighestTagSoFar} {
|
||||||
set HighestTagSoFar $tagno
|
set HighestTagSoFar $tagno
|
||||||
}
|
}
|
||||||
set ReminderTags($tagno) 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3433,7 +3511,7 @@ proc EditTaggedReminder { w } {
|
|||||||
}
|
}
|
||||||
set problem [catch {set rem [CreateReminder .mod]} err]
|
set problem [catch {set rem [CreateReminder .mod]} err]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "$err" error 0 Ok
|
show_error "$err"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if {$ModifyDialogResult == 4} {
|
if {$ModifyDialogResult == 4} {
|
||||||
@@ -3453,7 +3531,7 @@ proc EditTaggedReminder { w } {
|
|||||||
}
|
}
|
||||||
} err]
|
} err]
|
||||||
if {$problem} {
|
if {$problem} {
|
||||||
tk_dialog .error Error "Error: $err" error 0 Ok
|
show_error $err
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3516,7 +3594,7 @@ proc UniqueFileName { stem } {
|
|||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc DeleteTaggedReminder { tag } {
|
proc DeleteTaggedReminder { tag } {
|
||||||
global AppendFile
|
global AppendFile
|
||||||
global HighestTagSoFar
|
global HighestTagSoFar Ignore
|
||||||
|
|
||||||
set tmpfile [UniqueFileName $AppendFile]
|
set tmpfile [UniqueFileName $AppendFile]
|
||||||
set out [open $tmpfile "w"]
|
set out [open $tmpfile "w"]
|
||||||
@@ -3525,12 +3603,14 @@ proc DeleteTaggedReminder { tag } {
|
|||||||
|
|
||||||
set found 0
|
set found 0
|
||||||
|
|
||||||
set tagno 0
|
set tktag [extract_tktag $tag]
|
||||||
|
set syntag [extract_syntag $tag]
|
||||||
|
set h 0
|
||||||
while {[gets $in line] >= 0} {
|
while {[gets $in line] >= 0} {
|
||||||
if {[is_warning_header $line]} {
|
if {[is_warning_header $line]} {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if {[string match "REM TAG $tag *" $line]} {
|
if {[string match "REM TAG $tktag *" $line]} {
|
||||||
set found 1
|
set found 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -3545,13 +3625,12 @@ proc DeleteTaggedReminder { tag } {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
# Renumber tags
|
if {[regexp {^REM TAG TKTAG([0-9]+)} $line all tagno]} {
|
||||||
if {[regexp {^REM TAG TKTAG([0-9]+) (.*)$} $line all oldtag rest]} {
|
if {$tagno > $h} {
|
||||||
incr tagno
|
set h $tagno
|
||||||
puts $out "REM TAG TKTAG$tagno $rest"
|
}
|
||||||
} else {
|
}
|
||||||
puts $out $line
|
puts $out $line
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if {! $found } {
|
if {! $found } {
|
||||||
@@ -3561,9 +3640,13 @@ proc DeleteTaggedReminder { tag } {
|
|||||||
error "Did not find reminder with tag $tag"
|
error "Did not find reminder with tag $tag"
|
||||||
}
|
}
|
||||||
|
|
||||||
set HighestTagSoFar $tagno
|
if {$syntag != "*"} {
|
||||||
|
catch { unset Ignore($syntag) }
|
||||||
|
}
|
||||||
|
|
||||||
close $in
|
close $in
|
||||||
close $out
|
close $out
|
||||||
|
set HighestTagSoFar $h
|
||||||
file rename -force -- $tmpfile $AppendFile
|
file rename -force -- $tmpfile $AppendFile
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3740,7 +3823,7 @@ proc DoMoonSpecial { n stuff fntag day } {
|
|||||||
# Displays current date and time in status window
|
# Displays current date and time in status window
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc DisplayTime {} {
|
proc DisplayTime {} {
|
||||||
global TwentyFourHourMode
|
global TwentyFourHourMode DaemonFile
|
||||||
if {$TwentyFourHourMode} {
|
if {$TwentyFourHourMode} {
|
||||||
set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
|
set msg [clock format [clock seconds] -format "%e %b %Y %H:%M"]
|
||||||
} else {
|
} else {
|
||||||
@@ -3896,8 +3979,8 @@ proc ShowTodaysReminders {} {
|
|||||||
# Prompts for confirmation; then deletes reminder
|
# Prompts for confirmation; then deletes reminder
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
proc InteractiveDeleteReminder { tag } {
|
proc InteractiveDeleteReminder { tag } {
|
||||||
set ans [tk_dialog .error "Really Delete" "Really delete reminder?" warning 0 No Yes]
|
set ans [tk_messageBox -message "Really Delete" -detail "Really delete reminder?" -icon question -type yesno]
|
||||||
if {$ans == 1} {
|
if {$ans == yes} {
|
||||||
DeleteTaggedReminder $tag
|
DeleteTaggedReminder $tag
|
||||||
ScheduleUpdateForChanges
|
ScheduleUpdateForChanges
|
||||||
}
|
}
|
||||||
@@ -3919,8 +4002,8 @@ proc SendMail { recipient subject body } {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder rem_time } {
|
proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder rem_time qid } {
|
||||||
global Ignore
|
global DaemonFile Ignore
|
||||||
if {"$after_token" != ""} {
|
if {"$after_token" != ""} {
|
||||||
catch { after cancel $after_token }
|
catch { after cancel $after_token }
|
||||||
}
|
}
|
||||||
@@ -3933,10 +4016,20 @@ proc ClosePopup { w after_token mail_addr close_win ignore_or_kill tag reminder
|
|||||||
SendMail $mail_addr "Reminder for $rem_time" "Hello,\n\nThe following reminder is scheduled for $rem_time:\n\n$reminder\nRegards,\n\nTkRemind\n"
|
SendMail $mail_addr "Reminder for $rem_time" "Hello,\n\nThe following reminder is scheduled for $rem_time:\n\n$reminder\nRegards,\n\nTkRemind\n"
|
||||||
}
|
}
|
||||||
if {"$ignore_or_kill" == "ignore"} {
|
if {"$ignore_or_kill" == "ignore"} {
|
||||||
set Ignore($tag) 1
|
if {$qid != "*"} {
|
||||||
|
set syntag [extract_syntag $tag]
|
||||||
|
if {$syntag != "*"} {
|
||||||
|
set Ignore($syntag) 1
|
||||||
|
}
|
||||||
|
puts $DaemonFile "DEL $qid"
|
||||||
|
flush $DaemonFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if {"$ignore_or_kill" == "kill"} {
|
if {"$ignore_or_kill" == "kill"} {
|
||||||
InteractiveDeleteReminder $tag
|
set tktag [extract_tktag $tag]
|
||||||
|
if {$tktag != "*"} {
|
||||||
|
InteractiveDeleteReminder $tag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3952,30 +4045,6 @@ proc SetFonts {} {
|
|||||||
set SetFontsWorked 1
|
set SetFontsWorked 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set up inotify to watch for changes to reminder file/directory
|
|
||||||
proc SetupInotify {} {
|
|
||||||
global InotifyFP
|
|
||||||
global ReminderFile
|
|
||||||
set failed [catch {set InotifyFP [open "|inotifywait -r -q -m -e close_write -e move -e create -e delete $ReminderFile < /dev/null 2>/dev/null" "r"] } ]
|
|
||||||
if {$failed} {
|
|
||||||
# inotifywait probably not available... meh.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fileevent $InotifyFP readable [list InotifyReadable $InotifyFP]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Called when inotifywait reports an event. Schedule a calendar update
|
|
||||||
# and daemon reload.
|
|
||||||
proc InotifyReadable { fp } {
|
|
||||||
catch { set num [gets $fp line] }
|
|
||||||
if {$num < 0} {
|
|
||||||
catch { exec kill [pid $fp] }
|
|
||||||
catch { close $fp }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ScheduleUpdateForChanges
|
|
||||||
}
|
|
||||||
|
|
||||||
### Balloon help
|
### Balloon help
|
||||||
set Balloon(HelpTime) 400
|
set Balloon(HelpTime) 400
|
||||||
set Balloon(StayTime) 3500
|
set Balloon(StayTime) 3500
|
||||||
@@ -4048,13 +4117,17 @@ bind Balloon <Destroy> {
|
|||||||
catch { unset Balloon(helptext%W) }
|
catch { unset Balloon(helptext%W) }
|
||||||
}
|
}
|
||||||
|
|
||||||
proc balloon_add_help { w txt } {
|
proc balloon_set_help { w txt } {
|
||||||
global Balloon
|
global Balloon
|
||||||
if {"$txt" == ""} {
|
if {"$txt" == ""} {
|
||||||
catch { unset Balloon(helptext$w) }
|
catch { unset Balloon(helptext$w) }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
set Balloon(helptext$w) $txt
|
set Balloon(helptext$w) $txt
|
||||||
|
}
|
||||||
|
|
||||||
|
proc balloon_add_help { w txt } {
|
||||||
|
balloon_set_help $w $txt
|
||||||
bindtags $w "Balloon [bindtags $w]"
|
bindtags $w "Balloon [bindtags $w]"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4206,9 +4279,11 @@ proc update_color_buttons { w } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc set_button_to_queue {} {
|
proc set_button_to_queue {} {
|
||||||
|
balloon_set_help .b.queue "See the queue of pending reminders (debugging purposes only)"
|
||||||
.b.queue configure -text {Queue...} -command {DoQueue}
|
.b.queue configure -text {Queue...} -command {DoQueue}
|
||||||
}
|
}
|
||||||
proc set_button_to_errors {} {
|
proc set_button_to_errors {} {
|
||||||
|
balloon_set_help .b.queue "See the list of errors from the most recent operation"
|
||||||
.b.queue configure -text {Errors...} -command {ShowErrors}
|
.b.queue configure -text {Errors...} -command {ShowErrors}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,15 @@ install: all
|
|||||||
done
|
done
|
||||||
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
|
-mkdir -p $(DESTDIR)$(datarootdir)/remind || true
|
||||||
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
|
cp -R ../include/* $(DESTDIR)$(datarootdir)/remind
|
||||||
|
-mkdir -p $(DESTDIR)$(prefix)/share/pixmaps
|
||||||
|
-mkdir -p $(DESTDIR)$(prefix)/share/applications
|
||||||
|
$(INSTALL_DATA) $(srcdir)/../resources/tkremind.png $(DESTDIR)$(prefix)/share/pixmaps
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/../resources/tkremind.desktop $(DESTDIR)$(prefix)/share/applications
|
||||||
|
-if test "$(DESTDIR)" = ""; then \
|
||||||
|
update-desktop-database < /dev/null > /dev/null 2>&1 ; \
|
||||||
|
xdg-icon-resource install --novendor --size 64 $(DESTDIR)$(prefix)/share/pixmaps/tkremind.png < /dev/null > /dev/null 2>&1; \
|
||||||
|
xdg-desktop-menu install --novendor $(DESTDIR)$(prefix)/share/applications/tkremind.desktop < /dev/null > /dev/null 2>&1 ; \
|
||||||
|
fi
|
||||||
|
|
||||||
install-stripped: install
|
install-stripped: install
|
||||||
strip $(DESTDIR)$(bindir)/remind || true
|
strip $(DESTDIR)$(bindir)/remind || true
|
||||||
@@ -71,9 +80,6 @@ install-stripped: install
|
|||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ core *.bak $(PROGS)
|
rm -f *.o *~ core *.bak $(PROGS)
|
||||||
|
|
||||||
cppcheck:
|
|
||||||
cppcheck --force --enable=all --suppress=variableScope --suppress=ConfigurationNotChecked *.c
|
|
||||||
|
|
||||||
clobber:
|
clobber:
|
||||||
rm -f *.o *~ remind rem2ps test.out core *.bak
|
rm -f *.o *~ remind rem2ps test.out core *.bak
|
||||||
|
|
||||||
@@ -83,6 +89,9 @@ depend:
|
|||||||
# The next targets are not very useful to you. I use them to build
|
# The next targets are not very useful to you. I use them to build
|
||||||
# distributions, etc.
|
# distributions, etc.
|
||||||
|
|
||||||
|
cppcheck:
|
||||||
|
cppcheck -j`nproc` --force --enable=all --suppress=ConfigurationNotChecked --suppress=unmatchedSuppression --suppress=variableScope --inline-suppr .
|
||||||
|
|
||||||
# Build a tar file based on all files checked into git.
|
# Build a tar file based on all files checked into git.
|
||||||
distro:
|
distro:
|
||||||
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION).tar
|
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION).tar
|
||||||
|
|||||||
225
src/calendar.c
225
src/calendar.c
@@ -5,7 +5,7 @@
|
|||||||
/* 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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -475,7 +475,7 @@ void PrintJSONKeyPairTime(char const *name, int t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
void PutWideChar(wchar_t const wc)
|
void PutWideChar(wchar_t const wc, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
char buf[MB_CUR_MAX+1];
|
char buf[MB_CUR_MAX+1];
|
||||||
int len;
|
int len;
|
||||||
@@ -483,7 +483,11 @@ void PutWideChar(wchar_t const wc)
|
|||||||
len = wctomb(buf, wc);
|
len = wctomb(buf, wc);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
fputs(buf, stdout);
|
if (output) {
|
||||||
|
DBufPuts(output, buf);
|
||||||
|
} else {
|
||||||
|
fputs(buf, stdout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -556,11 +560,11 @@ static void goff(void)
|
|||||||
static void
|
static void
|
||||||
ClampColor(int *r, int *g, int *b)
|
ClampColor(int *r, int *g, int *b)
|
||||||
{
|
{
|
||||||
if (TerminalBackground == TERMINAL_BACKGROUND_UNKNOWN) {
|
if (GetTerminalBackground() == TERMINAL_BACKGROUND_UNKNOWN) {
|
||||||
/* No special clamping if terminal background is unknown */
|
/* No special clamping if terminal background is unknown */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
|
if (GetTerminalBackground() == TERMINAL_BACKGROUND_DARK) {
|
||||||
if (*r <= 64 && *g <= 64 && *b <= 64) {
|
if (*r <= 64 && *g <= 64 && *b <= 64) {
|
||||||
int max = *r;
|
int max = *r;
|
||||||
double factor;
|
double factor;
|
||||||
@@ -579,7 +583,7 @@ ClampColor(int *r, int *g, int *b)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
|
if (GetTerminalBackground() == TERMINAL_BACKGROUND_LIGHT) {
|
||||||
if (*r > 191 && *g > 191 && *b > 191) {
|
if (*r > 191 && *g > 191 && *b > 191) {
|
||||||
int min = *r;
|
int min = *r;
|
||||||
if (*g < min) min = *g;
|
if (*g < min) min = *g;
|
||||||
@@ -667,11 +671,11 @@ Colorize(int r, int g, int b, int bg, int clamp)
|
|||||||
if (b > 64) b = 1;
|
if (b > 64) b = 1;
|
||||||
else b = 0;
|
else b = 0;
|
||||||
|
|
||||||
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_DARK && !bg) {
|
if (clamp && GetTerminalBackground() == TERMINAL_BACKGROUND_DARK && !bg) {
|
||||||
/* Convert black-on-black to grey */
|
/* Convert black-on-black to grey */
|
||||||
if (!r && !g && !b) return VT100Colors[1][0][0][0];
|
if (!r && !g && !b) return VT100Colors[1][0][0][0];
|
||||||
}
|
}
|
||||||
if (clamp && TerminalBackground == TERMINAL_BACKGROUND_LIGHT && !bg) {
|
if (clamp && GetTerminalBackground() == TERMINAL_BACKGROUND_LIGHT && !bg) {
|
||||||
/* Convert white-on-white to grey */
|
/* Convert white-on-white to grey */
|
||||||
if (r && g && b) return VT100Colors[1][0][0][0];
|
if (r && g && b) return VT100Colors[1][0][0][0];
|
||||||
}
|
}
|
||||||
@@ -1037,7 +1041,7 @@ static void DoCalendarOneMonth(void)
|
|||||||
printf("\"entries\":[\n");
|
printf("\"entries\":[\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (WriteCalendarRow()) continue;
|
while (WriteCalendarRow()) /* continue */;
|
||||||
|
|
||||||
if (PsCal == PSCAL_LEVEL1) {
|
if (PsCal == PSCAL_LEVEL1) {
|
||||||
printf("%s\n", PSEND);
|
printf("%s\n", PSEND);
|
||||||
@@ -1218,7 +1222,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
if (!buf) {
|
if (!buf) {
|
||||||
/* Uh-oh... cannot recover */
|
/* Uh-oh... cannot recover */
|
||||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) mbstowcs(buf, s, len+1);
|
(void) mbstowcs(buf, s, len+1);
|
||||||
@@ -1227,7 +1231,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
ws = buf;
|
ws = buf;
|
||||||
for (i=0; i<width;) {
|
for (i=0; i<width;) {
|
||||||
if (*ws) {
|
if (*ws) {
|
||||||
PutWideChar(*ws++);
|
PutWideChar(*ws++, NULL);
|
||||||
i+= wcwidth(*ws);
|
i+= wcwidth(*ws);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -1235,7 +1239,7 @@ static void PrintLeft(char const *s, int width, char pad)
|
|||||||
}
|
}
|
||||||
/* Mop up any potential combining characters */
|
/* Mop up any potential combining characters */
|
||||||
while (*ws && wcwidth(*ws) == 0) {
|
while (*ws && wcwidth(*ws) == 0) {
|
||||||
PutWideChar(*ws++);
|
PutWideChar(*ws++, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Possibly send lrm control sequence */
|
/* Possibly send lrm control sequence */
|
||||||
@@ -1297,7 +1301,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
if (!buf) {
|
if (!buf) {
|
||||||
/* Uh-oh... cannot recover */
|
/* Uh-oh... cannot recover */
|
||||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) mbstowcs(buf, s, len+1);
|
(void) mbstowcs(buf, s, len+1);
|
||||||
@@ -1308,7 +1312,7 @@ 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 (*ws) {
|
if (*ws) {
|
||||||
PutWideChar(*ws++);
|
PutWideChar(*ws++, NULL);
|
||||||
if (wcwidth(*ws) == 0) {
|
if (wcwidth(*ws) == 0) {
|
||||||
/* Don't count this character... it's zero-width */
|
/* Don't count this character... it's zero-width */
|
||||||
i--;
|
i--;
|
||||||
@@ -1319,7 +1323,7 @@ static void PrintCentered(char const *s, int width, char *pad)
|
|||||||
}
|
}
|
||||||
/* Mop up any potential combining characters */
|
/* Mop up any potential combining characters */
|
||||||
while (*ws && wcwidth(*ws) == 0) {
|
while (*ws && wcwidth(*ws) == 0) {
|
||||||
PutWideChar(*ws++);
|
PutWideChar(*ws++, NULL);
|
||||||
}
|
}
|
||||||
/* Possibly send lrm control sequence */
|
/* Possibly send lrm control sequence */
|
||||||
send_lrm();
|
send_lrm();
|
||||||
@@ -1448,7 +1452,7 @@ static int WriteOneColLine(int col)
|
|||||||
}
|
}
|
||||||
numwritten += wcwidth(*ws);
|
numwritten += wcwidth(*ws);
|
||||||
}
|
}
|
||||||
PutWideChar(*ws);
|
PutWideChar(*ws, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->wc_pos = ws;
|
e->wc_pos = ws;
|
||||||
@@ -1463,7 +1467,7 @@ static int WriteOneColLine(int col)
|
|||||||
if (wcwidth(*ws) > 0) {
|
if (wcwidth(*ws) > 0) {
|
||||||
numwritten += wcwidth(*ws);
|
numwritten += wcwidth(*ws);
|
||||||
}
|
}
|
||||||
PutWideChar(*ws);
|
PutWideChar(*ws, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1603,7 +1607,7 @@ static void GenerateCalEntries(int col)
|
|||||||
r=IncludeFile(InitialFile);
|
r=IncludeFile(InitialFile);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
|
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
@@ -1611,7 +1615,7 @@ static void GenerateCalEntries(int col)
|
|||||||
if (r == E_EOF) return;
|
if (r == E_EOF) return;
|
||||||
if (r) {
|
if (r) {
|
||||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
s = FindInitialToken(&tok, CurLine);
|
s = FindInitialToken(&tok, CurLine);
|
||||||
|
|
||||||
@@ -2211,10 +2215,114 @@ static void WriteSimpleEntryProtocol1(CalEntry *e)
|
|||||||
printf("%s\n", e->text);
|
printf("%s\n", e->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteJSONTimeTrigger(TimeTrig const *tt)
|
||||||
|
{
|
||||||
|
PrintJSONKeyPairTime("time", tt->ttime);
|
||||||
|
PrintJSONKeyPairTime("nexttime", tt->nexttime);
|
||||||
|
PrintJSONKeyPairInt("tdelta", tt->delta);
|
||||||
|
PrintJSONKeyPairInt("trep", tt->rep);
|
||||||
|
if (tt->duration != NO_TIME) {
|
||||||
|
PrintJSONKeyPairInt("duration", tt->duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteJSONTrigger(Trigger const *t, int include_tags, int today)
|
||||||
|
{
|
||||||
|
/* wd is an array of days from 0=monday to 6=sunday.
|
||||||
|
We convert to array of strings */
|
||||||
|
if (t->wd != NO_WD) {
|
||||||
|
printf("\"wd\":[");
|
||||||
|
int done = 0;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<7; i++) {
|
||||||
|
if (t->wd & (1 << i)) {
|
||||||
|
if (done) {
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
done = 1;
|
||||||
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("],");
|
||||||
|
}
|
||||||
|
if (t->d != NO_DAY) {
|
||||||
|
PrintJSONKeyPairInt("d", t->d);
|
||||||
|
}
|
||||||
|
if (t->m != NO_MON) {
|
||||||
|
PrintJSONKeyPairInt("m", t->m+1);
|
||||||
|
}
|
||||||
|
if (t->y != NO_YR) {
|
||||||
|
PrintJSONKeyPairInt("y", t->y);
|
||||||
|
}
|
||||||
|
if (t->back) {
|
||||||
|
PrintJSONKeyPairInt("back", t->back);
|
||||||
|
}
|
||||||
|
if (t->delta) {
|
||||||
|
PrintJSONKeyPairInt("delta", t->delta);
|
||||||
|
}
|
||||||
|
if (t->rep) {
|
||||||
|
PrintJSONKeyPairInt("rep", t->rep);
|
||||||
|
}
|
||||||
|
/* Local omit is an array of days from 0=monday to 6=sunday.
|
||||||
|
We convert to array of strings */
|
||||||
|
if (t->localomit != NO_WD) {
|
||||||
|
printf("\"localomit\":[");
|
||||||
|
int done = 0;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<7; i++) {
|
||||||
|
if (t->localomit & (1 << i)) {
|
||||||
|
if (done) {
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
done = 1;
|
||||||
|
printf("\"%s\"", EnglishDayName[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("],");
|
||||||
|
}
|
||||||
|
switch(t->skip) {
|
||||||
|
case SKIP_SKIP:
|
||||||
|
PrintJSONKeyPairString("skip", "SKIP");
|
||||||
|
break;
|
||||||
|
case BEFORE_SKIP:
|
||||||
|
PrintJSONKeyPairString("skip", "BEFORE");
|
||||||
|
break;
|
||||||
|
case AFTER_SKIP:
|
||||||
|
PrintJSONKeyPairString("skip", "AFTER");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PrintJSONKeyPairDate("until", t->until);
|
||||||
|
if (t->once != NO_ONCE) {
|
||||||
|
PrintJSONKeyPairInt("once", t->once);
|
||||||
|
}
|
||||||
|
if (t->scanfrom != today) {
|
||||||
|
PrintJSONKeyPairDate("scanfrom", t->scanfrom);
|
||||||
|
}
|
||||||
|
PrintJSONKeyPairDate("from", t->from);
|
||||||
|
PrintJSONKeyPairInt("priority", t->priority);
|
||||||
|
PrintJSONKeyPairDateTime("eventstart", t->eventstart);
|
||||||
|
if (t->eventduration != NO_TIME) {
|
||||||
|
PrintJSONKeyPairInt("eventduration", t->eventduration);
|
||||||
|
}
|
||||||
|
if (t->maybe_uncomputable) {
|
||||||
|
PrintJSONKeyPairInt("maybe_uncomputable", 1);
|
||||||
|
}
|
||||||
|
if (t->noqueue) {
|
||||||
|
PrintJSONKeyPairInt("noqueue", 1);
|
||||||
|
}
|
||||||
|
PrintJSONKeyPairString("sched", t->sched);
|
||||||
|
PrintJSONKeyPairString("warn", t->warn);
|
||||||
|
PrintJSONKeyPairString("omitfunc", t->omitfunc);
|
||||||
|
if (t->addomit) {
|
||||||
|
PrintJSONKeyPairInt("addomit", 1);
|
||||||
|
}
|
||||||
|
if (include_tags) {
|
||||||
|
PrintJSONKeyPairString("tags", DBufValue(&(t->tags)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||||
{
|
{
|
||||||
int done = 0;
|
|
||||||
char const *s;
|
char const *s;
|
||||||
if (DoPrefixLineNo) {
|
if (DoPrefixLineNo) {
|
||||||
PrintJSONKeyPairString("filename", e->filename);
|
PrintJSONKeyPairString("filename", e->filename);
|
||||||
@@ -2234,88 +2342,13 @@ static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
|||||||
PrintJSONKeyPairInt("trep", e->tt.rep);
|
PrintJSONKeyPairInt("trep", e->tt.rep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e->trig.eventduration != NO_TIME) {
|
WriteJSONTrigger(&e->trig, 0, today);
|
||||||
PrintJSONKeyPairInt("eventduration", e->trig.eventduration);
|
|
||||||
}
|
|
||||||
/* wd is an array of days from 0=monday to 6=sunday.
|
|
||||||
We convert to array of strings */
|
|
||||||
if (e->trig.wd != NO_WD) {
|
|
||||||
printf("\"wd\":[");
|
|
||||||
done = 0;
|
|
||||||
int i;
|
|
||||||
for (i=0; i<7; i++) {
|
|
||||||
if (e->trig.wd & (1 << i)) {
|
|
||||||
if (done) {
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
done = 1;
|
|
||||||
printf("\"%s\"", EnglishDayName[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("],");
|
|
||||||
}
|
|
||||||
if (e->trig.d != NO_DAY) {
|
|
||||||
PrintJSONKeyPairInt("d", e->trig.d);
|
|
||||||
}
|
|
||||||
if (e->trig.m != NO_MON) {
|
|
||||||
PrintJSONKeyPairInt("m", e->trig.m+1);
|
|
||||||
}
|
|
||||||
if (e->trig.y != NO_YR) {
|
|
||||||
PrintJSONKeyPairInt("y", e->trig.y);
|
|
||||||
}
|
|
||||||
PrintJSONKeyPairDateTime("eventstart", e->trig.eventstart);
|
|
||||||
if (e->trig.back) {
|
|
||||||
PrintJSONKeyPairInt("back", e->trig.back);
|
|
||||||
}
|
|
||||||
if (e->trig.delta) {
|
|
||||||
PrintJSONKeyPairInt("delta", e->trig.delta);
|
|
||||||
}
|
|
||||||
if (e->trig.rep) {
|
|
||||||
PrintJSONKeyPairInt("rep", e->trig.rep);
|
|
||||||
}
|
|
||||||
if (e->nonconst_expr) {
|
if (e->nonconst_expr) {
|
||||||
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
|
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
|
||||||
}
|
}
|
||||||
if (e->if_depth) {
|
if (e->if_depth) {
|
||||||
PrintJSONKeyPairInt("if_depth", e->if_depth);
|
PrintJSONKeyPairInt("if_depth", e->if_depth);
|
||||||
}
|
}
|
||||||
switch(e->trig.skip) {
|
|
||||||
case SKIP_SKIP:
|
|
||||||
PrintJSONKeyPairString("skip", "SKIP");
|
|
||||||
break;
|
|
||||||
case BEFORE_SKIP:
|
|
||||||
PrintJSONKeyPairString("skip", "BEFORE");
|
|
||||||
break;
|
|
||||||
case AFTER_SKIP:
|
|
||||||
PrintJSONKeyPairString("skip", "AFTER");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Local omit is an array of days from 0=monday to 6=sunday.
|
|
||||||
We convert to array of strings */
|
|
||||||
if (e->trig.localomit != NO_WD) {
|
|
||||||
printf("\"localomit\":[");
|
|
||||||
done = 0;
|
|
||||||
int i;
|
|
||||||
for (i=0; i<7; i++) {
|
|
||||||
if (e->trig.localomit & (1 << i)) {
|
|
||||||
if (done) {
|
|
||||||
printf(",");
|
|
||||||
}
|
|
||||||
done = 1;
|
|
||||||
printf("\"%s\"", EnglishDayName[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("],");
|
|
||||||
}
|
|
||||||
PrintJSONKeyPairDate("until", e->trig.until);
|
|
||||||
if (e->trig.once != NO_ONCE) {
|
|
||||||
PrintJSONKeyPairInt("once", e->trig.once);
|
|
||||||
}
|
|
||||||
if (e->trig.scanfrom != today) {
|
|
||||||
PrintJSONKeyPairDate("scanfrom", e->trig.scanfrom);
|
|
||||||
}
|
|
||||||
PrintJSONKeyPairDate("from", e->trig.from);
|
|
||||||
PrintJSONKeyPairInt("priority", e->trig.priority);
|
|
||||||
|
|
||||||
if (e->is_color) {
|
if (e->is_color) {
|
||||||
PrintJSONKeyPairInt("r", e->r);
|
PrintJSONKeyPairInt("r", e->r);
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
/* Define if you have the <sys/types.h> header file. */
|
/* Define if you have the <sys/types.h> header file. */
|
||||||
#undef HAVE_SYS_TYPES_H
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define if you have the <sys/inotify.h> header file. */
|
||||||
|
#undef HAVE_SYS_INOTIFY_H
|
||||||
|
|
||||||
/* Define if you have the <glob.h> header file */
|
/* Define if you have the <glob.h> header file */
|
||||||
#undef HAVE_GLOB_H
|
#undef HAVE_GLOB_H
|
||||||
|
|
||||||
@@ -17,6 +20,8 @@
|
|||||||
|
|
||||||
#undef HAVE_LOCALE_H
|
#undef HAVE_LOCALE_H
|
||||||
|
|
||||||
|
#undef HAVE_INOTIFY_INIT1
|
||||||
|
|
||||||
#undef HAVE_LANGINFO_H
|
#undef HAVE_LANGINFO_H
|
||||||
|
|
||||||
#undef HAVE_GLOB
|
#undef HAVE_GLOB
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* which you can customize. */
|
/* which you can customize. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define VAL_STACK_SIZE 1000
|
#define VAL_STACK_SIZE 100
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
#define VAL_STACK_SIZE 1000
|
#define VAL_STACK_SIZE 100
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
|
||||||
|
|||||||
52
src/dorem.c
52
src/dorem.c
@@ -7,7 +7,7 @@
|
|||||||
/* commands. */
|
/* commands. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -192,7 +192,7 @@ int DoRem(ParsePtr p)
|
|||||||
|
|
||||||
r = OK;
|
r = OK;
|
||||||
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||||
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0)) ) {
|
if ( (r=TriggerReminder(p, &trig, &tim, dse, 0, NULL)) ) {
|
||||||
FreeTrig(&trig);
|
FreeTrig(&trig);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -679,6 +679,9 @@ static int ParseLocalOmit(ParsePtr s, Trigger *t)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (t->localomit == NO_WD) {
|
||||||
|
return E_EXPECTING_WEEKDAY;
|
||||||
|
}
|
||||||
PushToken(DBufValue(&buf), s);
|
PushToken(DBufValue(&buf), s);
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
return OK;
|
return OK;
|
||||||
@@ -910,7 +913,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
|||||||
/* Trigger the reminder if it's a RUN or MSG type. */
|
/* Trigger the reminder if it's a RUN or MSG type. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued)
|
int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
int r, y, m, d;
|
int r, y, m, d;
|
||||||
char PrioExpr[VAR_NAME_LEN+25];
|
char PrioExpr[VAR_NAME_LEN+25];
|
||||||
@@ -977,7 +980,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
}
|
}
|
||||||
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
|
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
|
||||||
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
|
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
|
||||||
&& !DidMsgReminder && !NextMode && !msg_command) {
|
&& !DidMsgReminder && !NextMode && !msg_command && !is_queued) {
|
||||||
DidMsgReminder = 1;
|
DidMsgReminder = 1;
|
||||||
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
if (!DoSubstFromString(DBufValue(&Banner), &buf,
|
||||||
DSEToday, NO_TIME) &&
|
DSEToday, NO_TIME) &&
|
||||||
@@ -1044,11 +1047,18 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s%s%s\n", DBufValue(&calRow), DBufValue(&pre_buf), DBufValue(&buf));
|
r = OK;
|
||||||
|
if (output) {
|
||||||
|
if (DBufPuts(output, DBufValue(&calRow)) != OK) r = E_NO_MEM;
|
||||||
|
if (DBufPuts(output, DBufValue(&pre_buf)) != OK) r = E_NO_MEM;
|
||||||
|
if (DBufPuts(output, DBufValue(&buf)) != OK) r = E_NO_MEM;
|
||||||
|
} else {
|
||||||
|
printf("%s%s%s\n", DBufValue(&calRow), DBufValue(&pre_buf), DBufValue(&buf));
|
||||||
|
}
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
DBufFree(&pre_buf);
|
DBufFree(&pre_buf);
|
||||||
DBufFree(&calRow);
|
DBufFree(&calRow);
|
||||||
return OK;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Correct colors */
|
/* Correct colors */
|
||||||
@@ -1144,18 +1154,27 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queue
|
|||||||
case MSG_TYPE:
|
case MSG_TYPE:
|
||||||
case PASSTHRU_TYPE:
|
case PASSTHRU_TYPE:
|
||||||
if (msg_command) {
|
if (msg_command) {
|
||||||
DoMsgCommand(msg_command, DBufValue(&buf));
|
DoMsgCommand(msg_command, DBufValue(&buf), is_queued);
|
||||||
} else {
|
} else {
|
||||||
printf("%s", DBufValue(&buf));
|
if (output) {
|
||||||
|
DBufPuts(output, DBufValue(&buf));
|
||||||
|
} else {
|
||||||
|
/* Add a space before "NOTE endreminder" */
|
||||||
|
if (IsServerMode() && !strncmp(DBufValue(&buf), "NOTE endreminder", 16)) {
|
||||||
|
printf(" %s", DBufValue(&buf));
|
||||||
|
} else {
|
||||||
|
printf("%s", DBufValue(&buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSF_TYPE:
|
case MSF_TYPE:
|
||||||
FillParagraph(DBufValue(&buf));
|
FillParagraph(DBufValue(&buf), output);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
System(DBufValue(&buf));
|
System(DBufValue(&buf), is_queued);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* Unknown/illegal type? */
|
default: /* Unknown/illegal type? */
|
||||||
@@ -1194,7 +1213,7 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
|||||||
if (DontIssueAts > 1) {
|
if (DontIssueAts > 1) {
|
||||||
/* If two or more -a options, then *DO* issue ats that are in the
|
/* If two or more -a options, then *DO* issue ats that are in the
|
||||||
future */
|
future */
|
||||||
if (tim->ttime < SystemTime(0) / 60) {
|
if (tim->ttime < MinutesPastMidnight(0)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1202,13 +1221,6 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int dse, int *err)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't trigger "old" timed reminders */
|
|
||||||
/*** REMOVED...
|
|
||||||
if (dse == DSEToday &&
|
|
||||||
tim->ttime != NO_TIME &&
|
|
||||||
tim->ttime < SystemTime(0) / 60) return 0;
|
|
||||||
*** ...UNTIL HERE */
|
|
||||||
|
|
||||||
/* If "infinite delta" option is chosen, always trigger future reminders */
|
/* If "infinite delta" option is chosen, always trigger future reminders */
|
||||||
if (InfiniteDelta || NextMode) return 1;
|
if (InfiniteDelta || NextMode) return 1;
|
||||||
|
|
||||||
@@ -1389,7 +1401,7 @@ static int ParsePriority(ParsePtr s, Trigger *t)
|
|||||||
/* Execute the '-k' command, escaping shell chars in message. */
|
/* Execute the '-k' command, escaping shell chars in message. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int DoMsgCommand(char const *cmd, char const *msg)
|
int DoMsgCommand(char const *cmd, char const *msg, int is_queued)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
int i, l;
|
int i, l;
|
||||||
@@ -1426,7 +1438,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
|
|||||||
}
|
}
|
||||||
r = OK;
|
r = OK;
|
||||||
|
|
||||||
System(DBufValue(&execBuffer));
|
System(DBufValue(&execBuffer), is_queued);
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
DBufFree(&buf);
|
DBufFree(&buf);
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -46,11 +46,11 @@
|
|||||||
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
|
int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode)
|
||||||
{
|
{
|
||||||
int diff = dse - DSEToday;
|
int diff = dse - DSEToday;
|
||||||
int curtime = SystemTime(0) / 60;
|
int curtime = MinutesPastMidnight(0);
|
||||||
int err, done;
|
int err, done;
|
||||||
int c;
|
int c;
|
||||||
int d, m, y;
|
int d, m, y;
|
||||||
int tim = tt->ttime;
|
int tim = NO_TIME;
|
||||||
int h, min, hh, ch, cmin, chh;
|
int h, min, hh, ch, cmin, chh;
|
||||||
int i;
|
int i;
|
||||||
char const *pm, *cpm;
|
char const *pm, *cpm;
|
||||||
@@ -72,6 +72,9 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse,
|
|||||||
|
|
||||||
FromDSE(dse, &y, &m, &d);
|
FromDSE(dse, &y, &m, &d);
|
||||||
|
|
||||||
|
if (tt) {
|
||||||
|
tim = tt->ttime;
|
||||||
|
}
|
||||||
if (tim == NO_TIME) tim = curtime;
|
if (tim == NO_TIME) tim = curtime;
|
||||||
tdiff = tim - curtime;
|
tdiff = tim - curtime;
|
||||||
adiff = ABS(tdiff);
|
adiff = ABS(tdiff);
|
||||||
@@ -894,7 +897,7 @@ int DoSubstFromString(char const *source, DynamicBuffer *dbuf,
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (dse == NO_DATE) dse=DSEToday;
|
if (dse == NO_DATE) dse=DSEToday;
|
||||||
if (tim == NO_TIME) tim=SystemTime(0)/60;
|
if (tim == NO_TIME) tim=MinutesPastMidnight(0);
|
||||||
CreateParser(source, &tempP);
|
CreateParser(source, &tempP);
|
||||||
tempP.allownested = 0;
|
tempP.allownested = 0;
|
||||||
tempTrig.typ = MSG_TYPE;
|
tempTrig.typ = MSG_TYPE;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* buffers. */
|
/* buffers. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
17
src/err.h
17
src/err.h
@@ -5,7 +5,7 @@
|
|||||||
/* Error definitions. */
|
/* Error definitions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -121,6 +121,8 @@
|
|||||||
#define E_STRING_TOO_LONG 101
|
#define E_STRING_TOO_LONG 101
|
||||||
#define E_TIME_TWICE 102
|
#define E_TIME_TWICE 102
|
||||||
#define E_DURATION_NO_AT 103
|
#define E_DURATION_NO_AT 103
|
||||||
|
#define E_EXPECTING_WEEKDAY 104
|
||||||
|
|
||||||
#ifdef MK_GLOBALS
|
#ifdef MK_GLOBALS
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#define EXTERN
|
#define EXTERN
|
||||||
@@ -129,6 +131,10 @@
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define STR(X) STR2(X)
|
||||||
|
#define STR2(X) #X
|
||||||
|
|
||||||
|
|
||||||
#ifndef L_ERR_OVERRIDE
|
#ifndef L_ERR_OVERRIDE
|
||||||
EXTERN char *ErrMsg[]
|
EXTERN char *ErrMsg[]
|
||||||
|
|
||||||
@@ -165,7 +171,7 @@ EXTERN char *ErrMsg[]
|
|||||||
"Number too high",
|
"Number too high",
|
||||||
"Number too low",
|
"Number too low",
|
||||||
"Can't open file",
|
"Can't open file",
|
||||||
"INCLUDE nested too deeply",
|
"INCLUDE nested too deeply (max. " STR(INCLUDE_NEST) ")",
|
||||||
"Parse error",
|
"Parse error",
|
||||||
"Can't compute trigger",
|
"Can't compute trigger",
|
||||||
"Too many nested IFs",
|
"Too many nested IFs",
|
||||||
@@ -189,8 +195,8 @@ EXTERN char *ErrMsg[]
|
|||||||
"Day specified twice",
|
"Day specified twice",
|
||||||
"Unknown token",
|
"Unknown token",
|
||||||
"Must specify month in OMIT command",
|
"Must specify month in OMIT command",
|
||||||
"Too many partial OMITs",
|
"Too many partial OMITs (max. " STR(MAX_PARTIAL_OMITS) ")",
|
||||||
"Too many full OMITs",
|
"Too many full OMITs (max. " STR(MAX_FULL_OMITS) ")",
|
||||||
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
|
||||||
"Error reading",
|
"Error reading",
|
||||||
"Expecting end-of-line",
|
"Expecting end-of-line",
|
||||||
@@ -237,7 +243,8 @@ EXTERN char *ErrMsg[]
|
|||||||
"No files matching *.rem",
|
"No files matching *.rem",
|
||||||
"String too long",
|
"String too long",
|
||||||
"Time specified twice",
|
"Time specified twice",
|
||||||
"Cannot specify DURATION without specifying AT"
|
"Cannot specify DURATION without specifying AT",
|
||||||
|
"Expecting weekday name"
|
||||||
}
|
}
|
||||||
#endif /* MK_GLOBALS */
|
#endif /* MK_GLOBALS */
|
||||||
;
|
;
|
||||||
|
|||||||
75
src/expr.c
75
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-2023 by Dianne Skoll */
|
/* Copyright 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -87,10 +87,11 @@ extern BuiltinFunc Func[];
|
|||||||
|
|
||||||
static Operator OpStack[OP_STACK_SIZE];
|
static Operator OpStack[OP_STACK_SIZE];
|
||||||
static int OpStackPtr = 0;
|
static int OpStackPtr = 0;
|
||||||
|
static int OpStackHiWater = 0;
|
||||||
/* ValStack can't be static - needed by funcs.c */
|
/* ValStack can't be static - needed by funcs.c */
|
||||||
Value ValStack[VAL_STACK_SIZE];
|
Value ValStack[VAL_STACK_SIZE];
|
||||||
int ValStackPtr = 0;
|
int ValStackPtr = 0;
|
||||||
|
int ValStackHiWater = 0;
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -944,7 +945,8 @@ static int Subtract(void)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int Multiply(void)
|
static int Multiply(void)
|
||||||
{
|
{
|
||||||
Value v1, v2;
|
Value v1, v2, v3;
|
||||||
|
char *ptr;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
PopValStack(v2);
|
PopValStack(v2);
|
||||||
@@ -964,6 +966,61 @@ static int Multiply(void)
|
|||||||
PushValStack(v1);
|
PushValStack(v1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* String times int means repeat the string that many times */
|
||||||
|
if ((v1.type == INT_TYPE && v2.type == STR_TYPE) ||
|
||||||
|
(v1.type == STR_TYPE && v2.type == INT_TYPE)) {
|
||||||
|
int rep = (v1.type == INT_TYPE ? v1.v.val : v2.v.val);
|
||||||
|
char const *str = (v1.type == INT_TYPE ? v2.v.str : v1.v.str);
|
||||||
|
int l;
|
||||||
|
|
||||||
|
/* Can't multiply by a negative number */
|
||||||
|
if (rep < 0) {
|
||||||
|
return E_2LOW;
|
||||||
|
}
|
||||||
|
if (rep == 0 || !str || !*str) {
|
||||||
|
/* Empty string */
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
v3.type = STR_TYPE;
|
||||||
|
v3.v.str = malloc(1);
|
||||||
|
if (!v3.v.str) {
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
*v3.v.str = 0;
|
||||||
|
PushValStack(v3);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the new value */
|
||||||
|
l = (int) strlen(str);
|
||||||
|
if (l * rep < 0) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
if ((unsigned long) l * (unsigned long) rep >= (unsigned long) INT_MAX) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
if (MaxStringLen > 0 && ((unsigned long) l * (unsigned long) rep) > (unsigned long)MaxStringLen) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_STRING_TOO_LONG;
|
||||||
|
}
|
||||||
|
v3.type = STR_TYPE;
|
||||||
|
v3.v.str = malloc(l * rep + 1);
|
||||||
|
if (!v3.v.str) {
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
*v3.v.str = 0;
|
||||||
|
ptr = v3.v.str;
|
||||||
|
for (int i=0; i<rep; i++) {
|
||||||
|
strcat(ptr, str);
|
||||||
|
ptr += l;
|
||||||
|
}
|
||||||
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
|
PushValStack(v3);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
DestroyValue(v1); DestroyValue(v2);
|
DestroyValue(v1); DestroyValue(v2);
|
||||||
return E_BAD_TYPE;
|
return E_BAD_TYPE;
|
||||||
}
|
}
|
||||||
@@ -1429,3 +1486,11 @@ int FnPopValStack(Value *val)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugExitFunc(void)
|
||||||
|
{
|
||||||
|
if (DebugFlag & DB_EXPR_STACKS) {
|
||||||
|
fprintf(stderr, "Operator stack high water: %d\n", OpStackHiWater);
|
||||||
|
fprintf(stderr, " Value stack high water: %d\n", ValStackHiWater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
34
src/expr.h
34
src/expr.h
@@ -5,19 +5,20 @@
|
|||||||
/* Contains a few definitions used by expression evaluator. */
|
/* Contains a few definitions used by expression evaluator. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|
||||||
/* Define the types of values */
|
/* Define the types of values */
|
||||||
#define ERR_TYPE 0
|
#define ERR_TYPE 0
|
||||||
#define INT_TYPE 1
|
#define INT_TYPE 1
|
||||||
#define TIME_TYPE 2
|
#define TIME_TYPE 2
|
||||||
#define DATE_TYPE 3
|
#define DATE_TYPE 3
|
||||||
#define STR_TYPE 4
|
#define STR_TYPE 4
|
||||||
#define DATETIME_TYPE 5
|
#define DATETIME_TYPE 5
|
||||||
#define SPECIAL_TYPE 6 /* Only for system variables */
|
#define SPECIAL_TYPE 6 /* Only for system variables */
|
||||||
|
#define CONST_INT_TYPE 7 /* Only for system variables */
|
||||||
|
|
||||||
/* Define stuff for parsing expressions */
|
/* Define stuff for parsing expressions */
|
||||||
#define BEG_OF_EXPR '['
|
#define BEG_OF_EXPR '['
|
||||||
@@ -32,10 +33,8 @@
|
|||||||
for speed. BEWARE: These macros invoke return if an error happens ! */
|
for speed. BEWARE: These macros invoke return if an error happens ! */
|
||||||
|
|
||||||
#define PushOpStack(op) \
|
#define PushOpStack(op) \
|
||||||
if (OpStackPtr >= OP_STACK_SIZE) \
|
do { if (OpStackPtr >= OP_STACK_SIZE) return E_OP_STK_OVER; \
|
||||||
return E_OP_STK_OVER; \
|
else { OpStack[OpStackPtr++] = (op); if (OpStackPtr > OpStackHiWater) OpStackHiWater = OpStackPtr; } } while(0)
|
||||||
else \
|
|
||||||
OpStack[OpStackPtr++] = (op)
|
|
||||||
|
|
||||||
#define PopOpStack(op) \
|
#define PopOpStack(op) \
|
||||||
if (OpStackPtr <= 0) \
|
if (OpStackPtr <= 0) \
|
||||||
@@ -44,10 +43,13 @@ else \
|
|||||||
(op) = OpStack[--OpStackPtr]
|
(op) = OpStack[--OpStackPtr]
|
||||||
|
|
||||||
#define PushValStack(val) \
|
#define PushValStack(val) \
|
||||||
if (ValStackPtr >= VAL_STACK_SIZE) \
|
do { if (ValStackPtr >= VAL_STACK_SIZE) { \
|
||||||
return E_VA_STK_OVER; \
|
DestroyValue(val); \
|
||||||
else \
|
return E_VA_STK_OVER; \
|
||||||
ValStack[ValStackPtr++] = (val)
|
} else { \
|
||||||
|
ValStack[ValStackPtr++] = (val); \
|
||||||
|
if (ValStackPtr > ValStackHiWater) ValStackHiWater = ValStackPtr; \
|
||||||
|
} } while (0);
|
||||||
|
|
||||||
#define PopValStack(val) \
|
#define PopValStack(val) \
|
||||||
if (ValStackPtr <= 0) \
|
if (ValStackPtr <= 0) \
|
||||||
|
|||||||
24
src/files.c
24
src/files.c
@@ -7,7 +7,7 @@
|
|||||||
/* files. */
|
/* files. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Convenient macros for closing files */
|
/* Convenient macros for closing files */
|
||||||
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
#define FCLOSE(fp) ((((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
#define PCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
#define PCLOSE(fp) ((((fp)!=stdin)) ? (pclose(fp),(fp)=NULL) : ((fp)=NULL))
|
||||||
|
|
||||||
/* Define the structures needed by the file caching system */
|
/* Define the structures needed by the file caching system */
|
||||||
typedef struct cache {
|
typedef struct cache {
|
||||||
@@ -100,6 +100,18 @@ static int CheckSafety (void);
|
|||||||
static int CheckSafetyAux (struct stat *statbuf);
|
static int CheckSafetyAux (struct stat *statbuf);
|
||||||
static int PopFile (void);
|
static int PopFile (void);
|
||||||
static int IncludeCmd(char const *);
|
static int IncludeCmd(char const *);
|
||||||
|
|
||||||
|
void set_cloexec(int fd)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags >= 0) {
|
||||||
|
flags |= FD_CLOEXEC;
|
||||||
|
fcntl(fd, F_SETFD, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void OpenPurgeFile(char const *fname, char const *mode)
|
static void OpenPurgeFile(char const *fname, char const *mode)
|
||||||
{
|
{
|
||||||
DynamicBuffer fname_buf;
|
DynamicBuffer fname_buf;
|
||||||
@@ -123,6 +135,7 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
|||||||
if (!PurgeFP) {
|
if (!PurgeFP) {
|
||||||
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
fprintf(ErrFp, "Cannot open `%s' for writing: %s\n", DBufValue(&fname_buf), strerror(errno));
|
||||||
}
|
}
|
||||||
|
set_cloexec(fileno(PurgeFP));
|
||||||
DBufFree(&fname_buf);
|
DBufFree(&fname_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,6 +340,7 @@ int OpenFile(char const *fname)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
if (fp) set_cloexec(fileno(fp));
|
||||||
if (DebugFlag & DB_TRACE_FILES) {
|
if (DebugFlag & DB_TRACE_FILES) {
|
||||||
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
fprintf(ErrFp, "Reading `%s': Opening file on disk\n", fname);
|
||||||
}
|
}
|
||||||
@@ -346,6 +360,7 @@ int OpenFile(char const *fname)
|
|||||||
if (strcmp(fname, "-")) {
|
if (strcmp(fname, "-")) {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||||
|
set_cloexec(fileno(fp));
|
||||||
if (PurgeMode) OpenPurgeFile(fname, "w");
|
if (PurgeMode) OpenPurgeFile(fname, "w");
|
||||||
} else {
|
} else {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
@@ -542,6 +557,7 @@ static int PopFile(void)
|
|||||||
if (strcmp(i->filename, "-")) {
|
if (strcmp(i->filename, "-")) {
|
||||||
fp = fopen(i->filename, "r");
|
fp = fopen(i->filename, "r");
|
||||||
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
if (!fp || !CheckSafety()) return E_CANT_OPEN;
|
||||||
|
set_cloexec(fileno(fp));
|
||||||
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
if (PurgeMode) OpenPurgeFile(i->filename, "a");
|
||||||
} else {
|
} else {
|
||||||
fp = stdin;
|
fp = stdin;
|
||||||
|
|||||||
53
src/funcs.c
53
src/funcs.c
@@ -6,7 +6,7 @@
|
|||||||
/* expressions. */
|
/* expressions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -195,6 +195,7 @@ static int CacheHebYear, CacheHebMon, CacheHebDay;
|
|||||||
/* We need access to the value stack */
|
/* We need access to the value stack */
|
||||||
extern Value ValStack[];
|
extern Value ValStack[];
|
||||||
extern int ValStackPtr;
|
extern int ValStackPtr;
|
||||||
|
extern int ValStackHiWater;
|
||||||
|
|
||||||
/* Macro for accessing arguments from the value stack - args are numbered
|
/* Macro for accessing arguments from the value stack - args are numbered
|
||||||
from 0 to (Nargs - 1) */
|
from 0 to (Nargs - 1) */
|
||||||
@@ -251,7 +252,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "defined", 1, 1, 0, FDefined },
|
{ "defined", 1, 1, 0, FDefined },
|
||||||
{ "dosubst", 1, 3, 0, FDosubst },
|
{ "dosubst", 1, 3, 0, FDosubst },
|
||||||
{ "dusk", 0, 1, 0, FDusk },
|
{ "dusk", 0, 1, 0, FDusk },
|
||||||
{ "easterdate", 1, 1, 0, FEasterdate },
|
{ "easterdate", 0, 1, 0, FEasterdate },
|
||||||
{ "evaltrig", 1, 2, 0, FEvalTrig },
|
{ "evaltrig", 1, 2, 0, FEvalTrig },
|
||||||
{ "filedate", 1, 1, 0, FFiledate },
|
{ "filedate", 1, 1, 0, FFiledate },
|
||||||
{ "filedatetime", 1, 1, 0, FFiledatetime },
|
{ "filedatetime", 1, 1, 0, FFiledatetime },
|
||||||
@@ -289,7 +290,7 @@ BuiltinFunc Func[] = {
|
|||||||
{ "nonomitted", 2, NO_MAX, 0, FNonomitted },
|
{ "nonomitted", 2, NO_MAX, 0, FNonomitted },
|
||||||
{ "now", 0, 0, 0, FNow },
|
{ "now", 0, 0, 0, FNow },
|
||||||
{ "ord", 1, 1, 1, FOrd },
|
{ "ord", 1, 1, 1, FOrd },
|
||||||
{ "orthodoxeaster",1, 1, 0, FOrthodoxeaster },
|
{ "orthodoxeaster",0, 1, 0, FOrthodoxeaster },
|
||||||
{ "ostype", 0, 0, 1, FOstype },
|
{ "ostype", 0, 0, 1, FOstype },
|
||||||
{ "pad", 3, 4, 1, FPad },
|
{ "pad", 3, 4, 1, FPad },
|
||||||
{ "plural", 1, 3, 1, FPlural },
|
{ "plural", 1, 3, 1, FPlural },
|
||||||
@@ -1421,28 +1422,28 @@ static int FRealtoday(func_info *info)
|
|||||||
static int FNow(func_info *info)
|
static int FNow(func_info *info)
|
||||||
{
|
{
|
||||||
RetVal.type = TIME_TYPE;
|
RetVal.type = TIME_TYPE;
|
||||||
RETVAL = (int) ( SystemTime(0) / 60L );
|
RETVAL = MinutesPastMidnight(0);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FRealnow(func_info *info)
|
static int FRealnow(func_info *info)
|
||||||
{
|
{
|
||||||
RetVal.type = TIME_TYPE;
|
RetVal.type = TIME_TYPE;
|
||||||
RETVAL = (int) ( SystemTime(1) / 60L );
|
RETVAL = MinutesPastMidnight(1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FCurrent(func_info *info)
|
static int FCurrent(func_info *info)
|
||||||
{
|
{
|
||||||
RetVal.type = DATETIME_TYPE;
|
RetVal.type = DATETIME_TYPE;
|
||||||
RETVAL = DSEToday * MINUTES_PER_DAY + (SystemTime(0) / 60);
|
RETVAL = DSEToday * MINUTES_PER_DAY + MinutesPastMidnight(0);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FRealCurrent(func_info *info)
|
static int FRealCurrent(func_info *info)
|
||||||
{
|
{
|
||||||
RetVal.type = DATETIME_TYPE;
|
RetVal.type = DATETIME_TYPE;
|
||||||
RETVAL = RealToday * MINUTES_PER_DAY + (SystemTime(1) / 60);
|
RETVAL = RealToday * MINUTES_PER_DAY + MinutesPastMidnight(1);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2364,13 +2365,17 @@ static int FEasterdate(func_info *info)
|
|||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
int g, c, x, z, e, n;
|
int g, c, x, z, e, n;
|
||||||
if (ARG(0).type == INT_TYPE) {
|
if (Nargs == 0) {
|
||||||
y = ARGV(0);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
if (y < BASE) return E_2LOW;
|
} else {
|
||||||
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
if (ARG(0).type == INT_TYPE) {
|
||||||
} else if (HASDATE(ARG(0))) {
|
y = ARGV(0);
|
||||||
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
if (y < BASE) return E_2LOW;
|
||||||
} else return E_BAD_TYPE;
|
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
||||||
|
} else if (HASDATE(ARG(0))) {
|
||||||
|
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
||||||
|
} else return E_BAD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
g = (y % 19) + 1; /* golden number */
|
g = (y % 19) + 1; /* golden number */
|
||||||
@@ -2409,13 +2414,17 @@ static int FOrthodoxeaster(func_info *info)
|
|||||||
{
|
{
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
int a, b, c, dd, e, f, dse;
|
int a, b, c, dd, e, f, dse;
|
||||||
if (ARG(0).type == INT_TYPE) {
|
if (Nargs == 0) {
|
||||||
y = ARGV(0);
|
FromDSE(DSEToday, &y, &m, &d);
|
||||||
if (y < BASE) return E_2LOW;
|
} else {
|
||||||
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
if (ARG(0).type == INT_TYPE) {
|
||||||
} else if (HASDATE(ARG(0))) {
|
y = ARGV(0);
|
||||||
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
if (y < BASE) return E_2LOW;
|
||||||
} else return E_BAD_TYPE;
|
else if (y > BASE+YR_RANGE) return E_2HIGH;
|
||||||
|
} else if (HASDATE(ARG(0))) {
|
||||||
|
FromDSE(DATEPART(ARG(0)), &y, &m, &d); /* We just want the year */
|
||||||
|
} else return E_BAD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
a = y % 4;
|
a = y % 4;
|
||||||
@@ -2492,7 +2501,7 @@ static int FTimezone(func_info *info)
|
|||||||
|
|
||||||
if (Nargs == 0) {
|
if (Nargs == 0) {
|
||||||
dse = DSEToday;
|
dse = DSEToday;
|
||||||
now = (SystemTime(0) / 60);
|
now = MinutesPastMidnight(0);
|
||||||
} else {
|
} else {
|
||||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||||
dse = DATEPART(ARG(0));
|
dse = DATEPART(ARG(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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ EXTERN FILE *ErrFp;
|
|||||||
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
|
||||||
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
|
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
|
||||||
|
|
||||||
#define DestroyValue(x) (void) (((x).type == STR_TYPE && (x).v.str) ? (free((x).v.str),(x).v.str = NULL,(x).type = ERR_TYPE) : 0)
|
#define DestroyValue(x) do { if ((x).type == STR_TYPE && (x).v.str) { free((x).v.str); (x).v.str = NULL; } (x).type = ERR_TYPE; } while (0)
|
||||||
|
|
||||||
EXTERN int DSEToday;
|
EXTERN int DSEToday;
|
||||||
EXTERN int RealToday;
|
EXTERN int RealToday;
|
||||||
@@ -50,6 +50,7 @@ EXTERN int LineNo;
|
|||||||
EXTERN int FreshLine;
|
EXTERN int FreshLine;
|
||||||
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
EXTERN uid_t TrustedUsers[MAX_TRUSTED_USERS];
|
||||||
|
|
||||||
|
EXTERN INIT( int MaxLateMinutes, 0);
|
||||||
EXTERN INIT( int NumTrustedUsers, 0);
|
EXTERN INIT( int NumTrustedUsers, 0);
|
||||||
EXTERN INIT( char const *MsgCommand, NULL);
|
EXTERN INIT( char const *MsgCommand, NULL);
|
||||||
EXTERN INIT( char const *QueuedMsgCommand, NULL);
|
EXTERN INIT( char const *QueuedMsgCommand, NULL);
|
||||||
@@ -78,7 +79,7 @@ EXTERN INIT( int SortByDate, 0);
|
|||||||
EXTERN INIT( int SortByPrio, 0);
|
EXTERN INIT( int SortByPrio, 0);
|
||||||
EXTERN INIT( int UntimedBeforeTimed, 0);
|
EXTERN INIT( int UntimedBeforeTimed, 0);
|
||||||
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||||
EXTERN INIT( long SysTime, -1L);
|
EXTERN INIT( int SysTime, -1);
|
||||||
EXTERN INIT( int ParseUntriggered, 1);
|
EXTERN INIT( int ParseUntriggered, 1);
|
||||||
|
|
||||||
EXTERN char const *InitialFile;
|
EXTERN char const *InitialFile;
|
||||||
@@ -91,6 +92,7 @@ EXTERN INIT( int DontQueue, 0);
|
|||||||
EXTERN INIT( int NumQueued, 0);
|
EXTERN INIT( int NumQueued, 0);
|
||||||
EXTERN INIT( int DontIssueAts, 0);
|
EXTERN INIT( int DontIssueAts, 0);
|
||||||
EXTERN INIT( int Daemon, 0);
|
EXTERN INIT( int Daemon, 0);
|
||||||
|
EXTERN INIT( int DaemonJSON, 0);
|
||||||
EXTERN INIT( char DateSep, DATESEP);
|
EXTERN INIT( char DateSep, DATESEP);
|
||||||
EXTERN INIT( char TimeSep, TIMESEP);
|
EXTERN INIT( char TimeSep, TIMESEP);
|
||||||
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
||||||
@@ -101,7 +103,7 @@ EXTERN INIT( int SynthesizeTags, 0);
|
|||||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||||
EXTERN INIT( int MaxSatIter, 1000);
|
EXTERN INIT( int MaxSatIter, 1000);
|
||||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||||
EXTERN INIT( char *FileName, NULL);
|
EXTERN INIT( char *FileName, NULL);
|
||||||
EXTERN INIT( int UseStdin, 0);
|
EXTERN INIT( int UseStdin, 0);
|
||||||
EXTERN INIT( int PurgeMode, 0);
|
EXTERN INIT( int PurgeMode, 0);
|
||||||
EXTERN INIT( int PurgeIncludeDepth, 0);
|
EXTERN INIT( int PurgeIncludeDepth, 0);
|
||||||
@@ -156,6 +158,9 @@ EXTERN INIT( char *EndSentIg, "\"')]}>");
|
|||||||
EXTERN DynamicBuffer Banner;
|
EXTERN DynamicBuffer Banner;
|
||||||
EXTERN DynamicBuffer LineBuffer;
|
EXTERN DynamicBuffer LineBuffer;
|
||||||
EXTERN DynamicBuffer ExprBuf;
|
EXTERN DynamicBuffer ExprBuf;
|
||||||
|
|
||||||
|
extern int NumFullOmits, NumPartialOmits;
|
||||||
|
|
||||||
/* List of months */
|
/* List of months */
|
||||||
EXTERN char *EnglishMonthName[]
|
EXTERN char *EnglishMonthName[]
|
||||||
#ifdef MK_GLOBALS
|
#ifdef MK_GLOBALS
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||||
|
|||||||
63
src/init.c
63
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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -78,6 +78,7 @@ static void ProcessLongOption(char const *arg);
|
|||||||
* t = Display trigger dates
|
* t = Display trigger dates
|
||||||
* v = Dump variables at end
|
* v = Dump variables at end
|
||||||
* l = Display entire line in error messages
|
* l = Display entire line in error messages
|
||||||
|
* s = Display expression-parsing stack usage before exit
|
||||||
* -e = Send messages normally sent to stderr to stdout instead
|
* -e = Send messages normally sent to stderr to stdout instead
|
||||||
* -z[n] = Daemon mode waking up every n (def 1) minutes.
|
* -z[n] = Daemon mode waking up every n (def 1) minutes.
|
||||||
* -bn = Time format for cal (0, 1, or 2)
|
* -bn = Time format for cal (0, 1, or 2)
|
||||||
@@ -176,7 +177,6 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
int x;
|
int x;
|
||||||
int dse;
|
int dse;
|
||||||
int ttyfd;
|
int ttyfd;
|
||||||
int r, g, b;
|
|
||||||
|
|
||||||
dse = NO_DATE;
|
dse = NO_DATE;
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
fprintf(stderr, "Invoked with a NULL argv[0]; bailing because that's just plain bizarre.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the command-line options */
|
/* Parse the command-line options */
|
||||||
@@ -426,7 +426,11 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 'z':
|
case 'z':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
DontFork = 1;
|
DontFork = 1;
|
||||||
if (*arg == '0') {
|
if (*arg == 'j' || *arg == 'J') {
|
||||||
|
while (*arg) arg++;
|
||||||
|
Daemon = -1;
|
||||||
|
DaemonJSON = 1;
|
||||||
|
} else if (*arg == '0') {
|
||||||
PARSENUM(Daemon, arg);
|
PARSENUM(Daemon, arg);
|
||||||
if (Daemon == 0) Daemon = -1;
|
if (Daemon == 0) Daemon = -1;
|
||||||
else if (Daemon < 1) Daemon = 1;
|
else if (Daemon < 1) Daemon = 1;
|
||||||
@@ -601,6 +605,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
case 'D':
|
case 'D':
|
||||||
while (*arg) {
|
while (*arg) {
|
||||||
switch(*arg++) {
|
switch(*arg++) {
|
||||||
|
case 's': case 'S': DebugFlag |= DB_EXPR_STACKS; break;
|
||||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||||
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
|
||||||
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
|
||||||
@@ -649,17 +654,6 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_guess_terminal_background) {
|
|
||||||
guess_terminal_background(&r, &g, &b);
|
|
||||||
if (r >= 0 && g >= 0 && b >= 0) {
|
|
||||||
if (r+g+b <= 85*3 && r <= 128 && g <= 128 && b <= 128) {
|
|
||||||
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
|
||||||
} else {
|
|
||||||
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the filename. */
|
/* Get the filename. */
|
||||||
if (!InvokedAsRem) {
|
if (!InvokedAsRem) {
|
||||||
if (i >= argc) {
|
if (i >= argc) {
|
||||||
@@ -765,7 +759,7 @@ void InitRemind(int argc, char const *argv[])
|
|||||||
|
|
||||||
/* Figure out the offset from UTC */
|
/* Figure out the offset from UTC */
|
||||||
if (CalculateUTC)
|
if (CalculateUTC)
|
||||||
(void) CalcMinsFromUTC(DSEToday, SystemTime(0)/60,
|
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||||
&MinsFromUTC, NULL);
|
&MinsFromUTC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,7 +773,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-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -1002,7 +996,7 @@ ProcessLongOption(char const *arg)
|
|||||||
{
|
{
|
||||||
if (!strcmp(arg, "version")) {
|
if (!strcmp(arg, "version")) {
|
||||||
printf("%s\n", VERSION);
|
printf("%s\n", VERSION);
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
fprintf(ErrFp, "%s: Unknown long option --%s\n", ArgV[0], arg);
|
fprintf(ErrFp, "%s: Unknown long option --%s\n", ArgV[0], arg);
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1006,7 @@ guess_terminal_background(int *r, int *g, int *b)
|
|||||||
{
|
{
|
||||||
int ttyfd;
|
int ttyfd;
|
||||||
struct pollfd p;
|
struct pollfd p;
|
||||||
int rr, gg, bb;
|
unsigned int rr, gg, bb;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
@@ -1042,7 +1036,12 @@ guess_terminal_background(int *r, int *g, int *b)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tty_raw(ttyfd);
|
tty_raw(ttyfd);
|
||||||
write(ttyfd, "\033]11;?\033\\", 8);
|
n = write(ttyfd, "\033]11;?\033\\", 8);
|
||||||
|
|
||||||
|
if (n != 8) {
|
||||||
|
/* write failed... WTF? Not much we can do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait up to 0.1s for terminal to respond */
|
/* Wait up to 0.1s for terminal to respond */
|
||||||
p.fd = ttyfd;
|
p.fd = ttyfd;
|
||||||
@@ -1073,9 +1072,9 @@ guess_terminal_background(int *r, int *g, int *b)
|
|||||||
/* Couldn't scan color codes */
|
/* Couldn't scan color codes */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*r = (rr >> 8) & 255;
|
*r = (int) ((rr >> 8) & 255);
|
||||||
*g = (gg >> 8) & 255;
|
*g = (int) ((gg >> 8) & 255);
|
||||||
*b = (bb >> 8) & 255;
|
*b = (int) ((bb >> 8) & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct termios orig_termios;
|
static struct termios orig_termios;
|
||||||
@@ -1110,3 +1109,21 @@ tty_reset(int fd)
|
|||||||
{
|
{
|
||||||
tcsetattr(fd, TCSAFLUSH, &orig_termios);
|
tcsetattr(fd, TCSAFLUSH, &orig_termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GetTerminalBackground(void)
|
||||||
|
{
|
||||||
|
int r, g, b;
|
||||||
|
if (should_guess_terminal_background) {
|
||||||
|
guess_terminal_background(&r, &g, &b);
|
||||||
|
if (r >= 0 && g >= 0 && b >= 0) {
|
||||||
|
if (r+g+b <= 85*3 && r <= 128 && g <= 128 && b <= 128) {
|
||||||
|
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
||||||
|
} else {
|
||||||
|
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
should_guess_terminal_background = 0;
|
||||||
|
}
|
||||||
|
return TerminalBackground;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Header file for language support for various languages. */
|
/* Header file for language support for various languages. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -245,7 +245,8 @@ EXTERN char *ErrMsg[] =
|
|||||||
"No files matching *.rem",
|
"No files matching *.rem",
|
||||||
"String too long",
|
"String too long",
|
||||||
"Time specified twice",
|
"Time specified twice",
|
||||||
"Cannot specify DURATION without specifying AT"
|
"Cannot specify DURATION without specifying AT".
|
||||||
|
"Odotettu viikonpäivän nimi"
|
||||||
};
|
};
|
||||||
#endif /* MK_GLOBALS */
|
#endif /* MK_GLOBALS */
|
||||||
|
|
||||||
@@ -254,7 +255,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-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
@@ -219,7 +219,8 @@ EXTERN char *ErrMsg[] =
|
|||||||
"No files matching *.rem",
|
"No files matching *.rem",
|
||||||
"String too long",
|
"String too long",
|
||||||
"Time specified twice",
|
"Time specified twice",
|
||||||
"Cannot specify DURATION without specifying AT"
|
"Cannot specify DURATION without specifying AT",
|
||||||
|
"Nom du jour de la semaine attendu",
|
||||||
};
|
};
|
||||||
#endif /* MK_GLOBALS */
|
#endif /* MK_GLOBALS */
|
||||||
|
|
||||||
@@ -228,7 +229,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-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Remind is copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Remind is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* Polish. */
|
/* Polish. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -235,7 +235,8 @@ EXTERN char *ErrMsg[] =
|
|||||||
"No files matching *.rem",
|
"No files matching *.rem",
|
||||||
"String too long",
|
"String too long",
|
||||||
"Time specified twice",
|
"Time specified twice",
|
||||||
"Cannot specify DURATION without specifying AT"
|
"Cannot specify DURATION without specifying AT",
|
||||||
|
"Oczekiwana nazwa dnia tygodnia"
|
||||||
};
|
};
|
||||||
#endif /* MK_GLOBALS */
|
#endif /* MK_GLOBALS */
|
||||||
|
|
||||||
@@ -244,7 +245,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-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||||
/* Dianne Skoll. */
|
/* Dianne Skoll. */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
@@ -244,7 +244,8 @@ EXTERN char *ErrMsg[] =
|
|||||||
"No files matching *.rem",
|
"No files matching *.rem",
|
||||||
"String too long",
|
"String too long",
|
||||||
"Time specified twice",
|
"Time specified twice",
|
||||||
"Cannot specify DURATION without specifying AT"
|
"Cannot specify DURATION without specifying AT",
|
||||||
|
"Esperando nome do dia da semana",
|
||||||
};
|
};
|
||||||
#endif /* MK_GLOBALS */
|
#endif /* MK_GLOBALS */
|
||||||
|
|
||||||
@@ -253,7 +254,7 @@ EXTERN char *ErrMsg[] =
|
|||||||
#define L_USAGE_OVERRIDE 1
|
#define L_USAGE_OVERRIDE 1
|
||||||
void Usage(void)
|
void Usage(void)
|
||||||
{
|
{
|
||||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2023 Dianne Skoll\n", VERSION, L_LANGNAME);
|
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2024 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||||
#ifdef BETA
|
#ifdef BETA
|
||||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* */
|
/* */
|
||||||
/* REMIND is Copyright (C) 1992-2023 by Dianne Skoll */
|
/* REMIND is Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
157
src/main.c
157
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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -45,6 +47,9 @@
|
|||||||
|
|
||||||
static void DoReminders(void);
|
static void DoReminders(void);
|
||||||
|
|
||||||
|
/* Macro for simplifying common block so as not to litter code */
|
||||||
|
#define OUTPUT(c) do { if (output) { DBufPutc(output, c); } else { putchar(c); } } while(0)
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/** **/
|
/** **/
|
||||||
@@ -71,6 +76,8 @@ int main(int argc, char *argv[])
|
|||||||
DBufInit(&(LastTrigger.tags));
|
DBufInit(&(LastTrigger.tags));
|
||||||
ClearLastTriggers();
|
ClearLastTriggers();
|
||||||
|
|
||||||
|
atexit(DebugExitFunc);
|
||||||
|
|
||||||
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
||||||
ProduceCalendar();
|
ProduceCalendar();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -181,14 +188,14 @@ static void DoReminders(void)
|
|||||||
|
|
||||||
if (FileAccessDate < 0) {
|
if (FileAccessDate < 0) {
|
||||||
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
|
fprintf(ErrFp, "%s: `%s': %s.\n", ErrMsg[E_CANTACCESS], InitialFile, strerror(errno));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
r=IncludeFile(InitialFile);
|
r=IncludeFile(InitialFile);
|
||||||
if (r) {
|
if (r) {
|
||||||
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING],
|
||||||
InitialFile, ErrMsg[r]);
|
InitialFile, ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
@@ -196,7 +203,7 @@ static void DoReminders(void)
|
|||||||
if (r == E_EOF) return;
|
if (r == E_EOF) return;
|
||||||
if (r) {
|
if (r) {
|
||||||
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
s = FindInitialToken(&tok, CurLine);
|
s = FindInitialToken(&tok, CurLine);
|
||||||
|
|
||||||
@@ -585,8 +592,8 @@ int EvaluateExpr(ParsePtr p, Value *v)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (p->isnested) return E_PARSE_ERR; /* Can't nest expressions */
|
if (p->isnested) return E_PARSE_ERR; /* Can't nest expressions */
|
||||||
while (isempty(*p->pos)) (p->pos)++;
|
|
||||||
if (!p->pos) return E_PARSE_ERR; /* Missing expression */
|
if (!p->pos) return E_PARSE_ERR; /* Missing expression */
|
||||||
|
while (isempty(*p->pos)) (p->pos)++;
|
||||||
if (*p->pos == BEG_OF_EXPR) {
|
if (*p->pos == BEG_OF_EXPR) {
|
||||||
(p->pos)++;
|
(p->pos)++;
|
||||||
bracketed = 1;
|
bracketed = 1;
|
||||||
@@ -747,19 +754,32 @@ int PushToken(char const *tok, ParsePtr p)
|
|||||||
/* Return the system time in seconds past midnight */
|
/* Return the system time in seconds past midnight */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
long SystemTime(int realtime)
|
int SystemTime(int realtime)
|
||||||
{
|
{
|
||||||
time_t tloc;
|
time_t now;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
|
|
||||||
if (!realtime && (SysTime != -1L)) return SysTime;
|
if (!realtime && (SysTime != -1)) return SysTime;
|
||||||
|
|
||||||
(void) time(&tloc);
|
now = time(NULL);
|
||||||
t = localtime(&tloc);
|
t = localtime(&now);
|
||||||
return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L +
|
return t->tm_hour * 3600L + t->tm_min * 60L +
|
||||||
(long) t->tm_sec;
|
t->tm_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* MinutesPastMidnight */
|
||||||
|
/* */
|
||||||
|
/* Return the system time in minutes past midnight */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
int MinutesPastMidnight(int realtime)
|
||||||
|
{
|
||||||
|
return (SystemTime(realtime) / 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* SystemDate */
|
/* SystemDate */
|
||||||
@@ -771,11 +791,11 @@ long SystemTime(int realtime)
|
|||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int SystemDate(int *y, int *m, int *d)
|
int SystemDate(int *y, int *m, int *d)
|
||||||
{
|
{
|
||||||
time_t tloc;
|
time_t now;
|
||||||
struct tm *t;
|
struct tm *t;
|
||||||
|
|
||||||
(void) time(&tloc);
|
now = time(NULL);
|
||||||
t = localtime(&tloc);
|
t = localtime(&now);
|
||||||
|
|
||||||
*d = t->tm_mday;
|
*d = t->tm_mday;
|
||||||
*m = t->tm_mon;
|
*m = t->tm_mon;
|
||||||
@@ -998,6 +1018,12 @@ int DoDebug(ParsePtr p)
|
|||||||
else DebugFlag &= ~DB_ECHO_LINE;
|
else DebugFlag &= ~DB_ECHO_LINE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
if (val) DebugFlag |= DB_EXPR_STACKS;
|
||||||
|
else DebugFlag &= ~DB_EXPR_STACKS;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
if (val) DebugFlag |= DB_PRTEXPR;
|
if (val) DebugFlag |= DB_PRTEXPR;
|
||||||
@@ -1238,19 +1264,19 @@ int CalcMinsFromUTC(int dse, int tim, int *mins, int *isdst)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char const *OutputEscapeSequences(char const *s, int print)
|
static char const *OutputEscapeSequences(char const *s, int print, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
while (*s == 0x1B && *(s+1) == '[') {
|
while (*s == 0x1B && *(s+1) == '[') {
|
||||||
if (print) putchar(*s);
|
if (print) OUTPUT(*s);
|
||||||
s++;
|
s++;
|
||||||
if (print) putchar(*s);
|
if (print) OUTPUT(*s);
|
||||||
s++;
|
s++;
|
||||||
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
||||||
if (print) putchar(*s);
|
if (print) OUTPUT(*s);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
if (*s) {
|
if (*s) {
|
||||||
if (print) putchar(*s);
|
if (print) OUTPUT(*s);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1259,19 +1285,19 @@ static char const *OutputEscapeSequences(char const *s, int print)
|
|||||||
|
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
|
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
|
||||||
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print)
|
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
while (*s == 0x1B && *(s+1) == '[') {
|
while (*s == 0x1B && *(s+1) == '[') {
|
||||||
if (print) PutWideChar(*s);
|
if (print) PutWideChar(*s, output);
|
||||||
s++;
|
s++;
|
||||||
if (print) PutWideChar(*s);
|
if (print) PutWideChar(*s, output);
|
||||||
s++;
|
s++;
|
||||||
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
while (*s && (*s < 0x40 || *s > 0x7E)) {
|
||||||
if (print) PutWideChar(*s);
|
if (print) PutWideChar(*s, output);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
if (*s) {
|
if (*s) {
|
||||||
if (print) PutWideChar(*s);
|
if (print) PutWideChar(*s, output);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1280,7 +1306,7 @@ static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FillParagraphWCAux(wchar_t const *s)
|
FillParagraphWCAux(wchar_t const *s, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
int line = 0;
|
int line = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -1295,7 +1321,7 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
|
|
||||||
/* If it's a carriage return, output it and start new paragraph */
|
/* If it's a carriage return, output it and start new paragraph */
|
||||||
if (*s == '\n') {
|
if (*s == '\n') {
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
s++;
|
s++;
|
||||||
line = 0;
|
line = 0;
|
||||||
while(ISWBLANK(*s)) s++;
|
while(ISWBLANK(*s)) s++;
|
||||||
@@ -1308,7 +1334,7 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
number of spaces */
|
number of spaces */
|
||||||
j = line ? SubsIndent : FirstIndent;
|
j = line ? SubsIndent : FirstIndent;
|
||||||
for (i=0; i<j; i++) {
|
for (i=0; i<j; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the amount of room left on this line */
|
/* Calculate the amount of room left on this line */
|
||||||
@@ -1321,7 +1347,7 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
if (*s == '\n') break;
|
if (*s == '\n') break;
|
||||||
while(1) {
|
while(1) {
|
||||||
t = s;
|
t = s;
|
||||||
s = OutputEscapeSequencesWS(s, 1);
|
s = OutputEscapeSequencesWS(s, 1, output);
|
||||||
if (s == t) break;
|
if (s == t) break;
|
||||||
while(ISWBLANK(*s)) s++;
|
while(ISWBLANK(*s)) s++;
|
||||||
}
|
}
|
||||||
@@ -1329,7 +1355,7 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
len = 0;
|
len = 0;
|
||||||
while(*s && !iswspace(*s)) {
|
while(*s && !iswspace(*s)) {
|
||||||
if (*s == 0x1B && *(s+1) == '[') {
|
if (*s == 0x1B && *(s+1) == '[') {
|
||||||
s = OutputEscapeSequencesWS(s, 0);
|
s = OutputEscapeSequencesWS(s, 0, output);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
len += wcwidth(*s);
|
len += wcwidth(*s);
|
||||||
@@ -1340,17 +1366,17 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
}
|
}
|
||||||
if (!pendspace || len+pendspace <= roomleft) {
|
if (!pendspace || len+pendspace <= roomleft) {
|
||||||
for (i=0; i<pendspace; i++) {
|
for (i=0; i<pendspace; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
while(t < s) {
|
while(t < s) {
|
||||||
PutWideChar(*t);
|
PutWideChar(*t, output);
|
||||||
if (strchr(EndSent, *t)) doublespace = 2;
|
if (strchr(EndSent, *t)) doublespace = 2;
|
||||||
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
||||||
t++;
|
t++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = t;
|
s = t;
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
line++;
|
line++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1361,7 +1387,7 @@ FillParagraphWCAux(wchar_t const *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
FillParagraphWC(char const *s)
|
FillParagraphWC(char const *s, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
@@ -1371,7 +1397,7 @@ FillParagraphWC(char const *s)
|
|||||||
buf = calloc(len+1, sizeof(wchar_t));
|
buf = calloc(len+1, sizeof(wchar_t));
|
||||||
if (!buf) return E_NO_MEM;
|
if (!buf) return E_NO_MEM;
|
||||||
(void) mbstowcs(buf, s, len+1);
|
(void) mbstowcs(buf, s, len+1);
|
||||||
FillParagraphWCAux(buf);
|
FillParagraphWCAux(buf, output);
|
||||||
free(buf);
|
free(buf);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1391,7 +1417,7 @@ FillParagraphWC(char const *s)
|
|||||||
/* A macro safe ONLY if used with arg with no side effects! */
|
/* A macro safe ONLY if used with arg with no side effects! */
|
||||||
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
||||||
|
|
||||||
void FillParagraph(char const *s)
|
void FillParagraph(char const *s, DynamicBuffer *output)
|
||||||
{
|
{
|
||||||
|
|
||||||
int line = 0;
|
int line = 0;
|
||||||
@@ -1409,7 +1435,7 @@ void FillParagraph(char const *s)
|
|||||||
if (!*s) return;
|
if (!*s) return;
|
||||||
|
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
if (FillParagraphWC(s) == OK) {
|
if (FillParagraphWC(s, output) == OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1419,7 +1445,7 @@ void FillParagraph(char const *s)
|
|||||||
|
|
||||||
/* If it's a carriage return, output it and start new paragraph */
|
/* If it's a carriage return, output it and start new paragraph */
|
||||||
if (*s == '\n') {
|
if (*s == '\n') {
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
s++;
|
s++;
|
||||||
line = 0;
|
line = 0;
|
||||||
while(ISBLANK(*s)) s++;
|
while(ISBLANK(*s)) s++;
|
||||||
@@ -1432,7 +1458,7 @@ void FillParagraph(char const *s)
|
|||||||
number of spaces */
|
number of spaces */
|
||||||
j = line ? SubsIndent : FirstIndent;
|
j = line ? SubsIndent : FirstIndent;
|
||||||
for (i=0; i<j; i++) {
|
for (i=0; i<j; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the amount of room left on this line */
|
/* Calculate the amount of room left on this line */
|
||||||
@@ -1445,7 +1471,7 @@ void FillParagraph(char const *s)
|
|||||||
if (*s == '\n') break;
|
if (*s == '\n') break;
|
||||||
while(1) {
|
while(1) {
|
||||||
t = s;
|
t = s;
|
||||||
s = OutputEscapeSequences(s, 1);
|
s = OutputEscapeSequences(s, 1, output);
|
||||||
if (s == t) break;
|
if (s == t) break;
|
||||||
while(ISBLANK(*s)) s++;
|
while(ISBLANK(*s)) s++;
|
||||||
}
|
}
|
||||||
@@ -1453,7 +1479,7 @@ void FillParagraph(char const *s)
|
|||||||
len = 0;
|
len = 0;
|
||||||
while(*s && !isspace(*s)) {
|
while(*s && !isspace(*s)) {
|
||||||
if (*s == 0x1B && *(s+1) == '[') {
|
if (*s == 0x1B && *(s+1) == '[') {
|
||||||
s = OutputEscapeSequences(s, 0);
|
s = OutputEscapeSequences(s, 0, output);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
@@ -1464,17 +1490,17 @@ void FillParagraph(char const *s)
|
|||||||
}
|
}
|
||||||
if (!pendspace || len+pendspace <= roomleft) {
|
if (!pendspace || len+pendspace <= roomleft) {
|
||||||
for (i=0; i<pendspace; i++) {
|
for (i=0; i<pendspace; i++) {
|
||||||
putchar(' ');
|
OUTPUT(' ');
|
||||||
}
|
}
|
||||||
while(t < s) {
|
while(t < s) {
|
||||||
putchar(*t);
|
OUTPUT(*t);
|
||||||
if (strchr(EndSent, *t)) doublespace = 2;
|
if (strchr(EndSent, *t)) doublespace = 2;
|
||||||
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
else if (!strchr(EndSentIg, *t)) doublespace = 1;
|
||||||
t++;
|
t++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = t;
|
s = t;
|
||||||
putchar('\n');
|
OUTPUT('\n');
|
||||||
line++;
|
line++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1638,12 +1664,51 @@ SaveLastTimeTrig(TimeTrig const *t)
|
|||||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrapper to ignore warnings about ignoring return value of system() */
|
/* Wrapper to ignore warnings about ignoring return value of system()
|
||||||
|
Also redirects stdin and stdout to /dev/null for queued reminders */
|
||||||
|
|
||||||
void
|
void
|
||||||
System(char const *cmd)
|
System(char const *cmd, int is_queued)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
pid_t kid;
|
||||||
|
int fd;
|
||||||
|
int status;
|
||||||
|
int do_exit = 0;
|
||||||
|
if (is_queued && IsServerMode()) {
|
||||||
|
do_exit = 1;
|
||||||
|
/* Server mode... redirect stdin and stdout to /dev/null */
|
||||||
|
kid = fork();
|
||||||
|
if (kid == (pid_t) -1) {
|
||||||
|
/* Fork failed... nothing we can do */
|
||||||
|
return;
|
||||||
|
} else if (kid == 0) {
|
||||||
|
/* In the child */
|
||||||
|
(void) close(STDIN_FILENO);
|
||||||
|
(void) close(STDOUT_FILENO);
|
||||||
|
fd = open("/dev/null", O_RDONLY);
|
||||||
|
if (fd >= 0 && fd != STDIN_FILENO) {
|
||||||
|
dup2(fd, STDIN_FILENO);
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
}
|
||||||
|
fd = open("/dev/null", O_WRONLY);
|
||||||
|
if (fd >= 0 && fd != STDOUT_FILENO) {
|
||||||
|
dup2(fd, STDOUT_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* In the parent */
|
||||||
|
while (waitpid(kid, &status, 0) != kid) /* continue */ ;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* This is the child process or original if we never forked */
|
||||||
r = system(cmd);
|
r = system(cmd);
|
||||||
|
if (do_exit) {
|
||||||
|
/* In the child process, so exit! */
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -412,7 +412,7 @@ static double phase(double pdate,
|
|||||||
Day = pdate - epoch; /* Date within epoch */
|
Day = pdate - epoch; /* Date within epoch */
|
||||||
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
|
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
|
||||||
M = fixangle(N + elonge - elongp); /* Convert from perigee
|
M = fixangle(N + elonge - elongp); /* Convert from perigee
|
||||||
co-ordinates to epoch 1980.0 */
|
coordinates to epoch 1980.0 */
|
||||||
Ec = kepler(M, eccent); /* Solve equation of Kepler */
|
Ec = kepler(M, eccent); /* Solve equation of Kepler */
|
||||||
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
|
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
|
||||||
Ec = 2 * todeg(atan(Ec)); /* 1 anomaly */
|
Ec = 2 * todeg(atan(Ec)); /* 1 anomaly */
|
||||||
|
|||||||
11
src/omit.c
11
src/omit.c
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
static int BexistsIntArray (int array[], int num, int key);
|
static int BexistsIntArray (int const array[], int num, int key);
|
||||||
static void InsertIntoSortedArray (int *array, int num, int key);
|
static void InsertIntoSortedArray (int *array, int num, int key);
|
||||||
|
|
||||||
/* Arrays for the global omits */
|
/* Arrays for the global omits */
|
||||||
@@ -32,7 +32,7 @@ static int PartialOmitArray[MAX_PARTIAL_OMITS];
|
|||||||
/* WeekdayOmits is declared in global.h */
|
/* WeekdayOmits is declared in global.h */
|
||||||
|
|
||||||
/* How many of each omit types do we have? */
|
/* How many of each omit types do we have? */
|
||||||
static int NumFullOmits, NumPartialOmits;
|
int NumFullOmits, NumPartialOmits;
|
||||||
|
|
||||||
/* The structure for saving and restoring OMIT contexts */
|
/* The structure for saving and restoring OMIT contexts */
|
||||||
typedef struct omitcontext {
|
typedef struct omitcontext {
|
||||||
@@ -251,7 +251,7 @@ int IsOmitted(int dse, int localomit, char const *omitfunc, int *omit)
|
|||||||
/* element is found, 0 otherwise. */
|
/* element is found, 0 otherwise. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
static int BexistsIntArray(int array[], int num, int key)
|
static int BexistsIntArray(int const array[], int num, int key)
|
||||||
{
|
{
|
||||||
int top=num-1, bot=0, mid;
|
int top=num-1, bot=0, mid;
|
||||||
|
|
||||||
@@ -445,6 +445,9 @@ int DoOmit(ParsePtr p)
|
|||||||
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
|
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
|
||||||
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
|
||||||
NumPartialOmits++;
|
NumPartialOmits++;
|
||||||
|
if (NumPartialOmits == 366) {
|
||||||
|
Wprint("You have OMITted everything! The space-time continuum is at risk.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mc == m[1] && dc == d[1]) {
|
if (mc == m[1] && dc == d[1]) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
27
src/protos.h
27
src/protos.h
@@ -5,7 +5,7 @@
|
|||||||
/* Function Prototypes. */
|
/* Function Prototypes. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -22,6 +22,9 @@
|
|||||||
/* Characters to ignore */
|
/* Characters to ignore */
|
||||||
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
#define isempty(c) (isspace(c) || ((c) == '\\'))
|
||||||
|
|
||||||
|
#define IsServerMode() (Daemon < 0)
|
||||||
|
#define ShouldFork (!DontFork)
|
||||||
|
|
||||||
#include "dynbuf.h"
|
#include "dynbuf.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
@@ -35,7 +38,7 @@ int DoRem (ParsePtr p);
|
|||||||
int DoFlush (ParsePtr p);
|
int DoFlush (ParsePtr p);
|
||||||
void DoExit (ParsePtr p);
|
void DoExit (ParsePtr p);
|
||||||
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
int ParseRem (ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||||
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued);
|
int TriggerReminder (ParsePtr p, Trigger *t, TimeTrig *tim, int dse, int is_queued, DynamicBuffer *output);
|
||||||
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
|
int ShouldTriggerReminder (Trigger *t, TimeTrig *tim, int dse, int *err);
|
||||||
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
|
int DoSubst (ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int dse, int mode);
|
||||||
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
|
int DoSubstFromString (char const *source, DynamicBuffer *dbuf, int dse, int tim);
|
||||||
@@ -71,7 +74,8 @@ void OutputLine (FILE *fp);
|
|||||||
void CreateParser (char const *s, ParsePtr p);
|
void CreateParser (char const *s, ParsePtr p);
|
||||||
void DestroyParser (ParsePtr p);
|
void DestroyParser (ParsePtr p);
|
||||||
int PushToken (char const *tok, ParsePtr p);
|
int PushToken (char const *tok, ParsePtr p);
|
||||||
long SystemTime (int realtime);
|
int SystemTime (int realtime);
|
||||||
|
int MinutesPastMidnight (int realtime);
|
||||||
int SystemDate (int *y, int *m, int *d);
|
int SystemDate (int *y, int *m, int *d);
|
||||||
int DoIf (ParsePtr p);
|
int DoIf (ParsePtr p);
|
||||||
int DoElse (ParsePtr p);
|
int DoElse (ParsePtr p);
|
||||||
@@ -104,7 +108,7 @@ char *StrDup (char const *s);
|
|||||||
int StrCmpi (char const *s1, char const *s2);
|
int StrCmpi (char const *s1, char const *s2);
|
||||||
Var *FindVar (char const *str, int create);
|
Var *FindVar (char const *str, int create);
|
||||||
int DeleteVar (char const *str);
|
int DeleteVar (char const *str);
|
||||||
int SetVar (char const *str, Value *val);
|
int SetVar (char const *str, Value const *val);
|
||||||
int GetVarValue (char const *str, Value *val, Var *locals, ParsePtr p);
|
int GetVarValue (char const *str, Value *val, Var *locals, ParsePtr p);
|
||||||
int DoSet (Parser *p);
|
int DoSet (Parser *p);
|
||||||
int DoUnset (Parser *p);
|
int DoUnset (Parser *p);
|
||||||
@@ -114,7 +118,7 @@ void DestroyVars (int all);
|
|||||||
int PreserveVar (char const *name);
|
int PreserveVar (char const *name);
|
||||||
int DoPreserve (Parser *p);
|
int DoPreserve (Parser *p);
|
||||||
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
||||||
int DoMsgCommand (char const *cmd, char const *msg);
|
int DoMsgCommand (char const *cmd, char const *msg, int is_queued);
|
||||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||||
unsigned int HashVal (char const *str);
|
unsigned int HashVal (char const *str);
|
||||||
int DateOK (int y, int m, int d);
|
int DateOK (int y, int m, int d);
|
||||||
@@ -138,7 +142,7 @@ int GetSysVar (char const *name, Value *val);
|
|||||||
int SetSysVar (char const *name, Value *val);
|
int SetSysVar (char const *name, Value *val);
|
||||||
void DumpSysVarByName (char const *name);
|
void DumpSysVarByName (char const *name);
|
||||||
int CalcMinsFromUTC (int dse, int tim, int *mins, int *isdst);
|
int CalcMinsFromUTC (int dse, int tim, int *mins, int *isdst);
|
||||||
void FillParagraph (char const *s);
|
void FillParagraph (char const *s, DynamicBuffer *output);
|
||||||
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||||
int MoonPhase (int date, int time);
|
int MoonPhase (int date, int time);
|
||||||
@@ -164,23 +168,30 @@ void PrintJSONKeyPairString(char const *name, char const *val);
|
|||||||
void PrintJSONKeyPairDate(char const *name, int dse);
|
void PrintJSONKeyPairDate(char const *name, int dse);
|
||||||
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
void PrintJSONKeyPairDateTime(char const *name, int dt);
|
||||||
void PrintJSONKeyPairTime(char const *name, int t);
|
void PrintJSONKeyPairTime(char const *name, int t);
|
||||||
void System(char const *cmd);
|
void System(char const *cmd, int queued);
|
||||||
int ShellEscape(char const *in, DynamicBuffer *out);
|
int ShellEscape(char const *in, DynamicBuffer *out);
|
||||||
int AddGlobalOmit(int dse);
|
int AddGlobalOmit(int dse);
|
||||||
void set_lat_and_long_from_components(void);
|
void set_lat_and_long_from_components(void);
|
||||||
void set_components_from_lat_and_long(void);
|
void set_components_from_lat_and_long(void);
|
||||||
|
|
||||||
|
void DebugExitFunc(void);
|
||||||
|
|
||||||
|
int GetTerminalBackground(void);
|
||||||
|
|
||||||
char const *get_day_name(int wkday);
|
char const *get_day_name(int wkday);
|
||||||
char const *get_month_name(int mon);
|
char const *get_month_name(int mon);
|
||||||
|
|
||||||
|
void set_cloexec(int fd);
|
||||||
int push_call(char const *filename, char const *func, int lineno);
|
int push_call(char const *filename, char const *func, int lineno);
|
||||||
void clear_callstack(void);
|
void clear_callstack(void);
|
||||||
int print_callstack(FILE *fp);
|
int print_callstack(FILE *fp);
|
||||||
void pop_call(void);
|
void pop_call(void);
|
||||||
void FixSpecialType(Trigger *trig);
|
void FixSpecialType(Trigger *trig);
|
||||||
|
void WriteJSONTrigger(Trigger const *t, int include_tags, int today);
|
||||||
|
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
||||||
#ifdef REM_USE_WCHAR
|
#ifdef REM_USE_WCHAR
|
||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
void PutWideChar(wchar_t const wc);
|
void PutWideChar(wchar_t const wc, DynamicBuffer *output);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
541
src/queue.c
541
src/queue.c
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -24,16 +24,35 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "protos.h"
|
#include "protos.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
|
#undef USE_INOTIFY
|
||||||
|
#if defined(HAVE_SYS_INOTIFY_H) && defined(HAVE_INOTIFY_INIT1)
|
||||||
|
#define USE_INOTIFY 1
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
|
||||||
|
int watch_fd = -1;
|
||||||
|
static void consume_inotify_events(int fd);
|
||||||
|
static int setup_inotify_watch(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* A list of filenames associated with queued reminders */
|
||||||
|
typedef struct queuedfname {
|
||||||
|
struct queuedfname *next;
|
||||||
|
char const *fname;
|
||||||
|
} QueuedFilename;
|
||||||
|
|
||||||
|
|
||||||
/* List structure for holding queued reminders */
|
/* List structure for holding queued reminders */
|
||||||
typedef struct queuedrem {
|
typedef struct queuedrem {
|
||||||
struct queuedrem *next;
|
struct queuedrem *next;
|
||||||
@@ -41,16 +60,18 @@ typedef struct queuedrem {
|
|||||||
int RunDisabled;
|
int RunDisabled;
|
||||||
int ntrig;
|
int ntrig;
|
||||||
char const *text;
|
char const *text;
|
||||||
|
char const *fname;
|
||||||
|
int lineno;
|
||||||
char passthru[PASSTHRU_LEN+1];
|
char passthru[PASSTHRU_LEN+1];
|
||||||
char sched[VAR_NAME_LEN+1];
|
char sched[VAR_NAME_LEN+1];
|
||||||
DynamicBuffer tags;
|
|
||||||
Trigger t;
|
Trigger t;
|
||||||
TimeTrig tt;
|
TimeTrig tt;
|
||||||
} QueuedRem;
|
} QueuedRem;
|
||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
|
|
||||||
static QueuedRem *QueueHead;
|
static QueuedRem *QueueHead = NULL;
|
||||||
|
static QueuedFilename *Files = NULL;
|
||||||
static time_t FileModTime;
|
static time_t FileModTime;
|
||||||
static struct stat StatBuf;
|
static struct stat StatBuf;
|
||||||
|
|
||||||
@@ -61,6 +82,105 @@ static int CalculateNextTimeUsingSched (QueuedRem *q);
|
|||||||
static void DaemonWait (struct timeval *sleep_tv);
|
static void DaemonWait (struct timeval *sleep_tv);
|
||||||
static void reread (void);
|
static void reread (void);
|
||||||
static void PrintQueue(void);
|
static void PrintQueue(void);
|
||||||
|
static char const *QueueFilename(char const *fname);
|
||||||
|
|
||||||
|
static void chomp(DynamicBuffer *buf)
|
||||||
|
{
|
||||||
|
char *s = DBufValue(buf);
|
||||||
|
int l = DBufLen(buf);
|
||||||
|
while (l) {
|
||||||
|
if (s[l-1] == '\n') {
|
||||||
|
s[l-1] = 0;
|
||||||
|
DBufLen(buf)--;
|
||||||
|
l--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *SimpleTimeNoSpace(int tim)
|
||||||
|
{
|
||||||
|
char *s = (char *) SimpleTime(tim);
|
||||||
|
if (s && *s) {
|
||||||
|
size_t l = strlen(s);
|
||||||
|
if (l > 0 && s[l-1] == ' ') {
|
||||||
|
s[l-1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* */
|
||||||
|
/* QueueFilename */
|
||||||
|
/* */
|
||||||
|
/* Add fname to the list of queued filenames if it's not */
|
||||||
|
/* already present. Either way, return a pointer to the */
|
||||||
|
/* filename. Returns NULL if out of memory */
|
||||||
|
/* */
|
||||||
|
/***************************************************************/
|
||||||
|
static QueuedFilename *last_file_found = NULL;
|
||||||
|
static char const *QueueFilename(char const *fname)
|
||||||
|
{
|
||||||
|
QueuedFilename *elem = Files;
|
||||||
|
|
||||||
|
/* Optimization: We are very likely in the same file as
|
||||||
|
before... */
|
||||||
|
if (last_file_found && !strcmp(fname, last_file_found->fname)) {
|
||||||
|
return last_file_found->fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No such luck; search the list */
|
||||||
|
while(elem) {
|
||||||
|
if (!strcmp(elem->fname, fname)) {
|
||||||
|
last_file_found = elem;
|
||||||
|
return elem->fname;
|
||||||
|
}
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
/* Not found... queue it */
|
||||||
|
elem = NEW(QueuedFilename);
|
||||||
|
if (!elem) return NULL;
|
||||||
|
elem->fname = StrDup(fname);
|
||||||
|
if (!elem->fname) {
|
||||||
|
free(elem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
elem->next = Files;
|
||||||
|
Files = elem;
|
||||||
|
last_file_found = elem;
|
||||||
|
return elem->fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_reminder(QueuedRem *qid)
|
||||||
|
{
|
||||||
|
QueuedRem *q = QueueHead;
|
||||||
|
QueuedRem *next;
|
||||||
|
if (!q) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (q == qid) {
|
||||||
|
QueueHead = q->next;
|
||||||
|
if (q->text) free((void *) q->text);
|
||||||
|
free(q);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while(q->next) {
|
||||||
|
next = q->next;
|
||||||
|
if (q->next == qid) {
|
||||||
|
q->next = q->next->next;
|
||||||
|
if (next->text) free((void *) next->text);
|
||||||
|
free(next);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
q = q->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_reminder_ul(unsigned long qid) {
|
||||||
|
del_reminder((QueuedRem *) qid);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
@@ -71,7 +191,7 @@ static void PrintQueue(void);
|
|||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int QueueReminder(ParsePtr p, Trigger *trig,
|
int QueueReminder(ParsePtr p, Trigger *trig,
|
||||||
TimeTrig *tim, char const *sched)
|
TimeTrig *tim, char const *sched)
|
||||||
{
|
{
|
||||||
QueuedRem *qelem;
|
QueuedRem *qelem;
|
||||||
|
|
||||||
@@ -79,7 +199,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
|||||||
trig->noqueue ||
|
trig->noqueue ||
|
||||||
tim->ttime == NO_TIME ||
|
tim->ttime == NO_TIME ||
|
||||||
trig->typ == CAL_TYPE ||
|
trig->typ == CAL_TYPE ||
|
||||||
tim->ttime < SystemTime(0) / 60 ||
|
tim->ttime < MinutesPastMidnight(0) ||
|
||||||
((trig->typ == RUN_TYPE) && RunDisabled)) return OK;
|
((trig->typ == RUN_TYPE) && RunDisabled)) return OK;
|
||||||
|
|
||||||
qelem = NEW(QueuedRem);
|
qelem = NEW(QueuedRem);
|
||||||
@@ -91,25 +211,84 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
|||||||
free(qelem);
|
free(qelem);
|
||||||
return E_NO_MEM;
|
return E_NO_MEM;
|
||||||
}
|
}
|
||||||
|
qelem->fname = QueueFilename(FileName);
|
||||||
|
if (!qelem->fname) {
|
||||||
|
free((void *) qelem->text);
|
||||||
|
free(qelem);
|
||||||
|
return E_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
qelem->lineno = LineNo;
|
||||||
NumQueued++;
|
NumQueued++;
|
||||||
qelem->typ = trig->typ;
|
qelem->typ = trig->typ;
|
||||||
strcpy(qelem->passthru, trig->passthru);
|
strcpy(qelem->passthru, trig->passthru);
|
||||||
qelem->tt = *tim;
|
qelem->tt = *tim;
|
||||||
qelem->t = *trig;
|
qelem->t = *trig;
|
||||||
DBufInit(&(qelem->t.tags));
|
DBufInit(&(qelem->t.tags));
|
||||||
|
DBufPuts(&(qelem->t.tags), DBufValue(&(trig->tags)));
|
||||||
|
if (SynthesizeTags) {
|
||||||
|
AppendTag(&(qelem->t.tags), SynthesizeTag());
|
||||||
|
}
|
||||||
qelem->next = QueueHead;
|
qelem->next = QueueHead;
|
||||||
qelem->RunDisabled = RunDisabled;
|
qelem->RunDisabled = RunDisabled;
|
||||||
qelem->ntrig = 0;
|
qelem->ntrig = 0;
|
||||||
strcpy(qelem->sched, sched);
|
strcpy(qelem->sched, sched);
|
||||||
DBufInit(&(qelem->tags));
|
|
||||||
DBufPuts(&(qelem->tags), DBufValue(&(trig->tags)));
|
|
||||||
if (SynthesizeTags) {
|
|
||||||
AppendTag(&(qelem->tags), SynthesizeTag());
|
|
||||||
}
|
|
||||||
QueueHead = qelem;
|
QueueHead = qelem;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_close(int fd)
|
||||||
|
{
|
||||||
|
int new_fd;
|
||||||
|
/* Don't close descriptors connected to a TTY, except for stdin */
|
||||||
|
if (fd && isatty(fd)) return;
|
||||||
|
|
||||||
|
(void) close(fd);
|
||||||
|
if (fd != STDIN_FILENO) {
|
||||||
|
new_fd = open("/dev/null", O_WRONLY);
|
||||||
|
} else {
|
||||||
|
new_fd = open("/dev/null", O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the open failed... well... not much we can do */
|
||||||
|
if (new_fd < 0) return;
|
||||||
|
|
||||||
|
/* If we got back the same fd as what we just closed, aces! */
|
||||||
|
if (fd == new_fd) return;
|
||||||
|
|
||||||
|
(void) dup2(new_fd, fd);
|
||||||
|
(void) close(new_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SigContHandler(int d)
|
||||||
|
{
|
||||||
|
UNUSED(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_num_queued(void)
|
||||||
|
{
|
||||||
|
int nqueued = 0;
|
||||||
|
QueuedRem *q = QueueHead;
|
||||||
|
while(q) {
|
||||||
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
|
nqueued++;
|
||||||
|
}
|
||||||
|
q = q->next;
|
||||||
|
}
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{");
|
||||||
|
PrintJSONKeyPairString("response", "queued");
|
||||||
|
PrintJSONKeyPairInt("nqueued", nqueued);
|
||||||
|
printf("\"command\":\"STATUS\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE queued %d\n", nqueued);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* HandleQueuedReminders */
|
/* HandleQueuedReminders */
|
||||||
@@ -123,17 +302,20 @@ void HandleQueuedReminders(void)
|
|||||||
int TimeToSleep;
|
int TimeToSleep;
|
||||||
unsigned SleepTime;
|
unsigned SleepTime;
|
||||||
Parser p;
|
Parser p;
|
||||||
Trigger trig;
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timeval sleep_tv;
|
struct timeval sleep_tv;
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
char qid[64];
|
||||||
/* Suppress the BANNER from being issued */
|
|
||||||
DidMsgReminder = 1;
|
|
||||||
|
|
||||||
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
|
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
|
||||||
SortByDate = 0;
|
SortByDate = 0;
|
||||||
|
|
||||||
|
/* Free FileName if necessary */
|
||||||
|
if (FileName) {
|
||||||
|
free(FileName);
|
||||||
|
FileName = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we are not connected to a tty, then we must close the
|
/* If we are not connected to a tty, then we must close the
|
||||||
* standard file descriptors. This is to prevent someone
|
* standard file descriptors. This is to prevent someone
|
||||||
* doing:
|
* doing:
|
||||||
@@ -143,9 +325,10 @@ void HandleQueuedReminders(void)
|
|||||||
* processed correctly are RUN commands, provided they mail
|
* processed correctly are RUN commands, provided they mail
|
||||||
* the result back or use their own resource (as a window).
|
* the result back or use their own resource (as a window).
|
||||||
*/
|
*/
|
||||||
if (!DontFork && (!isatty(1) || !isatty(2))) {
|
if (ShouldFork) {
|
||||||
close(1);
|
maybe_close(STDIN_FILENO);
|
||||||
close(2);
|
maybe_close(STDOUT_FILENO);
|
||||||
|
maybe_close(STDERR_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're a daemon, get the mod time of initial file */
|
/* If we're a daemon, get the mod time of initial file */
|
||||||
@@ -160,17 +343,24 @@ void HandleQueuedReminders(void)
|
|||||||
/* Initialize the queue - initialize all the entries time of issue */
|
/* Initialize the queue - initialize all the entries time of issue */
|
||||||
|
|
||||||
while (q) {
|
while (q) {
|
||||||
q->tt.nexttime = (int) (SystemTime(1)/60 - 1);
|
q->tt.nexttime = MinutesPastMidnight(1) - 1;
|
||||||
q->tt.nexttime = CalculateNextTime(q);
|
q->tt.nexttime = CalculateNextTime(q);
|
||||||
q = q->next;
|
q = q->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DontFork || Daemon) {
|
if (ShouldFork || Daemon) {
|
||||||
sa.sa_handler = SigIntHandler;
|
sa.sa_handler = SigIntHandler;
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
(void) sigaction(SIGINT, &sa, NULL);
|
(void) sigaction(SIGINT, &sa, NULL);
|
||||||
|
sa.sa_handler = SigContHandler;
|
||||||
|
(void) sigaction(SIGCONT, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (IsServerMode()) {
|
||||||
|
watch_fd = setup_inotify_watch();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Sit in a loop, issuing reminders when necessary */
|
/* Sit in a loop, issuing reminders when necessary */
|
||||||
while(1) {
|
while(1) {
|
||||||
q = FindNextReminder();
|
q = FindNextReminder();
|
||||||
@@ -179,7 +369,7 @@ void HandleQueuedReminders(void)
|
|||||||
if (!q && !Daemon) break;
|
if (!q && !Daemon) break;
|
||||||
|
|
||||||
if (Daemon && !q) {
|
if (Daemon && !q) {
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Sleep until midnight */
|
/* Sleep until midnight */
|
||||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -198,7 +388,7 @@ void HandleQueuedReminders(void)
|
|||||||
|
|
||||||
/* Wake up once a minute to recalibrate sleep time in
|
/* Wake up once a minute to recalibrate sleep time in
|
||||||
case of laptop hibernation */
|
case of laptop hibernation */
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Wake up on the next exact minute */
|
/* Wake up on the next exact minute */
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
sleep_tv.tv_sec = 60 - (tv.tv_sec % 60);
|
sleep_tv.tv_sec = 60 - (tv.tv_sec % 60);
|
||||||
@@ -209,6 +399,8 @@ void HandleQueuedReminders(void)
|
|||||||
sleep_tv.tv_usec = 0;
|
sleep_tv.tv_usec = 0;
|
||||||
}
|
}
|
||||||
DaemonWait(&sleep_tv);
|
DaemonWait(&sleep_tv);
|
||||||
|
/* A DEL command might have deleted our queued reminder! */
|
||||||
|
q = FindNextReminder();
|
||||||
} else {
|
} else {
|
||||||
sleep(SleepTime);
|
sleep(SleepTime);
|
||||||
}
|
}
|
||||||
@@ -222,14 +414,14 @@ void HandleQueuedReminders(void)
|
|||||||
if (!Daemon) {
|
if (!Daemon) {
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
if (RealToday != SystemDate(&y, &m, &d)) {
|
if (RealToday != SystemDate(&y, &m, &d)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Daemon > 0 && SleepTime) CheckInitialFile();
|
if (Daemon > 0 && SleepTime) CheckInitialFile();
|
||||||
|
|
||||||
if (Daemon && !q) {
|
if (Daemon && !q) {
|
||||||
if (Daemon < 0) {
|
if (IsServerMode()) {
|
||||||
/* Sleep until midnight */
|
/* Sleep until midnight */
|
||||||
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
TimeToSleep = MINUTES_PER_DAY*60 - SystemTime(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -244,31 +436,55 @@ void HandleQueuedReminders(void)
|
|||||||
/* Do NOT trigger the reminder if tt.nexttime is more than a
|
/* Do NOT trigger the reminder if tt.nexttime is more than a
|
||||||
minute in the past. This can happen if the clock is
|
minute in the past. This can happen if the clock is
|
||||||
changed or a laptop awakes from hibernation.
|
changed or a laptop awakes from hibernation.
|
||||||
However, DO trigger if tt.nexttime == tt.ttime so all
|
However, DO trigger if tt.nexttime == tt.ttime and we're
|
||||||
|
within MaxLateTrigger minutes so all
|
||||||
queued reminders are triggered at least once. */
|
queued reminders are triggered at least once. */
|
||||||
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
if ((SystemTime(1) - (q->tt.nexttime * 60) <= 60) ||
|
||||||
(q->tt.nexttime == q->tt.ttime)) {
|
(q->tt.nexttime == q->tt.ttime &&
|
||||||
|
(MaxLateMinutes == 0 || SystemTime(1) - (q->tt.nexttime * 60) <= 60 * MaxLateMinutes))) {
|
||||||
/* Trigger the reminder */
|
/* Trigger the reminder */
|
||||||
CreateParser(q->text, &p);
|
CreateParser(q->text, &p);
|
||||||
trig.typ = q->typ;
|
|
||||||
strcpy(trig.passthru, q->passthru);
|
|
||||||
RunDisabled = q->RunDisabled;
|
RunDisabled = q->RunDisabled;
|
||||||
if (Daemon < 0) {
|
if (IsServerMode() && q->typ != RUN_TYPE) {
|
||||||
printf("NOTE reminder %s",
|
if (DaemonJSON) {
|
||||||
SimpleTime(q->tt.ttime));
|
printf("{\"response\":\"reminder\",");
|
||||||
printf("%s", SimpleTime(SystemTime(1)/60));
|
snprintf(qid, sizeof(qid), "%lx", (unsigned long) q);
|
||||||
if (!*DBufValue(&q->tags)) {
|
PrintJSONKeyPairString("qid", qid);
|
||||||
printf("*\n");
|
PrintJSONKeyPairString("ttime", SimpleTimeNoSpace(q->tt.ttime));
|
||||||
} else {
|
PrintJSONKeyPairString("now", SimpleTimeNoSpace(MinutesPastMidnight(1)));
|
||||||
printf("%s\n", DBufValue(&(q->tags)));
|
PrintJSONKeyPairString("tags", DBufValue(&q->t.tags));
|
||||||
}
|
} else {
|
||||||
|
printf("NOTE reminder %s",
|
||||||
|
SimpleTime(q->tt.ttime));
|
||||||
|
printf("%s", SimpleTime(MinutesPastMidnight(1)));
|
||||||
|
if (!*DBufValue(&q->t.tags)) {
|
||||||
|
printf("*\n");
|
||||||
|
} else {
|
||||||
|
printf("%s\n", DBufValue(&(q->t.tags)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up global variables so some functions like trigdate()
|
/* Set up global variables so some functions like trigdate()
|
||||||
and trigtime() work correctly */
|
and trigtime() work correctly */
|
||||||
SaveAllTriggerInfo(&(q->t), &(q->tt), DSEToday, q->tt.ttime, 1);
|
SaveAllTriggerInfo(&(q->t), &(q->tt), DSEToday, q->tt.ttime, 1);
|
||||||
(void) TriggerReminder(&p, &trig, &q->tt, DSEToday, 1);
|
FileName = (char *) q->fname;
|
||||||
if (Daemon < 0) {
|
if (DaemonJSON) {
|
||||||
|
DynamicBuffer out;
|
||||||
|
DBufInit(&out);
|
||||||
|
(void) TriggerReminder(&p, &q->t, &q->tt, DSEToday, 1, &out);
|
||||||
|
if (q->typ != RUN_TYPE) {
|
||||||
|
printf("\"body\":\"");
|
||||||
|
chomp(&out);
|
||||||
|
PrintJSONString(DBufValue(&out));
|
||||||
|
printf("\"}\n");
|
||||||
|
}
|
||||||
|
DBufFree(&out);
|
||||||
|
} else {
|
||||||
|
(void) TriggerReminder(&p, &q->t, &q->tt, DSEToday, 1, NULL);
|
||||||
|
}
|
||||||
|
FileName = NULL;
|
||||||
|
if (IsServerMode() && !DaemonJSON && q->typ != RUN_TYPE) {
|
||||||
printf("NOTE endreminder\n");
|
printf("NOTE endreminder\n");
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@@ -277,8 +493,26 @@ void HandleQueuedReminders(void)
|
|||||||
|
|
||||||
/* Calculate the next trigger time */
|
/* Calculate the next trigger time */
|
||||||
q->tt.nexttime = CalculateNextTime(q);
|
q->tt.nexttime = CalculateNextTime(q);
|
||||||
|
|
||||||
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
|
/* If trigger time is way in the past because computer has been
|
||||||
|
suspended or hibernated, remove from queue */
|
||||||
|
if (q->tt.ttime < MinutesPastMidnight(1) - MaxLateMinutes &&
|
||||||
|
q->tt.nexttime < MinutesPastMidnight(1) - MaxLateMinutes) {
|
||||||
|
q->tt.nexttime = NO_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If queued reminder has expired, actually remove it from queue
|
||||||
|
and update status */
|
||||||
|
if (q->tt.nexttime == NO_TIME) {
|
||||||
|
del_reminder(q);
|
||||||
|
if (IsServerMode()) {
|
||||||
|
print_num_queued();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -474,7 +708,11 @@ static void
|
|||||||
json_queue(QueuedRem const *q)
|
json_queue(QueuedRem const *q)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"queue\",\"queue\":");
|
||||||
|
}
|
||||||
printf("[");
|
printf("[");
|
||||||
|
char idbuf[64];
|
||||||
while(q) {
|
while(q) {
|
||||||
if (q->tt.nexttime == NO_TIME) {
|
if (q->tt.nexttime == NO_TIME) {
|
||||||
q = q->next;
|
q = q->next;
|
||||||
@@ -485,6 +723,14 @@ json_queue(QueuedRem const *q)
|
|||||||
}
|
}
|
||||||
done = 1;
|
done = 1;
|
||||||
printf("{");
|
printf("{");
|
||||||
|
WriteJSONTrigger(&(q->t), 1, DSEToday);
|
||||||
|
WriteJSONTimeTrigger(&(q->tt));
|
||||||
|
snprintf(idbuf, sizeof(idbuf), "%lx", (unsigned long) q);
|
||||||
|
PrintJSONKeyPairString("qid", idbuf);
|
||||||
|
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
||||||
|
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
||||||
|
PrintJSONKeyPairString("filename", q->fname);
|
||||||
|
PrintJSONKeyPairInt("lineno", q->lineno);
|
||||||
switch(q->typ) {
|
switch(q->typ) {
|
||||||
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
|
case NO_TYPE: PrintJSONKeyPairString("type", "NO_TYPE"); break;
|
||||||
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
|
case MSG_TYPE: PrintJSONKeyPairString("type", "MSG_TYPE"); break;
|
||||||
@@ -497,26 +743,6 @@ json_queue(QueuedRem const *q)
|
|||||||
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
|
case PASSTHRU_TYPE: PrintJSONKeyPairString("type", "PASSTHRU_TYPE"); break;
|
||||||
default: PrintJSONKeyPairString("type", "?"); break;
|
default: PrintJSONKeyPairString("type", "?"); break;
|
||||||
}
|
}
|
||||||
PrintJSONKeyPairInt("rundisabled", q->RunDisabled);
|
|
||||||
PrintJSONKeyPairInt("ntrig", q->ntrig);
|
|
||||||
PrintJSONKeyPairTime("ttime", q->tt.ttime);
|
|
||||||
PrintJSONKeyPairTime("nextttime", q->tt.nexttime);
|
|
||||||
PrintJSONKeyPairInt("delta", q->tt.delta);
|
|
||||||
if (q->tt.rep != NO_TIME) {
|
|
||||||
PrintJSONKeyPairInt("rep", q->tt.rep);
|
|
||||||
}
|
|
||||||
if (q->tt.duration != NO_TIME) {
|
|
||||||
PrintJSONKeyPairInt("duration", q->tt.duration);
|
|
||||||
}
|
|
||||||
if (q->passthru[0]) {
|
|
||||||
PrintJSONKeyPairString("passthru", q->passthru);
|
|
||||||
}
|
|
||||||
if (q->sched[0]) {
|
|
||||||
PrintJSONKeyPairString("sched", q->sched);
|
|
||||||
}
|
|
||||||
if (DBufLen(&(q->tags))) {
|
|
||||||
PrintJSONKeyPairString("tags", DBufValue(&(q->tags)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Last one is a special case - no trailing comma */
|
/* Last one is a special case - no trailing comma */
|
||||||
printf("\"");
|
printf("\"");
|
||||||
@@ -530,7 +756,12 @@ json_queue(QueuedRem const *q)
|
|||||||
printf("\"}");
|
printf("\"}");
|
||||||
q = q->next;
|
q = q->next;
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]");
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf(",\"command\":\"QUEUE\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -545,15 +776,28 @@ static void DaemonWait(struct timeval *sleep_tv)
|
|||||||
fd_set readSet;
|
fd_set readSet;
|
||||||
int retval;
|
int retval;
|
||||||
int y, m, d;
|
int y, m, d;
|
||||||
|
int max = 1;
|
||||||
char cmdLine[256];
|
char cmdLine[256];
|
||||||
|
|
||||||
FD_ZERO(&readSet);
|
FD_ZERO(&readSet);
|
||||||
FD_SET(0, &readSet);
|
FD_SET(0, &readSet);
|
||||||
retval = select(1, &readSet, NULL, NULL, sleep_tv);
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (watch_fd >= 0) {
|
||||||
|
FD_SET(watch_fd, &readSet);
|
||||||
|
if (watch_fd > max-1)
|
||||||
|
max = watch_fd+1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
retval = select(max, &readSet, NULL, NULL, sleep_tv);
|
||||||
|
|
||||||
/* If date has rolled around, restart */
|
/* If date has rolled around, restart */
|
||||||
if (RealToday != SystemDate(&y, &m, &d)) {
|
if (RealToday != SystemDate(&y, &m, &d)) {
|
||||||
printf("NOTE newdate\nNOTE reread\n");
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"newdate\"}\n{\"response\":\"reread\",\"command\":\"newdate\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE newdate\nNOTE reread\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
reread();
|
reread();
|
||||||
}
|
}
|
||||||
@@ -561,70 +805,108 @@ static void DaemonWait(struct timeval *sleep_tv)
|
|||||||
/* If nothing readable or interrupted system call, return */
|
/* If nothing readable or interrupted system call, return */
|
||||||
if (retval <= 0) return;
|
if (retval <= 0) return;
|
||||||
|
|
||||||
|
/* If inotify watch descriptor is readable, handle it */
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
if (watch_fd >= 0) {
|
||||||
|
if (FD_ISSET(watch_fd, &readSet)) {
|
||||||
|
consume_inotify_events(watch_fd);
|
||||||
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"reread\",\"command\":\"inotify\"}\n");
|
||||||
|
} else {
|
||||||
|
/* In deprecated server mode, we need to spit out
|
||||||
|
a NOTE newdate to force the front-end to redraw
|
||||||
|
the calendar */
|
||||||
|
printf("NOTE newdate\nNOTE reread\n");
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
reread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* If stdin not readable, return */
|
/* If stdin not readable, return */
|
||||||
if (!FD_ISSET(0, &readSet)) return;
|
if (!FD_ISSET(0, &readSet)) return;
|
||||||
|
|
||||||
/* If EOF on stdin, exit */
|
/* If EOF on stdin, exit */
|
||||||
if (feof(stdin)) {
|
if (feof(stdin)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a line from stdin and interpret it */
|
/* Read a line from stdin and interpret it */
|
||||||
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
|
if (!fgets(cmdLine, sizeof(cmdLine), stdin)) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cmdLine, "EXIT\n")) {
|
if (!strcmp(cmdLine, "EXIT\n")) {
|
||||||
exit(0);
|
exit(EXIT_SUCCESS);
|
||||||
} else if (!strcmp(cmdLine, "STATUS\n")) {
|
} else if (!strcmp(cmdLine, "STATUS\n")) {
|
||||||
int nqueued = 0;
|
print_num_queued();
|
||||||
QueuedRem *q = QueueHead;
|
|
||||||
while(q) {
|
|
||||||
if (q->tt.nexttime != NO_TIME) {
|
|
||||||
nqueued++;
|
|
||||||
}
|
|
||||||
q = q->next;
|
|
||||||
}
|
|
||||||
printf("NOTE queued %d\n", nqueued);
|
|
||||||
fflush(stdout);
|
|
||||||
} else if (!strcmp(cmdLine, "QUEUE\n")) {
|
} else if (!strcmp(cmdLine, "QUEUE\n")) {
|
||||||
printf("NOTE queue\n");
|
if (DaemonJSON) {
|
||||||
QueuedRem *q = QueueHead;
|
json_queue(QueueHead);
|
||||||
while (q) {
|
} else {
|
||||||
if (q->tt.nexttime != NO_TIME) {
|
printf("NOTE queue\n");
|
||||||
switch (q->typ) {
|
QueuedRem *q = QueueHead;
|
||||||
case NO_TYPE: printf("NO_TYPE "); break;
|
while (q) {
|
||||||
case MSG_TYPE: printf("MSG_TYPE "); break;
|
if (q->tt.nexttime != NO_TIME) {
|
||||||
case RUN_TYPE: printf("RUN_TYPE "); break;
|
switch (q->typ) {
|
||||||
case CAL_TYPE: printf("CAL_TYPE "); break;
|
case NO_TYPE: printf("NO_TYPE"); break;
|
||||||
case SAT_TYPE: printf("SAT_TYPE "); break;
|
case MSG_TYPE: printf("MSG_TYPE"); break;
|
||||||
case PS_TYPE: printf("PS_TYPE "); break;
|
case RUN_TYPE: printf("RUN_TYPE"); break;
|
||||||
case PSF_TYPE: printf("PSF_TYPE "); break;
|
case CAL_TYPE: printf("CAL_TYPE"); break;
|
||||||
case MSF_TYPE: printf("MSF_TYPE "); break;
|
case SAT_TYPE: printf("SAT_TYPE"); break;
|
||||||
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE "); break;
|
case PS_TYPE: printf("PS_TYPE"); break;
|
||||||
default: printf("? "); break;
|
case PSF_TYPE: printf("PSF_TYPE"); break;
|
||||||
}
|
case MSF_TYPE: printf("MSF_TYPE"); break;
|
||||||
printf("RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
|
case PASSTHRU_TYPE: printf("PASSTHRU_TYPE"); break;
|
||||||
printf("%s %s %s\n",
|
default: printf("?"); break;
|
||||||
(q->passthru[0] ? q->passthru : "*"),
|
}
|
||||||
(q->sched[0] ? q->sched : "*"),
|
printf(" RunDisabled=%d ntrig=%d ttime=%02d:%02d nexttime=%02d:%02d delta=%d rep=%d duration=%d ", q->RunDisabled, q->ntrig, q->tt.ttime/60, q->tt.ttime % 60, q->tt.nexttime / 60, q->tt.nexttime % 60, q->tt.delta, (q->tt.rep != NO_TIME ? q->tt.rep : -1), (q->tt.duration != NO_TIME ? q->tt.duration : -1));
|
||||||
q->text ? q->text : "NULL");
|
printf("%s %s %s\n",
|
||||||
|
(q->passthru[0] ? q->passthru : "*"),
|
||||||
|
(q->sched[0] ? q->sched : "*"),
|
||||||
|
q->text ? q->text : "NULL");
|
||||||
|
}
|
||||||
|
q = q->next;
|
||||||
}
|
}
|
||||||
q = q->next;
|
printf("NOTE endqueue\n");
|
||||||
}
|
}
|
||||||
printf("NOTE endqueue\n");
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
|
} else if (!strcmp(cmdLine, "JSONQUEUE\n")) {
|
||||||
printf("NOTE JSONQUEUE\n");
|
if (!DaemonJSON) {
|
||||||
|
printf("NOTE JSONQUEUE\n");
|
||||||
|
}
|
||||||
json_queue(QueueHead);
|
json_queue(QueueHead);
|
||||||
printf("NOTE ENDJSONQUEUE\n");
|
if (!DaemonJSON) {
|
||||||
|
printf("NOTE ENDJSONQUEUE\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!strcmp(cmdLine, "REREAD\n")) {
|
} else if (!strcmp(cmdLine, "REREAD\n")) {
|
||||||
printf("NOTE reread\n");
|
if (DaemonJSON) {
|
||||||
|
printf("{\"response\":\"reread\",\"command\":\"REREAD\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("NOTE reread\n");
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
reread();
|
reread();
|
||||||
|
} else if (!strncmp(cmdLine, "DEL ", 4)) {
|
||||||
|
unsigned long qid;
|
||||||
|
if (sscanf(cmdLine, "DEL %lx", &qid) == 1) {
|
||||||
|
del_reminder_ul(qid);
|
||||||
|
}
|
||||||
|
print_num_queued();
|
||||||
|
fflush(stdout);
|
||||||
} else {
|
} else {
|
||||||
printf("ERR Invalid daemon command: %s", cmdLine);
|
if (DaemonJSON) {
|
||||||
|
size_t l = strlen(cmdLine);
|
||||||
|
if (l && cmdLine[l-1] == '\n') {
|
||||||
|
cmdLine[l-1] = 0;
|
||||||
|
}
|
||||||
|
printf("{\"response\":\"error\",\"error\":\"Unknown command\",\"command\":\"");
|
||||||
|
PrintJSONString(cmdLine);
|
||||||
|
printf("\"}\n");
|
||||||
|
} else {
|
||||||
|
printf("ERR Invalid daemon command: %s", cmdLine);
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,3 +923,56 @@ static void reread(void)
|
|||||||
execvp(ArgV[0], (char **) ArgV);
|
execvp(ArgV[0], (char **) ArgV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_INOTIFY
|
||||||
|
static void consume_inotify_events(int fd)
|
||||||
|
{
|
||||||
|
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
struct timespec sleeptime;
|
||||||
|
|
||||||
|
int slept = 0;
|
||||||
|
/* Consume all the inotify events */
|
||||||
|
while(1) {
|
||||||
|
n = read(fd, buf, sizeof(buf));
|
||||||
|
if (n > 0) {
|
||||||
|
/* Something new since we slept */
|
||||||
|
slept = 0;
|
||||||
|
}
|
||||||
|
if (n < 0) {
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
if (slept) {
|
||||||
|
/* Nothing new since we slept */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slept = 1;
|
||||||
|
/* HACK: sleep for 0.2 seconds to let multiple events queue up so we
|
||||||
|
only do a single reread */
|
||||||
|
sleeptime.tv_sec = 0;
|
||||||
|
sleeptime.tv_nsec = 200000000;
|
||||||
|
nanosleep(&sleeptime, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_inotify_watch(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* Don't inotify_watch stdin */
|
||||||
|
if (!strcmp(InitialFile, "-")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
if (inotify_add_watch(fd, InitialFile, IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
28
src/rem2ps.c
28
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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -186,19 +186,19 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
val = json_parse(DBufValue(buf), DBufLen(buf));
|
val = json_parse(DBufValue(buf), DBufLen(buf));
|
||||||
if (!val) {
|
if (!val) {
|
||||||
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val->type != json_object) {
|
if (val->type != json_object) {
|
||||||
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
||||||
DBufValue(buf));
|
DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = NEW(CalEntry);
|
c = NEW(CalEntry);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
c->special = SPECIAL_NORMAL;
|
c->special = SPECIAL_NORMAL;
|
||||||
@@ -221,7 +221,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
c->entry = malloc(strlen(s)+1);
|
c->entry = malloc(strlen(s)+1);
|
||||||
if (!c->entry) {
|
if (!c->entry) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strcpy(c->entry, s);
|
strcpy(c->entry, s);
|
||||||
got_body = 1;
|
got_body = 1;
|
||||||
@@ -253,7 +253,7 @@ JSONToCalEntry(DynamicBuffer *buf)
|
|||||||
|
|
||||||
if (!got_body || !got_date) {
|
if (!got_body || !got_date) {
|
||||||
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
|||||||
CalEntry *c = NEW(CalEntry);
|
CalEntry *c = NEW(CalEntry);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
c->next = NULL;
|
c->next = NULL;
|
||||||
c->special = SPECIAL_NORMAL;
|
c->special = SPECIAL_NORMAL;
|
||||||
@@ -296,7 +296,7 @@ TextToCalEntry(DynamicBuffer *buf)
|
|||||||
c->entry = malloc(strlen(startOfBody) + 1);
|
c->entry = malloc(strlen(startOfBody) + 1);
|
||||||
if (!c->entry) {
|
if (!c->entry) {
|
||||||
fprintf(stderr, "malloc failed - aborting.\n");
|
fprintf(stderr, "malloc failed - aborting.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
strcpy(c->entry, startOfBody);
|
strcpy(c->entry, startOfBody);
|
||||||
|
|
||||||
@@ -343,14 +343,14 @@ int main(int argc, char *argv[])
|
|||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
||||||
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
first_line = 0;
|
first_line = 0;
|
||||||
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
||||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2023 by Dianne Skoll\n\n", VERSION);
|
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2024 by Dianne Skoll\n\n", VERSION);
|
||||||
fprintf(stderr, "Generating PostScript calendar\n");
|
fprintf(stderr, "Generating PostScript calendar\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +361,7 @@ int main(int argc, char *argv[])
|
|||||||
if (!validfile) {
|
if (!validfile) {
|
||||||
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
|
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
|
||||||
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
|
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
printf("%%%%Trailer\n");
|
printf("%%%%Trailer\n");
|
||||||
printf("%%%%Pages: %d\n", validfile);
|
printf("%%%%Pages: %d\n", validfile);
|
||||||
@@ -486,7 +486,7 @@ void DoPsCal(void)
|
|||||||
while(1) {
|
while(1) {
|
||||||
if (feof(stdin)) {
|
if (feof(stdin)) {
|
||||||
fprintf(stderr, "Input from REMIND is corrupt!\n");
|
fprintf(stderr, "Input from REMIND is corrupt!\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBufGets(&buf, stdin);
|
DBufGets(&buf, stdin);
|
||||||
@@ -952,7 +952,7 @@ void Init(int argc, char *argv[])
|
|||||||
fprintf(stderr, " WxHin Specify size in inches (W and H are decimal numbers)\n");
|
fprintf(stderr, " WxHin Specify size in inches (W and H are decimal numbers)\n");
|
||||||
fprintf(stderr, " WxHcm Specify size in centimetres (W and H are decimal numbers)\n");
|
fprintf(stderr, " WxHcm Specify size in centimetres (W and H are decimal numbers)\n");
|
||||||
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
|
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1033,7 +1033,7 @@ void Usage(char const *s)
|
|||||||
fprintf(stderr, "-e Make calendar fill entire page\n");
|
fprintf(stderr, "-e Make calendar fill entire page\n");
|
||||||
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
||||||
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Define the PostScript prologue */
|
/* Define the PostScript prologue */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -14,7 +14,7 @@ char *PSProlog1[] =
|
|||||||
{
|
{
|
||||||
"% This file was produced by Remind and Rem2PS, written by",
|
"% This file was produced by Remind and Rem2PS, written by",
|
||||||
"% Dianne Skoll.",
|
"% Dianne Skoll.",
|
||||||
"% Remind and Rem2PS are Copyright 1992-2023 Dianne Skoll.",
|
"% Remind and Rem2PS are Copyright 1992-2024 Dianne Skoll.",
|
||||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -136,7 +136,7 @@ void IssueSortedReminders(void)
|
|||||||
switch(cur->typ) {
|
switch(cur->typ) {
|
||||||
case MSG_TYPE:
|
case MSG_TYPE:
|
||||||
if (MsgCommand && *MsgCommand) {
|
if (MsgCommand && *MsgCommand) {
|
||||||
DoMsgCommand(MsgCommand, cur->text);
|
DoMsgCommand(MsgCommand, cur->text, 0);
|
||||||
} else {
|
} else {
|
||||||
if (cur->trigdate != olddate) {
|
if (cur->trigdate != olddate) {
|
||||||
IssueSortBanner(cur->trigdate);
|
IssueSortBanner(cur->trigdate);
|
||||||
@@ -151,11 +151,11 @@ void IssueSortedReminders(void)
|
|||||||
IssueSortBanner(cur->trigdate);
|
IssueSortBanner(cur->trigdate);
|
||||||
olddate = cur->trigdate;
|
olddate = cur->trigdate;
|
||||||
}
|
}
|
||||||
FillParagraph(cur->text);
|
FillParagraph(cur->text, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RUN_TYPE:
|
case RUN_TYPE:
|
||||||
System(cur->text);
|
System(cur->text, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -72,7 +72,10 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
m++;
|
m++;
|
||||||
if (m == 12) { m = 0; y++; }
|
if (m == 12) { m = 0; y++; }
|
||||||
}
|
}
|
||||||
while (trig->d > DaysInMonth(m, trig->y)) m++;
|
while (trig->d > DaysInMonth(m, y)) {
|
||||||
|
m++;
|
||||||
|
if (m == 12) { m = 0; y++; }
|
||||||
|
}
|
||||||
j = DSE(y, m, trig->d);
|
j = DSE(y, m, trig->d);
|
||||||
return j;
|
return j;
|
||||||
|
|
||||||
@@ -241,6 +244,7 @@ static int NextSimpleTrig(int startdate, Trigger *trig, int *err)
|
|||||||
|
|
||||||
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;
|
||||||
|
/* cppcheck-suppress knownConditionTrueFalse */
|
||||||
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
if (trig->y > y || (trig->y == y && trig->m > m)) {
|
||||||
j = DSE(trig->y, trig->m, 1);
|
j = DSE(trig->y, trig->m, 1);
|
||||||
ADVANCE_TO_WD(j, trig->wd);
|
ADVANCE_TO_WD(j, trig->wd);
|
||||||
@@ -324,8 +328,11 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
start--;
|
start--;
|
||||||
|
if (start < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (iter > MaxSatIter) {
|
if (start < 0 || iter > MaxSatIter) {
|
||||||
/* omitfunc must have returned "true" too often */
|
/* omitfunc must have returned "true" too often */
|
||||||
*err = E_CANT_TRIG;
|
*err = E_CANT_TRIG;
|
||||||
return -2;
|
return -2;
|
||||||
@@ -388,6 +395,10 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
simple--;
|
simple--;
|
||||||
|
if (simple < 0) {
|
||||||
|
*err = E_CANT_TRIG;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (iter > MaxSatIter) {
|
if (iter > MaxSatIter) {
|
||||||
*err = E_CANT_TRIG;
|
*err = E_CANT_TRIG;
|
||||||
|
|||||||
@@ -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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -150,6 +150,7 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
|||||||
#define DB_DUMP_VARS 8
|
#define DB_DUMP_VARS 8
|
||||||
#define DB_ECHO_LINE 16
|
#define DB_ECHO_LINE 16
|
||||||
#define DB_TRACE_FILES 32
|
#define DB_TRACE_FILES 32
|
||||||
|
#define DB_EXPR_STACKS 64
|
||||||
|
|
||||||
/* Enumeration of the tokens */
|
/* Enumeration of the tokens */
|
||||||
enum TokTypes
|
enum TokTypes
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* functions. */
|
/* functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -349,7 +349,9 @@ int CallUserFunc(char const *name, int nargs, ParsePtr p)
|
|||||||
|
|
||||||
/* Skip the opening bracket, if there's one */
|
/* Skip the opening bracket, if there's one */
|
||||||
while (isempty(*s)) s++;
|
while (isempty(*s)) s++;
|
||||||
if (*s == BEG_OF_EXPR) s++;
|
if (*s == BEG_OF_EXPR) {
|
||||||
|
s++;
|
||||||
|
}
|
||||||
push_call(f->filename, f->name, f->lineno);
|
push_call(f->filename, f->name, f->lineno);
|
||||||
h = Evaluate(&s, f->locals, p);
|
h = Evaluate(&s, f->locals, p);
|
||||||
if (h == OK) {
|
if (h == OK) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
/* Useful utility functions. */
|
/* Useful utility functions. */
|
||||||
/* */
|
/* */
|
||||||
/* This file is part of REMIND. */
|
/* This file is part of REMIND. */
|
||||||
/* Copyright (C) 1992-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -36,6 +36,11 @@ char *StrnCpy(char *dest, char const *source, int n)
|
|||||||
{
|
{
|
||||||
char *odest = dest;
|
char *odest = dest;
|
||||||
|
|
||||||
|
if (n <= 0) {
|
||||||
|
*dest = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
while (n-- && (*dest++ = *source++)) ;
|
while (n-- && (*dest++ = *source++)) ;
|
||||||
if (*(dest-1)) *dest = 0;
|
if (*(dest-1)) *dest = 0;
|
||||||
return odest;
|
return odest;
|
||||||
@@ -108,7 +113,7 @@ int DateOK(int y, int m, int d)
|
|||||||
m > 11 ||
|
m > 11 ||
|
||||||
y > BASE + YR_RANGE ||
|
y > BASE + YR_RANGE ||
|
||||||
d > DaysInMonth(m, y) ) return 0;
|
d > DaysInMonth(m, y) ) return 0;
|
||||||
else return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions designed to defeat gcc optimizer */
|
/* Functions designed to defeat gcc optimizer */
|
||||||
|
|||||||
46
src/var.c
46
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-2023 by Dianne Skoll */
|
/* Copyright (C) 1992-2024 by Dianne Skoll */
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
@@ -167,6 +167,13 @@ static int latitude_func(int do_set, Value *val)
|
|||||||
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
return latitude_longitude_func(do_set, val, &Latitude, -90.0, 90.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int terminal_bg_func(int do_set, Value *val)
|
||||||
|
{
|
||||||
|
UNUSED(do_set);
|
||||||
|
val->type = INT_TYPE;
|
||||||
|
val->v.val = GetTerminalBackground();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int trig_date_func(int do_set, Value *val)
|
static int trig_date_func(int do_set, Value *val)
|
||||||
{
|
{
|
||||||
@@ -473,7 +480,7 @@ int DeleteVar(char const *str)
|
|||||||
/* Set the indicate variable to the specified value. */
|
/* Set the indicate variable to the specified value. */
|
||||||
/* */
|
/* */
|
||||||
/***************************************************************/
|
/***************************************************************/
|
||||||
int SetVar(char const *str, Value *val)
|
int SetVar(char const *str, Value const *val)
|
||||||
{
|
{
|
||||||
Var *v = FindVar(str, 1);
|
Var *v = FindVar(str, 1);
|
||||||
|
|
||||||
@@ -525,7 +532,9 @@ int DoSet (Parser *p)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
DynamicBuffer buf;
|
DynamicBuffer buf;
|
||||||
|
DynamicBuffer buf2;
|
||||||
DBufInit(&buf);
|
DBufInit(&buf);
|
||||||
|
DBufInit(&buf2);
|
||||||
|
|
||||||
r = ParseIdentifier(p, &buf);
|
r = ParseIdentifier(p, &buf);
|
||||||
if (r) return r;
|
if (r) return r;
|
||||||
@@ -541,6 +550,13 @@ int DoSet (Parser *p)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = ParseToken(p, &buf2);
|
||||||
|
if (r) return r;
|
||||||
|
if (DBufLen(&buf2)) {
|
||||||
|
DBufFree(&buf2);
|
||||||
|
return E_EXPECTING_EOL;
|
||||||
|
}
|
||||||
|
DBufFree(&buf2);
|
||||||
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
||||||
else r = SetVar(DBufValue(&buf), &v);
|
else r = SetVar(DBufValue(&buf), &v);
|
||||||
if (buf.len > VAR_NAME_LEN) {
|
if (buf.len > VAR_NAME_LEN) {
|
||||||
@@ -762,10 +778,14 @@ typedef struct {
|
|||||||
char modifiable;
|
char modifiable;
|
||||||
int type;
|
int type;
|
||||||
void *value;
|
void *value;
|
||||||
int min;
|
int min; /* Or const-value */
|
||||||
int max;
|
int max;
|
||||||
} SysVar;
|
} SysVar;
|
||||||
|
|
||||||
|
/* Macro to access "min" but as a constval. Just to make source more
|
||||||
|
readable */
|
||||||
|
#define constval min
|
||||||
|
|
||||||
/* If the type of a sys variable is STR_TYPE, then min is redefined
|
/* If the type of a sys variable is STR_TYPE, then min is redefined
|
||||||
to be a flag indicating whether or not the value has been malloc'd. */
|
to be a flag indicating whether or not the value has been malloc'd. */
|
||||||
#define been_malloced min
|
#define been_malloced min
|
||||||
@@ -825,6 +845,9 @@ static SysVar SysVarArr[] = {
|
|||||||
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0 },
|
{"LongMin", 1, SPECIAL_TYPE, longmin_func, 0, 0 },
|
||||||
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
|
{"LongSec", 1, SPECIAL_TYPE, longsec_func, 0, 0 },
|
||||||
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0 },
|
{"March", 1, STR_TYPE, &DynamicMonthName[2], 0, 0 },
|
||||||
|
{"MaxFullOmits", 0, CONST_INT_TYPE, NULL, MAX_FULL_OMITS, 0},
|
||||||
|
{"MaxLateMinutes", 1, INT_TYPE, &MaxLateMinutes, 0, 1440 },
|
||||||
|
{"MaxPartialOmits",0, CONST_INT_TYPE, NULL, MAX_PARTIAL_OMITS, 0},
|
||||||
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
{"MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
|
||||||
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
{"MaxStringLen", 1, INT_TYPE, &MaxStringLen, -1, ANY },
|
||||||
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0 },
|
{"May", 1, STR_TYPE, &DynamicMonthName[4], 0, 0 },
|
||||||
@@ -835,6 +858,8 @@ static SysVar SysVarArr[] = {
|
|||||||
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
{"NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
|
||||||
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0 },
|
{"November", 1, STR_TYPE, &DynamicMonthName[10],0, 0 },
|
||||||
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0 },
|
{"Now", 1, STR_TYPE, &DynamicNow, 0, 0 },
|
||||||
|
{"NumFullOmits", 0, INT_TYPE, &NumFullOmits, 0, 0 },
|
||||||
|
{"NumPartialOmits",0, INT_TYPE, &NumPartialOmits, 0, 0 },
|
||||||
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
{"NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
|
||||||
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
{"NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
|
||||||
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
|
{"October", 1, STR_TYPE, &DynamicMonthName[9], 0, 0 },
|
||||||
@@ -856,7 +881,7 @@ static SysVar SysVarArr[] = {
|
|||||||
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0 },
|
{"SysInclude", 0, STR_TYPE, &SysDir, 0, 0 },
|
||||||
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
|
{"T", 0, SPECIAL_TYPE, trig_date_func, 0, 0 },
|
||||||
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
|
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
|
||||||
{"TerminalBackground", 0, INT_TYPE, &TerminalBackground, 0, 0 },
|
{"TerminalBackground", 0, SPECIAL_TYPE, terminal_bg_func, 0, 0 },
|
||||||
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0 },
|
{"Thursday", 1, STR_TYPE, &DynamicDayName[3], 0, 0 },
|
||||||
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||||
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
|
{"Tm", 0, SPECIAL_TYPE, trig_mon_func, 0, 0 },
|
||||||
@@ -894,13 +919,13 @@ int SetSysVar(char const *name, Value *value)
|
|||||||
int r;
|
int r;
|
||||||
SysVar *v = FindSysVar(name);
|
SysVar *v = FindSysVar(name);
|
||||||
if (!v) return E_NOSUCH_VAR;
|
if (!v) return E_NOSUCH_VAR;
|
||||||
if (v->type != SPECIAL_TYPE &&
|
|
||||||
v->type != value->type) return E_BAD_TYPE;
|
|
||||||
if (!v->modifiable) {
|
if (!v->modifiable) {
|
||||||
Eprint("%s: `$%s'", ErrMsg[E_CANT_MODIFY], name);
|
Eprint("%s: `$%s'", ErrMsg[E_CANT_MODIFY], name);
|
||||||
return E_CANT_MODIFY;
|
return E_CANT_MODIFY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v->type != SPECIAL_TYPE &&
|
||||||
|
v->type != value->type) return E_BAD_TYPE;
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
r = f(1, value);
|
r = f(1, value);
|
||||||
@@ -941,6 +966,11 @@ int GetSysVar(char const *name, Value *val)
|
|||||||
|
|
||||||
val->type = ERR_TYPE;
|
val->type = ERR_TYPE;
|
||||||
if (!v) return E_NOSUCH_VAR;
|
if (!v) return E_NOSUCH_VAR;
|
||||||
|
if (v->type == CONST_INT_TYPE) {
|
||||||
|
val->v.val = v->constval;
|
||||||
|
val->type = INT_TYPE;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
return f(0, val);
|
return f(0, val);
|
||||||
@@ -1034,7 +1064,9 @@ static void DumpSysVar(char const *name, const SysVar *v)
|
|||||||
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
if (name) strcat(buffer, name); else strcat(buffer, v->name);
|
||||||
fprintf(ErrFp, "%16s ", buffer);
|
fprintf(ErrFp, "%16s ", buffer);
|
||||||
if (v) {
|
if (v) {
|
||||||
if (v->type == SPECIAL_TYPE) {
|
if (v->type == CONST_INT_TYPE) {
|
||||||
|
fprintf(ErrFp, "%d\n", v->constval);
|
||||||
|
} else if (v->type == SPECIAL_TYPE) {
|
||||||
SysVarFunc f = (SysVarFunc) v->value;
|
SysVarFunc f = (SysVarFunc) v->value;
|
||||||
f(0, &vtmp);
|
f(0, &vtmp);
|
||||||
PrintValue(&vtmp, ErrFp);
|
PrintValue(&vtmp, ErrFp);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ MSG UseVTColors is: [$UseVTColors]%
|
|||||||
MSG Use256Colors is: [$Use256Colors]%
|
MSG Use256Colors is: [$Use256Colors]%
|
||||||
MSG UseTrueColors is: [$UseTrueColors]%
|
MSG UseTrueColors is: [$UseTrueColors]%
|
||||||
MSG UseBGVTColors is: [$UseBGVTColors]%
|
MSG UseBGVTColors is: [$UseBGVTColors]%
|
||||||
set n ansicolor("")]
|
set n ansicolor("")
|
||||||
MSG This is [ansicolor(0,255,0)]green[n], [ansicolor("255 0 0")]red[n] and [ansicolor("0 0 255")]blue[n] text.%
|
MSG This is [ansicolor(0,255,0)]green[n], [ansicolor("255 0 0")]red[n] and [ansicolor("0 0 255")]blue[n] text.%
|
||||||
MSG This is [ansicolor(0,0,0)][ansicolor(0,255,0,1)]black text on a green background[n]%
|
MSG This is [ansicolor(0,0,0)][ansicolor(0,255,0,1)]black text on a green background[n]%
|
||||||
MSG This is [ansicolor(0,0,0,0,1)]clamped black text[n]%
|
MSG This is [ansicolor(0,0,0,0,1)]clamped black text[n]%
|
||||||
|
|||||||
6
tests/queue1.rem
Normal file
6
tests/queue1.rem
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FSET msgprefix(x) "Priority: " + x + "; Filename: " + filename() + ": "
|
||||||
|
|
||||||
|
REM at 23:56 MSG foo
|
||||||
|
REM PRIORITY 42 at 23:57 MSG bar
|
||||||
|
REM PRIORITY 999 at 23:58 MSQ quux
|
||||||
|
DO queue2.rem
|
||||||
1
tests/queue2.rem
Normal file
1
tests/queue2.rem
Normal file
@@ -0,0 +1 @@
|
|||||||
|
REM at 23:59 PRIORITY 2 MSG XXXX
|
||||||
103
tests/test-rem
103
tests/test-rem
@@ -7,7 +7,7 @@
|
|||||||
# in the build directory.
|
# in the build directory.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2023 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -31,6 +31,15 @@ fi
|
|||||||
TZ=UTC
|
TZ=UTC
|
||||||
export TZ
|
export TZ
|
||||||
|
|
||||||
|
RESULT=`(echo 'BANNER %'; echo 'IF now() > 23:55'; echo 'MSG late%'; echo 'ENDIF') | ../src/remind -h -`
|
||||||
|
|
||||||
|
if test "$RESULT" = "late" ; then
|
||||||
|
echo ""
|
||||||
|
echo "*** Please do not run the test suite between 23:55 and 00:00 UTC; it will fail."
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# If we're already in a utf-8 locale, do
|
# If we're already in a utf-8 locale, do
|
||||||
# nothing; otherwise, set LC_ALL
|
# nothing; otherwise, set LC_ALL
|
||||||
OK=0
|
OK=0
|
||||||
@@ -56,6 +65,8 @@ echo "Test 1" > ../tests/test.out
|
|||||||
echo "" >> ../tests/test.out
|
echo "" >> ../tests/test.out
|
||||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 12:13 >> ../tests/test.out 2>&1
|
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 12:13 >> ../tests/test.out 2>&1
|
||||||
echo "" >> ../tests/test.out
|
echo "" >> ../tests/test.out
|
||||||
|
echo 'set a 1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+2*3))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))' | ../src/remind -ds - 16 feb 1991 12:13 >> ../tests/test.out 2>&1
|
||||||
|
echo "" >> ../tests/test.out
|
||||||
echo "Test 2" >> ../tests/test.out
|
echo "Test 2" >> ../tests/test.out
|
||||||
echo "" >> ../tests/test.out
|
echo "" >> ../tests/test.out
|
||||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||||
@@ -440,6 +451,96 @@ rm -rf include_dir/ww
|
|||||||
# Test --version long option
|
# Test --version long option
|
||||||
../src/remind --version >> ../tests/test.out 2>&1
|
../src/remind --version >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Test queueing. Because eventstart depends on the actual system
|
||||||
|
# date, we have to convert it to some constant (in this case,
|
||||||
|
# VOLATILE) so that tests are not dependent on the system date.
|
||||||
|
echo JSONQUEUE | ../src/remind -z0 ../tests/queue1.rem 2>&1 | sed -e 's/"eventstart":"................"/"eventstart":"VOLATILE"/g' | sed -e 's/"qid":"[0-9a-f]*",//g' >> ../tests/test.out 2>&1
|
||||||
|
echo QUEUE | ../src/remind -zj ../tests/queue1.rem 2>&1 | sed -e 's/"eventstart":"................"/"eventstart":"VOLATILE"/g' | sed -e 's/"qid":"[0-9a-f]*",//g' >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
|
# Test for leap year bug that was fixed
|
||||||
|
../src/remind -dte - 28 Feb 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
BANNER %
|
||||||
|
REM 29 MSG One
|
||||||
|
REM 29 Feb MSG two
|
||||||
|
REM 29 2024 MSG three
|
||||||
|
REM 29 Feb 2024 MSG four
|
||||||
|
REM Thursday 29 MSG One
|
||||||
|
REM Thursday 29 Feb MSG two
|
||||||
|
REM Thursday 29 2024 MSG three
|
||||||
|
REM Thursday 29 Feb 2024 MSG four
|
||||||
|
REM Wednesday 29 MSG One
|
||||||
|
REM Wednesday 29 Feb MSG two
|
||||||
|
REM Wednesday 29 2024 MSG three
|
||||||
|
REM Wednesday 29 Feb 2024 MSG four
|
||||||
|
REM Friday 29 MSG One
|
||||||
|
REM Friday 29 Feb MSG two
|
||||||
|
REM Friday 29 2024 MSG three
|
||||||
|
REM Friday 29 Feb 2024 MSG four
|
||||||
|
EOF
|
||||||
|
|
||||||
|
../src/remind -dte - 1 Mar 2024 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
BANNER %
|
||||||
|
REM 29 MSG One
|
||||||
|
REM 29 Feb MSG two
|
||||||
|
REM 29 2024 MSG three
|
||||||
|
REM 29 Feb 2024 MSG four
|
||||||
|
REM Thursday 29 MSG One
|
||||||
|
REM Thursday 29 Feb MSG two
|
||||||
|
REM Thursday 29 2024 MSG three
|
||||||
|
REM Thursday 29 Feb 2024 MSG four
|
||||||
|
REM Wednesday 29 MSG One
|
||||||
|
REM Wednesday 29 Feb MSG two
|
||||||
|
REM Wednesday 29 2024 MSG three
|
||||||
|
REM Wednesday 29 Feb 2024 MSG four
|
||||||
|
REM Friday 29 MSG One
|
||||||
|
REM Friday 29 Feb MSG two
|
||||||
|
REM Friday 29 2024 MSG three
|
||||||
|
REM Friday 29 Feb 2024 MSG four
|
||||||
|
EOF
|
||||||
|
|
||||||
|
../src/remind -dte - 28 Feb 2025 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
BANNER %
|
||||||
|
REM 29 MSG One
|
||||||
|
REM 29 Feb MSG two
|
||||||
|
REM 29 2025 MSG three
|
||||||
|
REM 29 Feb 2025 MSG four
|
||||||
|
REM Thursday 29 MSG One
|
||||||
|
REM Thursday 29 Feb MSG two
|
||||||
|
REM Thursday 29 2025 MSG three
|
||||||
|
REM Thursday 29 Feb 2025 MSG four
|
||||||
|
REM Wednesday 29 MSG One
|
||||||
|
REM Wednesday 29 Feb MSG two
|
||||||
|
REM Wednesday 29 2025 MSG three
|
||||||
|
REM Wednesday 29 Feb 2025 MSG four
|
||||||
|
REM Friday 29 MSG One
|
||||||
|
REM Friday 29 Feb MSG two
|
||||||
|
REM Friday 29 2025 MSG three
|
||||||
|
REM Friday 29 Feb 2025 MSG four
|
||||||
|
EOF
|
||||||
|
|
||||||
|
../src/remind -dte - 1 Mar 2025 <<'EOF' >> ../tests/test.out 2>&1
|
||||||
|
BANNER %
|
||||||
|
REM 29 MSG One
|
||||||
|
REM 29 Feb MSG two
|
||||||
|
REM 29 2025 MSG three
|
||||||
|
REM 29 Feb 2025 MSG four
|
||||||
|
REM Thursday 29 MSG One
|
||||||
|
REM Thursday 29 Feb MSG two
|
||||||
|
REM Thursday 29 2025 MSG three
|
||||||
|
REM Thursday 29 Feb 2025 MSG four
|
||||||
|
REM Wednesday 29 MSG One
|
||||||
|
REM Wednesday 29 Feb MSG two
|
||||||
|
REM Wednesday 29 2025 MSG three
|
||||||
|
REM Wednesday 29 Feb 2025 MSG four
|
||||||
|
REM Friday 29 MSG One
|
||||||
|
REM Friday 29 Feb MSG two
|
||||||
|
REM Friday 29 2025 MSG three
|
||||||
|
REM Friday 29 Feb 2025 MSG four
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
(echo 'BANNER %'; echo 'REM 29 MSG No bug') | ../src/remind -dt - 29 Feb 2024 >> ../tests/test.out 2>&1
|
||||||
|
|
||||||
# Remove references to SysInclude, which is build-specific
|
# Remove references to SysInclude, which is build-specific
|
||||||
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
|
grep -F -v '$SysInclude' < ../tests/test.out > ../tests/test.out.1 && mv -f ../tests/test.out.1 ../tests/test.out
|
||||||
cmp -s ../tests/test.out ../tests/test.cmp
|
cmp -s ../tests/test.out ../tests/test.cmp
|
||||||
|
|||||||
1382
tests/test.cmp
1382
tests/test.cmp
File diff suppressed because one or more lines are too long
@@ -381,9 +381,11 @@ msg [a076]%
|
|||||||
set a077 dosubst("%*Y %*Z", '1992/5/5')
|
set a077 dosubst("%*Y %*Z", '1992/5/5')
|
||||||
msg [a077]%
|
msg [a077]%
|
||||||
set a078 easterdate(today())
|
set a078 easterdate(today())
|
||||||
|
set a078 easterdate()
|
||||||
set a079 easterdate(1992)
|
set a079 easterdate(1992)
|
||||||
set a080 easterdate(1995)
|
set a080 easterdate(1995)
|
||||||
set a078 orthodoxeaster(today())
|
set a078 orthodoxeaster(today())
|
||||||
|
set a078 orthodoxeaster()
|
||||||
set a079 orthodoxeaster(1992)
|
set a079 orthodoxeaster(1992)
|
||||||
set a080 orthodoxeaster(1995)
|
set a080 orthodoxeaster(1995)
|
||||||
set a080 orthodoxeaster(2023)
|
set a080 orthodoxeaster(2023)
|
||||||
@@ -882,11 +884,38 @@ set a htmlstriptags("this is > whut <b>foo</b>")
|
|||||||
set a htmlstriptags("<img src=\"foo\">")
|
set a htmlstriptags("<img src=\"foo\">")
|
||||||
|
|
||||||
# $ParseUntriggered
|
# $ParseUntriggered
|
||||||
REM 2 Jan 1990 MSG ["bad_expr" * 2]
|
REM 2 Jan 1990 MSG ["bad_expr" / 2]
|
||||||
SET $ParseUntriggered 0
|
SET $ParseUntriggered 0
|
||||||
REM 2 Jan 1990 MSG ["bad_expr" * 2]
|
REM 2 Jan 1990 MSG ["bad_expr" / 2]
|
||||||
SET $ParseUntriggered 1
|
SET $ParseUntriggered 1
|
||||||
|
|
||||||
|
# String multiplication
|
||||||
|
|
||||||
|
set a "low" * (-1)
|
||||||
|
set a (-1) * "low"
|
||||||
|
|
||||||
|
set a "zero" * 0
|
||||||
|
set a 0 * "zero"
|
||||||
|
|
||||||
|
set a "" * 10000000
|
||||||
|
set a 10000000 * ""
|
||||||
|
|
||||||
|
# Too long for default limits
|
||||||
|
set a "wookie" * 1000000
|
||||||
|
set a 1000000 * "wookie"
|
||||||
|
|
||||||
|
set a "Cabbage! " * 7
|
||||||
|
set a 7 * "Cabbage! "
|
||||||
|
|
||||||
|
# Should result in errors
|
||||||
|
set pqxya 1+2)
|
||||||
|
|
||||||
|
# Should result in an error
|
||||||
|
REM Tue OMIT 2024-01-01 MSG Wookie
|
||||||
|
|
||||||
|
# No error
|
||||||
|
REM Tue OMIT Wed 2024-01-01 MSG Blort
|
||||||
|
|
||||||
# Don't want Remind to queue reminders
|
# Don't want Remind to queue reminders
|
||||||
EXIT
|
EXIT
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# Use the output to verify your translations.
|
# Use the output to verify your translations.
|
||||||
#
|
#
|
||||||
# This file is part of REMIND.
|
# This file is part of REMIND.
|
||||||
# Copyright (C) 1992-2023 Dianne Skoll
|
# Copyright (C) 1992-2024 Dianne Skoll
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
#
|
#
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,341 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class Remind
|
|
||||||
{
|
|
||||||
# For validating commands we send to popen
|
|
||||||
function is_valid_day($d) {
|
|
||||||
return (preg_match('/^\d+$/', $d)) &&
|
|
||||||
$d >= 1 && $d <= 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_valid_month($m) {
|
|
||||||
return
|
|
||||||
($m == 'January') ||
|
|
||||||
($m == 'February') ||
|
|
||||||
($m == 'March') ||
|
|
||||||
($m == 'April') ||
|
|
||||||
($m == 'May') ||
|
|
||||||
($m == 'June') ||
|
|
||||||
($m == 'July') ||
|
|
||||||
($m == 'August') ||
|
|
||||||
($m == 'September') ||
|
|
||||||
($m == 'October') ||
|
|
||||||
($m == 'November') ||
|
|
||||||
($m == 'December');
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_valid_year($y) {
|
|
||||||
return preg_match('/^\d\d\d\d$/', $y) &&
|
|
||||||
$y >= 1900;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function get_el(&$array, $i)
|
|
||||||
{
|
|
||||||
if (!array_key_exists($i, $array)) return null;
|
|
||||||
return $array[$i];
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_elem($array, $indexes)
|
|
||||||
{
|
|
||||||
foreach ($indexes as $i) {
|
|
||||||
if (!is_array($array)) return null;
|
|
||||||
if (!array_key_exists($i, $array)) return null;
|
|
||||||
$array = $array[$i];
|
|
||||||
}
|
|
||||||
return $array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function munge_entry($day, &$results, &$specials, &$options, $str, &$e) {
|
|
||||||
return htmlspecialchars($str);
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_entry($day, &$results, &$specials, &$options, &$e) {
|
|
||||||
$special = $this->get_el($e, 'special');
|
|
||||||
$body = $this->get_el($e, 'body');
|
|
||||||
|
|
||||||
if ($body === null) $body = '';
|
|
||||||
if ($special === null || $special == '*') {
|
|
||||||
return $this->munge_entry($day, $results, $specials, $options, $body, $e);
|
|
||||||
}
|
|
||||||
if ($special == 'COLOR' || $special == 'COLOUR') {
|
|
||||||
if (preg_match('/^(\d+)\s+(\d+)\s+(\d+)\s+(.*)/', $body, $matches)) {
|
|
||||||
return sprintf('<span style="color: #%02x%02x%02x">%s</span>',
|
|
||||||
$matches[1] % 255,
|
|
||||||
$matches[2] % 255,
|
|
||||||
$matches[3] % 255,
|
|
||||||
$this->munge_entry($day, $results, $specials, $options, $matches[4], $e));
|
|
||||||
}
|
|
||||||
return 'Bad COLOR spec: ' . htmlspecialchars($body);
|
|
||||||
}
|
|
||||||
|
|
||||||
# HTML is passed through un-munged.
|
|
||||||
if ($special == 'HTML') return $body;
|
|
||||||
|
|
||||||
# Ignore unknown specials
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function format_entries($day, &$results, &$specials, &$options, &$entries) {
|
|
||||||
$html = '';
|
|
||||||
foreach ($entries as $e) {
|
|
||||||
$html .= '<div class="rem-entry">' . $this->format_entry($day, $results, $specials, $options, $e) . '</div>';
|
|
||||||
}
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function do_one_day($day, &$results, &$specials, &$options) {
|
|
||||||
$class = $this->get_elem($specials, array('HTMLCLASS', $day, 0, 'body'));
|
|
||||||
$shade = $this->get_elem($specials, array('SHADE', $day, 0, 'body'));
|
|
||||||
$moon = $this->get_elem($specials, array('MOON', $day, 0, 'body'));
|
|
||||||
|
|
||||||
if ($class === null) $class = 'rem-cell';
|
|
||||||
$bg = '';
|
|
||||||
if ($shade !== null) {
|
|
||||||
if (preg_match('/(\d+)\s+(\d+)\s+(\d+)/', $shade, $matches)) {
|
|
||||||
if ($matches[1] <= 255 && $matches[2] <= 255 && $matches[3] <= 255) {
|
|
||||||
$bg = sprintf(' style="background: #%02x%02x%02x"',
|
|
||||||
$matches[1], $matches[2], $matches[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$html = "<td class=\"$class\"$bg>";
|
|
||||||
|
|
||||||
$week = $this->get_elem($specials, array('WEEK', $day, 0, 'body'));
|
|
||||||
if ($week === null) {
|
|
||||||
$week = '';
|
|
||||||
} else {
|
|
||||||
$week = ' ' . $week;
|
|
||||||
}
|
|
||||||
|
|
||||||
$moon_html = '';
|
|
||||||
if ($moon !== null) {
|
|
||||||
$phase = -1;
|
|
||||||
if (preg_match('/(\d+)\s+(\S+)\s+(\S+)\s+(.*)$/', $moon, $matches)) {
|
|
||||||
$phase = $matches[1];
|
|
||||||
$moonsize = $matches[2];
|
|
||||||
$fontsize = $matches[3];
|
|
||||||
$msg = $matches[4];
|
|
||||||
} elseif (preg_match('/(\d+)/', $moon, $matches)) {
|
|
||||||
$phase = $matches[1];
|
|
||||||
$msg = '';
|
|
||||||
}
|
|
||||||
if ($phase >= 0) {
|
|
||||||
if ($phase == 0) {
|
|
||||||
$img = 'newmoon.png';
|
|
||||||
$title = 'New Moon';
|
|
||||||
$alt = 'new';
|
|
||||||
} elseif ($phase == 1) {
|
|
||||||
$img = 'firstquarter.png';
|
|
||||||
$title = 'First Quarter';
|
|
||||||
$alt = '1st';
|
|
||||||
} elseif ($phase == 2) {
|
|
||||||
$img = 'fullmoon.png';
|
|
||||||
$alt = 'full';
|
|
||||||
$title = 'Full Moon';
|
|
||||||
} else {
|
|
||||||
$img = 'lastquarter.png';
|
|
||||||
$alt = 'last';
|
|
||||||
$title = 'Last Quarter';
|
|
||||||
}
|
|
||||||
$base = rtrim($this->get_el($options, 'imgbase'), '/');
|
|
||||||
if ($base !== null) {
|
|
||||||
$img = $base . '/' . $img;
|
|
||||||
}
|
|
||||||
$moon_html = '<div class="rem-moon">' . "<img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">" . htmlspecialchars($msg) . '</div>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Day number
|
|
||||||
$html .= $moon_html . '<div class="rem-daynumber">' . $day . $week . '</div>';
|
|
||||||
|
|
||||||
# And the entries
|
|
||||||
$entries = $this->get_elem($results, array('entries', $day));
|
|
||||||
if (is_array($entries) && count($entries) > 0) {
|
|
||||||
$html .= '<div class="rem-entries">';
|
|
||||||
$html .= $this->format_entries($day, $results, $specials, $options, $entries);
|
|
||||||
$html .= '</div>';
|
|
||||||
}
|
|
||||||
$html .= "</td>\n";
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function small_calendar($results, $month, $monlen, $first_col, $which, &$options)
|
|
||||||
{
|
|
||||||
$monday_first = $results['monday_flag'];
|
|
||||||
if ($monday_first) {
|
|
||||||
$first_col--;
|
|
||||||
if ($first_col < 0) {
|
|
||||||
$first_col = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$html = "<td class=\"rem-small-calendar\">\n<table class=\"rem-sc-table\">\n<caption class=\"rem-sc-caption\">";
|
|
||||||
# TODO: URL for small calendar
|
|
||||||
$html .= $month;
|
|
||||||
$html .= "</caption>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
function generate_html(&$results, &$specials, &$options)
|
|
||||||
{
|
|
||||||
$monday_first = $results['monday_flag'];
|
|
||||||
$first_col = $results['first_day'];
|
|
||||||
if ($monday_first) {
|
|
||||||
$first_col--;
|
|
||||||
if ($first_col < 0) $first_col = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
$last_col = ($first_col + $results['days_in_mon'] -1) % 7;
|
|
||||||
|
|
||||||
$html = '<table class="rem-cal"><caption class="rem-cal-caption">' .
|
|
||||||
htmlspecialchars($results['month']) . ' ' . htmlspecialchars($results['year']) .
|
|
||||||
"</caption>\n";
|
|
||||||
|
|
||||||
$html .= '<tr class="rem-cal-hdr-row">';
|
|
||||||
if (!$monday_first) $html .= '<th class="rem-cal-hdr">' . htmlspecialchars($results['day_names'][0]) . '</th>';
|
|
||||||
for ($i=1; $i<7; $i++) $html .= '<th class="rem-cal-hdr">' . htmlspecialchars($results['day_names'][$i]) . '</th>';
|
|
||||||
if ($monday_first) $html .= '<th class="rem-cal-hdr">' . htmlspecialchars($results['day_names'][0]) . '</th>';
|
|
||||||
$html .= "</tr>\n";
|
|
||||||
|
|
||||||
# Do the leading empty columns
|
|
||||||
for ($col=0; $col < $first_col; $col++) {
|
|
||||||
if ($col == 0) $html .= '<tr class="rem-cal-body-row">';
|
|
||||||
$html .= '<td class="rem-empty"> </td>';
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($day=1; $day <= $results['days_in_mon']; $day++) {
|
|
||||||
if ($col == 0) $html .= '<tr class="rem-cal-body-row">';
|
|
||||||
$col++;
|
|
||||||
$html .= $this->do_one_day($day, $results, $specials, $options);
|
|
||||||
if ($col == 7) {
|
|
||||||
$html .= "</tr>\n";
|
|
||||||
$col = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($col) {
|
|
||||||
while ($col++ < 7) {
|
|
||||||
$html .= '<td class="rem-empty"> </td>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$html .= "</tr>\n";
|
|
||||||
|
|
||||||
$html .= "</table>\n";
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
function parse_remind_output ($fp)
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) break;
|
|
||||||
$line = trim($line);
|
|
||||||
if ($line == '# rem2ps begin') break;
|
|
||||||
}
|
|
||||||
if ($line === false) {
|
|
||||||
return array('success' => 0,
|
|
||||||
'error' => 'Could not find any Rem2PS data');
|
|
||||||
}
|
|
||||||
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) {
|
|
||||||
return array('success' => 0,
|
|
||||||
'error' => 'Unexpected end-of-file');
|
|
||||||
}
|
|
||||||
|
|
||||||
$line = trim($line);
|
|
||||||
list($month, $year, $days_in_mon, $first_day, $monday_flag) = explode(' ', $line);
|
|
||||||
$retval = array('month' => $month,
|
|
||||||
'year' => $year,
|
|
||||||
'days_in_mon' => $days_in_mon,
|
|
||||||
'first_day' => $first_day,
|
|
||||||
'monday_flag' => $monday_flag);
|
|
||||||
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) {
|
|
||||||
return array('success' => 0,
|
|
||||||
'error' => 'Unexpected end-of-file');
|
|
||||||
}
|
|
||||||
|
|
||||||
$line = trim($line);
|
|
||||||
$retval['day_names'] = explode(' ', $line);
|
|
||||||
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) {
|
|
||||||
return array('success' => 0,
|
|
||||||
'error' => 'Unexpected end-of-file');
|
|
||||||
}
|
|
||||||
$line = trim($line);
|
|
||||||
|
|
||||||
list($m, $n) = explode(' ', $line);
|
|
||||||
$retval['prev'] = array('month' => $m, 'days' => $n);
|
|
||||||
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) {
|
|
||||||
return array('success' => 0,
|
|
||||||
'error' => 'Unexpected end-of-file');
|
|
||||||
}
|
|
||||||
$line = trim($line);
|
|
||||||
|
|
||||||
list($m, $n) = explode(' ', $line);
|
|
||||||
$retval['next'] = array('month' => $m, 'days' => $n);
|
|
||||||
|
|
||||||
$line_info = 0;
|
|
||||||
|
|
||||||
$entries = array();
|
|
||||||
$specials = array();
|
|
||||||
while (1) {
|
|
||||||
$line = fgets($fp);
|
|
||||||
if ($line === false) break;
|
|
||||||
$line = trim($line);
|
|
||||||
if ($line == '# rem2ps end') break;
|
|
||||||
if (strpos($line, '# fileinfo ') === 0) {
|
|
||||||
list($lno, $fname) = explode(' ', substr($line, 11), 2);
|
|
||||||
$lineinfo = array('file' => $fname, 'line' => $lno);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
list($date, $special, $tags, $duration, $time, $body) = explode(' ', $line, 6);
|
|
||||||
list($y, $m, $d) = explode('/', $date);
|
|
||||||
$d = preg_replace('/^0(.)/', '$1', $d);
|
|
||||||
$m = preg_replace('/^0(.)/', '$1', $m);
|
|
||||||
$entry = array('day' => $d,
|
|
||||||
'month' => $m,
|
|
||||||
'year' => $y,
|
|
||||||
'special' => $special,
|
|
||||||
'tags' => $tags,
|
|
||||||
'duration' => $duration,
|
|
||||||
'time' => $time,
|
|
||||||
'body' => $body);
|
|
||||||
if (is_array($lineinfo)) {
|
|
||||||
$entry['line'] = $lineinfo['line'];
|
|
||||||
$entry['file'] = $lineinfo['file'];
|
|
||||||
$lineinfo = 0;
|
|
||||||
}
|
|
||||||
if ($special != '*' && $special != 'COLOR' && $special != 'COLOUR' && $special != 'HTML') {
|
|
||||||
if (!array_key_exists($special, $specials)) {
|
|
||||||
$specials[$special] = array();
|
|
||||||
}
|
|
||||||
if (!array_key_exists($d, $specials[$special])) {
|
|
||||||
$specials[$special][$d] = array();
|
|
||||||
}
|
|
||||||
$specials[$special][$d][] = $entry;
|
|
||||||
} else {
|
|
||||||
if (!array_key_exists($d, $entries)) {
|
|
||||||
$entries[$d] = array();
|
|
||||||
}
|
|
||||||
$entries[$d][] = $entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
$retval['entries'] = $entries;
|
|
||||||
return array('success' => 1, 'results' => $retval, 'specials' => $specials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$fp = popen('rem -p -l', 'r');
|
|
||||||
$r = new Remind;
|
|
||||||
$ans = $r->parse_remind_output($fp);
|
|
||||||
pclose($fp);
|
|
||||||
print_r($ans);
|
|
||||||
$options = array();
|
|
||||||
#print $r->generate_html($ans['results'], $ans['specials'], $options);
|
|
||||||
|
|
||||||
?>
|
|
||||||
Reference in New Issue
Block a user