mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
238 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
695a2a3c2d | ||
|
|
47aa542d4f | ||
|
|
5b4d1ae264 | ||
|
|
721ccb9af9 | ||
|
|
ab1a6c412a | ||
|
|
c3a555942b | ||
|
|
0d15977875 | ||
|
|
0a7e6ee219 | ||
|
|
baf049662f | ||
|
|
fd5d9a479d | ||
|
|
01d3081f19 | ||
|
|
7841077fc6 | ||
|
|
2003c7a703 | ||
|
|
4a603ce60d | ||
|
|
caad7f5aa3 | ||
|
|
ea2312c0b2 | ||
|
|
c0c49be0b5 | ||
|
|
c0594811bf | ||
|
|
b7e13845b6 | ||
|
|
94b340305c | ||
|
|
f477757ac0 | ||
|
|
a8017c6fc7 | ||
|
|
aad746bca3 | ||
|
|
953ff8c49e | ||
|
|
b5258b1eb5 | ||
|
|
82733e817b | ||
|
|
86e94009a4 | ||
|
|
04ea056820 | ||
|
|
d6ee16cc13 | ||
|
|
ead660fe41 | ||
|
|
58e5ae15b0 | ||
|
|
85a8a4b016 | ||
|
|
c43eaec274 | ||
|
|
13fd54b990 | ||
|
|
a48b2ec02e | ||
|
|
4e3562e2e4 | ||
|
|
2020ae35c1 | ||
|
|
9418043bb6 | ||
|
|
e2f786580c | ||
|
|
5aabb20630 | ||
|
|
a3c9ac2457 | ||
|
|
80e3671f9b | ||
|
|
e8e4362839 | ||
|
|
61ac3ca6ed | ||
|
|
eaf982e1cc | ||
|
|
0c27503a83 | ||
|
|
5878c2a714 | ||
|
|
6aa4d681e8 | ||
|
|
790a9ee384 | ||
|
|
d091af6e5b | ||
|
|
3ca9a69100 | ||
|
|
f6253d0fca | ||
|
|
3e6233b6f0 | ||
|
|
0ee5efa4df | ||
|
|
d4ed89f5ba | ||
|
|
34c864a38c | ||
|
|
6d4c38126e | ||
|
|
59c434ce34 | ||
|
|
a550af8fa6 | ||
|
|
3399646896 | ||
|
|
00e85e5ca2 | ||
|
|
9867d3cf34 | ||
|
|
0f4326726a | ||
|
|
1d208400cd | ||
|
|
b9b7e0d42a | ||
|
|
93316d754c | ||
|
|
14b6e23eaa | ||
|
|
7ae7edcb42 | ||
|
|
20a558f817 | ||
|
|
5118ccd120 | ||
|
|
18c4ed1c6d | ||
|
|
62e1a467f5 | ||
|
|
0933cd83b1 | ||
|
|
1ed7c83b24 | ||
|
|
3bae02f27d | ||
|
|
3b485f0632 | ||
|
|
a023d9dc5d | ||
|
|
4ccdfac8b8 | ||
|
|
1c52718ef0 | ||
|
|
4dde2a4b9d | ||
|
|
24f923ecfc | ||
|
|
45c0ba5e8f | ||
|
|
bccfe94921 | ||
|
|
f7e83ed082 | ||
|
|
40b87eff60 | ||
|
|
a8607cb012 | ||
|
|
6caa404e59 | ||
|
|
13e1e19855 | ||
|
|
96d40b81df | ||
|
|
30e4a9fc50 | ||
|
|
6d0fbeed20 | ||
|
|
3f1aaeefd2 | ||
|
|
326604fe18 | ||
|
|
57e93553bf | ||
|
|
a5aa5d901b | ||
|
|
1e0d43b63c | ||
|
|
188efaebba | ||
|
|
b701dc575f | ||
|
|
c9ae1c82f0 | ||
|
|
13cea56cce | ||
|
|
6661f32faf | ||
|
|
f6ab660c5e | ||
|
|
523cfb7bf5 | ||
|
|
82a4ba777d | ||
|
|
8f02868486 | ||
|
|
12d8e8e948 | ||
|
|
f5f364507b | ||
|
|
d514389c39 | ||
|
|
52c615ff61 | ||
|
|
7d3e6b3a72 | ||
|
|
c4e5190ec2 | ||
|
|
f197f5ef9d | ||
|
|
153cbfe276 | ||
|
|
2d9bea444b | ||
|
|
2ae8e51bec | ||
|
|
05d1608081 | ||
|
|
d093e8dea3 | ||
|
|
f9fac22bbf | ||
|
|
9ecbfbb314 | ||
|
|
612f3e7f16 | ||
|
|
d22f9979a5 | ||
|
|
291f648d2e | ||
|
|
351088fd4b | ||
|
|
ed57f62911 | ||
|
|
53dcce6a91 | ||
|
|
d12d327e35 | ||
|
|
a2f760fb91 | ||
|
|
4a9b4ff6e4 | ||
|
|
ce6061a29b | ||
|
|
878a5d9bed | ||
|
|
d1b55bae8d | ||
|
|
c13817015f | ||
|
|
bf74ad1eb7 | ||
|
|
f2eb06c752 | ||
|
|
8172acf102 | ||
|
|
949e00219d | ||
|
|
1fd19b89e2 | ||
|
|
22d6c0583a | ||
|
|
12fac555b6 | ||
|
|
085b781114 | ||
|
|
c9d7fbf479 | ||
|
|
42f868db07 | ||
|
|
2996275ec4 | ||
|
|
5586198a0e | ||
|
|
d17c48e751 | ||
|
|
e08a6370ef | ||
|
|
7a319466cf | ||
|
|
4158ad5977 | ||
|
|
9b07eed26f | ||
|
|
05ead8c40d | ||
|
|
35e222967c | ||
|
|
83ca07d34f | ||
|
|
36f4bb852b | ||
|
|
9642303d05 | ||
|
|
a6144baff7 | ||
|
|
17985c59c3 | ||
|
|
719295ccd7 | ||
|
|
3d74389713 | ||
|
|
80c7244d64 | ||
|
|
db27be1469 | ||
|
|
d59fe832fd | ||
|
|
88ebdf275e | ||
|
|
a7a6f8b5f0 | ||
|
|
3e248c069e | ||
|
|
65cca1fd8f | ||
|
|
5a889043ba | ||
|
|
6d1fcdf246 | ||
|
|
3476b965ef | ||
|
|
0bba2dc3b3 | ||
|
|
e5c27f19f5 | ||
|
|
f9aa53433e | ||
|
|
5323245529 | ||
|
|
deb12ac7cd | ||
|
|
a1488d93ad | ||
|
|
65add3d32e | ||
|
|
8d6f5efa7b | ||
|
|
eb996a8146 | ||
|
|
1cd6205cdd | ||
|
|
6d9ccc1522 | ||
|
|
0268020579 | ||
|
|
5803d1dd7e | ||
|
|
5dfce21af6 | ||
|
|
8ddb956f9a | ||
|
|
32421815cd | ||
|
|
dbe3bc13fa | ||
|
|
c68c716585 | ||
|
|
7a1a5abc0f | ||
|
|
53a1318306 | ||
|
|
78fecf28c4 | ||
|
|
6081d29b11 | ||
|
|
e0a5125ee0 | ||
|
|
c3f790a99b | ||
|
|
3eb507451e | ||
|
|
e9e0368418 | ||
|
|
759ae1ab80 | ||
|
|
e8602824a0 | ||
|
|
62301a88cc | ||
|
|
6b163092c7 | ||
|
|
f8ac99d22e | ||
|
|
4b7870f6b1 | ||
|
|
e11b899f7e | ||
|
|
8e4987eeba | ||
|
|
aa56d27aea | ||
|
|
b3278cd9d5 | ||
|
|
09814eac68 | ||
|
|
0e8889441d | ||
|
|
d9503bd14d | ||
|
|
a5c18f8825 | ||
|
|
f7fc9f57bd | ||
|
|
6931c81716 | ||
|
|
2eb80c4ba1 | ||
|
|
f5dbba3864 | ||
|
|
3fc57fb76e | ||
|
|
ff9d27a6ca | ||
|
|
e82767f821 | ||
|
|
772daaa877 | ||
|
|
941cb0f63e | ||
|
|
15960f7e4a | ||
|
|
f05ef363fc | ||
|
|
a22b0b8daf | ||
|
|
382ff47369 | ||
|
|
cab749b651 | ||
|
|
2dc5a7776d | ||
|
|
2723875a18 | ||
|
|
81a186607b | ||
|
|
5534bf8272 | ||
|
|
f726b09fc6 | ||
|
|
f07a6d1bed | ||
|
|
a0a362c418 | ||
|
|
0b45bc818b | ||
|
|
b6ad32749b | ||
|
|
ec36fc8cf8 | ||
|
|
2afb71b233 | ||
|
|
4bf9abc791 | ||
|
|
51d895dbb1 | ||
|
|
517251dd05 | ||
|
|
834741f91b | ||
|
|
19b33bb9bc |
@@ -3,7 +3,7 @@ THE REMIND COPYRIGHT
|
||||
1. REMIND refers to the entire set of files and documentation in the
|
||||
REMIND package.
|
||||
|
||||
2. REMIND is Copyright (C) 1992-2025 Dianne Skoll, except where noted in
|
||||
2. REMIND is Copyright (C) 1992-2026 Dianne Skoll, except where noted in
|
||||
individual files.
|
||||
|
||||
3. DISTRIBUTION AND USE
|
||||
|
||||
39
Makefile
39
Makefile
@@ -11,6 +11,33 @@ all: src/Makefile
|
||||
@echo ""
|
||||
@cd src && $(MAKE) all LANGDEF=$(LANGDEF)
|
||||
@$(MAKE) -C rem2pdf -f Makefile.top
|
||||
|
||||
uninstall-script:
|
||||
@echo "" >&2
|
||||
@echo "*****************************" >&2
|
||||
@echo "* *" >&2
|
||||
@echo "* Creating Uninstall Script *" >&2
|
||||
@echo "* *" >&2
|
||||
@echo "*****************************" >&2
|
||||
@echo "" >&2
|
||||
|
||||
@echo "#!/bin/sh"
|
||||
@echo "echo 'This script will uninstall Remind'"
|
||||
@echo "echo 'Enter y to uninstall Remind or anything else to abort'"
|
||||
@echo "read ans"
|
||||
@echo 'if test "$$ans" != "y" ; then'
|
||||
@echo " echo 'NOT uninstalling Remind'"
|
||||
@echo " exit 0"
|
||||
@echo "fi"
|
||||
@echo "echo 'Uninstalling Remind...'"
|
||||
-@rm -rf `pwd`/.uninstall-dir > /dev/null 2>&1
|
||||
@mkdir `pwd`/.uninstall-dir >&2
|
||||
@$(MAKE) install DESTDIR=`pwd`/.uninstall-dir >&2
|
||||
@cd `pwd`/.uninstall-dir && find . -type f | while read x ; do x=`echo $$x | sed -e 's|^\./|/|'`; echo "rm -f $$x"; done;
|
||||
@echo "echo 'Done'"
|
||||
-@rm -rf `pwd`/.uninstall-dir > /dev/null 2>&1
|
||||
|
||||
|
||||
install:
|
||||
@echo ""
|
||||
@echo "**********************************"
|
||||
@@ -19,9 +46,9 @@ install:
|
||||
@echo "* *"
|
||||
@echo "**********************************"
|
||||
@echo ""
|
||||
@$(MAKE) -C src install
|
||||
@$(MAKE) -C rem2html install
|
||||
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
|
||||
@$(MAKE) -C src install DESTDIR=$(DESTDIR)
|
||||
@$(MAKE) -C rem2html install DESTDIR=$(DESTDIR)
|
||||
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE) DESTDIR=$(DESTDIR)
|
||||
clean:
|
||||
-find . -name '*~' -exec rm {} \;
|
||||
-$(MAKE) -C src clean
|
||||
@@ -35,9 +62,9 @@ install-stripped:
|
||||
@echo "* *"
|
||||
@echo "**********************************"
|
||||
@echo ""
|
||||
@$(MAKE) -C src install-stripped
|
||||
@$(MAKE) -C rem2html install
|
||||
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
|
||||
@$(MAKE) -C src install-stripped DESTDIR=$(DESTDIR)
|
||||
@$(MAKE) -C rem2html install DESTDIR=$(DESTDIR)
|
||||
@$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE) DESTDIR=$(DESTDIR)
|
||||
|
||||
test: test-basic test-tz
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Remind is a full-featured calendar/alarm program. Copying policy is
|
||||
in the file "COPYRIGHT" included with the source; Remind is licensed under
|
||||
the GNU General Public License, Vesion 2.
|
||||
the GNU General Public License, Version 2.
|
||||
|
||||
## Prerequisites:
|
||||
|
||||
|
||||
2
build.tk
2
build.tk
@@ -8,7 +8,7 @@
|
||||
# A cheesy graphical front-end for building and installing REMIND.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2025 Dianne Skoll
|
||||
# Copyright (C) 1992-2026 Dianne Skoll
|
||||
#
|
||||
#--------------------------------------------------------------
|
||||
|
||||
|
||||
136
configure
vendored
136
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.72 for remind 06.01.05.
|
||||
# Generated by GNU Autoconf 2.72 for remind 06.02.04.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
|
||||
@@ -601,8 +601,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='remind'
|
||||
PACKAGE_TARNAME='remind'
|
||||
PACKAGE_VERSION='06.01.05'
|
||||
PACKAGE_STRING='remind 06.01.05'
|
||||
PACKAGE_VERSION='06.02.04'
|
||||
PACKAGE_STRING='remind 06.02.04'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
|
||||
|
||||
@@ -1258,7 +1258,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
'configure' configures remind 06.01.05 to adapt to many kinds of systems.
|
||||
'configure' configures remind 06.02.04 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1320,7 +1320,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of remind 06.01.05:";;
|
||||
short | recursive ) echo "Configuration of remind 06.02.04:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1408,7 +1408,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
remind configure 06.01.05
|
||||
remind configure 06.02.04
|
||||
generated by GNU Autoconf 2.72
|
||||
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
@@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by remind $as_me 06.01.05, which was
|
||||
It was created by remind $as_me 06.02.04, which was
|
||||
generated by GNU Autoconf 2.72. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -2477,6 +2477,7 @@ as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
|
||||
as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
|
||||
as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
|
||||
as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H"
|
||||
as_fn_append ac_header_c_list " sys/termios.h sys_termios_h HAVE_SYS_TERMIOS_H"
|
||||
as_fn_append ac_header_c_list " readline/readline.h readline_readline_h HAVE_READLINE_READLINE_H"
|
||||
as_fn_append ac_header_c_list " readline/history.h readline_history_h HAVE_READLINE_HISTORY_H"
|
||||
|
||||
@@ -2659,6 +2660,12 @@ cat <<'EOF'
|
||||
|
||||
EOF
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
ac_config_headers="$ac_config_headers src/config.h"
|
||||
|
||||
|
||||
@@ -4028,6 +4035,7 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
# The cast to long int works around a bug in the HP C Compiler
|
||||
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
|
||||
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
|
||||
@@ -4217,31 +4225,74 @@ printf "%s\n" "#define TM_IN_SYS_TIME 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
U="`uname -s`"
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
# LTO fails on Solaris for some reason
|
||||
if test "$U" != "SunOS" -a "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
# Check for link-time optimization support
|
||||
f=-flto=auto
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||
printf %s "checking whether $CC supports $f... " >&6; }
|
||||
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" "yes" >&6; }
|
||||
CFLAGS="$CFLAGS $f"
|
||||
f=-ffat-lto-objects
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $f" >&5
|
||||
printf %s "checking whether $CC supports $f... " >&6; }
|
||||
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" "yes" >&6; }
|
||||
CFLAGS="$CFLAGS $f"
|
||||
else
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
fi
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -flto=auto"
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -flto=auto" >&5
|
||||
printf %s "checking whether $CC supports -flto=auto... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int x = 1;
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
lto=yes
|
||||
else case e in #(
|
||||
e) lto=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lto" >&5
|
||||
printf "%s\n" "$lto" >&6; }
|
||||
if test "x$lto" != "xyes" ; then
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
else
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -ffat-lto-object" >&5
|
||||
printf %s "checking whether $CC supports -ffat-lto-object... " >&6; }
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror -ffat-lto-objects"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int x = 1;
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
lto=yes
|
||||
else case e in #(
|
||||
e) lto=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lto" >&5
|
||||
printf "%s\n" "$lto" >&6; }
|
||||
if test "x$lto" != "xyes" ; then
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
else
|
||||
CFLAGS="$OLDCFLAGS -ffat-lto-objects"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -4265,24 +4316,12 @@ if test "$?" != 0 ; then
|
||||
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
|
||||
exit 1
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup"
|
||||
if test "x$ac_cv_func_strdup" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h
|
||||
|
||||
if test "$ac_cv_header_wctype_h" != "yes" ; then
|
||||
echo "*** Remind requires the <wctype.h> header"
|
||||
exit 1
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp"
|
||||
if test "x$ac_cv_func_strcasecmp" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STRCASECMP 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp"
|
||||
if test "x$ac_cv_func_strncasecmp" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STRNCASECMP 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv"
|
||||
if test "x$ac_cv_func_setenv" = xyes
|
||||
then :
|
||||
@@ -4333,6 +4372,11 @@ then :
|
||||
fi
|
||||
|
||||
|
||||
if test "$ac_cv_func_mbstowcs" != "yes"; then
|
||||
echo "*** Remind requires the mbstowcs function"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$PACKAGE_VERSION
|
||||
CONFIG_CMD="$0$ac_configure_args_raw"
|
||||
CONFIG_CMD=`echo "$CONFIG_CMD" | sed -e 's/"/\\\\"/g'`
|
||||
@@ -4848,7 +4892,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by remind $as_me 06.01.05, which was
|
||||
This file was extended by remind $as_me 06.02.04, which was
|
||||
generated by GNU Autoconf 2.72. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -4913,7 +4957,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
remind config.status 06.01.05
|
||||
remind config.status 06.02.04
|
||||
configured by $0, generated by GNU Autoconf 2.72,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
67
configure.ac
67
configure.ac
@@ -1,6 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(remind, 06.01.05, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_INIT(remind, 06.02.04, , , https://dianne.skoll.ca/projects/remind/)
|
||||
AC_CONFIG_SRCDIR([src/queue.c])
|
||||
|
||||
cat <<'EOF'
|
||||
@@ -13,6 +13,7 @@ cat <<'EOF'
|
||||
|
||||
EOF
|
||||
|
||||
AC_LANG([C])
|
||||
AC_CONFIG_HEADERS([src/config.h])
|
||||
|
||||
AC_ARG_ENABLE(perl-build-artifacts,
|
||||
@@ -31,7 +32,7 @@ AC_PATH_PROG([PERL], [perl])
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB(m, sqrt)
|
||||
AC_CHECK_LIB(readline, readline)
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h stdint.h readline/readline.h readline/history.h])
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h sys/termios.h stdint.h readline/readline.h readline/history.h])
|
||||
|
||||
dnl Integer sizes
|
||||
AC_CHECK_SIZEOF(unsigned int)
|
||||
@@ -43,25 +44,42 @@ AC_CHECK_HEADERS(strings.h sys/types.h glob.h wctype.h locale.h langinfo.h sys/i
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
U="`uname -s`"
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
# LTO fails on Solaris for some reason
|
||||
if test "$U" != "SunOS" -a "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
|
||||
# Check for link-time optimization support
|
||||
f=-flto=auto
|
||||
AC_MSG_CHECKING([whether $CC supports $f])
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS $f"
|
||||
f=-ffat-lto-objects
|
||||
AC_MSG_CHECKING([whether $CC supports $f])
|
||||
if $CC -Werror -E $f - < /dev/null > /dev/null 2>&1 ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS $f"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -flto=auto"
|
||||
AC_MSG_CHECKING([whether $CC supports -flto=auto])
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[int x = 1;]],
|
||||
[[]])],
|
||||
[lto=yes],
|
||||
[lto=no]
|
||||
)
|
||||
AC_MSG_RESULT([$lto])
|
||||
if test "x$lto" != "xyes" ; then
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_CHECKING([whether $CC supports -ffat-lto-object])
|
||||
OLDCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror -ffat-lto-objects"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[int x = 1;]],
|
||||
[[]])],
|
||||
[lto=yes],
|
||||
[lto=no]
|
||||
)
|
||||
AC_MSG_RESULT([$lto])
|
||||
if test "x$lto" != "xyes" ; then
|
||||
CFLAGS="$OLDCFLAGS"
|
||||
else
|
||||
CFLAGS="$OLDCFLAGS -ffat-lto-objects"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -85,7 +103,18 @@ if test "$?" != 0 ; then
|
||||
echo "*** COULD NOT DETERMINE RELEASE DATE: docs/WHATSNEW is incorrect!"
|
||||
exit 1
|
||||
fi
|
||||
AC_CHECK_FUNCS(strdup strcasecmp strncasecmp setenv unsetenv glob mbstowcs setlocale initgroups inotify_init1 readline)
|
||||
|
||||
if test "$ac_cv_header_wctype_h" != "yes" ; then
|
||||
echo "*** Remind requires the <wctype.h> header"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups inotify_init1 readline)
|
||||
|
||||
if test "$ac_cv_func_mbstowcs" != "yes"; then
|
||||
echo "*** Remind requires the mbstowcs function"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION=$PACKAGE_VERSION
|
||||
CONFIG_CMD="$0$ac_configure_args_raw"
|
||||
|
||||
@@ -106,11 +106,12 @@
|
||||
"Syntax table for `remind-conf-mode'.")
|
||||
|
||||
;;; keyword sets
|
||||
|
||||
;;; MOON, WEEK, SHADE, COLOR and COLOUR are not really keywords,
|
||||
;;; but they are widely-supported SPECIALS, so I add them here.
|
||||
(defconst remind-keywords
|
||||
(sort
|
||||
(list "ADDOMIT" "AFTER" "AT" "BAN" "BANNER" "BEFORE" "CAL" "CLEAR"
|
||||
"CLEAR-OMIT-CONTEXT" "COMPLETE-THROUGH" "DEBUG" "DO" "DUMP" "DUMPVARS"
|
||||
"CLEAR-OMIT-CONTEXT" "COMPLETE-THROUGH" "COMPLETED-THROUGH" "DEBUG" "DO" "DUMP" "DUMPVARS"
|
||||
"DURATION" "ELSE" "ENDIF" "ERRMSG" "EXIT" "EXPR" "FIRST"
|
||||
"FLUSH" "FOURTH" "FRENAME" "FROM" "FSET" "FUNSET" "IF"
|
||||
"IFTRIG" "IN" "INC" "INCLUDE" "INCLUDECMD" "INFO" "LAST"
|
||||
@@ -120,7 +121,8 @@
|
||||
"PSFILE" "PUSH" "PUSH-FUNCS" "PUSH-VARS" "PUSH-OMIT-CONTEXT" "REM" "RETURN"
|
||||
"RUN" "SATISFY" "SCAN" "SCANFROM" "SCHED" "SECOND" "SET"
|
||||
"SKIP" "SPECIAL" "SYSINCLUDE" "TAG" "THIRD" "THROUGH" "TODO"
|
||||
"TRANSLATE" "TRANS" "TZ" "UNSET" "UNTIL" "WARN")
|
||||
"TRANSLATE" "TRANS" "TZ" "UNSET" "UNTIL" "WARN"
|
||||
"MOON" "WEEK" "SHADE" "COLOR" "COLOUR")
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
@@ -131,7 +133,7 @@
|
||||
|
||||
(defconst remind-builtin-variables
|
||||
(sort
|
||||
(list " $AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
||||
(list "$AddBlankLines" "$Ago" "$Am" "$And" "$April" "$At" "$August"
|
||||
"$CalcUTC" "$CalMode" "$CalType" "$Daemon" "$DateSep" "$DateTimeSep"
|
||||
"$December" "$DedupeReminders" "$DefaultColor" "$DefaultDelta"
|
||||
"$DefaultPrio" "$DefaultTDelta" "$DeltaOverride"
|
||||
@@ -145,10 +147,10 @@
|
||||
"$May" "$MinsFromUTC" "$Minute" "$Monday" "$Mplu" "$NextMode"
|
||||
"$November" "$Now" "$NumFullOmits" "$NumPartialOmits" "$NumQueued"
|
||||
"$NumTrig" "$October" "$On" "$OnceFile" "$ParseUntriggered" "$Pm"
|
||||
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September"
|
||||
"$PrefixLineNo" "$PSCal" "$RunOff" "$Saturday" "$September" "$Shaded"
|
||||
"$SimpleCal" "$SortByDate" "$SortByPrio" "$SortByTime" "$SubsIndent"
|
||||
"$Sunday" "$SuppressImplicitWarnings" "$SuppressLRM" "$SysInclude" "$T" "$Tb" "$Td"
|
||||
"$TerminalBackground" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today" "$TodoFilter"
|
||||
"$TerminalBackground" "$TerminalHyperlinks" "$Thursday" "$TimeSep" "$TimetIs64bit" "$Tm" "$Today" "$TodoFilter"
|
||||
"$Tomorrow" "$Tt" "$Tuesday" "$Tw" "$Ty" "$U" "$Ud" "$Um"
|
||||
"$UntimedFirst" "$Use256Colors" "$UseBGVTColors" "$UseTrueColors"
|
||||
"$UseVTColors" "$Uw" "$Uy" "$WarningLevel" "$Was" "$Wednesday")
|
||||
@@ -165,26 +167,151 @@
|
||||
|
||||
(defconst remind-builtin-functions
|
||||
(sort
|
||||
(list "_" "abs" "access" "adawn" "adusk" "ampm" "ansicolor" "args" "asc"
|
||||
"baseyr" "catch" "catcherr" "char" "choose" "codepoint" "coerce" "columns" "const" "current" "date"
|
||||
"datepart" "datetime" "dawn" "day" "daysinmon" "defined" "dosubst"
|
||||
"dusk" "easterdate" "escape" "eval" "evaltrig" "filedate" "filedatetime"
|
||||
"filedir" "filename" "getenv" "hebdate" "hebday" "hebmon" "hebyear" "hex"
|
||||
"hour" "htmlescape" "htmlstriptags" "iif" "index" "isany" "isconst" "isdst"
|
||||
"isleap" "isomitted" "language" "localtoutc" "lower" "max"
|
||||
"mbasc" "mbindex" "mbstrlen" "mbsubstr" "min"
|
||||
"minsfromutc" "minute" "mon" "monnum" "moondate" "moondatetime"
|
||||
"moonphase" "moonrise" "moonrisedir" "moonset" "moonsetdir" "moontime"
|
||||
"multitrig" "ndawn" "ndusk" "nonconst" "nonomitted" "now" "ord" "orthodoxeaster"
|
||||
"ostype" "pad" "plural" "psmoon" "psshade" "realcurrent" "realnow"
|
||||
"realtoday" "rows" "sgn" "shell" "shellescape" "slide" "soleq"
|
||||
"stdout" "strlen" "substr" "sunrise" "sunset" "time" "timepart"
|
||||
"timezone" "today" "trig" "trigback" "trigbase" "trigcompletethrough" "trigdate" "trigdatetime"
|
||||
"trigdelta" "trigduration" "trigeventduration" "trigeventstart" "trigeventstarttz"
|
||||
"trigfrom" "trigger" "triginfo" "trigistodo" "trigmaxoverdue" "trigpriority" "trigrep"
|
||||
"trigscanfrom" "trigtags" "trigtime" "trigtimedelta" "trigtimerep" "trigtimetz" "trigtz"
|
||||
"triguntil" "trigvalid" "typeof" "tzconvert" "upper" "utctolocal"
|
||||
"value" "version" "weekno" "wkday" "wkdaynum" "year"
|
||||
(list
|
||||
"_"
|
||||
"abs"
|
||||
"access"
|
||||
"adawn"
|
||||
"adusk"
|
||||
"ampm"
|
||||
"ansicolor"
|
||||
"args"
|
||||
"asc"
|
||||
"baseyr"
|
||||
"catch"
|
||||
"catcherr"
|
||||
"char"
|
||||
"choose"
|
||||
"codepoint"
|
||||
"coerce"
|
||||
"columns"
|
||||
"const"
|
||||
"current"
|
||||
"date"
|
||||
"datepart"
|
||||
"datetime"
|
||||
"dawn"
|
||||
"day"
|
||||
"daysinmon"
|
||||
"defined"
|
||||
"dosubst"
|
||||
"dusk"
|
||||
"easterdate"
|
||||
"escape"
|
||||
"eval"
|
||||
"evaltrig"
|
||||
"filedate"
|
||||
"filedatetime"
|
||||
"filedir"
|
||||
"filename"
|
||||
"getenv"
|
||||
"hebdate"
|
||||
"hebday"
|
||||
"hebmon"
|
||||
"hebyear"
|
||||
"hex"
|
||||
"hour"
|
||||
"htmlescape"
|
||||
"htmlstriptags"
|
||||
"iif"
|
||||
"index"
|
||||
"isany"
|
||||
"isconst"
|
||||
"isdst"
|
||||
"isleap"
|
||||
"isomitted"
|
||||
"ivritmon"
|
||||
"language"
|
||||
"localtoutc"
|
||||
"lower"
|
||||
"max"
|
||||
"mbasc"
|
||||
"mbindex"
|
||||
"mblower"
|
||||
"mbstrlen"
|
||||
"mbsubstr"
|
||||
"mbupper"
|
||||
"min"
|
||||
"minsfromutc"
|
||||
"minute"
|
||||
"mon"
|
||||
"monnum"
|
||||
"moondate"
|
||||
"moondatetime"
|
||||
"moonphase"
|
||||
"moonrise"
|
||||
"moonrisedir"
|
||||
"moonset"
|
||||
"moonsetdir"
|
||||
"moontime"
|
||||
"multitrig"
|
||||
"ndawn"
|
||||
"ndusk"
|
||||
"nonconst"
|
||||
"nonomitted"
|
||||
"now"
|
||||
"ord"
|
||||
"orthodoxeaster"
|
||||
"ostype"
|
||||
"pad"
|
||||
"plural"
|
||||
"psmoon"
|
||||
"psshade"
|
||||
"realcurrent"
|
||||
"realnow"
|
||||
"realtoday"
|
||||
"rows"
|
||||
"sgn"
|
||||
"shell"
|
||||
"shellescape"
|
||||
"slide"
|
||||
"soleq"
|
||||
"stdout"
|
||||
"strlen"
|
||||
"substr"
|
||||
"sunrise"
|
||||
"sunset"
|
||||
"time"
|
||||
"timepart"
|
||||
"timezone"
|
||||
"today"
|
||||
"trig"
|
||||
"trigback"
|
||||
"trigbase"
|
||||
"trigcompletethrough"
|
||||
"trigdate"
|
||||
"trigdatetime"
|
||||
"trigdelta"
|
||||
"trigduration"
|
||||
"trigeventduration"
|
||||
"trigeventstart"
|
||||
"trigeventstarttz"
|
||||
"trigfrom"
|
||||
"trigger"
|
||||
"triginfo"
|
||||
"trigistodo"
|
||||
"trigmaxoverdue"
|
||||
"trigpriority"
|
||||
"trigrep"
|
||||
"trigscanfrom"
|
||||
"trigtags"
|
||||
"trigtime"
|
||||
"trigtimedelta"
|
||||
"trigtimerep"
|
||||
"trigtimetz"
|
||||
"trigtz"
|
||||
"triguntil"
|
||||
"trigvalid"
|
||||
"typeof"
|
||||
"tzconvert"
|
||||
"upper"
|
||||
"utctolocal"
|
||||
"value"
|
||||
"version"
|
||||
"weekno"
|
||||
"wkday"
|
||||
"wkdaynum"
|
||||
"year"
|
||||
)
|
||||
#'(lambda (a b) (> (length a) (length b)))))
|
||||
|
||||
|
||||
498
docs/WHATSNEW
498
docs/WHATSNEW
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
# "#PSSTUFF" for nifty PostScript examples #
|
||||
# #
|
||||
# This file is part of REMIND. #
|
||||
# Copyright (C) 1992-2025 Dianne Skoll #
|
||||
# Copyright (C) 1992-2026 Dianne Skoll #
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# #
|
||||
#############################################################################
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
" Maintainer: Davide Alberani <da@erlug.linux.it>
|
||||
" Last Change: 02 Nov 2015 + 13 Mar 2022 by Dianne Skoll <dianne@skoll.ca>
|
||||
" Version: 0.7+dianne1
|
||||
" URL: http://ismito.it/vim/syntax/remind.vim
|
||||
" URL: https://github.com/alberanid/vim-config/blob/master/syntax/remind.vim
|
||||
"
|
||||
" remind is a sophisticated reminder service
|
||||
" you can download remind from:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Not all sequences are supported by all terminals.
|
||||
|
||||
# This file is part of REMIND
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
if !defined("ansi_bold")
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Localize if we can
|
||||
IF access($SysInclude + "/translations/" + _("LANGID") + "/holidays/chinese-new-year.rem", "r") >= 0
|
||||
SYSINCLUDE translations/[_("LANGID")]/holidays/chinese-new-year.rem
|
||||
ENDIF
|
||||
|
||||
REM 1 Feb 2022 INFO "Url: https://en.wikipedia.org/wiki/Tiger_(zodiac)" MSG %"%(Chinese New Year) (%(Tiger))%" %! %b.
|
||||
REM 22 Jan 2023 INFO "Url: https://en.wikipedia.org/wiki/Rabbit_(zodiac)" MSG %"%(Chinese New Year) (%(Rabbit))%" %! %b.
|
||||
REM 10 Feb 2024 INFO "Url: https://en.wikipedia.org/wiki/Dragon_(zodiac)" MSG %"%(Chinese New Year) (%(Dragon))%" %! %b.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Save variables and functions that we will mess with
|
||||
PUSH-VARS InIsrael IncludeIsraeliHolidays Reform IncludeOmer IncludeOmerCal SunCal
|
||||
PUSH-FUNCS _chan _h2 _h2I _YZ _PastSat _BackTwoSat
|
||||
PUSH-VARS InIsrael IncludeIsraeliHolidays Reform IncludeOmer IncludeOmerCal SunCal ostart yz
|
||||
PUSH-FUNCS _h2 _h2I _YZ _PastSat _BackTwoSat
|
||||
|
||||
SET InIsrael value("InIsrael", 0)
|
||||
SET IncludeIsraeliHolidays value("IncludeIsraeliHolidays", 1)
|
||||
@@ -37,10 +37,19 @@ REM [hebdate(21, "Tishrey")] INFO "Url: https://en.wikipedia.org/wiki/Hoshana_Ra
|
||||
REM [hebdate(22, "Tishrey")] INFO "Url: https://en.wikipedia.org/wiki/Shemini_Atzeret" MSG %"Shemini Atzeret%" %! %b.
|
||||
REM [_h2I(22, "Tishrey")] INFO "Url: https://en.wikipedia.org/wiki/Simchat_Torah" MSG %"Simchat Torah%" %! %b.
|
||||
|
||||
# If the reminder has expired, $T can be zero, hence the
|
||||
# ($T || $U) below
|
||||
REM [hebdate(25, "Kislev",$U-9)] through [hebdate(25, "Kislev",$U-9)+7] \
|
||||
INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah [($T || $U) - hebdate(25,"Kislev",$U-9) + 1]%" %! %b.
|
||||
# This reminder used to be done as a single reminder. I have split it
|
||||
# into 8 separate reminders because the "rem2dav" script uses
|
||||
# synthetic tags as UUIDs and it incorrectly coalesces the 8 days'
|
||||
# worth of reminders into a single 8-day reminder.
|
||||
|
||||
REM [hebdate(25, "Kislev", $U-9)] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 1%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+1] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 2%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+2] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 3%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+3] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 4%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+4] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 5%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+5] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 6%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+6] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 7%" %! %b.
|
||||
REM [hebdate(25, "Kislev", $U-9)+7] INFO "Url: https://en.wikipedia.org/wiki/Hanukkah" MSG %"Chanukah 8%" %! %b.
|
||||
|
||||
IF !Reform
|
||||
REM [hebdate(10, "Tevet")] INFO "Url: https://en.wikipedia.org/wiki/Tenth_of_Tevet" MSG %"Tzom Tevet%" %! %b.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Catalan language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file was created by Eloi Torrents <eloitor@disroot.org>
|
||||
|
||||
TRANSLATE "LANGID" "ca"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Danish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Mogens Lynnerup.
|
||||
|
||||
TRANSLATE "LANGID" "da"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the German language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Wolfgang Thronicke
|
||||
|
||||
TRANSLATE "LANGID" "de"
|
||||
@@ -73,34 +73,8 @@ FSET - subst_p(alt, d, t) iif(d == today()+1, "", "en")
|
||||
# Localization of various astronomical events
|
||||
|
||||
TRANSLATE "Perihelion" "Perihel"
|
||||
TRANSLATE "Vernal Equinox" "Frühlingsanfang"
|
||||
TRANSLATE "Summer Solstice" "Sommeranfang"
|
||||
TRANSLATE "Aphelion" "Aphel"
|
||||
TRANSLATE "Autumnal Equinox" "Herbstanfang"
|
||||
TRANSLATE "Winter Solstice" "Winteranfang"
|
||||
TRANSLATE "Daylight Saving Time Starts" "Beginn Sommerzeit"
|
||||
TRANSLATE "Daylight Saving Time Ends" "Ende Sommerzeit"
|
||||
|
||||
TRANSLATE "New Moon" "Neumond"
|
||||
TRANSLATE "First Quarter" "zunehmender Halbmond"
|
||||
TRANSLATE "Full Moon" "Vollmond"
|
||||
TRANSLATE "Last Quarter" "abnehmender Halbmond"
|
||||
|
||||
TRANSLATE "Chinese New Year" "Chinesisches Neujahr"
|
||||
TRANSLATE "Snake" "Schlange"
|
||||
TRANSLATE "Horse" "Pferd"
|
||||
TRANSLATE "Goat" "Ziege"
|
||||
TRANSLATE "Monkey" "Affe"
|
||||
TRANSLATE "Rooster" "Hahn"
|
||||
TRANSLATE "Dog" "Hund"
|
||||
TRANSLATE "Pig" "Schwein"
|
||||
TRANSLATE "Rat" "Ratte"
|
||||
TRANSLATE "Ox" "Ochse"
|
||||
TRANSLATE "Tiger" "Tiger"
|
||||
TRANSLATE "Rabbit" "Kaninchen"
|
||||
TRANSLATE "Dragon" "Drachen"
|
||||
|
||||
TRANSLATE "Sunrise" "Sonnenaufgang"
|
||||
TRANSLATE "Sunset" "Sonnenuntergang"
|
||||
|
||||
TRANSLATE "No reminders." "Keine Termine."
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Support for the English language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# Nothing to do for English since it is the default.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Spanish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Rafa Couto <rafacouto@biogate.com>
|
||||
|
||||
TRANSLATE "LANGID" "es"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Finnish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Mikko Silvonen
|
||||
|
||||
TRANSLATE "LANGID" "fi"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the French language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Laurent Duperval
|
||||
|
||||
TRANSLATE "LANGID" "fr"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Hellenic (Greek) language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by jarlaxl lamat (jarlaxl@freemail.gr)
|
||||
|
||||
TRANSLATE "LANGID" "gr"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Icelanding language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Björn Davíðsson (bjossi@snerpa.is)
|
||||
|
||||
TRANSLATE "LANGID" "is"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Italian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Valerio Aimale
|
||||
|
||||
TRANSLATE "LANGID" "it"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Dutch language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Willem Kasdorp and Erik-Jan Vens
|
||||
|
||||
TRANSLATE "LANGID" "nl"
|
||||
@@ -65,33 +65,6 @@ FSET - subst_s(a, d, t) iif(day(d) == 1 || day(d) == 8, "e", day(d) < 20, "de",
|
||||
|
||||
FSET - ordx(n) n + "e"
|
||||
|
||||
TRANSLATE "New Moon" "Nieuwe maan"
|
||||
TRANSLATE "First Quarter" "Eerste kwartier"
|
||||
TRANSLATE "Full Moon" "Volle maan"
|
||||
TRANSLATE "Last Quarter" "Laatste kwartier"
|
||||
|
||||
TRANSLATE "Vernal Equinox" "Lente-equinox"
|
||||
TRANSLATE "Summer Solstice" "Zomerzonnewende"
|
||||
TRANSLATE "Autumnal Equinox" "Herfst-equinox"
|
||||
TRANSLATE "Winter Solstice" "Winterzonnewende"
|
||||
|
||||
TRANSLATE "Chinese New Year" "Chinees Nieuwjaar"
|
||||
TRANSLATE "Snake" "Slang"
|
||||
TRANSLATE "Horse" "Paard"
|
||||
TRANSLATE "Goat" "Geit"
|
||||
TRANSLATE "Monkey" "Aap"
|
||||
TRANSLATE "Rooster" "Haan"
|
||||
TRANSLATE "Dog" "Hond"
|
||||
TRANSLATE "Pig" "Varken"
|
||||
TRANSLATE "Rat" "Rat"
|
||||
TRANSLATE "Ox" "Os"
|
||||
TRANSLATE "Tiger" "Tijger"
|
||||
TRANSLATE "Rabbit" "Konijn"
|
||||
TRANSLATE "Dragon" "Draak"
|
||||
|
||||
TRANSLATE "Sunrise" "Zonsopgang"
|
||||
TRANSLATE "Sunset" "Zonsondergang"
|
||||
|
||||
TRANSLATE "No reminders." "Geen herinneringen."
|
||||
|
||||
TRANSLATE "Daylight Saving Time Begins" "Daglicht-sparende tijd begint"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Norwegian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Trygve Randen
|
||||
|
||||
TRANSLATE "LANGID" "no"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Polish language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Jerzy Sobczyk
|
||||
|
||||
TRANSLATE "LANGID" "pl"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the (Brazilian) Portuguese language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Marco Paganini
|
||||
|
||||
TRANSLATE "LANGID" "pt"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Support for the Romanian language.
|
||||
# This file is part of REMIND.
|
||||
# REMIND is Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# REMIND is Copyright (C) 1992-2026 by Dianne Skoll
|
||||
# This file is derived from a translation by Liviu Daia
|
||||
|
||||
TRANSLATE "LANGID" "ro"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Moon phases
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Localize if we can
|
||||
IF access($SysInclude + "/translations/" + _("LANGID") + "/moonphases.rem", "r") >= 0
|
||||
SYSINCLUDE translations/[_("LANGID")]/moonphases.rem
|
||||
ENDIF
|
||||
|
||||
IF $CalMode || $PsCal
|
||||
REM [moondate(0)] INFO "Url: https://en.wikipedia.org/wiki/New_moon" SPECIAL MOON 0 -1 -1 [moontime(0)]
|
||||
REM [moondate(1)] INFO "Url: https://en.wikipedia.org/wiki/Lunar_phase" SPECIAL MOON 1 -1 -1 [moontime(1)]
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Equinoxes and solstices
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Localize if we can
|
||||
IF access($SysInclude + "/translations/" + _("LANGID") + "/seasons.rem", "r") >= 0
|
||||
SYSINCLUDE translations/[_("LANGID")]/seasons.rem
|
||||
ENDIF
|
||||
|
||||
IF $LatDeg >= 0
|
||||
# Northern Hemisphere
|
||||
REM NOQUEUE [soleq(0)] INFO "Url: https://en.wikipedia.org/wiki/March_equinox" MSG %"%(Vernal Equinox)%" [$Is] %3.
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# Sunrise and sunset
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
IF !$CalMode && !$PsCal
|
||||
REM NOQUEUE AT [sunrise()] MSG %"%"%(Sunrise) %! %2.
|
||||
REM NOQUEUE AT [sunset()] MSG %"%"%(Sunset) %! %2.
|
||||
# Localize if we can
|
||||
IF access($SysInclude + "/translations/" + _("LANGID") + "/sun.rem", "r") >= 0
|
||||
SYSINCLUDE translations/[_("LANGID")]/sun.rem
|
||||
ENDIF
|
||||
|
||||
IF !$CalMode && !$PsCal
|
||||
REM INFO "Url: https://en.wikipedia.org/wiki/Sunrise" NOQUEUE AT [sunrise()] MSG %"%"%(Sunrise) %! %2.
|
||||
REM INFO "Url: https://en.wikipedia.org/wiki/Sunset" NOQUEUE AT [sunset()] MSG %"%"%(Sunset) %! %2.
|
||||
ENDIF
|
||||
|
||||
17
include/translations/README.txt
Normal file
17
include/translations/README.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
The files here contain additional translations for various files
|
||||
distributed with Remind.
|
||||
|
||||
If you create a file in $SysInclude whose name is "myfile.rem", then
|
||||
you can enable translation by putting this at the top of your
|
||||
file:
|
||||
|
||||
#===================================================================
|
||||
# Localize if we can
|
||||
IF access($SysInclude + "/translations/" + _("LANGID") + "/myfile.rem", "r") >= 0
|
||||
SYSINCLUDE translations/[_("LANGID")]/myfile.rem
|
||||
ENDIF
|
||||
#===================================================================
|
||||
|
||||
Then you can localize your file by putting appropriate TRANSLATION directives
|
||||
in the file $SysInclude/translations/<LC>/myfile.rem where <LC> is the
|
||||
two-character language code.
|
||||
13
include/translations/de/holidays/chinese-new-year.rem
Normal file
13
include/translations/de/holidays/chinese-new-year.rem
Normal file
@@ -0,0 +1,13 @@
|
||||
TRANSLATE "Chinese New Year" "Chinesisches Neujahr"
|
||||
TRANSLATE "Snake" "Schlange"
|
||||
TRANSLATE "Horse" "Pferd"
|
||||
TRANSLATE "Goat" "Ziege"
|
||||
TRANSLATE "Monkey" "Affe"
|
||||
TRANSLATE "Rooster" "Hahn"
|
||||
TRANSLATE "Dog" "Hund"
|
||||
TRANSLATE "Pig" "Schwein"
|
||||
TRANSLATE "Rat" "Ratte"
|
||||
TRANSLATE "Ox" "Ochse"
|
||||
TRANSLATE "Tiger" "Tiger"
|
||||
TRANSLATE "Rabbit" "Kaninchen"
|
||||
TRANSLATE "Dragon" "Drachen"
|
||||
4
include/translations/de/moonphases.rem
Normal file
4
include/translations/de/moonphases.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
TRANSLATE "New Moon" "Neumond"
|
||||
TRANSLATE "First Quarter" "zunehmender Halbmond"
|
||||
TRANSLATE "Full Moon" "Vollmond"
|
||||
TRANSLATE "Last Quarter" "abnehmender Halbmond"
|
||||
4
include/translations/de/seasons.rem
Normal file
4
include/translations/de/seasons.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
TRANSLATE "Vernal Equinox" "Frühlingsanfang"
|
||||
TRANSLATE "Summer Solstice" "Sommeranfang"
|
||||
TRANSLATE "Autumnal Equinox" "Herbstanfang"
|
||||
TRANSLATE "Winter Solstice" "Winteranfang"
|
||||
2
include/translations/de/sun.rem
Normal file
2
include/translations/de/sun.rem
Normal file
@@ -0,0 +1,2 @@
|
||||
TRANSLATE "Sunrise" "Sonnenaufgang"
|
||||
TRANSLATE "Sunset" "Sonnenuntergang"
|
||||
13
include/translations/nl/holidays/chinese-new-year.rem
Normal file
13
include/translations/nl/holidays/chinese-new-year.rem
Normal file
@@ -0,0 +1,13 @@
|
||||
TRANSLATE "Chinese New Year" "Chinees Nieuwjaar"
|
||||
TRANSLATE "Snake" "Slang"
|
||||
TRANSLATE "Horse" "Paard"
|
||||
TRANSLATE "Goat" "Geit"
|
||||
TRANSLATE "Monkey" "Aap"
|
||||
TRANSLATE "Rooster" "Haan"
|
||||
TRANSLATE "Dog" "Hond"
|
||||
TRANSLATE "Pig" "Varken"
|
||||
TRANSLATE "Rat" "Rat"
|
||||
TRANSLATE "Ox" "Os"
|
||||
TRANSLATE "Tiger" "Tijger"
|
||||
TRANSLATE "Rabbit" "Konijn"
|
||||
TRANSLATE "Dragon" "Draak"
|
||||
4
include/translations/nl/moonphases.rem
Normal file
4
include/translations/nl/moonphases.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
TRANSLATE "New Moon" "Nieuwe maan"
|
||||
TRANSLATE "First Quarter" "Eerste kwartier"
|
||||
TRANSLATE "Full Moon" "Volle maan"
|
||||
TRANSLATE "Last Quarter" "Laatste kwartier"
|
||||
4
include/translations/nl/seasons.rem
Normal file
4
include/translations/nl/seasons.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
TRANSLATE "Vernal Equinox" "Lente-equinox"
|
||||
TRANSLATE "Summer Solstice" "Zomerzonnewende"
|
||||
TRANSLATE "Autumnal Equinox" "Herfst-equinox"
|
||||
TRANSLATE "Winter Solstice" "Winterzonnewende"
|
||||
2
include/translations/nl/sun.rem
Normal file
2
include/translations/nl/sun.rem
Normal file
@@ -0,0 +1,2 @@
|
||||
TRANSLATE "Sunrise" "Zonsopgang"
|
||||
TRANSLATE "Sunset" "Zonsondergang"
|
||||
@@ -1,5 +1,4 @@
|
||||
.TH REM 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||
.UC 4
|
||||
.TH REM 1 "@RELEASE_DATE@" "Remind" "VERSION @VERSION@"
|
||||
.SH NAME
|
||||
rem \- Invoke Remind with a default filename
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
.TH REM2PS 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||
.UC 4
|
||||
.TH REM2PS 1 "@RELEASE_DATE@" "Remind" "VERSION @VERSION@"
|
||||
.SH NAME
|
||||
rem2ps \- draw a PostScript calendar from Remind output
|
||||
.SH SYNOPSIS
|
||||
@@ -22,6 +21,9 @@ render characters outside the ASCII character set, see
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-\-version
|
||||
Print the version of \fBrem2ps\fR and exit.
|
||||
.TP
|
||||
.B \-v
|
||||
Be more verbose. This causes \fBrem2ps\fR to print progress messages
|
||||
to the standard error stream. Normally, it is silent.
|
||||
|
||||
210
man/remind.1.in
210
man/remind.1.in
@@ -1,5 +1,4 @@
|
||||
.TH REMIND 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||
.UC 4
|
||||
.TH REMIND 1 "@RELEASE_DATE@" "Remind" "VERSION @VERSION@"
|
||||
.SH NAME
|
||||
remind \- a sophisticated reminder service
|
||||
.SH SYNOPSIS
|
||||
@@ -103,6 +102,10 @@ flag also enables the use of the UNICODE "left-to-right" mark that
|
||||
can fix up formatting problems with right-to-left languages in the calendar
|
||||
display.
|
||||
.TP
|
||||
.B 'z'
|
||||
has the effect of setting the system variable \fB$TerminalHyperlinks\fR
|
||||
to 1. See the documentation of this variable in the section "SYSTEM VARIABLES"
|
||||
.TP
|
||||
.B 'c'
|
||||
causes \fBRemind\fR to use VT100 escape sequences to approximate
|
||||
SPECIAL COLOR reminders. Note that this flag is kept for
|
||||
@@ -162,7 +165,7 @@ foreground color of a reminder and the background color of a cell,
|
||||
then you know what you are doing.
|
||||
.RE
|
||||
.TP
|
||||
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
|
||||
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR[,\fIspc2\fR]]]]
|
||||
The \fB\-w\fR option specifies the output width, padding and spacing
|
||||
of the formatted calendar output. \fICol\fR specifies the number of
|
||||
columns in the output device. If \fIcol\fR is not specified, or is
|
||||
@@ -193,7 +196,9 @@ have many reminders on certain days that make your calendar too large
|
||||
to fit on a page, you can try reducing \fIpad\fR to make the empty
|
||||
boxes smaller. \fISpc\fR specifies how many blank lines to leave
|
||||
between the day number and the first reminder entry. It defaults to
|
||||
1.
|
||||
1. \fIspc2\fR may be 0 or 1 and it specifies whether or not blank
|
||||
lines should be printed in between reminders on the same day. The
|
||||
default is 1, which causes the blank lines to be printed.
|
||||
.PP
|
||||
Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you
|
||||
provide the correct number of commas. Don't use any spaces in the option.
|
||||
@@ -344,6 +349,10 @@ Echo lines when displaying error messages
|
||||
.B f
|
||||
Trace the reading of reminder files
|
||||
.TP
|
||||
.B p
|
||||
Issue warnings if a POP-OMIT-CONTEXT, POP-VARS or POP-FUNCS matches
|
||||
a corresponding PUSH that is in a different file.
|
||||
.TP
|
||||
.B s
|
||||
Trace expression parsing and display the internal expression node
|
||||
tree. This is unlikely to be useful unless you are working on
|
||||
@@ -514,7 +523,7 @@ your reminders will be triggered in the future. Similarly, you can
|
||||
supply a \fItime\fR to set \fBRemind\fR's notion of "now" to a
|
||||
particular time. Supplying a \fItime\fR on the command line also
|
||||
implicitly enables the \fB\-q\fR option and disables the \fB\-z\fR
|
||||
option. The \fItime\fR may be specified in 24-hour format (eg, 13:20)
|
||||
option. The \fItime\fR may be specified in 24-hour format (e.g., 13:20)
|
||||
or common "AM/PM" format (1:20pm).
|
||||
.PP
|
||||
If you would rather specify the date more succinctly, you can supply
|
||||
@@ -1355,11 +1364,11 @@ minutes. That is, 13:39 and 13.39 are equivalent.
|
||||
for a timed reminder is the same as the current system date, the
|
||||
reminder is queued for later activation. When \fBRemind\fR has
|
||||
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 reaches
|
||||
the specified time. Note that if you use the \fBNOQUEUE\fR modifier
|
||||
in the \fBREM\fR command, then this queuing and background activation
|
||||
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 (e.g., in the calendar) but are not
|
||||
interested in a popup reminder happening at the specified time.
|
||||
|
||||
.PP
|
||||
@@ -1486,6 +1495,15 @@ and description of a reminder like this:
|
||||
MSG Engineering meeting
|
||||
.fi
|
||||
.PP
|
||||
While back-ends can choose which INFO strings to support, all back-ends
|
||||
should endeavor to support three standard ones: \fBLocation:\fR,
|
||||
\fBDescription:\fR and \fBUrl:\fR. TkRemind supports all three of these,
|
||||
turning reminders with a \fBUrl:\fR INFO string into hyper-links, and
|
||||
popping up information windows for the \fBLocation:\fR and \fBDescription:\fR
|
||||
INFO strings. \fBLocation:\fR and \fBUrl:\fR are self-explanatory;
|
||||
\fBDescription:\fR is meant for a longer, more in-depth description
|
||||
of the reminder than the summary that is normally displayed.
|
||||
.PP
|
||||
The \fBDURATION\fR keyword makes sense only for timed reminders; it
|
||||
specifies the duration of an event. For example, if you have a
|
||||
90-minute meeting starting at 1:00pm, you could use any of the following:
|
||||
@@ -1789,7 +1807,7 @@ or \fB\-ppp\fR option.
|
||||
use \fBrem2pdf\fR instead.
|
||||
.TP
|
||||
.B o
|
||||
The "simple calendar" formats (ie, \fBremind\fR's \fB\-s\fR, \fB\-n\fR and
|
||||
The "simple calendar" formats (i.e., \fBremind\fR's \fB\-s\fR, \fB\-n\fR and
|
||||
\fB\-p\fR options) convert newlines to spaces.
|
||||
.PP
|
||||
All calendar back-ends collapse multiple spaces to a single space and
|
||||
@@ -1981,6 +1999,7 @@ reminding you of your 2027 taxes (starting 15 days before the due
|
||||
date.)
|
||||
.PP
|
||||
It is an error to specify COMPLETE-THROUGH without also specifying TODO.
|
||||
The keyword COMPLETED-THROUGH may be used as a synonym for COMPLETE-THROUGH.
|
||||
.PP
|
||||
.SH LIMITING REMINDERS ABOUT OVERDUE TODOS
|
||||
.PP
|
||||
@@ -2046,7 +2065,7 @@ for the month of August and need to water plants every Wednesday:
|
||||
.PP
|
||||
Running that command on 13 Aug yields: "Plants 7 days ago." because you
|
||||
have not told \fBRemind\fR that you completed the first watering. If you finish
|
||||
your duties and add a COMMPLETE-THROUGH date of 2025-08-27, then \fBRemind\fR
|
||||
your duties and add a COMPLETE-THROUGH date of 2025-08-27, then \fBRemind\fR
|
||||
never reminds you of that task in the future.
|
||||
.PP
|
||||
In Purge Mode, \fBRemind\fR will not purge TODOs unless they have been marked
|
||||
@@ -2133,7 +2152,7 @@ For example, the following sequences are equivalent:
|
||||
.fi
|
||||
.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
|
||||
OMITs. If you omit a range of \fIN\fR fully-specified (i.e., 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
|
||||
@@ -2573,16 +2592,13 @@ a sequence of more than one byte. For example, in a UTF-8 environment,
|
||||
the string "🙂" contains one character but four bytes. And the string
|
||||
"één" contains three characters but five bytes.
|
||||
.PP
|
||||
\fBRemind\fR has a set of functions
|
||||
that work on \fIbytes\fR, namely \fBindex\fR, \fBstrlen\fR and \fBsubstr\fR.
|
||||
These are not safe to use on multi-byte strings; instead use
|
||||
\fBmbindex\fR, \fBmbstrlen\fR and \fBmbsubstr\fR. If you know \fIfor sure\fR
|
||||
that a string contains only single-byte characters, then the byte-oriented
|
||||
versions may be used and are faster than the multi-byte versions.
|
||||
.PP
|
||||
Some ancient or embedded systems may lack the C library functions needed
|
||||
to deal with multi-byte strings. In that case, the \fBmb\fIxxx\fR functions
|
||||
all return an error.
|
||||
\fBRemind\fR has a set of functions that work on \fIbytes\fR, namely
|
||||
\fBindex\fR, \fBstrlen\fR and \fBsubstr\fR, and several more. These
|
||||
are not safe to use on multi-byte strings; instead use \fBmbindex\fR,
|
||||
\fBmbstrlen\fR and \fBmbsubstr\fR, and the \fBmb\fR variants of the
|
||||
others. If you know \fIfor sure\fR that a string contains only
|
||||
single-byte characters, then the byte-oriented versions may be used
|
||||
and are faster than the multi-byte versions.
|
||||
.RE
|
||||
.TP
|
||||
.B TIME
|
||||
@@ -2623,7 +2639,7 @@ The following examples illustrate constants in \fBRemind\fR expressions:
|
||||
12, 36, \-10, 0, 1209, 0x1F, 0xfe00 (the last two demonstrate the use of hexadecimal constants)
|
||||
.TP
|
||||
.B STRING constants
|
||||
"Hello there", "This is a test", "\\nHello\\tThere", ""
|
||||
"Hello there", "This is a test", "\\nHello\\tThere", "", "π is Cool! 🙂"
|
||||
.PP
|
||||
.RS
|
||||
Note that the empty string is represented by "". \fBRemind\fR supports
|
||||
@@ -3244,7 +3260,7 @@ near the beginning of the file and not change it after that.
|
||||
.TP
|
||||
.B $MaxSatIter
|
||||
The maximum number of iterations for the \fBSATISFY\fR clause
|
||||
(described later.) Must be at least 10.
|
||||
(described later.) Must be at least 10. The default value is 10,000.
|
||||
.TP
|
||||
.B $MaxStringLen
|
||||
A limit on the longest string that \fBRemind\fR will allow you
|
||||
@@ -3346,6 +3362,30 @@ If non-zero, then the \fB\-p\fR option was supplied on the command line.
|
||||
.B $RunOff (read-only)
|
||||
If non-zero, the \fBRUN\fR directives are disabled.
|
||||
.TP
|
||||
.B $Shaded (read-only)
|
||||
Returns the number of times a \fBSHADE\fR special reminder has triggered.
|
||||
\fIThis variable is set only in calendar mode, not agenda mode\fR. You
|
||||
can use this variable to avoid shading a calendar day that has already
|
||||
been shaded.
|
||||
.RS
|
||||
.PP
|
||||
For example, suppose you want to shade all calendar boxes yellow
|
||||
\fIif\fR any reminders have triggered on that day. But if a box has
|
||||
been explicitly shaded, you don't want to overwrite that shading.
|
||||
You could use something like this:
|
||||
.PP
|
||||
.nf
|
||||
SET n $NumTrig
|
||||
# Do all your reminders here...
|
||||
|
||||
# If anything has triggered and the box is
|
||||
# not already shaded, then shade it yellow
|
||||
IF $NumTrig > n && !$Shaded
|
||||
REM SPECIAL SHADE 255 255 128
|
||||
ENDIF
|
||||
.fi
|
||||
.RE
|
||||
.TP
|
||||
.B $SimpleCal (read-only)
|
||||
Set to a non-zero value if \fIeither\fR of the \fB\-p\fR or \fB\-s\fR
|
||||
command-line options was supplied.
|
||||
@@ -3431,7 +3471,7 @@ problems. See also the section "MACHINES WITH A 32-BIT TIME_T TYPE"
|
||||
.B $TodoFilter (read-only)
|
||||
If 0, then both events and TODOs are being output. If 1, then the
|
||||
\fB\-\-only-todos\fR command-line option was supplied. If 2, then
|
||||
the \fB\-\-only-events\fR command-line option was spplied.
|
||||
the \fB\-\-only-events\fR command-line option was supplied.
|
||||
.TP
|
||||
.B $UntimedFirst (read-only)
|
||||
Set to 1 if the \fB\-g\fR option is used with a fourth sort character
|
||||
@@ -3473,6 +3513,13 @@ to be "dark" if the average of the red, green and blue components is
|
||||
at most 85 out of 255, and if the maximum of any component is at most
|
||||
128 out of 255.
|
||||
.TP
|
||||
.B $TerminalHyperlinks (INT type)
|
||||
If your terminal supports escape sequences to allow HTML-like
|
||||
anchors around text (see https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda), then you can set this variable to 1. \fBRemind\fR will then
|
||||
make any reminder with a "Url:" info string into a hyperlink in your
|
||||
terminal. By default, \fB$TerminalHyperlinks\fR is set to 1 if \fBRemind\fR's
|
||||
standard output is a terminal, or to 0 if it is not.
|
||||
.TP
|
||||
.B $WarningLevel (STRING type)
|
||||
As new versions of \fBRemind\fR are released, new warnings may be added.
|
||||
If your formerly-fine scripts suddenly start issuing warnings when you
|
||||
@@ -3834,9 +3881,10 @@ integer.
|
||||
.TP
|
||||
.B columns([s_arg])
|
||||
If called with no arguments, \fBcolumns()\fR behaves as follows:
|
||||
If standard output is a TTY, returns the width of the terminal in columns.
|
||||
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
|
||||
the terminal size. If this fails, returns -1.
|
||||
If either standard output or standard error is a TTY, returns the
|
||||
width of the terminal in columns. If neither standard output nor
|
||||
standard error is a TTY, attempts to open "/dev/tty" to obtain the
|
||||
terminal size. If this fails, returns -1.
|
||||
.RS
|
||||
.PP
|
||||
If called with a single string argument, \fBcolumns(str)\fR returns
|
||||
@@ -4128,10 +4176,10 @@ Returns an \fBINT\fR that is the location of \fItarget\fR in the
|
||||
string \fIsearch\fR. Note that \fBindex\fR uses \fIbyte\fR positions,
|
||||
not character positions, so should not be used on non-ASCII strings. Use
|
||||
\fBmbindex\fR for non-ASCII strings.
|
||||
.RS
|
||||
.PP
|
||||
The first byte of a string is numbered 1. If \fItarget\fR does not
|
||||
exist in \fIsearch\fR, then 0 is returned.
|
||||
.RS
|
||||
.PP
|
||||
The optional parameter \fIstart\fR specifies the position in
|
||||
\fIsearch\fR at which to start looking for \fItarget\fR.
|
||||
@@ -4200,8 +4248,15 @@ Given a \fBDATETIME\fR object interpreted in the local time zone, return
|
||||
a \fBDATETIME\fR object that expresses the same time in UTC.
|
||||
.TP
|
||||
.B lower(s_string)
|
||||
Returns a \fBSTRING\fR with all upper-case bytes in \fIstring\fR
|
||||
converted to lower-case. \fBNote:\fR This function works correctly
|
||||
only for ASCII strings. If you are using Unicode characters outside
|
||||
the ASCII set, use \fBmblower\fR instead.
|
||||
.TP
|
||||
.B mblower(s_string)
|
||||
Returns a \fBSTRING\fR with all upper-case characters in \fIstring\fR
|
||||
converted to lower-case.
|
||||
converted to lower-case. This function works correctly on any
|
||||
Unicode string.
|
||||
.TP
|
||||
.B max(x_arg1 [,x_arg2...)
|
||||
Can take any number of arguments, and returns the maximum. The arguments
|
||||
@@ -4484,7 +4539,8 @@ to be considered \fInon-constant\fR. For details, see the section
|
||||
.TP
|
||||
.B now()
|
||||
Returns the current system time, as a \fBTIME\fR type. This may be
|
||||
the actual time, or a time supplied on the command line.
|
||||
the actual time, or a time supplied on the command line. Note that
|
||||
in Calendar Mode, \fBnow()\fR always returns 00:00.
|
||||
.TP
|
||||
.B ord(i_num)
|
||||
Returns a string that is the ordinal number \fInum\fR. For example,
|
||||
@@ -4515,8 +4571,8 @@ any longer.
|
||||
.TP
|
||||
.B pad(x_arg, s_padstr, i_len [, i_right])
|
||||
Converts the first argument \fIarg\fR to a string if necessary, and
|
||||
then if it is shorter than \fIlen\fR characters, pads to to
|
||||
\fIlen\fR characters using as many copies (including partial copies)
|
||||
then if it is shorter than \fIlen\fR bytes, pads to to
|
||||
\fIlen\fR bytes using as many copies (including partial copies)
|
||||
of \fIpadstr\fR as necessary. By default, the string is left-padded,
|
||||
but if \fIright\fR is supplied and non-zero, the string will
|
||||
be right-padded.
|
||||
@@ -4533,6 +4589,11 @@ Here are some examples:
|
||||
.fi
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B mbpad(x_arg, s_padstr, i_len [, i_right])
|
||||
This is the multibyte counterpart to \fBpad\fR. The length is
|
||||
specified in characters rather than bytes. Use \fBmbpad\fR rather
|
||||
than \fBpad\fR if either of the strings contains non-ASCII characters.
|
||||
.TP
|
||||
.B plural(i_num [,s_str1 [,s_str2]])
|
||||
Can take from one to three arguments. If one argument is supplied, returns
|
||||
@@ -4611,7 +4672,7 @@ may return a time supplied on the command line.
|
||||
.B realnow()
|
||||
Returns the true time of day as provided by the operating system.
|
||||
This is in contrast to \fBnow()\fR, which may return a time supplied
|
||||
on the command line.
|
||||
on the command line, or 00:00 in Calendar Mode.
|
||||
.TP
|
||||
.B realtoday()
|
||||
Returns the date as provided by the operating system. This is in contrast to
|
||||
@@ -4619,9 +4680,10 @@ Returns the date as provided by the operating system. This is in contrast to
|
||||
in calendar mode, or if a date has been supplied on the command line.
|
||||
.TP
|
||||
.B rows()
|
||||
If standard output is a TTY, returns the height of the terminal in rows.
|
||||
If standard output is not a TTY, attempts to open "/dev/tty" to obtain
|
||||
the terminal size. If this fails, returns -1.
|
||||
If either standard output or standard error is a TTY, returns the
|
||||
height of the terminal in rows. If neither standard output nor
|
||||
standard error is a TTY, attempts to open "/dev/tty" to obtain the
|
||||
terminal size. If this fails, returns -1.
|
||||
.TP
|
||||
.B sgn(i_num)
|
||||
Returns \-1 if \fInum\fR is negative, 1 if \fInum\fR is positive,
|
||||
@@ -4736,7 +4798,7 @@ to use \fBsoleq()\fR.
|
||||
Returns a string representing where Remind's standard output is going.
|
||||
The return values are one of the following: "TTY" if standard-output
|
||||
is a terminal, "BLOCKDEV" if it is a block device (very unlikely),
|
||||
"CHARDEV" if it is a character device (eg, /dev/null), "DIR" if it
|
||||
"CHARDEV" if it is a character device (e.g., /dev/null), "DIR" if it
|
||||
is a directory (very unlikely), "PIPE" if it is a pipe or FIFO,
|
||||
"SYMLINK" if it is a symlink (very unlikely), "SOCKET" if it is a
|
||||
socket, or "UNKNOWN" if it could not be determined.
|
||||
@@ -4809,9 +4871,9 @@ value of \fBcurrent()\fR. If a \fBDATE\fR rather than \fBDATETIME\fR
|
||||
is supplied, \fBRemind\fR uses a time part of 00:00.
|
||||
.TP
|
||||
.B today()
|
||||
Returns \fBRemind\fR's notion of "today." This may be the actual system
|
||||
date, or a date supplied on the command line, or the date of the
|
||||
calendar entry currently being computed.
|
||||
Returns \fBRemind\fR's notion of "today." This may be the actual
|
||||
system date, or a date supplied on the command line, or (in Calendar
|
||||
Mode) the date of the calendar entry currently being computed.
|
||||
.TP
|
||||
.B trig(s_1 [,s_2, ...])
|
||||
For each string argument s_\fIn\fR, \fBtrig\fR evaluates s_\fIn\fR
|
||||
@@ -5085,6 +5147,7 @@ If \fBdstzone\fR is omitted or is the empty string, the default system
|
||||
time zone is used as the destination zone. The return value is a
|
||||
DATETIME. Time zone names are system-dependent; consult your
|
||||
operating system for legal values. Here is an example:
|
||||
.RS
|
||||
.PP
|
||||
.nf
|
||||
tzconvert('2007-07-08@01:14', "Canada/Eastern", "Canada/Pacific")
|
||||
@@ -5094,10 +5157,23 @@ operating system for legal values. Here is an example:
|
||||
2007-07-07@22:14
|
||||
.fi
|
||||
.PP
|
||||
If your system includes the directory /usr/share/zoneinfo, \fBRemind\fR
|
||||
will warn you if you use an invalid time zone name for \fBsrczone\fR or
|
||||
\fBdstzone\fR. To suppress these warnings, add a "!" to the beginning
|
||||
of the time zone name.
|
||||
.RE
|
||||
.PP
|
||||
.TP
|
||||
.B upper(s_string)
|
||||
Returns a \fBSTRING\fR with all lower-case bytes in \fIstring\fR
|
||||
converted to upper-case. \fBNote:\fR This function works correctly
|
||||
only for ASCII strings. If you are using Unicode characters outside
|
||||
the ASCII set, use \fBmbupper\fR instead.
|
||||
.TP
|
||||
.B mbupper(s_string)
|
||||
Returns a \fBSTRING\fR with all lower-case characters in \fIstring\fR
|
||||
converted to upper-case.
|
||||
converted to upper-case. This function works correctly on any
|
||||
Unicode string.
|
||||
.TP
|
||||
.B utctolocal(q_datetime)
|
||||
Given a \fBDATETIME\fR object interpreted in UTC, return a
|
||||
@@ -5307,8 +5383,7 @@ expressions are evaluated only once, not recursively. Thus, writing:
|
||||
.fi
|
||||
.PP
|
||||
causes \fBRemind\fR to read the token "[a+b]". It does not interpret
|
||||
this as a pasted-in expression. In fact, the only way to get a literal
|
||||
left-bracket into a reminder is to use ["["].
|
||||
this as a pasted-in expression.
|
||||
.PP
|
||||
You can use expression pasting almost anywhere. However, there are a few
|
||||
exceptions:
|
||||
@@ -5595,8 +5670,6 @@ following example:
|
||||
# FSET -f(x) 2*x
|
||||
.fi
|
||||
.PP
|
||||
to define a function and suppress any "redefined function" warning.
|
||||
.PP
|
||||
.SH SAVING AND RESTORING FUNCTIONS
|
||||
.PP
|
||||
Occasionally, it is useful to redefine a function for a specific block of
|
||||
@@ -6453,7 +6526,7 @@ the trigger. For example:
|
||||
REM 1992-01-01 MSG This will be purged after Jan 1 1992
|
||||
REM [nonconst('1992-01-01')] MSG This will never be purged
|
||||
|
||||
REM Wed UNTIL 1993-12-31 MSG THis will be purged after 1993
|
||||
REM Wed UNTIL 1993-12-31 MSG This will be purged after 1993
|
||||
REM Wed UNTIL [nonconst('1993-12-31')] MSG Never purged
|
||||
.fi
|
||||
.PP
|
||||
@@ -6901,14 +6974,43 @@ jahrzeits (anniversaries of deaths) and smachot (joyous occasions.)
|
||||
.PP
|
||||
.B THE HEBREW YEAR
|
||||
.PP
|
||||
The Hebrew year has 12 months, alternately 30 and 29 days long. The months
|
||||
are: Tishrey, Heshvan, Kislev, Tevet, Shvat, Adar, Nisan, Iyar, Sivan, Tamuz,
|
||||
Av and Elul. In Biblical times, the year started in Nisan, but Rosh Hashana
|
||||
(Jewish New Year) is now celebrated on the 1st and 2nd of Tishrey.
|
||||
The Hebrew year has 12 months, alternately 30 and 29 days long. The
|
||||
months are: Tishrey, Heshvan, Kislev, Tevet, Shvat, Adar, Nisan, Iyar,
|
||||
Sivan, Tamuz, Av and Elul. If you are in a UTF-8 locale, you can
|
||||
\fIalso\fR use the UTF-8-encoded Hebrew spellings for the month names,
|
||||
namely:
|
||||
.PP
|
||||
תשרי, חשוון, כסלו, טבת, שבט, אדר, ניסן, אייר, סיון, תמוז, אב, אלול.
|
||||
.PP
|
||||
In a cycle of 19 years, there are 7 leap years, being years 3, 6, 8, 11,
|
||||
14, 17 and 19 of the cycle. In a leap year, an extra month of 30 days
|
||||
is added before Adar. The two Adars are called Adar A and Adar B.
|
||||
is added before Adar. The two Adars are called Adar A and Adar B,
|
||||
or in Hebrew, 'אדר א and 'אדר ב.
|
||||
.PP
|
||||
\fBRemind\fR also permits the following alternative spellings for
|
||||
Hebrew month names:
|
||||
.TP
|
||||
.B Tishrey
|
||||
Can also be spelled Tishri or Tishrei
|
||||
.TP
|
||||
.B Heshvan
|
||||
Can also be spelled Cheshvan or Kheshvan
|
||||
.TP
|
||||
.B Shvat
|
||||
Can also be spelled Shevat
|
||||
.TP
|
||||
.B Tamuz
|
||||
Can also be spelled Tammuz
|
||||
.TP
|
||||
.B Adar A
|
||||
Can also be spelled Adar 1, Adar I, אדר א or אדר 1.
|
||||
.TP
|
||||
.B Adar B
|
||||
Can also be spelled Adar 2, Adar II, אדר ב or אדר 2.
|
||||
.TP
|
||||
.B Iyar
|
||||
Can also be spelled Iyyar.
|
||||
|
||||
.PP
|
||||
For certain religious reasons, the year cannot start on a Sunday, Wednesday
|
||||
or Friday. To adjust for this, a day is taken off Kislev or added to Heshvan.
|
||||
@@ -6938,6 +7040,11 @@ Thus, hebday('1993/04/12') returns 21.
|
||||
Returns the name of the Hebrew month corresponding to \fIdate\fR.
|
||||
For example, hebmon('1993/04/12') returns "Nisan".
|
||||
.TP
|
||||
.B ivritmon(d_date)
|
||||
Returns the name of the Hebrew month corresponding to \fIdate\fR,
|
||||
in UTF-8-encoded Hebrew script. For example, ivritmon('1993/04/12')
|
||||
returns "ניסן".
|
||||
.TP
|
||||
.B hebyear(d_date)
|
||||
Returns the Hebrew year corresponding to \fIdate\fR. For example,
|
||||
hebyear('1993/04/12') returns 5753.
|
||||
@@ -6951,7 +7058,8 @@ corresponding to the Hebrew date.
|
||||
The \fIday\fR parameter can range from 1 to 30, and specifies the day of
|
||||
the Hebrew month. The \fIhebmon\fR parameter is a string that must name
|
||||
one of the Hebrew months specified above. Note that the month must be spelled
|
||||
out in full, and use the English transliteration shown previously. You can
|
||||
out in full, and use either the English transliteration shown previously, or
|
||||
the Hebrew spelling \fIencoded in UTF-8\fR. You can
|
||||
also specify "Adar A" and "Adar B." Month names are not case-sensitive.
|
||||
.PP
|
||||
The \fIyrstart\fR parameter can either be a \fBDATE\fR or an \fBINT\fR. If
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
.TH TKREMIND 1 "@RELEASE_DATE@" "User Commands" "VERSION @VERSION@"
|
||||
.UC 4
|
||||
.TH TKREMIND 1 "@RELEASE_DATE@" "Remind" "VERSION @VERSION@"
|
||||
.SH NAME
|
||||
tkremind \- graphical front-end to Remind calendar program
|
||||
.SH SYNOPSIS
|
||||
@@ -19,10 +18,12 @@ binary. If you are using Tcl/Tk 8.5, you may also need either the Img
|
||||
or the tkpng extension to handle PNG images.
|
||||
|
||||
.SH COMMAND-LINE OPTIONS
|
||||
\fBTkRemind\fR itself has no command-line options. However, it passes
|
||||
any command-line argument starting with \fB\-\fR to \fBRemind\fR as an
|
||||
option. In addition, \fBTkRemind\fR will respect the \fB\-m\fR and
|
||||
\fB\-b1\fR options and adjust its appearance accordingly.
|
||||
\fBTkRemind\fR itself has only one command-line option:
|
||||
\fB\-\-version\fR, which makes it print the version of \fBTkRemind\fR
|
||||
and exit. Any other command-line argument starting with \fB\-\fR to
|
||||
\fBRemind\fR as an option. In addition, \fBTkRemind\fR will respect
|
||||
the \fB\-m\fR and \fB\-b1\fR options and adjust its appearance
|
||||
accordingly.
|
||||
.PP
|
||||
\fIRead_file\fR is the file from which \fBTkRemind\fR reads reminders.
|
||||
It is in standard \fBRemind\fR format. \fIWrite_file\fR is the file
|
||||
@@ -54,29 +55,47 @@ directory before starting \fBTkRemind\fR.
|
||||
When you start \fBTkRemind\fR, it displays a calendar for the current
|
||||
month, with today's date highlighted. Reminders are filled into each
|
||||
box on the calendar. If a box contains many reminders, you can scroll
|
||||
it up and down by dragging mouse button 2 in the box. Note that there
|
||||
is no specific indication of an over-full box; you'll just have to
|
||||
notice that the box appears completely full.
|
||||
it up and down by dragging mouse button 2 in the box or by using the
|
||||
scroll wheel (if your mouse has one.) Note that there is no specific
|
||||
indication of an over-full box; you'll just have to notice that the
|
||||
box appears completely full.
|
||||
|
||||
.SH NAVIGATING
|
||||
To change to the previous or next month, click the \fB<\-\fR
|
||||
or \fB\->\fR button, respectively. You can also use the left/right arrow
|
||||
keys or PageUp/PageDown to navigate.
|
||||
keys or \fBPgUp\fR/\fBPgDn\fR to navigate.
|
||||
|
||||
To change back to the current month, click \fBToday\fR or press the
|
||||
Home key. To go to a specific month, click \fBGo To Date...\fR. This
|
||||
pops up a dialog box which allows you to select a month and enter a
|
||||
year. Once you've done this, click \fBGo\fR to go to the date, or
|
||||
\fBCancel\fR to cancel.
|
||||
\fBHome\fR key. To go to a specific month, click \fBGo To Date...\fR
|
||||
or press \fBg\fR. This pops up a dialog box which allows you to
|
||||
select a month and enter a year. Once you've done this, click
|
||||
\fBGo\fR to go to the date, or \fBCancel\fR to cancel. Note also that
|
||||
all pop-up windows in \fBTkRemind\fR can be dismissed by pressing
|
||||
\fBEsc\fR or \fBControl-w\fR.
|
||||
|
||||
To exit \fBTkRemind\fR, click \fBQuit\fR.
|
||||
To exit \fBTkRemind\fR, click \fBQuit\fR or press \fBControl-q\fR..
|
||||
|
||||
.SH CHANGING THE VIEW
|
||||
By default, \fBTkRemind\fR shows the calendar for an entire month.
|
||||
The \fBView...\fR menu lets you pick from the following choices: Display
|
||||
an entire month, or display one, two or four weeks' worth of reminders.
|
||||
If you change the view, \fBTkRemind\fR remembers the change and that
|
||||
view becomes the default view next time you start \fBTkRemind\fR
|
||||
|
||||
In the monthly view, the Next and Previous navigation buttons and keyboard
|
||||
shortcuts move by one month. In all other views, they move by one week.
|
||||
This is true even for views that display multiple weeks.
|
||||
|
||||
You can press the keys \fB1\fR, \fB2\fR, \fB4\fR or \fBm\fR over the
|
||||
main calendar window to change the view to one week, two weeks, four weeks
|
||||
or one month, respectively.
|
||||
|
||||
.SH ADDING REMINDERS
|
||||
To add a reminder, click button 1 in any day number in the calendar.
|
||||
The \fBAdd Reminder...\fR dialog will pop up, with values preselected for
|
||||
the day you clicked.
|
||||
|
||||
The dialog has six basic groups of controls. The first three lines
|
||||
The dialog has seven basic groups of controls. The first three lines
|
||||
select one of three types of reminders. Choose the type of reminder
|
||||
with the radio buttons, and choose the values of the days, months, and
|
||||
years by selecting values from pull-down menus. The pull-down menus
|
||||
@@ -127,23 +146,37 @@ reminder you entered using the \fBAdd Reminder...\fR dialog. You can
|
||||
edit the reminder, thereby gaining access to advanced features of
|
||||
\fBRemind\fR. You can also use it simply to play around and discover
|
||||
\fBRemind\fR's idioms for expressing different types of reminders.
|
||||
.PP
|
||||
\fBNOTE\fR: If you hand-edit a reminder, then that reminder will
|
||||
\fInot\fR be editable in TkRemind's graphical reminder dialog any more.
|
||||
You will have to hand-edit it to change it.
|
||||
|
||||
.SH SEEING A SINGLE DAY'S REMINDERS
|
||||
Right-click on any day number in the calendar to pop up a window with
|
||||
that day's reminders in Agenda Mode. You can left- or right-click the
|
||||
current date and time indicator at the bottom of the window to see today's
|
||||
reminders in Agenda Mode.
|
||||
current date and time indicator at the bottom of the calendar window
|
||||
to see today's reminders in Agenda Mode. You can also press \fBt\fR
|
||||
over the main calendar window to see today's reminders in Agenda Mode.
|
||||
|
||||
In the Agenda Mode display, hovering over a reminder will show ancillary
|
||||
information such as a Location, URL or Description. Clicking on a reminder
|
||||
will open an editor on the REM command that created the reminder.
|
||||
will open an editor on the REM command that created the reminder. You can
|
||||
also navigate in the Agenda Mode window one day at a time using the
|
||||
forward and back arrow buttons or left/right arrow keys or \fBPgUp\fR/\fBPgDn\fR.
|
||||
You can get back to today by clicking \fBToday\fR or pressing the
|
||||
\fBHome\fR key.
|
||||
|
||||
You can dismiss the Agenda Mode window by clicking \fBOK\fR or pressing
|
||||
the \fBEsc\fR key.
|
||||
|
||||
.SH PRINTING
|
||||
To print the current month's calendar, click \fBPrint...\fR on the
|
||||
main calendar window. This brings up the print dialog. Printing
|
||||
either produces a PostScript file or sends PostScript to a UNIX command.
|
||||
(If you have \fBrem2pdf\fR installed, you can choose to produce
|
||||
PDF output rather than PostScript.)
|
||||
main calendar window or press \fBp\fR or \fBControl-p\fR. This brings
|
||||
up the print dialog. Printing either produces a PostScript or PDF
|
||||
file, or sends PostScript or PDF to a UNIX command.
|
||||
|
||||
Note that you must have \fBrem2pdf\fR installed in order to be
|
||||
able to print.
|
||||
|
||||
Select the print destination by choosing either \fBTo file:\fR or
|
||||
\fBTo command:\fR in the print dialog. Press \fBBrowse...\fR to bring
|
||||
@@ -160,7 +193,7 @@ the directory.
|
||||
Select the appropriate paper size and orientation. Activate
|
||||
\fBFill page\fR if you want the calendar to fill the page. This should
|
||||
be the normal case unless you have many reminders in a particular
|
||||
day. (See the \fBRem2PS\fR or \fBrem2pdf\fR documentation.)
|
||||
day. (See the \fBrem2pdf\fR documentation.)
|
||||
|
||||
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Note
|
||||
that during printing, \fBRemind\fR is called with the
|
||||
@@ -168,6 +201,12 @@ that during printing, \fBRemind\fR is called with the
|
||||
option. If you are producing PDF output, then the option \fB-itkpdf=1\fR
|
||||
is also supplied to \fBRemind\fR.
|
||||
|
||||
If you click on \fBShow Command\fR rather than \fBPrint\fR, then
|
||||
\fBTkRemind\fR won't actually print anything. Instead, it will pop
|
||||
up a text window with the command that it \fIwould have used\fR to print
|
||||
the calendar. You can adjust the command as needed and then click \fBRun\fR
|
||||
to run the modified command. This lets you specify \fBrem2pdf\fR options
|
||||
that are not directly supported by \fBTkRemind\fR.
|
||||
|
||||
.SH EDITING REMINDERS
|
||||
|
||||
@@ -181,13 +220,11 @@ reminder entirely by selecting \fBDelete reminder\fR. The remaining
|
||||
buttons, \fBPreview reminder\fR and \fBCancel\fR operate identically
|
||||
to the dialog in "ADDING REMINDERS."
|
||||
|
||||
Note that if you edit a reminder (using \fBPreview reminder\fR),
|
||||
any edits you made are \fInot\fR retained in the dialog box. You
|
||||
should not attempt to edit such reminders; you have to retype them
|
||||
in the \fBPreview reminder\fR dialog.
|
||||
|
||||
If the reminder was not created with \fBTkRemind\fR, you can't edit
|
||||
it with \fBTkRemind\fR.
|
||||
Note that if you have hand-edited a reminder (using \fBPreview
|
||||
reminder\fR), or if the reminder was hand-created in the first place,
|
||||
then clicking on it will \fInot\fR pop up the TkRemind
|
||||
reminder-editing dialog. Instead, TkRemind will start up a text
|
||||
editor (if you have configured one) so you can hand-edit the reminder.
|
||||
|
||||
.SH USING A TEXT EDITOR
|
||||
|
||||
@@ -230,7 +267,8 @@ option of "turning off" the reminder for the rest of the day.
|
||||
.SH OPTIONS
|
||||
|
||||
The final button on the calendar window, \fBOptions\fR, lets you configure
|
||||
certain aspects of \fBTkRemind\fR. The configuration options are:
|
||||
certain aspects of \fBTkRemind\fR. You can also pop up the options
|
||||
window by pressing \fBo\fR. The configuration options are:
|
||||
|
||||
.TP
|
||||
.B Start up Iconified
|
||||
@@ -323,22 +361,6 @@ press \fBApply Options\fR to put them into effect, \fBSave Options\fR
|
||||
to put them into effect and save them in $HOME/.config/tkremindrc, or
|
||||
\fBCancel\fR to cancel any changes you made.
|
||||
|
||||
.SH KEYBOARD SHORTCUTS
|
||||
\fBTkRemind\fR's main window includes the following keyboard shortcuts:
|
||||
|
||||
.TP
|
||||
.B Ctrl-Q
|
||||
Quit
|
||||
.TP
|
||||
.B Left Arrow
|
||||
Previous Month
|
||||
.TP
|
||||
.B Right Arrow
|
||||
Next Month
|
||||
.TP
|
||||
.B Home
|
||||
Today
|
||||
|
||||
.SH IMMEDIATE UPDATES
|
||||
|
||||
If you are running \fBTkRemind\fR on Linux and \fBRemind\fR has been
|
||||
@@ -542,7 +564,7 @@ asynchronous status messages.
|
||||
.SH AUTHOR
|
||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
\fBTkRemind\fR is Copyright (C) 1996-2025 by Dianne Skoll.
|
||||
\fBTkRemind\fR is Copyright (C) 1996-2026 by Dianne Skoll.
|
||||
|
||||
.SH FILES
|
||||
|
||||
@@ -553,5 +575,5 @@ $HOME/.config/tkremindrc -- \fBTkRemind\fR saved options.
|
||||
.SH HOME PAGE
|
||||
https://dianne.skoll.ca/projects/remind/
|
||||
.SH SEE ALSO
|
||||
\fBremind\fR, \fBrem2ps\fR, \fBrem2pdf\fR, \fBrem2html\fR
|
||||
\fBremind\fR, \fBrem2pdf\fR, \fBrem2html\fR
|
||||
|
||||
|
||||
@@ -96,6 +96,14 @@ without any E<lt>htmlE<gt> or E<lt>bodyE<gt> tags.
|
||||
Use I<title> as the content between E<lt>titleE<gt> and E<lt>/titleE<gt>
|
||||
tags.
|
||||
|
||||
=item --yaag
|
||||
|
||||
Instead of making 7-column tables for each month, show each month
|
||||
as a I<single> table row of 38 columns. This is the so-called
|
||||
"year-at-a-glance" format. You must use the "-ppp" option to
|
||||
C<remind> or the --yaag option will be ignored. And this format
|
||||
works best if you create a calendar for an entire year (so, starting
|
||||
in January and using "-ppp12" to get 12 months' worth of reminders.)
|
||||
|
||||
=item --prologue I<html_text>
|
||||
|
||||
@@ -188,6 +196,7 @@ Options:
|
||||
--title string What to put in <title>...</title> tags
|
||||
--prologue html_text Text to insert at the top of the body
|
||||
--epilogue html_text Text to insert at the end of the body
|
||||
--yaag Output one month per row for year-at-a-glance format
|
||||
EOM
|
||||
exit($exit_status);
|
||||
}
|
||||
@@ -218,6 +227,7 @@ sub parse_options
|
||||
"man",
|
||||
"utf8",
|
||||
"pngs",
|
||||
"yaag",
|
||||
"version",
|
||||
"stylesheet=s",
|
||||
"nostyle",
|
||||
@@ -316,6 +326,10 @@ sub parse_input
|
||||
if ($_ eq '[') {
|
||||
return parse_input_ppp();
|
||||
}
|
||||
if ($Options{yaag}) {
|
||||
$Options{yaag} = 0;
|
||||
print STDERR "Ignoring option --yaag: You must use remind -ppp for this option\n";
|
||||
}
|
||||
if (/# translations/) {
|
||||
slurp_translations();
|
||||
next;
|
||||
@@ -472,6 +486,10 @@ sub parse_input_ppp
|
||||
}
|
||||
if (exists($array->[0]{caltype}) &&
|
||||
$array->[0]{caltype} eq 'weekly') {
|
||||
if ($Options{yaag}) {
|
||||
$Options{yaag} = 0;
|
||||
print STDERR "Ignoring option --yaag for a weekly calendar\n";
|
||||
}
|
||||
emit_ppp_calendars($array, 'weekly');
|
||||
} else {
|
||||
emit_ppp_calendars($array, 'monthly');
|
||||
@@ -488,11 +506,51 @@ sub parse_input_ppp
|
||||
}
|
||||
}
|
||||
|
||||
sub print_yaag_weekday_row
|
||||
{
|
||||
my ($cal) = @_;
|
||||
print "<tr class=\"rem-yaag-weekday-row\">";
|
||||
print "<th class=\"rem-yaag-empty-header\"> </th>";
|
||||
my $ex;
|
||||
for (my $i=0; $i<37; $i++) {
|
||||
my $day;
|
||||
if ($cal->{mondayfirst}) {
|
||||
$day = $cal->{daynames}->[($i+1) % 7];
|
||||
} else {
|
||||
$day = $cal->{daynames}->[$i % 7];
|
||||
}
|
||||
if (($i % 7) == 6) {
|
||||
$ex = " rem-yaag-end-of-week";
|
||||
} else {
|
||||
$ex = "";
|
||||
}
|
||||
print "<th class=\"rem-yaag-weekday-header$ex\">$day</th>";
|
||||
}
|
||||
print "</tr>\n";
|
||||
}
|
||||
|
||||
sub emit_ppp_calendars
|
||||
{
|
||||
my ($array, $type) = @_;
|
||||
my $prev_year = 0;
|
||||
my $done_one = 0;
|
||||
foreach my $cal (@$array) {
|
||||
if ($Options{yaag}) {
|
||||
if ($cal->{year} != $prev_year) {
|
||||
$prev_year = $cal->{year};
|
||||
if ($done_one) {
|
||||
print "</table>\n";
|
||||
}
|
||||
print "<span class=\"year_heading\">$prev_year</span>\n";
|
||||
print "<table class=\"rem-yaag\">\n";
|
||||
print_yaag_weekday_row($cal);
|
||||
}
|
||||
}
|
||||
emit_one_ppp_calendar($cal, $type);
|
||||
$done_one = 1;
|
||||
}
|
||||
if ($done_one) {
|
||||
print "</table>\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,42 +824,79 @@ sub output_calendar
|
||||
|
||||
# Start the table
|
||||
my $class;
|
||||
if ($Options{nostyle}) {
|
||||
print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
|
||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||
print '<tr>';
|
||||
$class = ' width="14%"';
|
||||
} else {
|
||||
if ($type eq 'monthly') {
|
||||
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
|
||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||
if (!$Options{yaag}) {
|
||||
if ($Options{nostyle}) {
|
||||
print '<table width="100%" border="1" cellspacing="0">';
|
||||
if ($type eq 'monthly') {
|
||||
print "<caption>$Month $Year </caption>";
|
||||
}
|
||||
print "\n<tr>";
|
||||
$class = ' width="14%"';
|
||||
} else {
|
||||
print '<table class="rem-cal">' . "\n";
|
||||
if ($type eq 'monthly') {
|
||||
print '<table class="rem-cal"><caption class="rem-cal-caption">' .
|
||||
$Month . ' ' . $Year . '</caption>' . "\n";
|
||||
} else {
|
||||
print '<table class="rem-cal">' . "\n";
|
||||
}
|
||||
print '<tr class="rem-cal-hdr-row">';
|
||||
$class = ' class="rem-cal-hdr"';
|
||||
}
|
||||
print '<tr class="rem-cal-hdr-row">';
|
||||
$class = ' class="rem-cal-hdr"';
|
||||
}
|
||||
if ($type eq 'monthly') {
|
||||
if (!$Mondayfirst) {
|
||||
print "<th$class>" . $Daynames[0] . '</th>';
|
||||
if ($type eq 'monthly') {
|
||||
if (!$Mondayfirst) {
|
||||
print "<th$class>" . $Daynames[0] . '</th>';
|
||||
}
|
||||
for (my $i=1; $i<7; $i++) {
|
||||
print "<th$class>" . $Daynames[$i] . '</th>';
|
||||
}
|
||||
if ($Mondayfirst) {
|
||||
print "<th$class>" . $Daynames[0] . '</th>';
|
||||
}
|
||||
} else {
|
||||
for (my $i=0; $i<7; $i++) {
|
||||
my $inf = $date_info->[$i];
|
||||
print "<th$class>" . $inf->{dayname} . "<br>" .
|
||||
$inf->{day} . ' ' .
|
||||
$inf->{month} . ' ' .
|
||||
$inf->{year} . '</th>';
|
||||
}
|
||||
}
|
||||
for (my $i=1; $i<7; $i++) {
|
||||
print "<th$class>" . $Daynames[$i] . '</th>';
|
||||
}
|
||||
if ($Mondayfirst) {
|
||||
print "<th$class>" . $Daynames[0] . '</th>';
|
||||
}
|
||||
} else {
|
||||
for (my $i=0; $i<7; $i++) {
|
||||
my $inf = $date_info->[$i];
|
||||
print "<th$class>" . $inf->{dayname} . "<br>" .
|
||||
$inf->{day} . ' ' .
|
||||
$inf->{month} . ' ' .
|
||||
$inf->{year} . '</th>';
|
||||
}
|
||||
}
|
||||
|
||||
print "</tr>\n";
|
||||
print "</tr>\n";
|
||||
} else {
|
||||
# For year-at-a-glance calendar, it's just a row
|
||||
print '<tr class="rem-yaag-cal-row">';
|
||||
print '<th class="rem-yaag-cal-hdr">' . $Month . "</th>\n";
|
||||
|
||||
my $cells_drawn = 0;
|
||||
# Print the blank ones
|
||||
for (my $i=0; $i<$first_col; $i++) {
|
||||
print "<td class=\"rem-yaag-cal-blank\"> </td>";
|
||||
$cells_drawn++;
|
||||
}
|
||||
|
||||
# All the entries
|
||||
for (my $day=1; $day <= $Numdays; $day++) {
|
||||
if (($cells_drawn % 7) == 6) {
|
||||
draw_day_cell($day, 1, $type, ' rem-yaag-end-of-week');
|
||||
} else {
|
||||
draw_day_cell($day, 1, $type);
|
||||
}
|
||||
$cells_drawn++;
|
||||
}
|
||||
|
||||
# And fill in the remaining ones
|
||||
while ($cells_drawn < 37) {
|
||||
if (($cells_drawn % 7) == 6) {
|
||||
print "<td class=\"rem-yaag-cal-blank rem-yaag-end-of-week\"> </td>";
|
||||
} else {
|
||||
print "<td class=\"rem-yaag-cal-blank\"> </td>";
|
||||
}
|
||||
$cells_drawn++;
|
||||
}
|
||||
print "</tr>\n";
|
||||
return;
|
||||
}
|
||||
# Start the calendar rows
|
||||
my $col = 0;
|
||||
if ($Options{nostyle}) {
|
||||
@@ -895,9 +990,10 @@ sub output_calendar
|
||||
|
||||
sub draw_day_cell
|
||||
{
|
||||
my($day, $number_of_rows, $type) = @_;
|
||||
my($day, $number_of_rows, $type, $extra_class) = @_;
|
||||
my $shade = $shades->[$day];
|
||||
my $week = '';
|
||||
$extra_class = '' unless defined($extra_class);
|
||||
if (exists($weeks->{$day})) {
|
||||
if ($weeks->{$day}->{url}) {
|
||||
$week = ' <a href="' . $weeks->{$day}->{url} . '">' . escape_html($weeks->{$day}->{body}) . '</a>';
|
||||
@@ -905,19 +1001,22 @@ sub draw_day_cell
|
||||
$week = ' ' . escape_html($weeks->{$day}->{body});
|
||||
}
|
||||
}
|
||||
my $class;
|
||||
if ($Options{nostyle}) {
|
||||
$class = $classes->[$day] || '';
|
||||
} else {
|
||||
$class = $classes->[$day] || "rem-cell rem-cell-$number_of_rows-rows";
|
||||
my $class = $classes->[$day] || '';
|
||||
if (!$Options{nostyle}) {
|
||||
$class .= ' ' if $class ne '';
|
||||
if ($Options{yaag}) {
|
||||
$class .= "rem-yaag-cell"
|
||||
} else {
|
||||
$class .= "rem-cell rem-cell-$number_of_rows-rows";
|
||||
}
|
||||
}
|
||||
if ($shade) {
|
||||
$shade = " style=\"background: $shade;\"";
|
||||
} else {
|
||||
$shade = "";
|
||||
}
|
||||
if ($class ne '') {
|
||||
print "<td class=\"$class\"$shade>\n";
|
||||
if ($class ne '' || $extra_class ne '') {
|
||||
print "<td class=\"$class$extra_class\"$shade>\n";
|
||||
} else {
|
||||
print "<td valign=\"top\" $shade>\n";
|
||||
}
|
||||
@@ -982,7 +1081,11 @@ sub draw_day_cell
|
||||
print "<div style=\"float: right\">$day$week</div>\n";
|
||||
print "<p> </p>\n";
|
||||
} else {
|
||||
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
||||
if ($Options{yaag}) {
|
||||
print "<div class=\"rem-yaag-daynumber\">$day$week</div>\n";
|
||||
} else {
|
||||
print "<div class=\"rem-daynumber\">$day$week</div>\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($Options{nostyle}) {
|
||||
@@ -1016,7 +1119,7 @@ if ($Options{help}) {
|
||||
system("perldoc $0");
|
||||
exit(0);
|
||||
} elsif ($Options{version}) {
|
||||
print "rem2html version $rem2html_version.\n";
|
||||
print "rem2html version $rem2html_version\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -1048,6 +1151,11 @@ table.rem-cal {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
span.year_heading {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 28pt;
|
||||
}
|
||||
|
||||
table.rem-sc-table {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
@@ -1073,14 +1181,6 @@ td.rem-empty, td.rem-cell, td.rem-small-calendar {
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
td.rem-today {
|
||||
width: 14%;
|
||||
height: 7em;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: #EE3333;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.rem-cal {
|
||||
width: 100%;
|
||||
@@ -1116,5 +1216,84 @@ td.rem-sc-empty-cell, td.rem-sc-cell {
|
||||
caption.rem-sc-caption {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
table.rem-yaag {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 8pt;
|
||||
table-layout: fixed;
|
||||
cellspacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td.rem-yaag-cell {
|
||||
height: 7em;
|
||||
border-style: solid;
|
||||
border-color: #adadad;
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th.rem-yaag-weekday-header {
|
||||
font-weight: 100;
|
||||
font-size: 9pt;
|
||||
padding: 6px 0 0 6px;
|
||||
text-align:left;
|
||||
border-style: solid;
|
||||
border-color: #adadad;
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.rem-yaag-cal-blank {
|
||||
height: 7em;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #adadad;
|
||||
background-color: #d5d6d5;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.rem-yaag-end-of-week {
|
||||
border-right-width: 3;
|
||||
}
|
||||
|
||||
th.rem-yaag-end-of-week {
|
||||
border-right-width: 3;
|
||||
}
|
||||
|
||||
th.rem-yaag-cal-hdr {
|
||||
text-align: right;
|
||||
padding-top: 8px;
|
||||
padding-right: 5px;
|
||||
font-weight: 100;
|
||||
font-size: 9pt;
|
||||
border-style: solid;
|
||||
border-color: #adadad;
|
||||
border-width: 1px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.rem-yaag-daynumber {
|
||||
float: right;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
tr.rem-yaag-cal-row:nth-child(3n+1) {
|
||||
border-bottom: 3px solid #000;
|
||||
}
|
||||
|
||||
.rem-yaag-weekday-row .rem-yaag-empty-header {
|
||||
height: 20pt;
|
||||
width: 70px !important;
|
||||
}
|
||||
|
||||
td.rem-today {
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-color: #EE3333;
|
||||
}
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use ExtUtils::MakeMaker;
|
||||
sub manifypods {
|
||||
my ($self,%attribs) = @_;
|
||||
my $result = $self->SUPER::manifypods(%attribs);
|
||||
$result =~ s/^(POD2MAN_EXE\s*=\s*)(.+)$/$1$2 --center 'VERSION @VERSION@' --date '@RELEASE_DATE@'/m;
|
||||
$result =~ s/^(POD2MAN_EXE\s*=\s*)(.+)$/$1$2 --center 'VERSION @VERSION@' --date '@RELEASE_DATE@' --release Remind/m;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ my $media_to_size = {
|
||||
};
|
||||
|
||||
my $help = 0;
|
||||
my $version = 0;
|
||||
|
||||
my $settings = {
|
||||
landscape => 0,
|
||||
@@ -48,9 +49,10 @@ my $settings = {
|
||||
entry_font => 'Sans',
|
||||
small_cal_font => 'Sans',
|
||||
|
||||
title_url => '',
|
||||
title_size => 14,
|
||||
header_size => 12,
|
||||
daynum_size => 14,
|
||||
daynum_size => -1,
|
||||
entry_size => 8,
|
||||
|
||||
border_size => 4,
|
||||
@@ -65,6 +67,12 @@ my $settings = {
|
||||
eps => 0,
|
||||
verbose => 0,
|
||||
|
||||
line_color => '000000',
|
||||
title_color => '000000',
|
||||
header_color => '000000',
|
||||
daynum_color => '000000',
|
||||
smallcal_color => '000000',
|
||||
bg_color => '',
|
||||
weeks_per_page => 1,
|
||||
};
|
||||
|
||||
@@ -110,8 +118,16 @@ Options:
|
||||
--margin-bottom=S Specify bottom margin size in 1/72nds of an inch
|
||||
--margin-left=S Specify left margin size in 1/72nds of an inch
|
||||
--margin-right=S Specify right margin size in 1/72nds of an inch
|
||||
--line-color=RRGGBB Set line color
|
||||
--title-color=RRGGBB Set title color
|
||||
--header-color=RRGGBB Set header color
|
||||
--daynum-color=RRGGBB Set day number color
|
||||
--smallcal-color=RRGGBB Set small calendar color
|
||||
--bg-color=RRGGBB Set background color
|
||||
--title-url=URL Link calendar title to URL
|
||||
--verbose, -v Print progress messages
|
||||
--help Display this help
|
||||
--version Print version and exit
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -130,6 +146,7 @@ my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
||||
'wrap|y' => \$settings->{wrap_calendar},
|
||||
'height|h=i' => \$settings->{height},
|
||||
'title-font=s' => \$settings->{title_font},
|
||||
'title-url=s' => \$settings->{title_url},
|
||||
'header-font=s' => \$settings->{header_font},
|
||||
'daynum-font=s' => \$settings->{daynum_font},
|
||||
'entry-font=s' => \$settings->{entry_font},
|
||||
@@ -145,6 +162,13 @@ my $ret = GetOptions('landscape|l' => \$settings->{landscape},
|
||||
'margin-left=f' => \$settings->{margin_left},
|
||||
'margin-right=f' => \$settings->{margin_right},
|
||||
'verbose|v' => \$settings->{verbose},
|
||||
'line-color=s' => \$settings->{line_color},
|
||||
'bg-color=s' => \$settings->{bg_color},
|
||||
'title-color=s' => \$settings->{title_color},
|
||||
'header-color=s' => \$settings->{header_color},
|
||||
'daynum-color=s' => \$settings->{daynum_color},
|
||||
'smallcal-color=s' => \$settings->{smallcal_color},
|
||||
'version' => \$version,
|
||||
'help' => \$help
|
||||
);
|
||||
if (!$ret) {
|
||||
@@ -157,6 +181,33 @@ if ($help) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($version) {
|
||||
print "rem2pdf version $VERSION\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $bad = 0;
|
||||
foreach my $setting (qw(bg_color line_color title_color header_color daynum_color smallcal_color)) {
|
||||
my $c = $settings->{$setting};
|
||||
if ($setting eq 'bg_color' && $c eq '') {
|
||||
$settings->{bg_color} = [-1, -1, -1];
|
||||
next;
|
||||
}
|
||||
my $color = Remind::PDF->get_rgb($c);
|
||||
if (!defined($color)) {
|
||||
my $s = $setting;
|
||||
$s =~ s/_/-/g;
|
||||
print STDERR "Invalid color value `$c' for option --$s\n";
|
||||
$bad = 1;
|
||||
} else {
|
||||
$settings->{$setting} = $color;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bad) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($settings->{weeks_per_page} < 1) {
|
||||
$settings->{weeks_per_page} = 1;}
|
||||
elsif ($settings->{weeks_per_page} > 4) {
|
||||
@@ -208,7 +259,8 @@ if ($settings->{eps}) {
|
||||
# Don't read from a terminal
|
||||
if (-t STDIN) { ## no critic
|
||||
print STDERR "I can't read data from a terminal. Please run like this:\n";
|
||||
print STDERR " remind -pp [options] filename | $me [options] > out.pdf\n";
|
||||
print STDERR " remind -pp [options] filename | $me [options] > out.pdf\n\n";
|
||||
print STDERR "For help, run: $me --help\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -441,7 +493,7 @@ The default media size will be marked with an asterisk.
|
||||
=item --width=I<n>, -wI<n>, --height=I<m>, -hI<m>
|
||||
|
||||
Rather than specifying a named media size, directly specify the width
|
||||
and height of the output in 1/72ths of an inch. You must specify both
|
||||
and height of the output in 1/72ndths of an inch. You must specify both
|
||||
width and height for the options to be respected.
|
||||
|
||||
=item --title-font=I<font>
|
||||
@@ -471,28 +523,30 @@ calendars. The default is Sans.
|
||||
|
||||
=item --title-size=I<n>
|
||||
|
||||
Specify the size of the title font in 1/72ths of an inch. The default
|
||||
Specify the size of the title font in 1/72ndths of an inch. The default
|
||||
is 14. This size, and indeed all following sizes, may be specified as
|
||||
floating-point numbers.
|
||||
|
||||
=item --header-size=I<n>
|
||||
|
||||
Specify the size of the header font in 1/72ths of an inch. The default is 14.
|
||||
Specify the size of the header font in 1/72ndths of an inch. The default is 14.
|
||||
|
||||
=item --daynum-size=I<n>
|
||||
|
||||
Specify the size of the day number font in 1/72ths of an inch. The
|
||||
default is 14.
|
||||
Specify the size of the day number font in 1/72ndths of an inch. The
|
||||
default is 14 for monthly calendars or 10 for weekly calendars. (Weekly
|
||||
calendars don't have day numbers in the calendar boxes, but this setting
|
||||
is used to scale the size of moon phase indicators.)
|
||||
|
||||
=item --entry-size=I<n>
|
||||
|
||||
Specify the size of the calendar entry font in 1/72ths of an inch.
|
||||
Specify the size of the calendar entry font in 1/72ndths of an inch.
|
||||
The default is 8.
|
||||
|
||||
=item --border-size=I<n>
|
||||
|
||||
Specify the size of the blank border between the contents of a calendar
|
||||
box and the centre of the lines surrounding it, in 1/72ths of an inch.
|
||||
box and the centre of the lines surrounding it, in 1/72ndths of an inch.
|
||||
The default is 4.
|
||||
|
||||
=item --line-thickness=I<n>
|
||||
@@ -501,24 +555,61 @@ Specify the thickness of the lines drawn on the calendar. The default is 1.
|
||||
|
||||
=item --margin-top=I<n>
|
||||
|
||||
The size of the margin at the top of the page in 1/72ths of an inch.
|
||||
The size of the margin at the top of the page in 1/72ndths of an inch.
|
||||
The default is 36.
|
||||
|
||||
=item --margin-bottom=I<n>
|
||||
|
||||
The size of the margin at the bottom of the page in 1/72ths of an inch.
|
||||
The size of the margin at the bottom of the page in 1/72ndths of an inch.
|
||||
The default is 36.
|
||||
|
||||
=item --margin-left=I<n>
|
||||
|
||||
The size of the margin at the left of the page in 1/72ths of an inch.
|
||||
The size of the margin at the left of the page in 1/72ndths of an inch.
|
||||
The default is 36.
|
||||
|
||||
=item --margin-right=I<n>
|
||||
|
||||
The size of the margin at the right of the page in 1/72ths of an inch.
|
||||
The size of the margin at the right of the page in 1/72ndths of an inch.
|
||||
The default is 36.
|
||||
|
||||
=item --line-color=RGB
|
||||
|
||||
The color of the calendar grid lines. For this option and all
|
||||
following color options, the color may be specified as either 3 or 6
|
||||
hex digits, specifying the R, G and B components respectively. For
|
||||
example, FFFFFF is white, FF0000 is a saturated red, and so on. If
|
||||
you supply 3 hex digits, then they are effectively doubled, so that
|
||||
(for example) 5AF is expanded to 55AAFF.
|
||||
|
||||
=item --title-color=RGB
|
||||
|
||||
The color of the calendar title at the top of the page.
|
||||
|
||||
=item --header-color=RGB
|
||||
|
||||
The color of the weekday names in the header row.
|
||||
|
||||
=item --daynum-color=RGB
|
||||
|
||||
The color of the day numbers (and the moon phases, if any.)
|
||||
|
||||
=item --smallcal-color=RGB
|
||||
|
||||
The color of the small monthly calendars, if any.
|
||||
|
||||
=item --bg-color=RGB
|
||||
|
||||
The color of the page background.
|
||||
|
||||
Note that all colors default to black (000) except for the
|
||||
page background, which defaults to no color at all (ie, transparent).
|
||||
|
||||
=item --title-url=URL
|
||||
|
||||
Make the calendar title a link to URL. Note that no syntax checking is
|
||||
done on the URL; it's up to you to make sure it is valid.
|
||||
|
||||
=item --wrap, -y
|
||||
|
||||
Modify the calendar so that if it would normally require 6 rows to print,
|
||||
@@ -537,11 +628,19 @@ to print per page; it is an integer that can range from 1 to 4.
|
||||
Print (on STDERR) the name of the month and year for each month that
|
||||
is rendered.
|
||||
|
||||
=item --version
|
||||
|
||||
Print the version of rem2pdf and exit.
|
||||
|
||||
=item --help
|
||||
|
||||
Print a brief summary of rem2pdf usage.
|
||||
|
||||
=back
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
To use B<rem2df>, pipe the output of B<remind> with one of the
|
||||
To use B<rem2pdf>, pipe the output of B<remind> with one of the
|
||||
B<-p>, B<-pp> or B<-ppp> options into B<rem2pdf>. The PDF output
|
||||
will be sent to standard output. So for example, to print a 12-month
|
||||
calendar for the year 2030, use:
|
||||
@@ -602,7 +701,10 @@ of the right side of the calendar box.
|
||||
A positive I<y> value positions the top edge of the text I<y> points
|
||||
below the top of the calendar box, while a negative I<y> value
|
||||
positions the bottom edge of the text I<y> points above the bottom of
|
||||
the calendar box.
|
||||
the calendar box. Note that the coordinates are relative to the center
|
||||
of the lines that delineate the boxes; you should use an I<x> value
|
||||
whose absolute value is at least 2 and a I<y> value whose absolute
|
||||
value is at least 4 to avoid colliding with the lines.
|
||||
|
||||
If you use absolutely-positioned text, it's up to you to make sure it
|
||||
doesn't overlap other text; B<rem2pdf> takes no special precautions to
|
||||
@@ -611,7 +713,7 @@ prevent this.
|
||||
As an example, this places Sunrise and Sunset times at the bottom left
|
||||
of each calendar box:
|
||||
|
||||
REM SPECIAL PANGO @1,-1 <span size="4800"><i>Rise [sunrise($U)] Set [sunset($U)]</i></span>
|
||||
REM SPECIAL PANGO @2,-4 <span size="4800"><i>Rise [sunrise($U)] Set [sunset($U)]</i></span>
|
||||
|
||||
(Note that Pango expresses font sizes in 1024's of a point, so a size of
|
||||
4800 works out to about 4.6 points.)
|
||||
|
||||
@@ -468,6 +468,9 @@ sub render
|
||||
{
|
||||
my ($self, $cr, $settings, $index, $total) = @_;
|
||||
|
||||
if ($settings->{daynum_size} < 0) {
|
||||
$settings->{daynum_size} = 14;
|
||||
}
|
||||
if ($settings->{svg} || $settings->{eps}) {
|
||||
if ($index > 1) {
|
||||
if ($index == 2) {
|
||||
@@ -476,6 +479,14 @@ sub render
|
||||
return;
|
||||
}
|
||||
}
|
||||
my ($r, $g, $b) = @{$settings->{bg_color}};
|
||||
if ($r >= 0 && $g >= 0 && $b >= 0) {
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{bg_color});
|
||||
$cr->rectangle(0, 0, $settings->{width}, $settings->{height});
|
||||
$cr->fill();
|
||||
$cr->restore;
|
||||
}
|
||||
$self->setup_daymap($settings);
|
||||
$self->{horiz_lines} = [];
|
||||
$cr->set_line_cap('square');
|
||||
@@ -521,6 +532,10 @@ sub render
|
||||
print STDERR "WARNING: overfull calendar box\n";
|
||||
}
|
||||
# The vertical lines
|
||||
|
||||
# Set the color
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{line_color});
|
||||
my $cell = ($settings->{width} - $settings->{margin_left} - $settings->{margin_right}) / 7;
|
||||
for (my $i=0; $i<=7; $i++) {
|
||||
$cr->move_to($settings->{margin_left} + $i * $cell, $top_line);
|
||||
@@ -535,6 +550,7 @@ sub render
|
||||
$cr->stroke();
|
||||
}
|
||||
|
||||
$cr->restore;
|
||||
if ($settings->{verbose}) {
|
||||
print STDERR "rem2pdf: Rendered " . $self->{monthname} . ' ' . $self->{year} . "\n";
|
||||
}
|
||||
@@ -542,6 +558,18 @@ sub render
|
||||
$cr->show_page();
|
||||
}
|
||||
|
||||
sub set_cr_color {
|
||||
my ($self, $cr, $color_array) = @_;
|
||||
my ($r, $g, $b) = @$color_array;
|
||||
if ($r < 0 || $g < 0 || $b < 0 ||
|
||||
$r > 255 || $g > 255 || $b > 255) {
|
||||
return;
|
||||
}
|
||||
$cr->set_source_rgb($r / 255,
|
||||
$g / 255,
|
||||
$b / 255);
|
||||
}
|
||||
|
||||
=head2 draw_row($cr, $settings, $so_far, $row, $start_day, $start_col)
|
||||
|
||||
Draw a single row in the calendar. C<$cr> is a Cairo drawing context
|
||||
@@ -603,7 +631,7 @@ sub col_box_coordinates
|
||||
$settings->{margin_left} + $cell * $col,
|
||||
$so_far,
|
||||
$settings->{margin_left} + $cell * ($col + 1),
|
||||
$so_far + $height + $settings->{border_size},
|
||||
$so_far + $height + 2* $settings->{border_size},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -655,6 +683,7 @@ sub draw_day
|
||||
# Don't actually draw if we're just previewing to get the cell height
|
||||
if ($height) {
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{daynum_color});
|
||||
if ($settings->{numbers_on_left}) {
|
||||
$cr->move_to($x1 + $settings->{border_size}, $so_far + $settings->{border_size});
|
||||
} else {
|
||||
@@ -664,7 +693,7 @@ sub draw_day
|
||||
$cr->restore();
|
||||
}
|
||||
|
||||
$so_far += $h + 2 * $settings->{border_size};
|
||||
$so_far += $h + $settings->{border_size};
|
||||
my $entry_height = 0;
|
||||
my $done = 0;
|
||||
foreach my $entry (@{$self->{entries}->[$day]}) {
|
||||
@@ -740,6 +769,7 @@ sub draw_daynames
|
||||
|
||||
my ($wid, $h) = $layout->get_pixel_size();
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{header_color});
|
||||
$cr->move_to($settings->{margin_left} + $i * $cell + $cell/2 - $wid/2, $so_far);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -765,6 +795,8 @@ sub draw_title
|
||||
my ($self, $cr, $settings) = @_;
|
||||
my $title = $self->{monthname} . ' ' . $self->{year};
|
||||
|
||||
my $url = $settings->{title_url} // '';
|
||||
|
||||
# set_page_label not available in older versions of Cairo
|
||||
eval { $cr->get_target()->set_page_label($title); };
|
||||
my $layout = Pango::Cairo::create_layout($cr);
|
||||
@@ -775,12 +807,44 @@ sub draw_title
|
||||
|
||||
my ($w, $h) = $layout->get_pixel_size();
|
||||
$cr->save();
|
||||
$self->set_cr_color($cr, $settings->{title_color});
|
||||
$cr->move_to($settings->{width}/2 - $w/2, $settings->{margin_top});
|
||||
if ($url ne '') {
|
||||
$cr->tag_begin(Cairo::TAG_LINK, "uri='$url'");
|
||||
}
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
if ($url ne '') {
|
||||
$cr->tag_end(Cairo::TAG_LINK);
|
||||
}
|
||||
$cr->restore();
|
||||
return $h + $settings->{margin_top} + $settings->{border_size};
|
||||
}
|
||||
|
||||
=head2 get_rgb($color)
|
||||
|
||||
Parses a 3- or 6-hex-digit color value and returns [red, green, blue]. If
|
||||
color could not be parsed, returns undef
|
||||
|
||||
=cut
|
||||
sub get_rgb
|
||||
{
|
||||
my ($self, $color) = @_;
|
||||
my ($r, $g, $b);
|
||||
if ($color =~ /^([0-9a-f])([0-9a-f])([0-9a-f])$/i) {
|
||||
$r = hex($1);
|
||||
$g = hex($2);
|
||||
$b = hex($3);
|
||||
$r = $r * 16 + $r;
|
||||
$g = $g * 16 + $g;
|
||||
$b = $b * 16 + $b;
|
||||
return [$r, $g, $b];
|
||||
} elsif ($color =~ /^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i) {
|
||||
return [hex($1), hex($2), hex($3)];
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
=head2 draw_small_calendar($cr, $x, $y, $width, $height, $settings, $month, $days, $start_wkday)
|
||||
|
||||
Draw a small calendar on the Cairo context C<$cr>. The top left-hand
|
||||
@@ -828,6 +892,7 @@ sub draw_small_calendar
|
||||
$layout->set_text(Encode::decode('UTF-8', $month));
|
||||
my ($mw, $mh) = $layout->get_pixel_size();
|
||||
$cr->save();
|
||||
$self->set_cr_color($cr, $settings->{smallcal_color});
|
||||
$cr->move_to($x + $width/2 - $mw/2, $y);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -849,6 +914,7 @@ sub draw_small_calendar
|
||||
$layout->set_font_description($desc);
|
||||
$layout->set_text($l);
|
||||
$cr->save();
|
||||
$self->set_cr_color($cr, $settings->{smallcal_color});
|
||||
$cr->move_to($x + $col*$wid, $y);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -866,6 +932,7 @@ sub draw_small_calendar
|
||||
}
|
||||
$layout->set_text($dt);
|
||||
$cr->save();
|
||||
$self->set_cr_color($cr, $settings->{smallcal_color});
|
||||
$cr->move_to($x + $col*$wid, $y);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -1047,6 +1114,9 @@ Remind::PDF::Weekly - render a weekly calendar
|
||||
sub render
|
||||
{
|
||||
my ($self, $cr, $settings, $index, $total) = @_;
|
||||
if ($settings->{daynum_size} < 0) {
|
||||
$settings->{daynum_size} = 10;
|
||||
}
|
||||
if ($settings->{svg} || $settings->{eps}) {
|
||||
if ($index > $settings->{weeks_per_page}) {
|
||||
if ($index == $settings->{weeks_per_page}+1) {
|
||||
@@ -1055,8 +1125,18 @@ sub render
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((($index-1) % $settings->{weeks_per_page}) == 0) {
|
||||
my ($r, $g, $b) = @{$settings->{bg_color}};
|
||||
if ($r >= 0 && $g >= 0 && $b >= 0) {
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{bg_color});
|
||||
$cr->rectangle(0, 0, $settings->{width}, $settings->{height});
|
||||
$cr->fill();
|
||||
$cr->restore;
|
||||
}
|
||||
}
|
||||
|
||||
$settings->{numbers_on_left} = 1;
|
||||
$settings->{numbers_on_left} = 0;
|
||||
# Set up bounding box
|
||||
if ($settings->{weeks_per_page} == 1) {
|
||||
$self->{bounding_box} = [
|
||||
@@ -1065,22 +1145,16 @@ sub render
|
||||
$settings->{width} - $settings->{margin_right},
|
||||
$settings->{height} - $settings->{margin_bottom}]
|
||||
} else {
|
||||
my $gap = $settings->{margin_top} * 0.5;
|
||||
my $total_height = $settings->{height} - $settings->{margin_top} - $settings->{margin_bottom};
|
||||
my $week_height = $total_height / $settings->{weeks_per_page};
|
||||
my $top_offset = (($index-1) % $settings->{weeks_per_page}) * $week_height;
|
||||
my $week_height = ($total_height - $gap * ($settings->{weeks_per_page}-1)) / $settings->{weeks_per_page};
|
||||
my $top_offset = ((($index-1) % $settings->{weeks_per_page}) * $week_height) + (($index-1) % $settings->{weeks_per_page}) * $gap;
|
||||
my $bot_offset = $top_offset + $week_height;
|
||||
$self->{bounding_box} =
|
||||
$self->{bounding_box} = [
|
||||
$settings->{margin_left},
|
||||
$settings->{margin_top} + $top_offset,
|
||||
$settings->{width} - $settings->{margin_right},
|
||||
$settings->{margin_top} + $bot_offset];
|
||||
if ($index != 1) {
|
||||
$self->{bounding_box}[1] += 0.25 * $settings->{margin_top};
|
||||
}
|
||||
if ($index != $settings->{weeks_per_page}) {
|
||||
$self->{bounding_box}[3] -= 0.25 * $settings->{margin_top};
|
||||
}
|
||||
$self->{bounding_box} = [
|
||||
$settings->{margin_left},
|
||||
$settings->{margin_top} + $top_offset,
|
||||
$settings->{width} - $settings->{margin_right},
|
||||
$settings->{margin_top} + $bot_offset];
|
||||
}
|
||||
$self->draw_headings($cr, $settings);
|
||||
for (my $i=0; $i<7; $i++) {
|
||||
@@ -1117,6 +1191,7 @@ sub draw_headings
|
||||
|
||||
my ($wid, $h) = $layout->get_pixel_size();
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{header_color});
|
||||
$cr->move_to($settings->{margin_left} + $i * $cell + $cell/2 - $wid/2, $self->{bounding_box}[1]);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -1132,6 +1207,7 @@ sub draw_headings
|
||||
|
||||
my ($wid2, $h2) = $layout->get_pixel_size();
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{header_color});
|
||||
$cr->move_to($settings->{margin_left} + $i * $cell + $cell/2 - $wid2/2, $self->{bounding_box}[1] + $h);
|
||||
Pango::Cairo::show_layout($cr, $layout);
|
||||
$cr->restore();
|
||||
@@ -1186,7 +1262,13 @@ sub draw_entries
|
||||
$layout->set_font_description($desc);
|
||||
my ($wid, $h) = $layout->get_pixel_size();
|
||||
|
||||
my $so_far = $box->[1] + $h + $settings->{border_size};
|
||||
my $so_far = $box->[1] + $settings->{border_size};
|
||||
foreach my $entry (@{$self->{entries}->[$i]}) {
|
||||
if ($entry->isa('Remind::PDF::Entry::moon')) {
|
||||
$so_far = $box->[1] + $h + $settings->{border_size};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
my $box_height = $box->[3] - $box->[1];
|
||||
my $done = 0;
|
||||
@@ -1232,6 +1314,8 @@ sub draw_lines
|
||||
{
|
||||
my ($self, $cr, $settings) = @_;
|
||||
|
||||
$cr->save;
|
||||
$self->set_cr_color($cr, $settings->{line_color});
|
||||
# Top horizonal line
|
||||
$cr->move_to($self->{bounding_box}[0], $self->{bounding_box}[1]);
|
||||
$cr->line_to($self->{bounding_box}[2], $self->{bounding_box}[1]);
|
||||
@@ -1255,6 +1339,7 @@ sub draw_lines
|
||||
$cr->line_to($x, $self->{bounding_box}[3]);
|
||||
$cr->stroke();
|
||||
}
|
||||
$cr->restore;
|
||||
}
|
||||
|
||||
sub create_from_hash
|
||||
|
||||
@@ -151,7 +151,8 @@ sub render
|
||||
my ($wid, $h) = $layout->get_pixel_size();
|
||||
|
||||
$cr->save();
|
||||
$cr->move_to($x2 - $settings->{border_size}/4 - $wid, $y2 - $settings->{border_size}/4 - $h);
|
||||
Remind::PDF->set_cr_color($cr, $settings->{daynum_color});
|
||||
$cr->move_to($x2 - $settings->{border_size}/2 - $wid, $y2 - $h);
|
||||
my $url;
|
||||
if ($self->{info} && $self->{info}->{url}) {
|
||||
$url = $self->{info}->{url};
|
||||
@@ -234,12 +235,13 @@ sub render
|
||||
if ($url) {
|
||||
$cr->tag_begin(Cairo::TAG_LINK, "uri='$url'");
|
||||
}
|
||||
$self->draw_moon($xc, $yc, $cr);
|
||||
$self->draw_moon($xc, $yc, $cr, $settings);
|
||||
if ($url) {
|
||||
$cr->tag_end(Cairo::TAG_LINK);
|
||||
}
|
||||
if ($layout) {
|
||||
$cr->save();
|
||||
Remind::PDF->set_cr_color($cr, $settings->{daynum_color});
|
||||
$cr->move_to ($xc + ($self->{size}/2) + $settings->{border_size},
|
||||
$yc + ($self->{size}/2) - $self->{fontsize} );
|
||||
if ($url) {
|
||||
@@ -255,8 +257,9 @@ sub render
|
||||
|
||||
sub draw_moon
|
||||
{
|
||||
my ($self, $xc, $yc, $cr) = @_;
|
||||
my ($self, $xc, $yc, $cr, $settings) = @_;
|
||||
$cr->save();
|
||||
Remind::PDF->set_cr_color($cr, $settings->{daynum_color});
|
||||
$cr->new_path();
|
||||
$cr->arc($xc, $yc, $self->{size}/2, 0, 2*3.1415926535);
|
||||
if ($self->{phase} == 0) {
|
||||
@@ -351,7 +354,7 @@ sub render
|
||||
$x = $x1 + $self->{atx};
|
||||
}
|
||||
if ($self->{aty} < 0) {
|
||||
$y = $y2 + $self->{aty} - $h;
|
||||
$y = $y2 + $self->{aty} - $h + $settings->{border_size};
|
||||
} else {
|
||||
$y = $y1 + $self->{aty};
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ Icon=tkremind
|
||||
Terminal=false
|
||||
Name=tkremind
|
||||
Comment=TkRemind Calendar Program
|
||||
Comment[nl]=TkRemind Kalender Programma
|
||||
Categories=Office;Calendar;
|
||||
Keywords=Calendar;remind;
|
||||
Keywords[ca]=Calendari;remind;
|
||||
Keywords[de]=Kalender;remind;
|
||||
Keywords[en_GB]=Calendar;remind;
|
||||
Keywords[es]=Calendario;remind;
|
||||
|
||||
Keywords[nl]=Kalender;remind;
|
||||
|
||||
1499
scripts/tkremind.in
1499
scripts/tkremind.in
File diff suppressed because it is too large
Load Diff
221
src/calendar.c
221
src/calendar.c
@@ -5,7 +5,7 @@
|
||||
/* The code for generating a calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -23,10 +23,8 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
#include <langinfo.h>
|
||||
@@ -44,10 +42,8 @@ typedef struct cal_entry {
|
||||
char *text;
|
||||
char *raw_text;
|
||||
char const *pos;
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t *wc_text;
|
||||
wchar_t const *wc_pos;
|
||||
#endif
|
||||
int is_color;
|
||||
int r, g, b;
|
||||
int time;
|
||||
@@ -179,6 +175,17 @@ static char const *moonphase_emojis[] = {
|
||||
"\xF0\x9F\x8C\x97"
|
||||
};
|
||||
|
||||
/* Color weights for gamma-correction */
|
||||
unsigned char cwts[] = {
|
||||
0x46, 0x75, 0x63, 0x6b, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x68, 0x6f, 0x62, 0x69, 0x63,
|
||||
0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52,
|
||||
0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x73, 0x2e,
|
||||
0x20, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x20, 0x72, 0x69, 0x67,
|
||||
0x68, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x68, 0x75, 0x6d,
|
||||
0x61, 0x6e, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2e
|
||||
};
|
||||
|
||||
/* Moon phases for each day 1-31, up to 32 chars per moon-phase string
|
||||
including termination \0 */
|
||||
static char moons[32][32];
|
||||
@@ -301,6 +308,7 @@ static void WriteTopCalLine (void);
|
||||
static void WriteBottomCalLine (void);
|
||||
static void WriteIntermediateCalLine (void);
|
||||
static void WriteCalDays (void);
|
||||
static char const *get_url(TrigInfo *infos);
|
||||
|
||||
static int
|
||||
DayOf(int dse)
|
||||
@@ -317,6 +325,9 @@ Backgroundize(int d)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cwts[d] == 0) {
|
||||
return;
|
||||
}
|
||||
if (!UseBGVTColors) {
|
||||
return;
|
||||
}
|
||||
@@ -342,7 +353,6 @@ UnBackgroundize(int d)
|
||||
printf("%s", Decolorize());
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static void
|
||||
send_lrm(void)
|
||||
{
|
||||
@@ -357,7 +367,6 @@ send_lrm(void)
|
||||
printf("\xE2\x80\x8E");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static char const *
|
||||
despace(char const *s)
|
||||
@@ -514,7 +523,6 @@ static void PrintJSONKeyPairTime(char const *name, int t)
|
||||
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
void PutWideChar(wchar_t const wc, DynamicBuffer *output)
|
||||
{
|
||||
char buf[MB_CUR_MAX+1];
|
||||
@@ -530,16 +538,11 @@ void PutWideChar(wchar_t const wc, DynamicBuffer *output)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static char const *
|
||||
get_month_abbrev(char const *mon)
|
||||
{
|
||||
static char buf[80];
|
||||
#ifndef REM_USE_WCHAR
|
||||
snprintf(buf, sizeof(buf), "%.3s", mon);
|
||||
return buf;
|
||||
#else
|
||||
char *s;
|
||||
wchar_t tmp_buf[128] = {0};
|
||||
wchar_t *ws;
|
||||
@@ -564,10 +567,8 @@ get_month_abbrev(char const *mon)
|
||||
}
|
||||
*s = 0;
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static int make_wchar_versions(CalEntry *e)
|
||||
{
|
||||
size_t len;
|
||||
@@ -584,7 +585,6 @@ static int make_wchar_versions(CalEntry *e)
|
||||
e->wc_pos = buf;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gon(void)
|
||||
{
|
||||
@@ -1337,14 +1337,6 @@ static int WriteCalendarRow(void)
|
||||
/***************************************************************/
|
||||
static void PrintLeft(char const *s, int width, char pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
int i;
|
||||
for (i=0; i<len && i<width; i++) {
|
||||
fputc(*(s+i), stdout);
|
||||
}
|
||||
while (i++ < width) putchar(pad);
|
||||
#else
|
||||
size_t len = mbstowcs(NULL, s, 0);
|
||||
int i;
|
||||
wchar_t static_buf[128];
|
||||
@@ -1395,8 +1387,6 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
i++;
|
||||
}
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1408,26 +1398,6 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
/***************************************************************/
|
||||
static void PrintCentered(char const *s, int width, char const *pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
int d = (width - len) / 2;
|
||||
int i;
|
||||
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width-d; i++) {
|
||||
if (*s) {
|
||||
if (isspace(*s)) {
|
||||
putchar(' ');
|
||||
s++;
|
||||
} else {
|
||||
putchar(*s++);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||
#else
|
||||
size_t len = mbstowcs(NULL, s, 0);
|
||||
int display_len;
|
||||
int i;
|
||||
@@ -1482,7 +1452,6 @@ static void PrintCentered(char const *s, int width, char const *pad)
|
||||
i++;
|
||||
}
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1535,6 +1504,14 @@ static int WriteOneCalLine(int start_dse, int wd)
|
||||
return done;
|
||||
}
|
||||
|
||||
static void FreeCalEntry(CalEntry *e)
|
||||
{
|
||||
if (e->text) free(e->text);
|
||||
if (e->raw_text) free(e->raw_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* WriteOneColLine */
|
||||
@@ -1549,19 +1526,22 @@ static int WriteOneColLine(int col)
|
||||
char const *s;
|
||||
char const *space;
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *ws;
|
||||
wchar_t const *wspace;
|
||||
int width;
|
||||
#endif
|
||||
|
||||
int clamp = 1;
|
||||
int numwritten = 0;
|
||||
int d = ColToDay[col];
|
||||
char const *url;
|
||||
|
||||
if (d && UseBGVTColors && bgcolor[d][0] != -1) {
|
||||
clamp = 0;
|
||||
}
|
||||
PRINTROW:
|
||||
url = get_url(e->infos);
|
||||
|
||||
/* Print as many characters as possible within the column */
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) {
|
||||
wspace = NULL;
|
||||
ws = e->wc_pos;
|
||||
@@ -1569,14 +1549,17 @@ static int WriteOneColLine(int col)
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*ws && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
if (CalSepLine) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
}
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
return 1;
|
||||
FreeCalEntry(e);
|
||||
if (!CalSepLine) {
|
||||
e = CalColumn[col];
|
||||
goto PRINTROW;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
@@ -1605,6 +1588,9 @@ static int WriteOneColLine(int col)
|
||||
ColorizeEntry(e, clamp);
|
||||
}
|
||||
|
||||
if (url) {
|
||||
printf("\x1B]8;;%s\x1B\\", url);
|
||||
}
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!wspace) {
|
||||
for (ws = e->wc_pos; numwritten < ColSpaces; ws++) {
|
||||
@@ -1639,6 +1625,9 @@ static int WriteOneColLine(int col)
|
||||
}
|
||||
}
|
||||
|
||||
if (url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
/* Decolorize reminder if necessary, but keep any SHADE */
|
||||
if (UseVTColors && e->is_color) {
|
||||
printf("%s", Decolorize());
|
||||
@@ -1657,33 +1646,30 @@ static int WriteOneColLine(int col)
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*ws && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
FreeCalEntry(e);
|
||||
} else {
|
||||
e->wc_pos = ws;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
} else {
|
||||
#endif
|
||||
space = NULL;
|
||||
s = e->pos;
|
||||
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
if (CalSepLine) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
}
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e->raw_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
return 1;
|
||||
FreeCalEntry(e);
|
||||
if (!CalSepLine) {
|
||||
e = CalColumn[col];
|
||||
fprintf(stderr, "BLOOP\n");
|
||||
goto PRINTROW;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
@@ -1738,20 +1724,12 @@ static int WriteOneColLine(int col)
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free(e->text);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e->raw_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
free(e);
|
||||
FreeCalEntry(e);
|
||||
} else {
|
||||
e->pos = s;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
#ifdef REM_USE_WCHAR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1870,7 +1848,9 @@ static void GenerateCalEntries(int col)
|
||||
|
||||
default:
|
||||
if (!SuppressImplicitRemWarnings) {
|
||||
Wprint("Unrecognized command; interpreting as REM");
|
||||
if (warning_level("05.00.03")) {
|
||||
Wprint(tr("Unrecognized command; interpreting as REM"));
|
||||
}
|
||||
WarnedAboutImplicit = 1;
|
||||
}
|
||||
CreateParser(CurLine, &p);
|
||||
@@ -2063,6 +2043,11 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (dse < 0 && !ParseUntriggered) {
|
||||
/* Expired */
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
EnterTimezone(trig.tz);
|
||||
@@ -2075,10 +2060,15 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (dse < 0 && !ParseUntriggered) {
|
||||
/* Expired */
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust trigger date/time to time zone */
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim);
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
|
||||
|
||||
/* Add to global OMITs if so indicated */
|
||||
if (trig.addomit) {
|
||||
@@ -2109,7 +2099,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
|
||||
/* Save nonconst_expr flag */
|
||||
nonconst_expr = p->nonconst_expr;
|
||||
nonconst_expr = trig.nonconst_expr;
|
||||
/* Convert PS and PSF to PASSTHRU */
|
||||
if (trig.typ == PS_TYPE) {
|
||||
strcpy(trig.passthru, "PostScript");
|
||||
@@ -2133,8 +2123,9 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
}
|
||||
if (trig.typ == PASSTHRU_TYPE) {
|
||||
if (!PsCal && !StrCmpi(trig.passthru, "SHADE")) {
|
||||
if (dse == DSEToday) {
|
||||
if (!strcasecmp(trig.passthru, "SHADE") && dse == DSEToday) {
|
||||
Shaded++;
|
||||
if (!PsCal) {
|
||||
DBufInit(&obuf);
|
||||
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
|
||||
if (r) {
|
||||
@@ -2146,7 +2137,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufFree(&obuf);
|
||||
}
|
||||
}
|
||||
if (!PsCal && !StrCmpi(trig.passthru, "WEEK")) {
|
||||
if (!PsCal && !strcasecmp(trig.passthru, "WEEK")) {
|
||||
if (dse == DSEToday) {
|
||||
DBufInit(&obuf);
|
||||
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
|
||||
@@ -2159,11 +2150,11 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufFree(&obuf);
|
||||
}
|
||||
}
|
||||
if (!PsCal && StrCmpi(trig.passthru, "COLOR") && StrCmpi(trig.passthru, "COLOUR") && StrCmpi(trig.passthru, "MOON")) {
|
||||
if (!PsCal && strcasecmp(trig.passthru, "COLOR") && strcasecmp(trig.passthru, "COLOUR") && strcasecmp(trig.passthru, "MOON")) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (!PsCal && !StrCmpi(trig.passthru, "MOON")) {
|
||||
if (!PsCal && !strcasecmp(trig.passthru, "MOON")) {
|
||||
if (dse == DSEToday) {
|
||||
DBufInit(&obuf);
|
||||
r = DoSubst(p, &obuf, &trig, &tim, dse, CAL_MODE);
|
||||
@@ -2176,8 +2167,8 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufFree(&obuf);
|
||||
}
|
||||
}
|
||||
if (!StrCmpi(trig.passthru, "COLOR") ||
|
||||
!StrCmpi(trig.passthru, "COLOUR")) {
|
||||
if (!strcasecmp(trig.passthru, "COLOR") ||
|
||||
!strcasecmp(trig.passthru, "COLOUR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
@@ -2241,8 +2232,8 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
/* Suppress time if it's not today or if it's a non-COLOR special */
|
||||
if (dse != DSEToday ||
|
||||
(trig.typ == PASSTHRU_TYPE &&
|
||||
StrCmpi(trig.passthru, "COLOUR") &&
|
||||
StrCmpi(trig.passthru, "COLOR"))) {
|
||||
strcasecmp(trig.passthru, "COLOUR") &&
|
||||
strcasecmp(trig.passthru, "COLOR"))) {
|
||||
if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&raw_buf);
|
||||
@@ -2351,19 +2342,17 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
e->if_depth = get_if_pointer() - get_base_if_pointer();
|
||||
e->trig = trig;
|
||||
if (e->trig.tz) {
|
||||
e->trig.tz = StrDup(e->trig.tz);
|
||||
e->trig.tz = strdup(e->trig.tz);
|
||||
}
|
||||
e->tt = tim;
|
||||
#ifdef REM_USE_WCHAR
|
||||
e->wc_pos = NULL;
|
||||
e->wc_text = NULL;
|
||||
#endif
|
||||
e->is_color = is_color;
|
||||
e->r = col_r;
|
||||
e->g = col_g;
|
||||
e->b = col_b;
|
||||
e->text = StrDup(s);
|
||||
e->raw_text = StrDup(DBufValue(&raw_buf));
|
||||
e->text = strdup(s);
|
||||
e->raw_text = strdup(DBufValue(&raw_buf));
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
@@ -2375,9 +2364,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
#ifdef REM_USE_WCHAR
|
||||
make_wchar_versions(e);
|
||||
#endif
|
||||
DBufInit(&(e->tags));
|
||||
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
||||
if (SynthesizeTags) {
|
||||
@@ -2460,6 +2447,34 @@ void WriteJSONTimeTrigger(TimeTrig const *tt)
|
||||
}
|
||||
}
|
||||
|
||||
static char const *
|
||||
get_url(TrigInfo *infos)
|
||||
{
|
||||
TrigInfo *ti = infos;
|
||||
char const *url;
|
||||
if (!TerminalHyperlinks) {
|
||||
/* Nope, not doing links in terminal */
|
||||
return NULL;
|
||||
}
|
||||
while (ti) {
|
||||
char const *colon = strchr(ti->info, ':');
|
||||
if (!colon) {
|
||||
ti = ti->next;
|
||||
continue;
|
||||
}
|
||||
if (!strncasecmp(ti->info, "url", colon-ti->info)) {
|
||||
url = colon+1;
|
||||
while (*url && isspace(*url)) {
|
||||
url++;
|
||||
}
|
||||
if (!*url) return NULL;
|
||||
return url;
|
||||
}
|
||||
ti = ti->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
WriteJSONInfoChain(TrigInfo *ti)
|
||||
{
|
||||
@@ -2535,7 +2550,7 @@ void WriteJSONTrigger(Trigger const *t, int include_tags)
|
||||
PrintJSONKeyPairInt("rep", t->rep);
|
||||
}
|
||||
if (t->d != NO_DAY && t->m != NO_MON && t->y != NO_YR) {
|
||||
printf("\"trigbase\":\"%04d-%02d-%-2d\",",
|
||||
printf("\"trigbase\":\"%04d-%02d-%02d\",",
|
||||
t->y, t->m+1, t->d);
|
||||
}
|
||||
/* Local omit is an array of days from 0=monday to 6=sunday.
|
||||
@@ -2653,7 +2668,7 @@ static void WriteSimpleEntryProtocol2(CalEntry *e)
|
||||
PrintJSONKeyPairInt("r", e->r);
|
||||
PrintJSONKeyPairInt("g", e->g);
|
||||
PrintJSONKeyPairInt("b", e->b);
|
||||
} else if (!StrCmpi(e->passthru, "SHADE")) {
|
||||
} else if (!strcasecmp(e->passthru, "SHADE")) {
|
||||
int r, g, b, n;
|
||||
n = sscanf(e->text, "%d %d %d", &r, &g, &b);
|
||||
if (n < 3) {
|
||||
@@ -2759,9 +2774,7 @@ static void WriteSimpleEntries(int col, int dse)
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
FreeTrigInfoChain(e->infos);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
n = e->next;
|
||||
free(e);
|
||||
e = n;
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `mbstowcs' function. */
|
||||
#undef HAVE_MBSTOWCS
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
@@ -48,24 +45,18 @@
|
||||
/* Define to 1 if you have the `readline' function. */
|
||||
#undef HAVE_READLINE
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#undef HAVE_STRDUP
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#undef HAVE_STRNCASECMP
|
||||
|
||||
/* Define to 1 if you have the <sys/inotify.h> header file. */
|
||||
#undef HAVE_SYS_INOTIFY_H
|
||||
|
||||
/* Define to 1 if you have the <sys/termios.h> header file. */
|
||||
#undef HAVE_SYS_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
@@ -81,9 +72,6 @@
|
||||
/* Define to 1 if you have the `unsetenv' function. */
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
/* Define to 1 if you have the <readline/history.h> header file. */
|
||||
#undef HAVE_READLINE_HISTORY_H
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -154,12 +154,6 @@
|
||||
#define PSBEGIN2 "# rem2ps2 begin"
|
||||
#define PSEND2 "# rem2ps2 end"
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
|
||||
#define USE_READLINE 1
|
||||
#else
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -154,12 +154,6 @@
|
||||
#define PSBEGIN2 "# rem2ps2 begin"
|
||||
#define PSEND2 "# rem2ps2 end"
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_READLINE) && defined(HAVE_READLINE_READLINE_H)
|
||||
#define USE_READLINE 1
|
||||
#else
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Code to suppress duplicate reminders */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
88
src/dorem.c
88
src/dorem.c
@@ -7,7 +7,7 @@
|
||||
/* commands. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -35,7 +35,7 @@ static int ComputeTrigDuration(TimeTrig const *t);
|
||||
|
||||
static int CalledEnterTimezone = 0;
|
||||
|
||||
int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim)
|
||||
int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim, int debug_ok)
|
||||
{
|
||||
int y, m, d, hour, minute;
|
||||
int r;
|
||||
@@ -59,7 +59,7 @@ int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim)
|
||||
/* Adjust eventstart also */
|
||||
trig->eventstart = dse * MINUTES_PER_DAY + tim->ttime;
|
||||
SaveAllTriggerInfo(trig, tim, dse, tim->ttime, 1);
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
if (debug_ok && (DebugFlag & DB_PRTTRIG)) {
|
||||
fprintf(ErrFp, "%s(%s): Trig(tz_adj %s) = %s, %d %s, %d AT %02d:%02d",
|
||||
GetCurrentFilename(), line_range(LineNoStart, LineNo), trig->tz,
|
||||
get_day_name(dse % 7), tm.tm_mday, get_month_name(tm.tm_mon),
|
||||
@@ -306,11 +306,11 @@ ensure_satnode_mentions_trigdate_aux(expr_node *node, int *mentioned)
|
||||
} else {
|
||||
name = node->u.value.v.str;
|
||||
}
|
||||
if (!StrCmpi(name, "T") ||
|
||||
!StrCmpi(name, "Td") ||
|
||||
!StrCmpi(name, "Tm") ||
|
||||
!StrCmpi(name, "Tw") ||
|
||||
!StrCmpi(name, "Ty")) {
|
||||
if (!strcasecmp(name, "T") ||
|
||||
!strcasecmp(name, "Td") ||
|
||||
!strcasecmp(name, "Tm") ||
|
||||
!strcasecmp(name, "Tw") ||
|
||||
!strcasecmp(name, "Ty")) {
|
||||
*mentioned = 1;
|
||||
return;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
|
||||
/* Adjust trigger date/time to time zone */
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim);
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
|
||||
|
||||
/* Add to global OMITs if so indicated */
|
||||
if (trig.addomit) {
|
||||
@@ -546,8 +546,8 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
if (PurgeMode) {
|
||||
if (trig.expired || (!trig.is_todo && dse < DSEToday)) {
|
||||
if (p->expr_happened) {
|
||||
if (p->nonconst_expr) {
|
||||
if (trig.expr_happened) {
|
||||
if (trig.nonconst_expr) {
|
||||
if (!Hush) {
|
||||
PurgeEchoLine("%s\n", "#!P: Next line may have expired, but contains non-constant expression");
|
||||
PurgeEchoLine("%s\n", "#!P: or a relative SCANFROM clause");
|
||||
@@ -632,7 +632,7 @@ int DoRem(ParsePtr p)
|
||||
PrintJSONKeyPairInt("time_in_tz", tim.ttime_orig);
|
||||
}
|
||||
}
|
||||
if (p->nonconst_expr) {
|
||||
if (trig.nonconst_expr) {
|
||||
PrintJSONKeyPairInt("nonconst_expr", 1);
|
||||
}
|
||||
if (if_depth) {
|
||||
@@ -833,6 +833,8 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
trig->adj_for_last = 0;
|
||||
trig->infos = NULL;
|
||||
trig->tz = NULL;
|
||||
trig->nonconst_expr = 0;
|
||||
trig->expr_happened = 0;
|
||||
|
||||
int parsing = 1;
|
||||
while(parsing) {
|
||||
@@ -1097,6 +1099,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
s->expr_happened = 1;
|
||||
nonconst_debug(s->nonconst_expr, tr("OMITFUNC counts as a non-constant expression"));
|
||||
s->nonconst_expr = 1;
|
||||
trig->nonconst_expr = 1;
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
@@ -1117,7 +1120,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
trig->tz = StrDup(DBufValue(&buf));
|
||||
trig->tz = strdup(DBufValue(&buf));
|
||||
if (!trig->tz) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
@@ -1201,6 +1204,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
}
|
||||
}
|
||||
|
||||
if (s->nonconst_expr) {
|
||||
trig->nonconst_expr = 1;
|
||||
}
|
||||
if (s->expr_happened) {
|
||||
trig->expr_happened = 1;
|
||||
}
|
||||
if (trig->need_wkday && trig->wd == NO_WD) {
|
||||
Eprint("Weekday name(s) required");
|
||||
return E_PARSE_ERR;
|
||||
@@ -1237,7 +1246,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->nonconst_expr) {
|
||||
if (!trig->nonconst_expr) {
|
||||
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
|
||||
if (DSE(trig->y, trig->m, trig->d) > trig->until) {
|
||||
Wprint(tr("Warning: UNTIL/THROUGH date earlier than start date"));
|
||||
@@ -1273,10 +1282,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
|
||||
|
||||
/* Remove leading ! from TZ spec */
|
||||
if (trig->tz && *trig->tz == '!') {
|
||||
char *s = (char *) trig->tz;
|
||||
while (*s) {
|
||||
*s = *(s+1);
|
||||
s++;
|
||||
char *stz = (char *) trig->tz;
|
||||
while (*stz) {
|
||||
*stz = *(stz+1);
|
||||
stz++;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
@@ -1497,6 +1506,7 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
s->expr_happened = 1;
|
||||
nonconst_debug(s->nonconst_expr, tr("Relative SCANFROM counts as a non-constant expression"));
|
||||
s->nonconst_expr = 1;
|
||||
t->nonconst_expr = 1;
|
||||
return OK;
|
||||
|
||||
default:
|
||||
@@ -1545,6 +1555,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is
|
||||
DynamicBuffer pre_buf;
|
||||
char const *s;
|
||||
char const *msg_command = NULL;
|
||||
char const *url;
|
||||
Value v;
|
||||
|
||||
if (MsgCommand) {
|
||||
@@ -1566,14 +1577,14 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is
|
||||
DBufInit(&calRow);
|
||||
DBufInit(&pre_buf);
|
||||
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
|
||||
if ((t->typ == PASSTHRU_TYPE && StrCmpi(t->passthru, "COLOR") && StrCmpi(t->passthru, "COLOUR")) ||
|
||||
if ((t->typ == PASSTHRU_TYPE && strcasecmp(t->passthru, "COLOR") && strcasecmp(t->passthru, "COLOUR")) ||
|
||||
t->typ == CAL_TYPE ||
|
||||
t->typ == PS_TYPE ||
|
||||
t->typ == PSF_TYPE)
|
||||
return OK;
|
||||
|
||||
/* Handle COLOR types */
|
||||
if (t->typ == PASSTHRU_TYPE && (!StrCmpi(t->passthru, "COLOR") || !StrCmpi(t->passthru, "COLOUR"))) {
|
||||
if (t->typ == PASSTHRU_TYPE && (!strcasecmp(t->passthru, "COLOR") || !strcasecmp(t->passthru, "COLOUR"))) {
|
||||
/* Strip off three tokens */
|
||||
r = ParseToken(p, &buf);
|
||||
sscanf(DBufValue(&buf), "%d", &red);
|
||||
@@ -1820,9 +1831,16 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are sorting, just queue it up in the sort buffer */
|
||||
/* Get the url if terminal hyperlinks are enabled */
|
||||
if (TerminalHyperlinks) {
|
||||
url = FindTrigInfo(t, "url");
|
||||
} else {
|
||||
url = NULL;
|
||||
}
|
||||
|
||||
/* If we are sorting, just queue it up in the sort buffer */
|
||||
if (SortByDate) {
|
||||
if (InsertIntoSortBuffer(dse, tim->ttime, DBufValue(&buf),
|
||||
if (InsertIntoSortBuffer(dse, tim->ttime, url, DBufValue(&buf),
|
||||
t->typ, t->priority) == OK) {
|
||||
DBufFree(&buf);
|
||||
NumTriggered++;
|
||||
@@ -1845,14 +1863,20 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig const *tim, int dse, int is
|
||||
if (IsServerMode() && !strncmp(DBufValue(&buf), "NOTE endreminder", 16)) {
|
||||
printf(" %s", DBufValue(&buf));
|
||||
} else {
|
||||
if (url) {
|
||||
printf("\x1B]8;;%s\x1B\\", url);
|
||||
}
|
||||
printf("%s", DBufValue(&buf));
|
||||
if (url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSF_TYPE:
|
||||
FillParagraph(DBufValue(&buf), output);
|
||||
FillParagraph(url, DBufValue(&buf), output);
|
||||
break;
|
||||
|
||||
case RUN_TYPE:
|
||||
@@ -2259,7 +2283,9 @@ static int ShouldTriggerBasedOnWarn(Trigger const *t, int dse, int *err)
|
||||
while(iter++ <= max) {
|
||||
j--;
|
||||
*err = IsOmitted(j, t->localomit, t->omitfunc, &omit);
|
||||
if (*err) return 0;
|
||||
if (*err) {
|
||||
return (dse == DSEToday);
|
||||
}
|
||||
if (!omit) v.v.val++;
|
||||
if (!v.v.val) {
|
||||
break;
|
||||
@@ -2267,7 +2293,7 @@ static int ShouldTriggerBasedOnWarn(Trigger const *t, int dse, int *err)
|
||||
}
|
||||
if (iter > max) {
|
||||
Eprint("Delta: Bad OMITFUNC? %s", GetErr(E_CANT_TRIG));
|
||||
return 0;
|
||||
return (dse == DSEToday);
|
||||
}
|
||||
if (j == DSEToday) return 1;
|
||||
}
|
||||
@@ -2281,17 +2307,17 @@ void FixSpecialType(Trigger *t)
|
||||
}
|
||||
|
||||
/* Convert SPECIAL MSG / MSF / RUN / CAL to just plain MSG / MSF / etc */
|
||||
if (!StrCmpi(t->passthru, "MSG")) {
|
||||
if (!strcasecmp(t->passthru, "MSG")) {
|
||||
t->typ = MSG_TYPE;
|
||||
} else if (!StrCmpi(t->passthru, "MSF")) {
|
||||
} else if (!strcasecmp(t->passthru, "MSF")) {
|
||||
t->typ = MSF_TYPE;
|
||||
} else if (!StrCmpi(t->passthru, "RUN")) {
|
||||
} else if (!strcasecmp(t->passthru, "RUN")) {
|
||||
t->typ = RUN_TYPE;
|
||||
} else if (!StrCmpi(t->passthru, "CAL")) {
|
||||
} else if (!strcasecmp(t->passthru, "CAL")) {
|
||||
t->typ = CAL_TYPE;
|
||||
} else if (!StrCmpi(t->passthru, "PS")) {
|
||||
} else if (!strcasecmp(t->passthru, "PS")) {
|
||||
t->typ = PS_TYPE;
|
||||
} else if (!StrCmpi(t->passthru, "PSFILE")) {
|
||||
} else if (!strcasecmp(t->passthru, "PSFILE")) {
|
||||
t->typ = PSF_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* reminders are triggered. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
14
src/dynbuf.c
14
src/dynbuf.c
@@ -6,7 +6,7 @@
|
||||
/* buffers. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -17,6 +17,15 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static size_t NumMallocs = 0;
|
||||
static size_t BytesMalloced = 0;
|
||||
|
||||
void DBufGetMallocStats(size_t *num_mallocs, size_t *bytes_malloced)
|
||||
{
|
||||
*num_mallocs = NumMallocs;
|
||||
*bytes_malloced = BytesMalloced;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
%FUNCTION: DBufMakeRoom
|
||||
%ARGUMENTS:
|
||||
@@ -45,6 +54,9 @@ static int DBufMakeRoom(DynamicBuffer *dbuf, size_t n)
|
||||
buf = malloc(size);
|
||||
if (!buf) return E_NO_MEM;
|
||||
|
||||
NumMallocs++;
|
||||
BytesMalloced += size;
|
||||
|
||||
/* Copy contents */
|
||||
strcpy(buf, dbuf->buffer);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Declaration of functions for manipulating dynamic buffers */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -29,6 +29,8 @@ int DBufPuts(DynamicBuffer *dbuf, char const *str);
|
||||
void DBufFree(DynamicBuffer *dbuf);
|
||||
int DBufGets(DynamicBuffer *dbuf, FILE *fp);
|
||||
|
||||
void DBufGetMallocStats(size_t *num_mallocs, size_t *bytes_malloced);
|
||||
|
||||
#define DBufValue(bufPtr) ((bufPtr)->buffer)
|
||||
#define DBufLen(bufPtr) ((bufPtr)->len)
|
||||
|
||||
|
||||
17
src/err.h
17
src/err.h
@@ -5,7 +5,7 @@
|
||||
/* Error definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -134,9 +134,12 @@
|
||||
#define E_MAX_OVERDUE_WITHOUT_TODO 110
|
||||
#define E_TZ_SPECIFIED_TWICE 111
|
||||
#define E_TZ_NO_AT 112
|
||||
#define E_NO_MB 113
|
||||
#define E_BAD_MB_SEQ 114
|
||||
#define E_EXPR_NODES_EXCEEDED 115
|
||||
#define E_BAD_MB_SEQ 113
|
||||
#define E_EXPR_NODES_EXCEEDED 114
|
||||
#define E_EXPECTING_EOXPR 115
|
||||
#define E_EXPECTING_ATOM 116
|
||||
#define E_BAD_VAL_FOR_SYSVAR 117
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
@@ -149,7 +152,6 @@
|
||||
#define STR2(X) #X
|
||||
|
||||
|
||||
#ifndef L_ERR_OVERRIDE
|
||||
EXTERN char *ErrMsg[]
|
||||
|
||||
#ifdef MK_GLOBALS
|
||||
@@ -267,13 +269,14 @@ EXTERN char *ErrMsg[]
|
||||
/* E_MAX_OVERDUE_WITHOUT_TODO */ "MAX-OVERDUE specified without TODO",
|
||||
/* E_TZ_SPECIFIED_TWICE */ "TZ specified twice",
|
||||
/* E_TZ_NO_AT */ "TZ specified for non-timed reminder",
|
||||
/* E_NO_MB */ "C library does not support multibyte characters",
|
||||
/* E_BAD_MB_SEQ */ "Invalid multibyte sequence",
|
||||
/* E_EXPR_NODES_EXCEEDED */ "Maximum expression complexity exceeded",
|
||||
/* E_EXPECTING_EOXPR */ "Expecting operator or end-of-expression",
|
||||
/* E_EXPECTING_ATOM */ "Expecting constant, variable, function call or (expression)",
|
||||
/* E_BAD_VAL_FOR_SYSVAR */ "Invalid value for system variable",
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
#endif /* L_ERR_OVERRIDE */
|
||||
|
||||
EXTERN int NumErrs
|
||||
#ifdef MK_GLOBALS
|
||||
|
||||
148
src/expr.c
148
src/expr.c
@@ -12,7 +12,7 @@
|
||||
/* evaluated. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -170,6 +170,8 @@ static expr_node *expr_node_free_list = NULL;
|
||||
/* Maximum parse level before we bail (to avoid SEGV from filling stack)*/
|
||||
#define MAX_PARSE_LEVEL 2000
|
||||
|
||||
/* Legal punctuation characters in an expression */
|
||||
#define LEGAL_CHARS "+-*/%&|=<>!)"
|
||||
static int parse_level_high_water = 0;
|
||||
#define CHECK_PARSE_LEVEL() do { if (level > parse_level_high_water) { parse_level_high_water = level; if (level > MAX_PARSE_LEVEL) { *r = E_OP_STK_OVER; return NULL; } } } while(0)
|
||||
|
||||
@@ -240,6 +242,31 @@ find_end_of_expr(char const *s)
|
||||
return e;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* node_str - get string associated with a node */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static char const *
|
||||
node_str(expr_node const *node)
|
||||
{
|
||||
switch(node->type) {
|
||||
case N_VARIABLE:
|
||||
case N_SYSVAR:
|
||||
case N_USER_FUNC:
|
||||
return node->u.value.v.str;
|
||||
|
||||
case N_SHORT_VAR:
|
||||
case N_SHORT_SYSVAR:
|
||||
case N_SHORT_USER_FUNC:
|
||||
case N_SHORT_STR:
|
||||
return node->u.name;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* alloc_expr_node - allocate an expr_node object */
|
||||
@@ -416,11 +443,7 @@ get_var(expr_node *node, Value *ans, int *nonconst)
|
||||
Var *v;
|
||||
char const *str;
|
||||
|
||||
if (node->type == N_SHORT_VAR) {
|
||||
str = node->u.name;
|
||||
} else {
|
||||
str = node->u.value.v.str;
|
||||
}
|
||||
str = node_str(node);
|
||||
v = FindVar(str, 0);
|
||||
if (!v) {
|
||||
Eprint("%s: `%s'", GetErr(E_NOSUCH_VAR), str);
|
||||
@@ -446,11 +469,7 @@ get_var(expr_node *node, Value *ans, int *nonconst)
|
||||
static int
|
||||
get_sysvar(expr_node const *node, Value *ans)
|
||||
{
|
||||
if (node->type == N_SHORT_SYSVAR) {
|
||||
return GetSysVar(node->u.name, ans);
|
||||
} else {
|
||||
return GetSysVar(node->u.value.v.str, ans);
|
||||
}
|
||||
return GetSysVar(node_str(node), ans);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -617,13 +636,9 @@ eval_builtin(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
static void
|
||||
debug_enter_userfunc(expr_node *node, Value *locals, int nargs)
|
||||
{
|
||||
char const *fname;
|
||||
int i;
|
||||
if (node->type == N_SHORT_USER_FUNC) {
|
||||
fname = node->u.name;
|
||||
} else {
|
||||
fname = node->u.value.v.str;
|
||||
}
|
||||
char const *fname = node_str(node);
|
||||
|
||||
fprintf(ErrFp, "%s %s(", GetErr(E_ENTER_FUN), fname);
|
||||
for (i=0; i<nargs; i++) {
|
||||
if (i) fprintf(ErrFp, ", ");
|
||||
@@ -643,13 +658,9 @@ debug_enter_userfunc(expr_node *node, Value *locals, int nargs)
|
||||
static void
|
||||
debug_exit_userfunc(expr_node *node, Value const *ans, int r, Value *locals, int nargs)
|
||||
{
|
||||
char const *fname;
|
||||
char const *fname = node_str(node);
|
||||
int i;
|
||||
if (node->type == N_SHORT_USER_FUNC) {
|
||||
fname = node->u.name;
|
||||
} else {
|
||||
fname = node->u.value.v.str;
|
||||
}
|
||||
|
||||
fprintf(ErrFp, "%s %s(", GetErr(E_LEAVE_FUN), fname);
|
||||
for (i=0; i<nargs; i++) {
|
||||
if (i) fprintf(ErrFp, ", ");
|
||||
@@ -700,12 +711,7 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
Value stack_locals[STACK_ARGS_MAX];
|
||||
|
||||
/* Get the function name */
|
||||
char const *fname;
|
||||
if (node->type == N_SHORT_USER_FUNC) {
|
||||
fname = node->u.name;
|
||||
} else {
|
||||
fname = node->u.value.v.str;
|
||||
}
|
||||
char const *fname = node_str(node);
|
||||
|
||||
/* Find the function */
|
||||
f = FindUserFunc(fname);
|
||||
@@ -911,13 +917,9 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
return CopyValue(ans, &(node->u.value));
|
||||
|
||||
case N_SHORT_VAR:
|
||||
r = get_var(node, ans, nonconst);
|
||||
DBG(debug_evaluation(ans, r, "%s", node->u.name));
|
||||
return r;
|
||||
|
||||
case N_VARIABLE:
|
||||
r = get_var(node, ans, nonconst);
|
||||
DBG(debug_evaluation(ans, r, "%s", node->u.value.v.str));
|
||||
DBG(debug_evaluation(ans, r, "%s", node_str(node)));
|
||||
return r;
|
||||
|
||||
case N_LOCAL_VAR:
|
||||
@@ -927,19 +929,12 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
return r;
|
||||
|
||||
case N_SHORT_SYSVAR:
|
||||
/* System var? Return it and note non-constant expression */
|
||||
nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node->u.name);
|
||||
*nonconst = 1;
|
||||
r = get_sysvar(node, ans);
|
||||
DBG(debug_evaluation(ans, r, "$%s", node->u.name));
|
||||
return r;
|
||||
|
||||
case N_SYSVAR:
|
||||
/* System var? Return it and note non-constant expression */
|
||||
nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node->u.value.v.str);
|
||||
nonconst_debug(*nonconst, tr("System variable `$%s' makes expression non-constant"), node_str(node));
|
||||
*nonconst = 1;
|
||||
r = get_sysvar(node, ans);
|
||||
DBG(debug_evaluation(ans, r, "$%s", node->u.value.v.str));
|
||||
DBG(debug_evaluation(ans, r, "$%s", node_str(node)));
|
||||
return r;
|
||||
|
||||
case N_BUILTIN_FUNC:
|
||||
@@ -950,8 +945,8 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
return eval_builtin(node, locals, ans, nonconst);
|
||||
|
||||
case N_USER_FUNC:
|
||||
case N_SHORT_USER_FUNC:
|
||||
case N_USER_FUNC:
|
||||
/* User-defined function? Evaluate it */
|
||||
return eval_userfunc(node, locals, ans, nonconst);
|
||||
|
||||
@@ -2228,9 +2223,15 @@ static int set_constant_value(expr_node *atom)
|
||||
atom->u.value.v.val = val;
|
||||
return OK;
|
||||
}
|
||||
|
||||
atom->u.value.type = ERR_TYPE;
|
||||
Eprint("`%s': %s", DBufValue(&ExprBuf), GetErr(E_ILLEGAL_CHAR));
|
||||
return E_ILLEGAL_CHAR;
|
||||
if (strchr(LEGAL_CHARS, *s) != NULL) {
|
||||
r = E_EXPECTING_ATOM;
|
||||
} else {
|
||||
r = E_ILLEGAL_CHAR;
|
||||
}
|
||||
Eprint("`%s': %s", DBufValue(&ExprBuf), GetErr(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -2248,7 +2249,7 @@ static int make_atom(expr_node *atom, Var *locals)
|
||||
/* Variable */
|
||||
if (isalpha(*s) || *s == '_') {
|
||||
while(v) {
|
||||
if (! StrinCmp(s, v->name, VAR_NAME_LEN)) {
|
||||
if (! strncasecmp(s, v->name, VAR_NAME_LEN)) {
|
||||
atom->type = N_LOCAL_VAR;
|
||||
atom->u.arg = i;
|
||||
return OK;
|
||||
@@ -2346,8 +2347,13 @@ static expr_node *parse_atom(char const **e, int *r, Var *locals, int level)
|
||||
*s != '$' &&
|
||||
*s != '"' &&
|
||||
*s != '\'') {
|
||||
Eprint("%s `%c'", GetErr(E_ILLEGAL_CHAR), *s);
|
||||
*r = E_ILLEGAL_CHAR;
|
||||
if (strchr(LEGAL_CHARS, *s) != NULL) {
|
||||
*r = E_EXPECTING_ATOM;
|
||||
Eprint("%s", GetErr(*r));
|
||||
} else {
|
||||
*r = E_ILLEGAL_CHAR;
|
||||
Eprint("%s `%c'", GetErr(*r), *s);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2759,9 +2765,24 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
|
||||
print_expr_tree(node, ErrFp);
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
if (**e && (**e != ']')) {
|
||||
orig = o2;
|
||||
}
|
||||
while (**e && isempty(**e)) {
|
||||
(*e)++;
|
||||
}
|
||||
if (**e && (**e != ']')) {
|
||||
if (DebugFlag & DB_PARSE_EXPR) {
|
||||
fprintf(ErrFp, " Unparsed: %s\n", *e);
|
||||
}
|
||||
if (*r == OK) {
|
||||
*r = E_EXPECTING_EOXPR;
|
||||
}
|
||||
}
|
||||
if (*r != OK) {
|
||||
if (node) {
|
||||
free_expr_tree(node);
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
if (!SuppressErrorOutputInCatch) {
|
||||
if (*r == E_EXPECT_COMMA ||
|
||||
@@ -2771,9 +2792,11 @@ expr_node *parse_expression(char const **e, int *r, Var *locals)
|
||||
*r == E_2FEW_ARGS ||
|
||||
*r == E_PARSE_ERR ||
|
||||
*r == E_EOLN ||
|
||||
*r == E_EXPECTING_EOXPR ||
|
||||
*r == E_BAD_NUMBER ||
|
||||
*r == E_BAD_DATE ||
|
||||
*r == E_BAD_TIME ||
|
||||
*r == E_EXPECTING_ATOM ||
|
||||
*r == E_ILLEGAL_CHAR) {
|
||||
end_of_expr = find_end_of_expr(orig);
|
||||
while (**e && isempty(**e)) {
|
||||
@@ -2839,16 +2862,12 @@ static void print_expr_tree(expr_node *node, FILE *fp)
|
||||
fprintf(fp, "\"%s\"", node->u.name);
|
||||
return;
|
||||
case N_SHORT_VAR:
|
||||
fprintf(fp, "%s", node->u.name);
|
||||
return;
|
||||
case N_VARIABLE:
|
||||
fprintf(fp, "%s", node->u.value.v.str);
|
||||
fprintf(fp, "%s", node_str(node));
|
||||
return;
|
||||
case N_SHORT_SYSVAR:
|
||||
fprintf(fp, "$%s", node->u.name);
|
||||
return;
|
||||
case N_SYSVAR:
|
||||
fprintf(fp, "$%s", node->u.value.v.str);
|
||||
fprintf(fp, "$%s", node_str(node));
|
||||
return;
|
||||
case N_LOCAL_VAR:
|
||||
fprintf(fp, "arg[%d]", node->u.arg);
|
||||
@@ -2862,13 +2881,8 @@ static void print_expr_tree(expr_node *node, FILE *fp)
|
||||
fprintf(fp, ")");
|
||||
return;
|
||||
case N_SHORT_USER_FUNC:
|
||||
fprintf(fp, "(%s", node->u.name);
|
||||
if (node->child) fprintf(fp, " ");
|
||||
print_kids(node, fp);
|
||||
fprintf(fp, ")");
|
||||
return;
|
||||
case N_USER_FUNC:
|
||||
fprintf(fp, "(%s", node->u.value.v.str);
|
||||
fprintf(fp, "(%s", node_str(node));
|
||||
if (node->child) fprintf(fp, " ");
|
||||
print_kids(node, fp);
|
||||
fprintf(fp, ")");
|
||||
@@ -2964,7 +2978,6 @@ int EvalExpr(char const **e, Value *v, ParsePtr p)
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
/* Truncate a wide-char string to MAX_PRT_LEN characters */
|
||||
static char const *truncate_string(char const *src)
|
||||
{
|
||||
@@ -2984,7 +2997,6 @@ static char const *truncate_string(char const *src)
|
||||
cbuf[MAX_PRT_LEN*8] = 0;
|
||||
return cbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -3010,7 +3022,6 @@ char const *PrintValue (Value const *v, FILE *fp)
|
||||
}
|
||||
|
||||
if (v->type == STR_TYPE) {
|
||||
#ifdef REM_USE_WCHAR
|
||||
s = (unsigned char const *) truncate_string(v->v.str);
|
||||
if (s != (unsigned char const *) v->v.str) {
|
||||
max_str_put = INT_MAX;
|
||||
@@ -3018,9 +3029,6 @@ char const *PrintValue (Value const *v, FILE *fp)
|
||||
truncated = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
s = (unsigned char const *) v->v.str;
|
||||
#endif
|
||||
PV_PUTC(fp, '"');
|
||||
for (y=0; y<max_str_put && *s; y++) {
|
||||
switch(*s) {
|
||||
@@ -3115,7 +3123,7 @@ int CopyValue(Value *dest, const Value *src)
|
||||
{
|
||||
dest->type = ERR_TYPE;
|
||||
if (src->type == STR_TYPE) {
|
||||
dest->v.str = StrDup(src->v.str);
|
||||
dest->v.str = strdup(src->v.str);
|
||||
if (!dest->v.str) return E_NO_MEM;
|
||||
} else {
|
||||
dest->v.val = src->v.val;
|
||||
@@ -3288,7 +3296,7 @@ int DoCoerce(char type, Value *v)
|
||||
default: return E_CANT_COERCE;
|
||||
}
|
||||
v->type = STR_TYPE;
|
||||
v->v.str = StrDup(coerce_buf);
|
||||
v->v.str = strdup(coerce_buf);
|
||||
if (!v->v.str) {
|
||||
v->type = ERR_TYPE;
|
||||
return E_NO_MEM;
|
||||
|
||||
15
src/files.c
15
src/files.c
@@ -7,7 +7,7 @@
|
||||
/* files. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -225,8 +225,9 @@ static void OpenPurgeFile(char const *fname, char const *mode)
|
||||
if (!PurgeFP) {
|
||||
fprintf(ErrFp, tr("Cannot open `%s' for writing: %s"), DBufValue(&fname_buf), strerror(errno));
|
||||
fprintf(ErrFp, "\n");
|
||||
} else {
|
||||
set_cloexec(fileno(PurgeFP));
|
||||
}
|
||||
set_cloexec(fileno(PurgeFP));
|
||||
DBufFree(&fname_buf);
|
||||
}
|
||||
|
||||
@@ -558,7 +559,7 @@ static int CacheFile(char const *fname, int use_pclose)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
cf->cache = NULL;
|
||||
cf->filename = StrDup(fname);
|
||||
cf->filename = strdup(fname);
|
||||
if (!cf->filename) {
|
||||
ShouldCache = 0;
|
||||
if (use_pclose) {
|
||||
@@ -626,7 +627,7 @@ static int CacheFile(char const *fname, int use_pclose)
|
||||
cl->next = NULL;
|
||||
cl->LineNo = LineNo;
|
||||
cl->LineNoStart = LineNoStart;
|
||||
cl->text = StrDup(s);
|
||||
cl->text = strdup(s);
|
||||
DBufFree(&LineBuffer);
|
||||
if (!cl->text) {
|
||||
DestroyCache(cf);
|
||||
@@ -873,7 +874,7 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
i->chain = NULL;
|
||||
if (!*dirname) return E_CANT_OPEN;
|
||||
|
||||
dir = StrDup(dirname);
|
||||
dir = strdup(dirname);
|
||||
if (!dir) return E_NO_MEM;
|
||||
|
||||
/* Strip trailing slashes off directory */
|
||||
@@ -915,7 +916,7 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
if (ShouldCache) {
|
||||
dc = malloc(sizeof(DirectoryFilenameChain));
|
||||
if (dc) {
|
||||
dc->dirname = StrDup(dir);
|
||||
dc->dirname = strdup(dir);
|
||||
if (!dc->dirname) {
|
||||
free(dc);
|
||||
dc = NULL;
|
||||
@@ -971,7 +972,7 @@ static int SetupGlobChain(char const *dirname, IncludeStruct *i)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
ch->filename = StrDup(glob_buf.gl_pathv[r]);
|
||||
ch->filename = strdup(glob_buf.gl_pathv[r]);
|
||||
if (!ch->filename) {
|
||||
globfree(&glob_buf);
|
||||
FreeChain(i->chain);
|
||||
|
||||
285
src/funcs.c
285
src/funcs.c
@@ -6,18 +6,21 @@
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
#include "version.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
/* Required on OpenIndiana / Solaris */
|
||||
#ifdef __sun
|
||||
#define __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -28,6 +31,12 @@
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TERMIOS_H
|
||||
#ifdef __sun
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -124,14 +133,18 @@ static int FIsconst (expr_node *, Value *, Value *, int *);
|
||||
static int FIsdst (func_info *);
|
||||
static int FIsleap (func_info *);
|
||||
static int FIsomitted (func_info *);
|
||||
static int FIvritmon (func_info *);
|
||||
static int FLanguage (func_info *);
|
||||
static int FLocalToUTC (func_info *);
|
||||
static int FLower (func_info *);
|
||||
static int FMax (func_info *);
|
||||
static int FMbchar (func_info *);
|
||||
static int FMbindex (func_info *);
|
||||
static int FMblower (func_info *);
|
||||
static int FMbpad (func_info *);
|
||||
static int FMbstrlen (func_info *);
|
||||
static int FMbsubstr (func_info *);
|
||||
static int FMbupper (func_info *);
|
||||
static int FMin (func_info *);
|
||||
static int FMinsfromutc (func_info *);
|
||||
static int FMinute (func_info *);
|
||||
@@ -309,14 +322,18 @@ BuiltinFunc Func[] = {
|
||||
{ "isdst", 0, 2, 0, FIsdst, NULL },
|
||||
{ "isleap", 1, 1, 1, FIsleap, NULL },
|
||||
{ "isomitted", 1, 1, 0, FIsomitted, NULL },
|
||||
{ "ivritmon", 1, 1, 0, FIvritmon, NULL },
|
||||
{ "language", 0, 0, 1, FLanguage, NULL },
|
||||
{ "localtoutc", 1, 1, 1, FLocalToUTC, NULL },
|
||||
{ "lower", 1, 1, 1, FLower, NULL },
|
||||
{ "max", 1, NO_MAX, 1, FMax, NULL },
|
||||
{ "mbchar", 1, NO_MAX, 1, FMbchar, NULL },
|
||||
{ "mbindex", 2, 3, 1, FMbindex, NULL },
|
||||
{ "mblower", 1, 1, 1, FMblower, NULL },
|
||||
{ "mbpad", 3, 4, 1, FMbpad, NULL },
|
||||
{ "mbstrlen", 1, 1, 1, FMbstrlen, NULL },
|
||||
{ "mbsubstr", 2, 3, 1, FMbsubstr, NULL },
|
||||
{ "mbupper", 1, 1, 1, FMbupper, NULL },
|
||||
{ "min", 1, NO_MAX, 1, FMin, NULL },
|
||||
{ "minsfromutc", 0, 2, 0, FMinsfromutc, NULL },
|
||||
{ "minute", 1, 1, 1, FMinute, NULL },
|
||||
@@ -437,7 +454,7 @@ static int RetStrVal(char const *s, func_info *info)
|
||||
RetVal.v.str = malloc(1);
|
||||
if (RetVal.v.str) *RetVal.v.str = 0;
|
||||
} else {
|
||||
RetVal.v.str = StrDup(s);
|
||||
RetVal.v.str = strdup(s);
|
||||
}
|
||||
|
||||
if (!RetVal.v.str) {
|
||||
@@ -495,7 +512,6 @@ static int FStrlen(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FMbstrlen(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
size_t l = mbstowcs(NULL, ARGSTR(0), 0);
|
||||
if (l == (size_t) -1) {
|
||||
@@ -505,9 +521,6 @@ static int FMbstrlen(func_info *info)
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = (int) l;
|
||||
return OK;
|
||||
#else
|
||||
return E_NO_MB;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -645,11 +658,11 @@ static int FCoerce(func_info *info)
|
||||
it won't be destroyed */
|
||||
DCOPYVAL(RetVal, ARG(1));
|
||||
|
||||
if (! StrCmpi(s, "int")) r = DoCoerce(INT_TYPE, &RetVal);
|
||||
else if (! StrCmpi(s, "date")) r = DoCoerce(DATE_TYPE, &RetVal);
|
||||
else if (! StrCmpi(s, "time")) r = DoCoerce(TIME_TYPE, &RetVal);
|
||||
else if (! StrCmpi(s, "string")) r = DoCoerce(STR_TYPE, &RetVal);
|
||||
else if (! StrCmpi(s, "datetime")) r = DoCoerce(DATETIME_TYPE, &RetVal);
|
||||
if (! strcasecmp(s, "int")) r = DoCoerce(INT_TYPE, &RetVal);
|
||||
else if (! strcasecmp(s, "date")) r = DoCoerce(DATE_TYPE, &RetVal);
|
||||
else if (! strcasecmp(s, "time")) r = DoCoerce(TIME_TYPE, &RetVal);
|
||||
else if (! strcasecmp(s, "string")) r = DoCoerce(STR_TYPE, &RetVal);
|
||||
else if (! strcasecmp(s, "datetime")) r = DoCoerce(DATETIME_TYPE, &RetVal);
|
||||
else {
|
||||
Eprint("coerce(): Invalid type `%s'", s);
|
||||
return E_CANT_COERCE;
|
||||
@@ -757,7 +770,6 @@ static int FHex(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FCodepoint(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t arr[2];
|
||||
size_t len;
|
||||
|
||||
@@ -771,9 +783,6 @@ static int FCodepoint(func_info *info)
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = (int) arr[0];
|
||||
return OK;
|
||||
#else
|
||||
return E_NO_MB;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -832,7 +841,6 @@ static int FChar(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FMbchar(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
int i;
|
||||
size_t len;
|
||||
wchar_t *arr;
|
||||
@@ -878,9 +886,6 @@ static int FMbchar(func_info *info)
|
||||
RetVal.type = STR_TYPE;
|
||||
RetVal.v.str = s;
|
||||
return OK;
|
||||
#else
|
||||
return E_NO_MB;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -1431,6 +1436,125 @@ static int FPad(func_info *info)
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FMbpad - multibyte version of Fpad */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int FMbpad(func_info *info)
|
||||
{
|
||||
int r;
|
||||
wchar_t *s;
|
||||
wchar_t *d;
|
||||
|
||||
size_t len;
|
||||
size_t len2;
|
||||
size_t wantlen;
|
||||
size_t i;
|
||||
|
||||
wchar_t *src;
|
||||
wchar_t *pad;
|
||||
wchar_t *dest;
|
||||
|
||||
char *result;
|
||||
ASSERT_TYPE(1, STR_TYPE);
|
||||
ASSERT_TYPE(2, INT_TYPE);
|
||||
if (Nargs == 4) {
|
||||
ASSERT_TYPE(3, INT_TYPE);
|
||||
}
|
||||
|
||||
if (ARG(0).type != STR_TYPE) {
|
||||
r = DoCoerce(STR_TYPE, &ARG(0));
|
||||
if (r != OK) return r;
|
||||
}
|
||||
|
||||
wantlen = ARGV(2);
|
||||
|
||||
/* Convert ARGV(0) and ARGV(1) to wide-char strings */
|
||||
len = mbstowcs(NULL, ARGSTR(0), 0);
|
||||
if (len == (size_t) -1) {
|
||||
return E_BAD_MB_SEQ;
|
||||
}
|
||||
|
||||
if (len >= wantlen) {
|
||||
DCOPYVAL(RetVal, ARG(0));
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (strlen(ARGSTR(1)) == 0) {
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
|
||||
if (MaxStringLen > 0 && wantlen > (size_t) MaxStringLen) {
|
||||
return E_STRING_TOO_LONG;
|
||||
}
|
||||
|
||||
src = calloc(len+1, sizeof(wchar_t));
|
||||
if (!src) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
(void) mbstowcs(src, ARGSTR(0), len+1);
|
||||
len2 = mbstowcs(NULL, ARGSTR(1), 0);
|
||||
if (len2 == (size_t) -1) {
|
||||
free(src);
|
||||
return E_BAD_MB_SEQ;
|
||||
}
|
||||
pad = calloc(len2+1, sizeof(wchar_t));
|
||||
if (!pad) {
|
||||
free(src);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
(void) mbstowcs(pad, ARGSTR(1), len2+1);
|
||||
|
||||
dest = calloc(wantlen+1, sizeof(wchar_t));
|
||||
if (!dest) {
|
||||
free(src);
|
||||
free(pad);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
d = dest;
|
||||
if (Nargs < 4 || !ARGV(3)) {
|
||||
/* Pad on the LEFT */
|
||||
s = pad;
|
||||
for (i=0; i<wantlen-len; i++) {
|
||||
*d++ = *s++;
|
||||
if (!*s) s = pad;
|
||||
}
|
||||
s = src;
|
||||
while (*s) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
} else {
|
||||
s = src;
|
||||
while (*s) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
s = pad;
|
||||
for (i=0; i<wantlen-len; i++) {
|
||||
*d++ = *s++;
|
||||
if (!*s) s = pad;
|
||||
}
|
||||
}
|
||||
|
||||
len = wcstombs(NULL, dest, 0);
|
||||
result = calloc(len+1, 1);
|
||||
if (!result) {
|
||||
free(src);
|
||||
free(pad);
|
||||
free(dest);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
(void) wcstombs(result, dest, len+1);
|
||||
|
||||
r = RetStrVal(result, info);
|
||||
free(result);
|
||||
free(src);
|
||||
free(pad);
|
||||
free(dest);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -1506,6 +1630,7 @@ static int FIsconst(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
PUT(PrintValue(ans, NULL));
|
||||
OUT();
|
||||
}
|
||||
DestroyValue(junk);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -2552,7 +2677,6 @@ static int FSubstr(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FMbsubstr(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t *str;
|
||||
wchar_t *s;
|
||||
wchar_t const *t;
|
||||
@@ -2607,9 +2731,6 @@ static int FMbsubstr(func_info *info)
|
||||
RetVal.v.str = converted;
|
||||
free( (void *) str);
|
||||
return OK;
|
||||
#else
|
||||
return E_NO_MB;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -2659,7 +2780,6 @@ static int FIndex(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FMbindex(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t *haystack;
|
||||
wchar_t *needle;
|
||||
wchar_t const *s;
|
||||
@@ -2712,9 +2832,6 @@ static int FMbindex(func_info *info)
|
||||
free( (void *) haystack);
|
||||
free( (void *) needle);
|
||||
return OK;
|
||||
#else
|
||||
return E_NO_MB;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -2767,6 +2884,7 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
|
||||
if (truthy(&v)) {
|
||||
DestroyValue(v);
|
||||
r = evaluate_expr_node(cur->sibling, locals, ans, nonconst);
|
||||
if (r == OK && DBGX) {
|
||||
PUT(", ");
|
||||
@@ -2782,6 +2900,8 @@ static int FIif(expr_node *node, Value *locals, Value *ans, int *nonconst)
|
||||
}
|
||||
DBG(DBufFree(&DebugBuf));
|
||||
return r;
|
||||
} else {
|
||||
DestroyValue(v);
|
||||
}
|
||||
DBG(PUT(", ?"));
|
||||
cur = cur->sibling->sibling;
|
||||
@@ -3067,6 +3187,26 @@ static int FHebmon(func_info *info)
|
||||
return RetStrVal(HebMonthName(m, y), info);
|
||||
}
|
||||
|
||||
static int FIvritmon(func_info *info)
|
||||
{
|
||||
int y, m, d, v;
|
||||
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
v = DATEPART(ARG(0));
|
||||
|
||||
if (v == CacheHebDse) {
|
||||
m = CacheHebMon;
|
||||
y = CacheHebYear;
|
||||
} else {
|
||||
DSEToHeb(v, &y, &m, &d);
|
||||
CacheHebDse = v;
|
||||
CacheHebYear = y;
|
||||
CacheHebMon = m;
|
||||
CacheHebDay = d;
|
||||
}
|
||||
return RetStrVal(IvritMonthName(m, y), info);
|
||||
}
|
||||
|
||||
static int FHebyear(func_info *info)
|
||||
{
|
||||
int y, m, d, v;
|
||||
@@ -3522,7 +3662,7 @@ static int UTCToLocalHelper(int datetime, int *ret)
|
||||
|
||||
old_tz = getenv("TZ");
|
||||
if (old_tz) {
|
||||
old_tz = StrDup(old_tz);
|
||||
old_tz = strdup(old_tz);
|
||||
if (!old_tz) return E_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -4266,7 +4406,7 @@ int tz_convert(int year, int month, int day,
|
||||
/* backup old TZ env var */
|
||||
old_tz = getenv("TZ");
|
||||
if (old_tz) {
|
||||
old_tz = StrDup(old_tz);
|
||||
old_tz = strdup(old_tz);
|
||||
if (!old_tz) return E_NO_MEM;
|
||||
}
|
||||
if (tgt_tz == NULL || !*tgt_tz) {
|
||||
@@ -4320,6 +4460,7 @@ static int FTzconvert(func_info *info)
|
||||
{
|
||||
int year, month, day, hour, minute, r;
|
||||
int dse, tim;
|
||||
char const *src_tz, *tgt_tz;
|
||||
struct tm tm;
|
||||
|
||||
if (ARG(0).type != DATETIME_TYPE ||
|
||||
@@ -4333,11 +4474,26 @@ static int FTzconvert(func_info *info)
|
||||
minute = r % 60;
|
||||
|
||||
if (Nargs == 2) {
|
||||
src_tz = ARGSTR(1);
|
||||
warn_if_timezone_bad(src_tz);
|
||||
if (*src_tz == '!') {
|
||||
src_tz++;
|
||||
}
|
||||
r = tz_convert(year, month, day, hour, minute,
|
||||
ARGSTR(1), NULL, &tm);
|
||||
src_tz, NULL, &tm);
|
||||
} else {
|
||||
src_tz = ARGSTR(1);
|
||||
warn_if_timezone_bad(src_tz);
|
||||
if (*src_tz == '!') {
|
||||
src_tz++;
|
||||
}
|
||||
tgt_tz = ARGSTR(2);
|
||||
warn_if_timezone_bad(tgt_tz);
|
||||
if (*tgt_tz == '!') {
|
||||
tgt_tz++;
|
||||
}
|
||||
r = tz_convert(year, month, day, hour, minute,
|
||||
ARGSTR(1), ARGSTR(2), &tm);
|
||||
src_tz, tgt_tz, &tm);
|
||||
}
|
||||
|
||||
if (r == -1) return E_CANT_CONVERT_TZ;
|
||||
@@ -4605,7 +4761,7 @@ FEvalTrig(func_info *info)
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = dse;
|
||||
} else {
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim);
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = (MINUTES_PER_DAY * dse) + tim.ttime;
|
||||
}
|
||||
@@ -4720,7 +4876,7 @@ FTrig(func_info *info)
|
||||
FreeTrig(&trig);
|
||||
continue;
|
||||
}
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim);
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
|
||||
if (ShouldTriggerReminder(&trig, &tim, dse, &r)) {
|
||||
LastTrig = dse;
|
||||
RETVAL = dse;
|
||||
@@ -4737,10 +4893,13 @@ rows_or_cols(func_info *info, int want_rows)
|
||||
{
|
||||
struct winsize w;
|
||||
int fd = STDOUT_FILENO;
|
||||
|
||||
int opened = 0;
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
if (!isatty(fd)) {
|
||||
/* Try STDERR fd if STDOUT fd is not a tty */
|
||||
fd = STDERR_FILENO;
|
||||
}
|
||||
if (!isatty(fd)) {
|
||||
fd = open("/dev/tty", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@@ -4767,16 +4926,14 @@ static int FRows(func_info *info)
|
||||
}
|
||||
static int FColumns(func_info *info)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
size_t len;
|
||||
wchar_t *buf, *s;
|
||||
int width;
|
||||
#endif
|
||||
|
||||
if (Nargs == 0) {
|
||||
return rows_or_cols(info, 0);
|
||||
}
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
#ifdef REM_USE_WCHAR
|
||||
len = mbstowcs(NULL, ARGSTR(0), 0);
|
||||
if (len == (size_t) -1) return E_NO_MEM;
|
||||
buf = calloc(len+1, sizeof(wchar_t));
|
||||
@@ -4804,9 +4961,6 @@ static int FColumns(func_info *info)
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = width;
|
||||
return OK;
|
||||
#else
|
||||
return E_BAD_TYPE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The following sets of functions are for computing solstices and equinoxes.
|
||||
@@ -5023,3 +5177,50 @@ print_builtinfunc_tokens(void)
|
||||
printf("%s\n", Func[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static int mbupper_lower(func_info *info, int upper)
|
||||
{
|
||||
wchar_t *ws;
|
||||
char *s;
|
||||
size_t i, len;
|
||||
int r;
|
||||
ASSERT_TYPE(0, STR_TYPE);
|
||||
len = mbstowcs(NULL, ARGSTR(0), 0);
|
||||
if (len == (size_t) -1) {
|
||||
return E_BAD_MB_SEQ;
|
||||
}
|
||||
ws = calloc(len+1, sizeof(wchar_t));
|
||||
if (!ws) {
|
||||
return E_NO_MEM;
|
||||
}
|
||||
(void) mbstowcs(ws, ARGSTR(0), len+1);
|
||||
for (i=0; i<len; i++) {
|
||||
if (upper) {
|
||||
ws[i] = towupper(ws[i]);
|
||||
} else {
|
||||
ws[i] = towlower(ws[i]);
|
||||
}
|
||||
}
|
||||
len = wcstombs(NULL, ws, 0);
|
||||
s = calloc(len+1, 1);
|
||||
if (!s) {
|
||||
free(ws);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
(void) wcstombs(s, ws, len+1);
|
||||
r = RetStrVal(s, info);
|
||||
free(s);
|
||||
free(ws);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int FMblower(func_info *info)
|
||||
{
|
||||
return mbupper_lower(info, 0);
|
||||
}
|
||||
|
||||
static int FMbupper(func_info *info)
|
||||
{
|
||||
return mbupper_lower(info, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* globals.h and err.h */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -106,6 +106,7 @@ EXTERN INIT( int DefaultPrio, NO_PRIORITY);
|
||||
EXTERN INIT( int SysTime, -1);
|
||||
EXTERN INIT( int LocalSysTime, -1);
|
||||
EXTERN INIT( int ParseUntriggered, 0);
|
||||
EXTERN INIT( int Shaded, 0);
|
||||
|
||||
EXTERN char const *InitialFile;
|
||||
EXTERN char const *LocalTimeZone;
|
||||
@@ -127,7 +128,7 @@ EXTERN INIT( int DefaultColorB, -1);
|
||||
EXTERN INIT( int DefaultColorG, -1);
|
||||
EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 1000);
|
||||
EXTERN INIT( int MaxSatIter, 10000);
|
||||
EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
|
||||
EXTERN INIT( int UseStdin, 0);
|
||||
EXTERN INIT( int PurgeMode, 0);
|
||||
@@ -146,6 +147,7 @@ EXTERN int ArgC;
|
||||
EXTERN char const **ArgV;
|
||||
EXTERN INIT( int CalLines, CAL_LINES);
|
||||
EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int CalSepLine, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseBGVTColors, 0);
|
||||
EXTERN INIT( int UseUTF8Chars, 0);
|
||||
@@ -170,6 +172,10 @@ EXTERN INIT( double Latitude, DEFAULT_LATITUDE);
|
||||
|
||||
EXTERN INIT( char *Location, LOCATION);
|
||||
|
||||
/* Support hyperlinks in terminal emulators?
|
||||
https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
||||
*/
|
||||
EXTERN INIT( int TerminalHyperlinks, -1);
|
||||
/* UTC calculation stuff */
|
||||
EXTERN INIT( int MinsFromUTC, 0);
|
||||
EXTERN INIT( int CalculateUTC, 1);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Implementation of hash table. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Header file for hash-table related functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Utility function to print hash table stats. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
90
src/hbcal.c
90
src/hbcal.c
@@ -5,7 +5,7 @@
|
||||
/* Support for the Hebrew calendar */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||
@@ -61,10 +61,58 @@
|
||||
#define ADAR2ADARA 1
|
||||
#define ADAR2BOTH 2
|
||||
|
||||
struct AltMonthName {
|
||||
char const *name;
|
||||
int mon;
|
||||
};
|
||||
|
||||
static char const *HebMonthNames[] = {
|
||||
"Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B",
|
||||
"Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"};
|
||||
|
||||
static char const *IvritMonthNames[] = {
|
||||
"תשרי",
|
||||
"חשוון",
|
||||
"כסלו",
|
||||
"טבת",
|
||||
"שבט",
|
||||
"אדר א'",
|
||||
"אדר ב'",
|
||||
"ניסן",
|
||||
"אייר",
|
||||
"סיון",
|
||||
"תמוז",
|
||||
"אב",
|
||||
"אלול",
|
||||
"אדר" };
|
||||
|
||||
/* Alternate spellings */
|
||||
static struct AltMonthName AltMonthSpellings[] = {
|
||||
{ "Tishri", TISHREY },
|
||||
{ "Tishrei", TISHREY },
|
||||
|
||||
{ "Cheshvan", HESHVAN },
|
||||
{ "Kheshvan", HESHVAN },
|
||||
|
||||
{ "Shevat", SHVAT },
|
||||
|
||||
{ "Tammuz", TAMUZ },
|
||||
|
||||
{ "Adar 1", ADARA },
|
||||
{ "Adar I", ADARA },
|
||||
{ "אדר א", ADARA },
|
||||
{ "אדר 1", ADARA },
|
||||
{ "אדר I", ADARA },
|
||||
|
||||
{ "Adar 2", ADARB },
|
||||
{ "Adar II", ADARB },
|
||||
{ "אדר ב", ADARB },
|
||||
{ "אדר 2", ADARB },
|
||||
{ "אדר II", ADARB },
|
||||
|
||||
{ "Iyyar", IYAR }
|
||||
};
|
||||
|
||||
static char MaxMonLen[] = {
|
||||
30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29};
|
||||
|
||||
@@ -245,14 +293,32 @@ int HebNameToNum(char const *mname)
|
||||
int i;
|
||||
int m=-1;
|
||||
|
||||
for (i=0; i<14; i++)
|
||||
if (!StrCmpi(mname, HebMonthNames[i])) {
|
||||
for (i=0; i<14; i++) {
|
||||
if (!strcasecmp(mname, HebMonthNames[i])) {
|
||||
m = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m == -1) {
|
||||
for (i=0; i<14; i++) {
|
||||
if (!strcmp(mname, IvritMonthNames[i])) {
|
||||
m = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try the alternate spellings */
|
||||
if (m == -1) {
|
||||
for (i=0; i < (int) (sizeof(AltMonthSpellings) / sizeof(AltMonthSpellings[0])); i++) {
|
||||
if (!strcasecmp(mname, AltMonthSpellings[i].name)) {
|
||||
m = AltMonthSpellings[i].mon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -270,6 +336,22 @@ char const *HebMonthName(int m, int y)
|
||||
else return HebMonthNames[m];
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IvritMonthname */
|
||||
/* */
|
||||
/* Convert a Hebrew month's number to its name in Hebrew */
|
||||
/* script, given the year. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char const *IvritMonthName(int m, int y)
|
||||
{
|
||||
if (m != ADARA && m != ADARB) return IvritMonthNames[m];
|
||||
|
||||
if (!HebIsLeap[(y-1)%19]) return IvritMonthNames[ADAR];
|
||||
else return IvritMonthNames[m];
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* GetValidHebDate */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Logic for tracking the state of the IF... ELSE... ENDIF */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
41
src/init.c
41
src/init.c
@@ -7,7 +7,7 @@
|
||||
/* in normal mode. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -35,6 +35,13 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TERMIOS_H
|
||||
#ifdef __sun
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "protos.h"
|
||||
@@ -189,7 +196,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
/* Initialize local time zone */
|
||||
LocalTimeZone = getenv("TZ");
|
||||
if (LocalTimeZone) {
|
||||
LocalTimeZone = StrDup(LocalTimeZone);
|
||||
LocalTimeZone = strdup(LocalTimeZone);
|
||||
if (!LocalTimeZone) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
@@ -507,6 +514,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'z' || *arg == 'Z') {
|
||||
TerminalHyperlinks = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'c' || *arg == 'C') {
|
||||
UseVTColors = 1;
|
||||
arg++;
|
||||
@@ -637,8 +649,17 @@ void InitRemind(int argc, char const *argv[])
|
||||
}
|
||||
if (*arg == ',') {
|
||||
arg++;
|
||||
PARSENUM(CalPad, arg);
|
||||
if (CalPad > 20) CalPad = 20;
|
||||
if (*arg != ',') {
|
||||
PARSENUM(CalPad, arg);
|
||||
if (CalPad > 20) CalPad = 20;
|
||||
}
|
||||
if (*arg == ',') {
|
||||
arg++;
|
||||
PARSENUM(CalSepLine, arg);
|
||||
if (CalSepLine) {
|
||||
CalSepLine = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -647,6 +668,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'D':
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
case 'p': case 'P': DebugFlag |= DB_PUSHPOP; break;
|
||||
case 's': case 'S': DebugFlag |= DB_PARSE_EXPR; break;
|
||||
case 'h': case 'H': DebugFlag |= DB_HASHSTATS; break;
|
||||
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
|
||||
@@ -828,6 +850,15 @@ void InitRemind(int argc, char const *argv[])
|
||||
(void) CalcMinsFromUTC(DSEToday, MinutesPastMidnight(0),
|
||||
&MinsFromUTC, NULL);
|
||||
}
|
||||
|
||||
/* If stdout is a tty, enable terminal hyperlinks by default */
|
||||
if (TerminalHyperlinks == -1) {
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
TerminalHyperlinks = 1;
|
||||
} else {
|
||||
TerminalHyperlinks = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -840,7 +871,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
#ifndef L_USAGE_OVERRIDE
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s Copyright (C) 1992-2025 Dianne Skoll\n", VERSION);
|
||||
fprintf(ErrFp, "\nREMIND %s Copyright (C) 1992-2026 Dianne Skoll\n", VERSION);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
48
src/main.c
48
src/main.c
@@ -6,7 +6,7 @@
|
||||
/* routines, etc. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -39,10 +39,8 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef REM_USE_WCHAR
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
@@ -64,12 +62,17 @@ exitfunc(void)
|
||||
/* Kill any execution-time-limiter process */
|
||||
unlimit_execution_time();
|
||||
|
||||
size_t num_mallocs, bytes_malloced;
|
||||
|
||||
if (DebugFlag & DB_UNUSED_VARS) {
|
||||
DumpUnusedVars();
|
||||
}
|
||||
if (DebugFlag & DB_HASHSTATS) {
|
||||
fflush(stdout);
|
||||
fflush(ErrFp);
|
||||
DBufGetMallocStats(&num_mallocs, &bytes_malloced);
|
||||
fprintf(ErrFp, "DynBuf Mallocs: %lu mallocs; %lu bytes\n",
|
||||
(unsigned long) num_mallocs, (unsigned long) bytes_malloced);
|
||||
fprintf(ErrFp, "Variable hash table statistics:\n");
|
||||
dump_var_hash_stats();
|
||||
|
||||
@@ -292,6 +295,7 @@ PerIterationInit(void)
|
||||
DefaultColorG = -1;
|
||||
DefaultColorB = -1;
|
||||
NumTriggered = 0;
|
||||
Shaded = 0;
|
||||
JSONLinesEmitted = 0;
|
||||
ClearLastTriggers();
|
||||
ClearDedupeTable();
|
||||
@@ -1307,7 +1311,7 @@ int DoIfTrig(ParsePtr p)
|
||||
push_if(0, 0);
|
||||
} else {
|
||||
if (dse >= 0) {
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim);
|
||||
dse = AdjustTriggerForTimeZone(&trig, dse, &tim, 1);
|
||||
}
|
||||
if (ShouldTriggerReminder(&trig, &tim, dse, &err)) {
|
||||
push_if(1, 0);
|
||||
@@ -1385,6 +1389,12 @@ static int DoDebug(ParsePtr p)
|
||||
val = 0;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'P':
|
||||
if (val) DebugFlag |= DB_PUSHPOP;
|
||||
else DebugFlag &= ~DB_PUSHPOP;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
if (val) DebugFlag |= DB_ECHO_LINE;
|
||||
@@ -1518,11 +1528,11 @@ int DoRun(ParsePtr p)
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
|
||||
/* Only allow RUN ON in top-level script */
|
||||
if (! StrCmpi(DBufValue(&buf), "ON")) {
|
||||
if (! strcasecmp(DBufValue(&buf), "ON")) {
|
||||
if (TopLevel()) RunDisabled &= ~RUN_SCRIPT;
|
||||
}
|
||||
/* But allow RUN OFF anywhere */
|
||||
else if (! StrCmpi(DBufValue(&buf), "OFF"))
|
||||
else if (! strcasecmp(DBufValue(&buf), "OFF"))
|
||||
RunDisabled |= RUN_SCRIPT;
|
||||
else {
|
||||
DBufFree(&buf);
|
||||
@@ -1550,11 +1560,11 @@ int DoExpr(ParsePtr p)
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
|
||||
/* Only allow EXPR ON in top-level script */
|
||||
if (! StrCmpi(DBufValue(&buf), "ON")) {
|
||||
if (! strcasecmp(DBufValue(&buf), "ON")) {
|
||||
if (TopLevel()) ExpressionEvaluationDisabled = 0;
|
||||
}
|
||||
/* But allow EXPR OFF anywhere */
|
||||
else if (! StrCmpi(DBufValue(&buf), "OFF"))
|
||||
else if (! strcasecmp(DBufValue(&buf), "OFF"))
|
||||
ExpressionEvaluationDisabled = 1;
|
||||
else {
|
||||
DBufFree(&buf);
|
||||
@@ -1730,7 +1740,6 @@ static char const *OutputEscapeSequences(char const *s, int print, DynamicBuffer
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
#define ISWBLANK(c) (iswspace(c) && (c) != '\n')
|
||||
static wchar_t const *OutputEscapeSequencesWS(wchar_t const *s, int print, DynamicBuffer *output)
|
||||
{
|
||||
@@ -1848,7 +1857,7 @@ FillParagraphWC(char const *s, DynamicBuffer *output)
|
||||
free(buf);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* FillParagraph */
|
||||
@@ -1864,7 +1873,7 @@ FillParagraphWC(char const *s, DynamicBuffer *output)
|
||||
/* A macro safe ONLY if used with arg with no side effects! */
|
||||
#define ISBLANK(c) (isspace(c) && (c) != '\n')
|
||||
|
||||
void FillParagraph(char const *s, DynamicBuffer *output)
|
||||
void FillParagraph(char const *url, char const *s, DynamicBuffer *output)
|
||||
{
|
||||
|
||||
int line = 0;
|
||||
@@ -1881,11 +1890,16 @@ void FillParagraph(char const *s, DynamicBuffer *output)
|
||||
while(ISBLANK(*s)) s++;
|
||||
if (!*s) return;
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (url) {
|
||||
printf("\x1B]8;;%s\x1B\\", url);
|
||||
}
|
||||
|
||||
if (FillParagraphWC(s, output) == OK) {
|
||||
if (url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Start formatting */
|
||||
while(1) {
|
||||
@@ -1899,6 +1913,9 @@ void FillParagraph(char const *s, DynamicBuffer *output)
|
||||
continue;
|
||||
}
|
||||
if (!*s) {
|
||||
if (url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Over here, we're at the beginning of a line. Emit the correct
|
||||
@@ -1933,6 +1950,9 @@ void FillParagraph(char const *s, DynamicBuffer *output)
|
||||
len++;
|
||||
}
|
||||
if (s == t) {
|
||||
if (url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!pendspace || len+pendspace <= roomleft) {
|
||||
@@ -2122,7 +2142,7 @@ SaveLastTrigger(Trigger const *t)
|
||||
DBufInit(&(LastTrigger.tags));
|
||||
|
||||
if (LastTrigger.tz) {
|
||||
LastTrigger.tz = StrDup(LastTrigger.tz);
|
||||
LastTrigger.tz = strdup(LastTrigger.tz);
|
||||
}
|
||||
DBufPuts(&(LastTrigger.tags), DBufValue(&(t->tags)));
|
||||
TrigInfo *cur = t->infos;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Calculations for figuring out moon phases. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
11
src/omit.c
11
src/omit.c
@@ -6,7 +6,7 @@
|
||||
/* the data structures for OMITted dates. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -176,8 +176,10 @@ int PopOmitContext(ParsePtr p)
|
||||
/* Remove the context from the stack */
|
||||
SavedOmitContexts = c->next;
|
||||
|
||||
if (c->filename && fname && strcmp(c->filename, fname)) {
|
||||
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), fname, LineNo, c->filename, c->lineno);
|
||||
if (DebugFlag & DB_PUSHPOP) {
|
||||
if (c->filename && fname && strcmp(c->filename, fname)) {
|
||||
Wprint(tr("POP-OMIT-CONTEXT at %s:%d matches PUSH-OMIT-CONTEXT in different file: %s:%d"), fname, LineNo, c->filename, c->lineno);
|
||||
}
|
||||
}
|
||||
/* Free memory used by the saved context */
|
||||
if (c->partsave) free(c->partsave);
|
||||
@@ -501,6 +503,9 @@ int DoOmit(ParsePtr p)
|
||||
int
|
||||
AddGlobalOmit(int dse)
|
||||
{
|
||||
if (dse < 0) {
|
||||
return OK;
|
||||
}
|
||||
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
|
||||
if (!BexistsIntArray(FullOmitArray, NumFullOmits, dse)) {
|
||||
InsertIntoSortedArray(FullOmitArray, NumFullOmits, dse);
|
||||
|
||||
37
src/protos.h
37
src/protos.h
@@ -5,7 +5,7 @@
|
||||
/* Function Prototypes. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -13,20 +13,8 @@
|
||||
/* Suppress unused variable warnings */
|
||||
#define UNUSED(x) (void) x
|
||||
|
||||
#ifdef HAVE_STRDUP
|
||||
#define StrDup strdup
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRNCASECMP
|
||||
#define StrinCmp strncasecmp
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRCASECMP
|
||||
#define StrCmpi strcasecmp
|
||||
#endif
|
||||
|
||||
/* Define a string assignment macro - be careful!!! */
|
||||
#define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); }
|
||||
#define STRSET(x, str) { if (x) free(x); (x) = strdup(str); }
|
||||
|
||||
/* Define a general malloc routine for creating pointers to objects */
|
||||
#define NEW(type) (malloc(sizeof(type)))
|
||||
@@ -131,18 +119,6 @@ int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig const *ti
|
||||
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
int StrinCmp (char const *s1, char const *s2, int n);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *StrDup (char const *s);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASECMP
|
||||
int StrCmpi (char const *s1, char const *s2);
|
||||
#endif
|
||||
|
||||
void strtolower(char *s);
|
||||
|
||||
Var *FindVar (char const *str, int create);
|
||||
@@ -168,13 +144,14 @@ int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||
unsigned int HashVal_preservecase(char const *str);
|
||||
int DateOK (int y, int m, int d);
|
||||
BuiltinFunc *FindBuiltinFunc (char const *name);
|
||||
int InsertIntoSortBuffer (int dse, int tim, char const *body, int typ, int prio);
|
||||
int InsertIntoSortBuffer (int dse, int tim, char const *url, char const *body, int typ, int prio);
|
||||
void IssueSortedReminders (void);
|
||||
UserFunc *FindUserFunc(char const *name);
|
||||
int UserFuncExists (char const *fn);
|
||||
void DSEToHeb (int dse, int *hy, int *hm, int *hd);
|
||||
int HebNameToNum (char const *mname);
|
||||
char const *HebMonthName (int m, int y);
|
||||
char const *IvritMonthName (int m, int y);
|
||||
int HebToDSE (int hy, int hm, int hd);
|
||||
int GetValidHebDate (int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr);
|
||||
int GetNextHebrewDate (int dsestart, int hm, int hd, int yahr, int adarbehave, int *ans);
|
||||
@@ -183,7 +160,7 @@ int GetSysVar (char const *name, Value *val);
|
||||
int SetSysVar (char const *name, Value *val);
|
||||
void DumpSysVarByName (char const *name);
|
||||
int CalcMinsFromUTC (int dse, int tim, int *mins, int *isdst);
|
||||
void FillParagraph (char const *s, DynamicBuffer *output);
|
||||
void FillParagraph (char const *url, char const *s, DynamicBuffer *output);
|
||||
void LocalToUTC (int locdate, int loctime, int *utcdate, int *utctime);
|
||||
void UTCToLocal (int utcdate, int utctime, int *locdate, int *loctime);
|
||||
int MoonPhase (int date, int time);
|
||||
@@ -224,12 +201,10 @@ void FixSpecialType(Trigger *trig);
|
||||
void WriteJSONTrigger(Trigger const *t, int include_tags);
|
||||
void WriteJSONTimeTrigger(TimeTrig const *tt);
|
||||
int GetOnceDate(void);
|
||||
#ifdef REM_USE_WCHAR
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
void PutWideChar(wchar_t const wc, DynamicBuffer *output);
|
||||
#endif
|
||||
|
||||
/* These functions are in utils.c and are used to detect overflow
|
||||
in various arithmetic operators. They have to be in separate
|
||||
@@ -300,7 +275,7 @@ int system_to_stderr(char const *cmd);
|
||||
int system1(char const *cmd);
|
||||
int tz_set_tz (char const *tz);
|
||||
int tz_convert(int year, int month, int day, int hour, int minute, char const *src_tz, char const *tgt_tz, struct tm *tm);
|
||||
int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim);
|
||||
int AdjustTriggerForTimeZone(Trigger *trig, int dse, TimeTrig *tim, int debug_ok);
|
||||
void EnterTimezone(char const *tz);
|
||||
void ExitTimezone(char const *tz);
|
||||
int warning_level(char const *which);
|
||||
|
||||
15
src/queue.c
15
src/queue.c
@@ -5,7 +5,7 @@
|
||||
/* Queue up reminders for subsequent execution. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -140,7 +140,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
TimeTrig const *tim, char const *sched)
|
||||
{
|
||||
QueuedRem *qelem;
|
||||
|
||||
TrigInfo *ti;
|
||||
if (DontQueue ||
|
||||
trig->noqueue ||
|
||||
tim->ttime == NO_TIME ||
|
||||
@@ -155,7 +155,7 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->red = DefaultColorR;
|
||||
qelem->green = DefaultColorG;
|
||||
qelem->blue = DefaultColorB;
|
||||
qelem->text = StrDup(p->pos); /* Guaranteed that parser is not nested. */
|
||||
qelem->text = strdup(p->pos); /* Guaranteed that parser is not nested. */
|
||||
if (!qelem->text) {
|
||||
free(qelem);
|
||||
return E_NO_MEM;
|
||||
@@ -169,8 +169,13 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->tt = *tim;
|
||||
qelem->t = *trig;
|
||||
|
||||
/* Take over infos */
|
||||
trig->infos = NULL;
|
||||
/* Copy infos */
|
||||
qelem->t.infos = NULL;
|
||||
ti = trig->infos;
|
||||
while(ti) {
|
||||
(void) AppendTrigInfo(&qelem->t, ti->info);
|
||||
ti = ti->next;
|
||||
}
|
||||
|
||||
DBufInit(&(qelem->t.tags));
|
||||
DBufPuts(&(qelem->t.tags), DBufValue(&(trig->tags)));
|
||||
|
||||
61
src/rem2ps.c
61
src/rem2ps.c
@@ -5,7 +5,7 @@
|
||||
/* Print a PostScript calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -154,24 +154,6 @@ put_escaped_string(char const *s)
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrCmpi */
|
||||
/* */
|
||||
/* Compare strings, case insensitive. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static int StrCmpi(char const *s1, char const *s2)
|
||||
{
|
||||
int r;
|
||||
while (*s1 && *s2) {
|
||||
r = toupper(*s1) - toupper(*s2);
|
||||
if (r) return r;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return toupper(*s1) - toupper(*s2);
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* Parse the new-style JSON intermediate format */
|
||||
@@ -229,18 +211,18 @@ JSONToCalEntry(DynamicBuffer const *buf)
|
||||
} else if (!strcmp(nm, "passthru")) {
|
||||
if (v->type == json_string) {
|
||||
s = v->u.string.ptr;
|
||||
if (!StrCmpi(s, "PostScript")) {
|
||||
if (!strcasecmp(s, "PostScript")) {
|
||||
c->special = SPECIAL_POSTSCRIPT;
|
||||
} else if (!StrCmpi(s, "SHADE")) {
|
||||
} else if (!strcasecmp(s, "SHADE")) {
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!StrCmpi(s, "MOON")) {
|
||||
} else if (!strcasecmp(s, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!StrCmpi(s, "WEEK")) {
|
||||
} else if (!strcasecmp(s, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else if (!StrCmpi(s, "PSFile")) {
|
||||
} else if (!strcasecmp(s, "PSFile")) {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
} else if (!StrCmpi(s, "COLOUR") ||
|
||||
!StrCmpi(s, "COLOR")) {
|
||||
} else if (!strcasecmp(s, "COLOUR") ||
|
||||
!strcasecmp(s, "COLOR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
} else {
|
||||
c->special = SPECIAL_UNKNOWN;
|
||||
@@ -301,20 +283,20 @@ TextToCalEntry(DynamicBuffer *buf)
|
||||
strcpy(c->entry, startOfBody);
|
||||
|
||||
/* Save the type of SPECIAL */
|
||||
if (!StrCmpi(passthru, "PostScript")) {
|
||||
if (!strcasecmp(passthru, "PostScript")) {
|
||||
c->special = SPECIAL_POSTSCRIPT;
|
||||
} else if (!StrCmpi(passthru, "SHADE")) {
|
||||
} else if (!strcasecmp(passthru, "SHADE")) {
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!StrCmpi(passthru, "MOON")) {
|
||||
} else if (!strcasecmp(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!StrCmpi(passthru, "WEEK")) {
|
||||
} else if (!strcasecmp(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else if (!StrCmpi(passthru, "PSFile")) {
|
||||
} else if (!strcasecmp(passthru, "PSFile")) {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
} else if (!StrCmpi(passthru, "COLOUR") ||
|
||||
!StrCmpi(passthru, "COLOR")) {
|
||||
} else if (!strcasecmp(passthru, "COLOUR") ||
|
||||
!strcasecmp(passthru, "COLOR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
} else if (StrCmpi(passthru, "*")) {
|
||||
} else if (strcasecmp(passthru, "*")) {
|
||||
c->special = SPECIAL_UNKNOWN;
|
||||
}
|
||||
return c;
|
||||
@@ -350,7 +332,7 @@ int main(int argc, char const *argv[])
|
||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||
if (!validfile) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright (C) 1992-2025 by Dianne Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright (C) 1992-2026 by Dianne Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Generating PostScript calendar\n");
|
||||
}
|
||||
}
|
||||
@@ -1003,6 +985,14 @@ static void Init(int argc, char const *argv[])
|
||||
|
||||
case 'e': FillPage = 1; break;
|
||||
|
||||
case '-':
|
||||
if (!strcmp(s, "version")) {
|
||||
printf("rem2ps version %s\n", VERSION);
|
||||
exit(0);
|
||||
}
|
||||
Usage("Unrecognized option");
|
||||
break;
|
||||
|
||||
default: Usage("Unrecognized option");
|
||||
}
|
||||
}
|
||||
@@ -1034,6 +1024,7 @@ void Usage(char const *s)
|
||||
fprintf(stderr, "-e Make calendar fill entire page\n");
|
||||
fprintf(stderr, "-x Put day numbers on left instead of right\n");
|
||||
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
|
||||
fprintf(stderr, "--version Print the version of rem2ps and exit\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Define the PostScript prologue */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -14,7 +14,7 @@ char *PSProlog1[] =
|
||||
{
|
||||
"% This file was produced by Remind and Rem2PS, written by",
|
||||
"% Dianne Skoll.",
|
||||
"% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.",
|
||||
"% Remind and Rem2PS are Copyright (C) 1992-2026 Dianne Skoll.",
|
||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||
|
||||
77
src/sort.c
77
src/sort.c
@@ -5,7 +5,7 @@
|
||||
/* Routines for sorting reminders by trigger date */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -25,6 +25,7 @@
|
||||
typedef struct sortrem {
|
||||
struct sortrem *next;
|
||||
char const *text;
|
||||
char const *url;
|
||||
int trigdate;
|
||||
int trigtime;
|
||||
int typ;
|
||||
@@ -34,7 +35,7 @@ typedef struct sortrem {
|
||||
/* The sorted reminder queue */
|
||||
static Sortrem *SortedQueue = (Sortrem *) NULL;
|
||||
|
||||
static Sortrem *MakeSortRem (int dse, int tim, char const *body, int typ, int prio);
|
||||
static Sortrem *MakeSortRem (int dse, int tim, char const *url, char const *body, int typ, int prio);
|
||||
static void IssueSortBanner (int dse);
|
||||
|
||||
/***************************************************************/
|
||||
@@ -44,23 +45,33 @@ static void IssueSortBanner (int dse);
|
||||
/* Create a new Sortrem entry - return NULL on failure. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static Sortrem *MakeSortRem(int dse, int tim, char const *body, int typ, int prio)
|
||||
static Sortrem *MakeSortRem(int dse, int tim, char const *url, char const *body, int typ, int prio)
|
||||
{
|
||||
Sortrem *new = NEW(Sortrem);
|
||||
if (!new) return NULL;
|
||||
Sortrem *srem = NEW(Sortrem);
|
||||
if (!srem) return NULL;
|
||||
|
||||
new->text = StrDup(body);
|
||||
if (!new->text) {
|
||||
free(new);
|
||||
srem->text = strdup(body);
|
||||
if (!srem->text) {
|
||||
free(srem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new->trigdate = dse;
|
||||
new->trigtime = tim;
|
||||
new->typ = typ;
|
||||
new->priority = prio;
|
||||
new->next = NULL;
|
||||
return new;
|
||||
if (url) {
|
||||
srem->url = strdup(url);
|
||||
if (!srem->url) {
|
||||
free((char *) srem->text);
|
||||
free(srem);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
srem->url = NULL;
|
||||
}
|
||||
|
||||
srem->trigdate = dse;
|
||||
srem->trigtime = tim;
|
||||
srem->typ = typ;
|
||||
srem->priority = prio;
|
||||
srem->next = NULL;
|
||||
return srem;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -70,13 +81,13 @@ static Sortrem *MakeSortRem(int dse, int tim, char const *body, int typ, int pri
|
||||
/* Insert a reminder into the sort buffer */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int InsertIntoSortBuffer(int dse, int tim, char const *body, int typ, int prio)
|
||||
int InsertIntoSortBuffer(int dse, int tim, char const *url, char const *body, int typ, int prio)
|
||||
{
|
||||
Sortrem *new = MakeSortRem(dse, tim, body, typ, prio);
|
||||
Sortrem *srem = MakeSortRem(dse, tim, url, body, typ, prio);
|
||||
Sortrem *cur = SortedQueue, *prev = NULL;
|
||||
int ShouldGoAfter;
|
||||
|
||||
if (!new) {
|
||||
if (!srem) {
|
||||
Eprint("%s", GetErr(E_NO_MEM));
|
||||
IssueSortedReminders();
|
||||
SortByDate = 0;
|
||||
@@ -88,11 +99,11 @@ int InsertIntoSortBuffer(int dse, int tim, char const *body, int typ, int prio)
|
||||
|
||||
/* Find the correct place in the sorted list */
|
||||
if (!SortedQueue) {
|
||||
SortedQueue = new;
|
||||
SortedQueue = srem;
|
||||
return OK;
|
||||
}
|
||||
while (cur) {
|
||||
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
|
||||
ShouldGoAfter = CompareRems(srem->trigdate, srem->trigtime, srem->priority,
|
||||
cur->trigdate, cur->trigtime, cur->priority,
|
||||
SortByDate, SortByTime, SortByPrio, UntimedBeforeTimed);
|
||||
|
||||
@@ -101,22 +112,21 @@ int InsertIntoSortBuffer(int dse, int tim, char const *body, int typ, int prio)
|
||||
cur = cur->next;
|
||||
} else {
|
||||
if (prev) {
|
||||
prev->next = new;
|
||||
new->next = cur;
|
||||
prev->next = srem;
|
||||
srem->next = cur;
|
||||
} else {
|
||||
SortedQueue = new;
|
||||
new->next = cur;
|
||||
SortedQueue = srem;
|
||||
srem->next = cur;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
prev->next = new;
|
||||
new->next = cur; /* For safety - actually redundant */
|
||||
prev->next = srem;
|
||||
srem->next = cur; /* For safety - actually redundant */
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* IssueSortedReminders */
|
||||
@@ -141,7 +151,13 @@ void IssueSortedReminders(void)
|
||||
IssueSortBanner(cur->trigdate);
|
||||
olddate = cur->trigdate;
|
||||
}
|
||||
if (cur->url) {
|
||||
printf("\x1B]8;;%s\x1B\\", cur->url);
|
||||
}
|
||||
printf("%s", cur->text);
|
||||
if (cur->url) {
|
||||
printf("\x1B]8;;\x1B\\");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -150,7 +166,7 @@ void IssueSortedReminders(void)
|
||||
IssueSortBanner(cur->trigdate);
|
||||
olddate = cur->trigdate;
|
||||
}
|
||||
FillParagraph(cur->text, NULL);
|
||||
FillParagraph(cur->url, cur->text, NULL);
|
||||
break;
|
||||
|
||||
case RUN_TYPE:
|
||||
@@ -159,6 +175,9 @@ void IssueSortedReminders(void)
|
||||
}
|
||||
|
||||
free((char *) cur->text);
|
||||
if (cur->url) {
|
||||
free((char *) cur->url);
|
||||
}
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* classifying the tokens parsed. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -48,6 +48,7 @@ Token TokArray[] = {
|
||||
{ "cal", 3, T_RemType, CAL_TYPE },
|
||||
{ "clear-omit-context", 5, T_Clr, 0 },
|
||||
{ "complete-through", 16, T_CompleteThrough, 0 },
|
||||
{ "completed-through", 17, T_CompleteThrough, 0 },
|
||||
{ "debug", 5, T_Debug, 0 },
|
||||
{ "december", 3, T_Month, 11 },
|
||||
{ "do", 2, T_IncludeR, 0 },
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* the TRANSLATE keyword. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -443,19 +443,19 @@ DoTranslate(ParsePtr p)
|
||||
r = ParseToken(p, &orig);
|
||||
if (r) return r;
|
||||
r = VerifyEoln(p);
|
||||
if (!StrCmpi(DBufValue(&orig), "dump")) {
|
||||
if (!strcasecmp(DBufValue(&orig), "dump")) {
|
||||
DBufFree(&orig);
|
||||
if (r) return r;
|
||||
DumpTranslationTable(stdout, 0);
|
||||
return OK;
|
||||
}
|
||||
if (!StrCmpi(DBufValue(&orig), "clear")) {
|
||||
if (!strcasecmp(DBufValue(&orig), "clear")) {
|
||||
DBufFree(&orig);
|
||||
if (r) return r;
|
||||
ClearTranslationTable();
|
||||
return OK;
|
||||
}
|
||||
if (!StrCmpi(DBufValue(&orig), "generate")) {
|
||||
if (!strcasecmp(DBufValue(&orig), "generate")) {
|
||||
DBufFree(&orig);
|
||||
if (r) return r;
|
||||
GenerateTranslationTemplate();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Routines for figuring out the trigger date of a reminder */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -623,7 +623,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig const *tim
|
||||
int new_result;
|
||||
int force_retry = 0;
|
||||
ExitTimezone(trig->tz);
|
||||
new_result = AdjustTriggerForTimeZone(trig, result, ©);
|
||||
new_result = AdjustTriggerForTimeZone(trig, result, ©, 0);
|
||||
if (trig->scanfrom == NO_SCANFROM && new_result < DSEToday) {
|
||||
force_retry = 1;
|
||||
}
|
||||
@@ -738,7 +738,7 @@ NewTrigInfo(char const *i)
|
||||
return NULL;
|
||||
}
|
||||
ti->next = NULL;
|
||||
ti->info = StrDup(i);
|
||||
ti->info = strdup(i);
|
||||
if (!ti->info) {
|
||||
free(ti);
|
||||
return NULL;
|
||||
|
||||
34
src/types.h
34
src/types.h
@@ -5,7 +5,7 @@
|
||||
/* Type definitions all dumped here. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -143,10 +143,13 @@ typedef struct {
|
||||
int eventstart; /* Original event start (datetime) */
|
||||
int eventstart_orig; /* Original event start in TZ (datetime) */
|
||||
int eventduration; /* Original event duration (minutes) */
|
||||
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
||||
int addomit; /* Add trigger date to global OMITs */
|
||||
int noqueue; /* Don't queue even if timed */
|
||||
int max_overdue; /* Stop warning if TODO is too far overdue */
|
||||
unsigned char addomit; /* Add trigger date to global OMITs */
|
||||
unsigned char maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
|
||||
unsigned char nonconst_expr; /* Non-constant expression encountered */
|
||||
unsigned char expr_happened;
|
||||
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
@@ -218,18 +221,19 @@ typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
#define NO_MAX 127
|
||||
|
||||
/* DEFINES for debugging flags */
|
||||
#define DB_PRTLINE 0x001
|
||||
#define DB_PRTEXPR 0x002
|
||||
#define DB_PRTTRIG 0x004
|
||||
#define DB_DUMP_VARS 0x008
|
||||
#define DB_ECHO_LINE 0x010
|
||||
#define DB_TRACE_FILES 0x020
|
||||
#define DB_PARSE_EXPR 0x040
|
||||
#define DB_HASHSTATS 0x080
|
||||
#define DB_TRANSLATE 0x100
|
||||
#define DB_NONCONST 0x200
|
||||
#define DB_UNUSED_VARS 0x400
|
||||
#define DB_SWITCH_ZONE 0x800
|
||||
#define DB_PRTLINE 0x0001
|
||||
#define DB_PRTEXPR 0x0002
|
||||
#define DB_PRTTRIG 0x0004
|
||||
#define DB_DUMP_VARS 0x0008
|
||||
#define DB_ECHO_LINE 0x0010
|
||||
#define DB_TRACE_FILES 0x0020
|
||||
#define DB_PARSE_EXPR 0x0040
|
||||
#define DB_HASHSTATS 0x0080
|
||||
#define DB_TRANSLATE 0x0100
|
||||
#define DB_NONCONST 0x0200
|
||||
#define DB_UNUSED_VARS 0x0400
|
||||
#define DB_SWITCH_ZONE 0x0800
|
||||
#define DB_PUSHPOP 0x1000
|
||||
|
||||
/* Enumeration of the tokens */
|
||||
enum TokTypes
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -318,7 +318,7 @@ int DoFset(ParsePtr p)
|
||||
}
|
||||
/* If we've already seen this local variable, error */
|
||||
for (i=0; i<func->nargs; i++) {
|
||||
if (!StrinCmp(DBufValue(&buf), local_array[i].name, VAR_NAME_LEN)) {
|
||||
if (!strncasecmp(DBufValue(&buf), local_array[i].name, VAR_NAME_LEN)) {
|
||||
DBufFree(&buf);
|
||||
DestroyUserFunc(func);
|
||||
return E_REPEATED_ARG;
|
||||
@@ -393,7 +393,7 @@ int DoFset(ParsePtr p)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
for (i=0; i<func->nargs; i++) {
|
||||
func->args[i] = StrDup(local_array[i].name);
|
||||
func->args[i] = strdup(local_array[i].name);
|
||||
if (!func->args[i]) {
|
||||
DestroyUserFunc(func);
|
||||
return E_NO_MEM;
|
||||
@@ -619,7 +619,7 @@ static UserFunc *clone_userfunc(char const *name, int *r)
|
||||
return NULL;
|
||||
}
|
||||
for (i=0; i<dest->nargs; i++) {
|
||||
dest->args[i] = StrDup(src->args[i]);
|
||||
dest->args[i] = strdup(src->args[i]);
|
||||
if (!dest->args[i]) {
|
||||
DestroyUserFunc(dest);
|
||||
return NULL;
|
||||
@@ -744,8 +744,10 @@ int PopUserFuncs(ParsePtr p)
|
||||
return E_POPF_NO_PUSH;
|
||||
}
|
||||
UserFuncStack = UserFuncStack->next;
|
||||
if (strcmp(pf->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-FUNCS at %s:%d matches PUSH-FUNCS in different file: %s:%d"), GetCurrentFilename(), LineNo, pf->filename, pf->lineno);
|
||||
if (DebugFlag & DB_PUSHPOP) {
|
||||
if (strcmp(pf->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-FUNCS at %s:%d matches PUSH-FUNCS in different file: %s:%d"), GetCurrentFilename(), LineNo, pf->filename, pf->lineno);
|
||||
}
|
||||
}
|
||||
for (i=0; i<pf->num_funcs; i++) {
|
||||
UserFunc *clone = pf->funcs[i];
|
||||
|
||||
66
src/utils.c
66
src/utils.c
@@ -5,7 +5,7 @@
|
||||
/* Useful utility functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -140,67 +140,6 @@ char *StrnCpy(char *dest, char const *source, int n)
|
||||
return odest;
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRNCASECMP
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrinCmp - compare strings, case-insensitive */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrinCmp(char const *s1, char const *s2, int n)
|
||||
{
|
||||
register int r;
|
||||
while (n && *s1 && *s2) {
|
||||
n--;
|
||||
r = toupper(*s1) - toupper(*s2);
|
||||
if (r) return r;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if (n) return (toupper(*s1) - toupper(*s2)); else return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrDup */
|
||||
/* */
|
||||
/* Like ANSI strdup */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
char *StrDup(char const *s)
|
||||
{
|
||||
char *ret = malloc(strlen(s)+1);
|
||||
if (!ret) return NULL;
|
||||
strcpy(ret, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASECMP
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrCmpi */
|
||||
/* */
|
||||
/* Compare strings, case insensitive. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrCmpi(char const *s1, char const *s2)
|
||||
{
|
||||
int r;
|
||||
while (*s1 && *s2) {
|
||||
r = toupper(*s1) - toupper(*s2);
|
||||
if (r) return r;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return toupper(*s1) - toupper(*s2);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DateOK */
|
||||
@@ -410,6 +349,9 @@ warn_if_timezone_bad(char const *tz)
|
||||
if (!tz) {
|
||||
return;
|
||||
}
|
||||
if (!*tz) {
|
||||
return;
|
||||
}
|
||||
if (*tz == '!') {
|
||||
return;
|
||||
}
|
||||
|
||||
67
src/var.c
67
src/var.c
@@ -6,7 +6,7 @@
|
||||
/* user- and system-defined variables. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2025 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
@@ -52,7 +52,7 @@ static int VarCompareFunc(void const *a, void const *b)
|
||||
{
|
||||
Var *x = (Var *) a;
|
||||
Var *y = (Var *) b;
|
||||
return StrCmpi(x->name, y->name);
|
||||
return strcasecmp(x->name, y->name);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -172,7 +172,7 @@ static int latitude_longitude_func(int do_set, Value *val, double *var, double m
|
||||
} else {
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
x = strtod_in_c_locale(val->v.str, &endptr);
|
||||
if (*endptr) return E_BAD_TYPE;
|
||||
if (*endptr) return E_BAD_VAL_FOR_SYSVAR;
|
||||
}
|
||||
if (x < min) return E_2LOW;
|
||||
if (x > max) return E_2HIGH;
|
||||
@@ -220,15 +220,15 @@ static int warning_level_func(int do_set, Value *val)
|
||||
if (!strcmp(val->v.str, VERSION)) {
|
||||
WarningLevel = NULL;
|
||||
} else {
|
||||
WarningLevel = StrDup(val->v.str);
|
||||
WarningLevel = strdup(val->v.str);
|
||||
if (!WarningLevel) return E_NO_MEM;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
if (!WarningLevel) {
|
||||
val->v.str = StrDup(VERSION);
|
||||
val->v.str = strdup(VERSION);
|
||||
} else {
|
||||
val->v.str = StrDup(WarningLevel);
|
||||
val->v.str = strdup(WarningLevel);
|
||||
}
|
||||
if (!val->v.str) {
|
||||
return E_NO_MEM;
|
||||
@@ -257,14 +257,14 @@ static int oncefile_func(int do_set, Value *val)
|
||||
if (OnceFile) {
|
||||
free( (void *) OnceFile);
|
||||
}
|
||||
OnceFile = StrDup(val->v.str);
|
||||
OnceFile = strdup(val->v.str);
|
||||
if (!OnceFile) return E_NO_MEM;
|
||||
return OK;
|
||||
}
|
||||
if (!OnceFile) {
|
||||
val->v.str = StrDup("");
|
||||
val->v.str = strdup("");
|
||||
} else {
|
||||
val->v.str = StrDup(OnceFile);
|
||||
val->v.str = strdup(OnceFile);
|
||||
}
|
||||
if (!val->v.str) return E_NO_MEM;
|
||||
val->type = STR_TYPE;
|
||||
@@ -403,6 +403,14 @@ static int trig_wday_func(int do_set, Value *val)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Cache $Ud, $Um and $Uy */
|
||||
static int Ucached = -1;
|
||||
static int Udcached = -1;
|
||||
static int Umcached = -1;
|
||||
static int Uycached = -1;
|
||||
|
||||
#define FILL_U_CACHE(x) do { if (Ucached != x) { FromDSE(x, &Uycached, &Umcached, &Udcached); Ucached = x; } } while(0)
|
||||
|
||||
static int today_date_func(int do_set, Value *val)
|
||||
{
|
||||
UNUSED(do_set);
|
||||
@@ -412,31 +420,28 @@ static int today_date_func(int do_set, Value *val)
|
||||
}
|
||||
static int today_day_func(int do_set, Value *val)
|
||||
{
|
||||
int d;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, NULL, NULL, &d);
|
||||
val->v.val = d;
|
||||
FILL_U_CACHE(DSEToday);
|
||||
val->v.val = Udcached;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_mon_func(int do_set, Value *val)
|
||||
{
|
||||
int m;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, NULL, &m, NULL);
|
||||
val->v.val = m+1;
|
||||
FILL_U_CACHE(DSEToday);
|
||||
val->v.val = Umcached + 1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int today_year_func(int do_set, Value *val)
|
||||
{
|
||||
int y;
|
||||
UNUSED(do_set);
|
||||
val->type = INT_TYPE;
|
||||
FromDSE(DSEToday, &y, NULL, NULL);
|
||||
val->v.val = y;
|
||||
FILL_U_CACHE(DSEToday);
|
||||
val->v.val = Uycached;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -461,7 +466,7 @@ static int datetime_sep_func(int do_set, Value *val)
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (strcmp(val->v.str, "T") &&
|
||||
strcmp(val->v.str, "@")) {
|
||||
return E_BAD_TYPE;
|
||||
return E_BAD_VAL_FOR_SYSVAR;
|
||||
}
|
||||
DateTimeSep = val->v.str[0];
|
||||
return OK;
|
||||
@@ -507,7 +512,7 @@ static int default_color_func(int do_set, Value *val)
|
||||
}
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) {
|
||||
return E_BAD_TYPE;
|
||||
return E_BAD_VAL_FOR_SYSVAR;
|
||||
}
|
||||
/* They either all have to be -1, or all between 0 and 255 */
|
||||
if (col_r == -1 && col_g == -1 && col_b == -1) {
|
||||
@@ -542,7 +547,7 @@ static int date_sep_func(int do_set, Value *val)
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (strcmp(val->v.str, "/") &&
|
||||
strcmp(val->v.str, "-")) {
|
||||
return E_BAD_TYPE;
|
||||
return E_BAD_VAL_FOR_SYSVAR;
|
||||
}
|
||||
DateSep = val->v.str[0];
|
||||
return OK;
|
||||
@@ -561,7 +566,7 @@ static int time_sep_func(int do_set, Value *val)
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (strcmp(val->v.str, ":") &&
|
||||
strcmp(val->v.str, ".")) {
|
||||
return E_BAD_TYPE;
|
||||
return E_BAD_VAL_FOR_SYSVAR;
|
||||
}
|
||||
TimeSep = val->v.str[0];
|
||||
return OK;
|
||||
@@ -1096,6 +1101,7 @@ static SysVar SysVarArr[] = {
|
||||
{"RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
|
||||
{"Saturday", 1, TRANS_TYPE, "Saturday", 0, 0 },
|
||||
{"September", 1, TRANS_TYPE, "September", 0, 0 },
|
||||
{"Shaded" , 0, INT_TYPE, &Shaded, 0, 0 },
|
||||
{"SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
|
||||
{"SortByDate", 0, INT_TYPE, &SortByDate, 0, 0 },
|
||||
{"SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0 },
|
||||
@@ -1109,6 +1115,7 @@ static SysVar SysVarArr[] = {
|
||||
{"Tb", 0, SPECIAL_TYPE, trig_base_func, 0, 0 },
|
||||
{"Td", 0, SPECIAL_TYPE, trig_day_func, 0, 0 },
|
||||
{"TerminalBackground", 0, SPECIAL_TYPE, terminal_bg_func, 0, 0 },
|
||||
{"TerminalHyperlinks", 1, INT_TYPE, &TerminalHyperlinks, 0, 1 },
|
||||
{"Thursday", 1, TRANS_TYPE, "Thursday", 0, 0 },
|
||||
{"TimeSep", 1, SPECIAL_TYPE, time_sep_func, 0, 0 },
|
||||
{"TimetIs64bit", 0, SPECIAL_TYPE, timet_is_64_func, 0, 0 },
|
||||
@@ -1337,8 +1344,10 @@ PopVars(ParsePtr p)
|
||||
return E_POPV_NO_PUSH;
|
||||
}
|
||||
VarStack = VarStack->next;
|
||||
if (strcmp(pv->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-VARS at %s:%d matches PUSH-VARS in different file: %s:%d"), GetCurrentFilename(), LineNo, pv->filename, pv->lineno);
|
||||
if (DebugFlag & DB_PUSHPOP) {
|
||||
if (strcmp(pv->filename, GetCurrentFilename())) {
|
||||
Wprint(tr("POP-VARS at %s:%d matches PUSH-VARS in different file: %s:%d"), GetCurrentFilename(), LineNo, pv->filename, pv->lineno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop the sysvars */
|
||||
@@ -1397,9 +1406,9 @@ static int GetTranslatableVariable(SysVar const *v, Value *value)
|
||||
{
|
||||
char const *translated = tr((char const *) v->value);
|
||||
if (translated) {
|
||||
value->v.str = StrDup(translated);
|
||||
value->v.str = strdup(translated);
|
||||
} else {
|
||||
value->v.str = StrDup("");
|
||||
value->v.str = strdup("");
|
||||
}
|
||||
if (!value->v.str) return E_NO_MEM;
|
||||
value->type = STR_TYPE;
|
||||
@@ -1491,9 +1500,9 @@ int GetSysVar(char const *name, Value *val)
|
||||
return f(0, val);
|
||||
} else if (v->type == STR_TYPE) {
|
||||
if (! * (char **) v->value) {
|
||||
val->v.str = StrDup("");
|
||||
val->v.str = strdup("");
|
||||
} else {
|
||||
val->v.str = StrDup(*((char **) v->value));
|
||||
val->v.str = strdup(*((char **) v->value));
|
||||
}
|
||||
if (!val->v.str) return E_NO_MEM;
|
||||
} else {
|
||||
@@ -1524,7 +1533,7 @@ SysVar *FindSysVar(char const *name)
|
||||
int r;
|
||||
|
||||
while (top >= bottom) {
|
||||
r = StrCmpi(name, SysVarArr[mid].name);
|
||||
r = strcasecmp(name, SysVarArr[mid].name);
|
||||
if (!r) return &SysVarArr[mid];
|
||||
else if (r>0) bottom = mid+1;
|
||||
else top = mid-1;
|
||||
|
||||
1018
tests/manpage-personal-dict
Normal file
1018
tests/manpage-personal-dict
Normal file
File diff suppressed because it is too large
Load Diff
15
tests/shaded.rem
Normal file
15
tests/shaded.rem
Normal file
@@ -0,0 +1,15 @@
|
||||
REM Wed SPECIAL SHADE 255 0 0
|
||||
IF !$Shaded
|
||||
REM 15 SPECIAL SHADE 0 255 0
|
||||
ENDIF
|
||||
IF !$Shaded
|
||||
REM SATISFY [$Td % 4 == 0] SPECIAL SHADE 0 0 255
|
||||
ENDIF
|
||||
|
||||
IF !$Shaded
|
||||
REM Sunday SPECIAL SHADE 0 255 255
|
||||
ENDIF
|
||||
|
||||
IF !$Shaded
|
||||
REM SPECIAL SHADE 255 255 0
|
||||
ENDIF
|
||||
4
tests/test-pushpop1.rem
Normal file
4
tests/test-pushpop1.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
PUSH-OMIT-CONTEXT
|
||||
PUSH-FUNCS a b c
|
||||
PUSH-VARS a b c
|
||||
DO test-pushpop2.rem
|
||||
4
tests/test-pushpop2.rem
Normal file
4
tests/test-pushpop2.rem
Normal file
@@ -0,0 +1,4 @@
|
||||
POP-VARS
|
||||
POP-FUNCS
|
||||
POP-OMIT-CONTEXT
|
||||
|
||||
197
tests/test-rem
197
tests/test-rem
@@ -7,7 +7,7 @@
|
||||
# in the build directory.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2025 Dianne Skoll
|
||||
# Copyright (C) 1992-2026 Dianne Skoll
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -27,13 +27,31 @@ if test `id -u` = 0 ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REMIND="../src/remind --flush -q"
|
||||
REMIND_CMD=${REMIND_CMD:-../src/remind}
|
||||
REM2PS=${REM2PS:-../src/rem2ps}
|
||||
REMIND="$REMIND_CMD --flush -q"
|
||||
OUT="../tests/test.out"
|
||||
CMP="../tests/test.cmp"
|
||||
# Set a known timezone so moon phases show up in predictable places
|
||||
TZ=UTC
|
||||
export TZ
|
||||
|
||||
# No localization, but we want a UTF-8 locale.
|
||||
LANG=C.UTF-8
|
||||
export LANG
|
||||
LC_ALL=C.UTF-8
|
||||
export LC_ALL
|
||||
|
||||
unset LC_PAPER
|
||||
|
||||
# Check if "grep" accepts "-a" flag
|
||||
echo TEST | grep -a TEST > /dev/null 2>&1
|
||||
if test $? = 0 ; then
|
||||
GREP_A="-a"
|
||||
else
|
||||
GREP_A=""
|
||||
fi
|
||||
|
||||
# Colorize output iff stdout is a tty
|
||||
stty <&1 > /dev/null 2>&1
|
||||
if test $? = 0; then
|
||||
@@ -54,31 +72,12 @@ else
|
||||
DELAY=1
|
||||
fi
|
||||
|
||||
# If we're already in a utf-8 locale, do
|
||||
# nothing; otherwise, set LC_ALL
|
||||
OK=0
|
||||
if echo $LC_ALL | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
OK=1
|
||||
fi
|
||||
|
||||
if test -z "$LC_ALL" ; then
|
||||
if echo $LANG | grep -i utf-8 > /dev/null 2>&1 ; then
|
||||
export LC_ALL="$LANG"
|
||||
OK=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$OK" = 0 ; then
|
||||
export LC_ALL=C.UTF-8
|
||||
export LANG=C.UTF-8
|
||||
fi
|
||||
|
||||
chmod 000 include_dir/04cantread.rem
|
||||
TEST_GETENV="foo bar baz" ; export TEST_GETENV
|
||||
echo "Test 1" > $OUT
|
||||
echo "" >> $OUT
|
||||
echo "Running main tests"
|
||||
$REMIND -e -dxte ../tests/test.rem 16 feb 1991 12:13 2>&1 | grep -v -a 'TimetIs64bit' >> $OUT 2>&1
|
||||
$REMIND -e -dxte ../tests/test.rem 16 feb 1991 12:13 2>&1 | grep -v $GREP_A 'TimetIs64bit' >> $OUT 2>&1
|
||||
echo "" >> $OUT
|
||||
echo "Test 2" >> $OUT
|
||||
echo "" >> $OUT
|
||||
@@ -181,8 +180,8 @@ rm -f ../tests/purge_dir/*.rem.purged >> $OUT 2>&1
|
||||
|
||||
$REMIND ../tests/runtest.rem >> $OUT 2>&1
|
||||
|
||||
$REMIND -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> $OUT 2>&1
|
||||
$REMIND -pp ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> $OUT 2>&1
|
||||
$REMIND -p ../tests/shade.rem 1 August 2009 | "$REM2PS" -e -l -c3 >> $OUT 2>&1
|
||||
$REMIND -pp ../tests/shade.rem 1 August 2009 | "$REM2PS" -e -l -c3 >> $OUT 2>&1
|
||||
|
||||
TZ=America/Toronto $REMIND ../tests/sunmoon.rem 1 Jan 2011 >> $OUT 2>&1
|
||||
|
||||
@@ -456,8 +455,8 @@ $REMIND -c ../tests/test-addomit.rem 1 Sep 2021 >> $OUT
|
||||
$REMIND -cu ../tests/utf-8.rem 1 Nov 2019 >> $OUT
|
||||
$REMIND -cu '-i$SuppressLRM=1' ../tests/utf-8.rem 1 Nov 2019 >> $OUT
|
||||
|
||||
TZ=America/Toronto $REMIND -dxe ../tests/tz.rem >> $OUT 2>&1
|
||||
TZ=Europe/Berlin $REMIND -dxe ../tests/tz.rem >> $OUT 2>&1
|
||||
TZ=America/Toronto $REMIND -dxe ../tests/tz.rem 2026-02-01 >> $OUT 2>&1
|
||||
TZ=Europe/Berlin $REMIND -dxe ../tests/tz.rem 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
$REMIND ../tests/soleq.rem 1 April 2044 >> $OUT 2>&1
|
||||
|
||||
@@ -480,18 +479,18 @@ echo "REM May 22 +10 MSG Bar %b" | $REMIND -tz - 2023-05-21 >> $OUT 2>&1
|
||||
rm -rf include_dir/ww
|
||||
touch include_dir/ww
|
||||
chmod 0666 include_dir/ww
|
||||
$REMIND include_dir/ww >> $OUT 2>&1
|
||||
$REMIND include_dir/ww 2026-02-01 >> $OUT 2>&1
|
||||
rm -rf include_dir/ww
|
||||
|
||||
# World-writable directory
|
||||
mkdir -p include_dir/ww
|
||||
touch include_dir/ww/0.rem
|
||||
chmod 0777 include_dir/ww
|
||||
$REMIND include_dir/ww >> $OUT 2>&1
|
||||
$REMIND include_dir/ww 2026-02-01 >> $OUT 2>&1
|
||||
rm -rf include_dir/ww
|
||||
|
||||
# This segfaulted in 04.02.03
|
||||
$REMIND -h '-imsgprefix(x)="foo"' /dev/null >> $OUT 2>&1
|
||||
$REMIND -h '-imsgprefix(x)="foo"' /dev/null 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
# Test --version long option
|
||||
$REMIND --version >> $OUT 2>&1
|
||||
@@ -499,8 +498,8 @@ $REMIND --version >> $OUT 2>&1
|
||||
# Test queueing. Because eventstart depends on the actual system
|
||||
# date, we use the --test flag to fake the date and time.
|
||||
# We can't use $REMIND here because it includes the -q flag.
|
||||
echo JSONQUEUE | ../src/remind --flush --test -z0 ../tests/queue1.rem >> $OUT 2>&1
|
||||
echo QUEUE | ../src/remind --flush --test -zj ../tests/queue1.rem >> $OUT 2>&1
|
||||
echo JSONQUEUE | "$REMIND_CMD" --flush --test -z0 ../tests/queue1.rem >> $OUT 2>&1
|
||||
echo QUEUE | "$REMIND_CMD" --flush --test -zj ../tests/queue1.rem >> $OUT 2>&1
|
||||
|
||||
# Test for leap year bug that was fixed
|
||||
$REMIND -dte - 28 Feb 2024 <<'EOF' >> $OUT 2>&1
|
||||
@@ -586,19 +585,19 @@ EOF
|
||||
|
||||
(echo 'BANNER %'; echo 'REM 29 MSG No bug') | $REMIND -dt - 29 Feb 2024 >> $OUT 2>&1
|
||||
|
||||
$REMIND -ifoo - <<'EOF' >> $OUT 2>&1
|
||||
$REMIND -ifoo - 2026-02-01 <<'EOF' >> $OUT 2>&1
|
||||
BANNER %
|
||||
DUMP
|
||||
EOF
|
||||
|
||||
$REMIND '-i$AddBlankLines' - <<'EOF' >> $OUT 2>&1
|
||||
$REMIND '-i$AddBlankLines' - 2026-02-01 <<'EOF' >> $OUT 2>&1
|
||||
BANNER %
|
||||
DUMP $AddBlankLines
|
||||
EOF
|
||||
|
||||
$REMIND ../tests/expr.rem >> $OUT 2>&1
|
||||
$REMIND ../tests/expr.rem 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
$REMIND - <<'EOF' >> $OUT 2>&1
|
||||
$REMIND - 2026-02-01 <<'EOF' >> $OUT 2>&1
|
||||
PUSH
|
||||
POP
|
||||
PUSH
|
||||
@@ -638,7 +637,7 @@ $REMIND -c ../tests/dedupe.rem 1 November 2023 >> $OUT 2>&1
|
||||
$REMIND -q ../tests/dedupe.rem 8 November 2023 >> $OUT 2>&1
|
||||
|
||||
# Remove references to SysInclude, which is build-specific
|
||||
grep -F -v -a '$SysInclude' < $OUT > $OUT.1 && mv -f $OUT.1 $OUT
|
||||
grep -F -v $GREP_A '$SysInclude' < $OUT > $OUT.1 && mv -f $OUT.1 $OUT
|
||||
|
||||
# If "man" accepts the --warnings flag, test all the man pages.
|
||||
RUNMAN=0
|
||||
@@ -654,11 +653,63 @@ for i in ../man/*.1 ; do
|
||||
fi
|
||||
done
|
||||
|
||||
if test -d ../rem2pdf/blib ; then
|
||||
PERLMANS=`find ../rem2pdf/blib -name '*.1p' -o -name '*.3pm'`
|
||||
else
|
||||
PERLMANS=""
|
||||
fi
|
||||
|
||||
# If we have "spellintian", run it against man pages
|
||||
cat <<'EOF' >> $OUT
|
||||
|
||||
If spellintian is installed, its output (if any) follows...
|
||||
|
||||
EOF
|
||||
|
||||
spellintian /dev/null < /dev/null > /dev/null 2>&1
|
||||
if test $? = 0 ; then
|
||||
echo "Linting man pages"
|
||||
# we grep out some false-positives from rem2ps
|
||||
spellintian --picky $PERLMANS ../man/*.1 2>&1 | grep -v -F 'MinX MinX (duplicate word)' | grep -v -F 'MinY MinY (duplicate word)' | grep -v -F 'show show (duplicate word)' >> $OUT 2>&1
|
||||
fi
|
||||
|
||||
# If we have "hunspell", run it against man pages
|
||||
cat <<'EOF' >> $OUT
|
||||
|
||||
If hunspell is installed, its output (if any) follows...
|
||||
|
||||
EOF
|
||||
|
||||
HUNSPELL="hunspell -d en_US -l -p manpage-personal-dict"
|
||||
GOT_HUNSPELL=0
|
||||
$HUNSPELL /dev/null < /dev/null > /dev/null 2>&1
|
||||
|
||||
# Hunspell runs. Do we have the en_US dictionary?
|
||||
if test $? = 0 ; then
|
||||
X=`(echo color; echo colour; echo returm) | hunspell -d en_US -l 2>/dev/null`
|
||||
X=`echo $X | sed -e 's/\n/ /g'`
|
||||
if test "$X" = "colour returm" ; then
|
||||
GOT_HUNSPELL=1
|
||||
fi
|
||||
fi
|
||||
if test "$GOT_HUNSPELL" = "1"; then
|
||||
echo "Spell-checking man pages, WHATSNEW and README.md"
|
||||
cat ../man/*.1 $PERLMANS | $HUNSPELL -n >> $OUT 2>&1
|
||||
cat ../docs/WHATSNEW | $HUNSPELL >> $OUT 2>&1
|
||||
cat ../README.md | $HUNSPELL >> $OUT 2>&1
|
||||
# If we have pod2man, check rem2pdf and rem2html man pages too
|
||||
pod2man < ../rem2html/rem2html.in > /dev/null 2>&1
|
||||
if test $? = 0 ; then
|
||||
pod2man < ../rem2html/rem2html.in | $HUNSPELL -n >> $OUT 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "" >> $OUT
|
||||
# Test --print-tokens long option
|
||||
$REMIND --print-tokens < /dev/null >> $OUT 2>&1
|
||||
|
||||
# Torture test #2
|
||||
$REMIND ../tests/torture2.rem >> $OUT 2>&1
|
||||
$REMIND ../tests/torture2.rem 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
# Expression error-reporting
|
||||
$REMIND -de - 1 Feb 2024 <<'EOF' >> $OUT 2>&1
|
||||
@@ -675,7 +726,7 @@ EOF
|
||||
|
||||
# Make sure stupidly-long translations of "am" and "pm" can't cause a
|
||||
# segmentation fault
|
||||
$REMIND -c - 1 Feb 2024 <<'EOF' >> $OUT 2>&1
|
||||
$REMIND -c - 1 Feb 2024 <<'EOF' >> $OUT 2>&1
|
||||
TRANS "am" "alsdkjalksdj alksjd alksdj alksjd laksjd laksjd laksjd laksjd laksjd laksjd laksjd laksjd lkasjd laksjd laksjd lkajs dlkajs dlkasj dlkasjd lkajsd lkajs dlkasjd lkasj dlkajsd lkasjd lkasjd laksjd laksjd laksjd alskdj alskdj alksdj alksdj alskdj alksdj aslkdj"
|
||||
TRANS "pm" "oiwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwjwwwwwwwwwwwwwwwjwpqoejkpqwojepqowjepqojwepqowjepqowjepqowjepqowjepqowjepqowjepqojwepqowjepqowjepqowjepqowjepqowjeqpweoj"
|
||||
|
||||
@@ -759,10 +810,10 @@ REM Wed MSG Wookie
|
||||
EOF
|
||||
|
||||
# Test year-folding
|
||||
TZ=America/Toronto $REMIND -dx ../tests/yearfold.rem >> $OUT 2>&1
|
||||
TZ=America/Toronto $REMIND -dx ../tests/yearfold.rem 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
# Test unused-variable debugging
|
||||
$REMIND -du - <<'EOF' >> $OUT 2>&1
|
||||
$REMIND -du - 2026-02-01 <<'EOF' >> $OUT 2>&1
|
||||
set a 1
|
||||
set b a*2
|
||||
set c "What"
|
||||
@@ -807,7 +858,7 @@ $REMIND --json ../tests/json-redirect.rem 1 Jan 2025 > /dev/null 2>> $OUT
|
||||
|
||||
# Test %: substitution sequence in all the languages
|
||||
for i in ../include/lang/??.rem ; do
|
||||
$REMIND "-ii=\"$i\"" -p - 2025-08-13 <<'EOF' 2>&1 | grep -a 2025/ >> $OUT
|
||||
$REMIND "-ii=\"$i\"" -p - 2025-08-13 <<'EOF' 2>&1 | grep $GREP_A 2025/ >> $OUT
|
||||
DO [i]
|
||||
REM TODO 2025-08-13 MSG %(LANGID) Task1%:
|
||||
REM TODO 2025-08-13 COMPLETE-THROUGH 2025-08-12 MSG %(LANGID) Task2%:
|
||||
@@ -879,6 +930,70 @@ EOF
|
||||
# For this one, we need to force an error so we make sure the error is
|
||||
# reported in -stdin- and not cat|
|
||||
(echo 'INCLUDECMD cat'; sleep $DELAY; echo 'set a 1/0') | $REMIND - 2025-10-01 >> $OUT 2>&1
|
||||
|
||||
$REMIND --json - 2025-10-01 <<'EOF' >> $OUT 2>&1
|
||||
# Nonconst-expr in trigger
|
||||
set a nonconst(1)
|
||||
REM 2025-10-01 MSG Nonconst NOT set [today()]
|
||||
REM 2025 Oct [a] MSG Nonconst IS set [today()]
|
||||
REM 2025 Oct [a] MSG Nonconst IS set
|
||||
EOF
|
||||
|
||||
$REMIND -j - 2025-12-31 <<'EOF' >> $OUT 2>&1
|
||||
# Nonconst-expr in trigger
|
||||
set $ParseUntriggered 1
|
||||
set a nonconst(1)
|
||||
REM 2025-10-01 MSG Nonconst NOT set [today()]
|
||||
REM 2025 Oct [a] MSG Nonconst IS set [today()]
|
||||
REM 2025 Oct [a] MSG Nonconst IS set
|
||||
REM 2025 Oct [1] MSG Expr but not nonconst [today()]
|
||||
REM 2025-10-01 MSG No expr seen [1+2]
|
||||
EOF
|
||||
|
||||
# Early exit from calendar processing
|
||||
$REMIND -p - 2026-01-01 <<'EOF' >> $OUT 2>&1
|
||||
REM 1 Jan 1994 MSG 1/0 = [1/0]
|
||||
EOF
|
||||
|
||||
# No early exit from calendar processing
|
||||
$REMIND -p - 2026-01-01 <<'EOF' >> $OUT 2>&1
|
||||
SET $ParseUntriggered 1
|
||||
REM 1 Jan 1994 MSG 1/0 = [1/0]
|
||||
EOF
|
||||
|
||||
# Calendars with hyperlinks
|
||||
$REMIND -w,0,0 -@2 -c - 1 Jan 2020 <<'EOF' >> $OUT 2>&1
|
||||
SET $TerminalHyperlinks 1
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" MSG Hello, linky!
|
||||
REM 16 INFO "Url: https://dianne.skoll.ca" MSF Hello, linky!
|
||||
REM 17 INFO "Url: https://dianne.skoll.ca" CAL Hello, linky!
|
||||
REM 18 INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky!
|
||||
EOF
|
||||
|
||||
# Turn off spacing between reminders, and test the 'z' -c flag.
|
||||
$REMIND -w,0,0,0 -@2 -cz - 1 Jan 2020 <<'EOF' >> $OUT 2>&1
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" MSG Hello, linky 1!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" MSF Hello, linky 2!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" CAL Hello, linky 3!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky 4!
|
||||
EOF
|
||||
|
||||
# Turn on spacing between reminders..
|
||||
$REMIND -w,0,0,1 -@2 -c - 1 Jan 2020 <<'EOF' >> $OUT 2>&1
|
||||
SET $TerminalHyperlinks 1
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" MSG Hello, linky 1!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" MSF Hello, linky 2!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" CAL Hello, linky 3!
|
||||
REM 15 INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky 4!
|
||||
EOF
|
||||
|
||||
# Test the $Shaded system variable
|
||||
$REMIND -pp ../tests/shaded.rem 2026-02-01 >> $OUT 2>&1
|
||||
|
||||
# Test the push/pop warnings
|
||||
$REMIND ../tests/test-pushpop1.rem 2026-01-01 >> $OUT 2>&1
|
||||
$REMIND -dp ../tests/test-pushpop1.rem 2026-01-01 >> $OUT 2>&1
|
||||
|
||||
cmp -s $OUT $CMP
|
||||
if [ "$?" = "0" ]; then
|
||||
echo "Remind: Acceptance tests ${GRN}PASSED${NRM}"
|
||||
|
||||
@@ -40,7 +40,7 @@ OUT=../tests/tz.out
|
||||
CMP=../tests/tz.cmp
|
||||
|
||||
echo "Running timezone tests"
|
||||
echo -n "" > $OUT 2>&1
|
||||
cp /dev/null $OUT
|
||||
|
||||
TZ=Europe/Amsterdam $REMIND - 2025-09-03@14:00 <<'EOF' >> $OUT 2>&1
|
||||
SET $AddBlankLines=0
|
||||
|
||||
464
tests/test.cmp
464
tests/test.cmp
@@ -1046,7 +1046,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "06.01.05"
|
||||
version() => "06.02.04"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -2609,7 +2609,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a007 "1991-02-16"
|
||||
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
a008 "11:44"
|
||||
a058 "06.01.05"
|
||||
a058 "06.02.04"
|
||||
a059 "Saturday"
|
||||
a010 12
|
||||
a060 6
|
||||
@@ -5040,8 +5040,9 @@ set a 7 * "Cabbage! "
|
||||
|
||||
# Should result in errors
|
||||
set pqxya 1+2)
|
||||
1 + 2 => 3
|
||||
../tests/test.rem(1014): Expecting end-of-line
|
||||
1+2)
|
||||
^-- here
|
||||
../tests/test.rem(1014): Expecting operator or end-of-expression
|
||||
|
||||
# Should result in an error
|
||||
REM Tue OMIT 2024-01-01 MSG Wookie
|
||||
@@ -5562,8 +5563,8 @@ REM SATISFY ""
|
||||
REM SATISFY [version() > "01.00.00"]
|
||||
../tests/test.rem(1074): SATISFY: expression has no reference to trigdate() or $T...
|
||||
../tests/test.rem(1074): Trig = Saturday, 16 February, 1991
|
||||
version() => "06.01.05"
|
||||
"06.01.05" > "01.00.00" => 1
|
||||
version() => "06.02.04"
|
||||
"06.02.04" > "01.00.00" => 1
|
||||
../tests/test.rem(1074): Trig(satisfied) = Saturday, 16 February, 1991
|
||||
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
|
||||
../tests/test.rem(1075): SATISFY: expression has no reference to trigdate() or $T...
|
||||
@@ -16426,9 +16427,14 @@ eval("1/0") => 1 / 0 => Division by zero
|
||||
../tests/test.rem(1590): `/': Division by zero
|
||||
Division by zero
|
||||
set a eval("1 / / 2")
|
||||
eval("1 / / 2") => ../tests/test.rem(1591): Illegal character `/'
|
||||
eval("1 / / 2") => ../tests/test.rem(1591): Expecting constant, variable, function call or (expression)
|
||||
1 / / 2
|
||||
^-- here
|
||||
Expecting constant, variable, function call or (expression)
|
||||
set a eval("1 / # 2")
|
||||
eval("1 / # 2") => ../tests/test.rem(1592): Illegal character `#'
|
||||
1 / # 2
|
||||
^-- here
|
||||
Illegal character
|
||||
set a catch(eval("1 +"), 33)
|
||||
eval("1 +") => Unexpected end of line
|
||||
@@ -16438,7 +16444,10 @@ eval("1/0") => 1 / 0 => Division by zero
|
||||
Division by zero
|
||||
catch(*Division by zero*, 34) => 34
|
||||
set a catch(eval("1 / / 2"), 35)
|
||||
eval("1 / / 2") => Illegal character
|
||||
eval("1 / / 2") => Expecting constant, variable, function call or (expression)
|
||||
catch(*Expecting constant, variable, function call or (expression)*, 35) => 35
|
||||
set a catch(eval("1 / # 2"), 35)
|
||||
eval("1 / # 2") => Illegal character
|
||||
catch(*Illegal character*, 35) => 35
|
||||
|
||||
# Ensure RUN is disabled in eval
|
||||
@@ -16446,7 +16455,7 @@ set a shell("echo foo")
|
||||
shell("echo foo") => "foo"
|
||||
set a eval("shell(\"echo foo\")")
|
||||
eval("shell(\"echo foo\")") => shell("echo foo") => RUN disabled
|
||||
../tests/test.rem(1598): shell(): RUN disabled
|
||||
../tests/test.rem(1600): shell(): RUN disabled
|
||||
RUN disabled
|
||||
set a shell("echo foo")
|
||||
shell("echo foo") => "foo"
|
||||
@@ -16459,8 +16468,8 @@ Leaving UserFN i() => "foo"
|
||||
set a eval("i()")
|
||||
eval("i()") => Entering UserFN i()
|
||||
shell("echo foo") => RUN disabled
|
||||
../tests/test.rem(1603): shell(): RUN disabled
|
||||
../tests/test.rem(1601): [#0] In function `i'
|
||||
../tests/test.rem(1605): shell(): RUN disabled
|
||||
../tests/test.rem(1603): [#0] In function `i'
|
||||
Leaving UserFN i() => RUN disabled
|
||||
RUN disabled
|
||||
set a i()
|
||||
@@ -16473,19 +16482,19 @@ set b eval(a)
|
||||
a => "eval(\"1\")+ shell(\"ls\")"
|
||||
eval("eval(\"1\")+ shell(\"ls\")") => eval("1") => 1
|
||||
shell("ls") => RUN disabled
|
||||
../tests/test.rem(1607): shell(): RUN disabled
|
||||
../tests/test.rem(1609): shell(): RUN disabled
|
||||
RUN disabled
|
||||
|
||||
# "value" should use lazy evaluation
|
||||
set a value(4:33)
|
||||
value(04:33) => Type mismatch
|
||||
../tests/test.rem(1610): Type mismatch
|
||||
../tests/test.rem(1612): Type mismatch
|
||||
set a value('2020-01-01', 42)
|
||||
value(2020-01-01, ?) => Type mismatch
|
||||
../tests/test.rem(1611): Type mismatch
|
||||
../tests/test.rem(1613): Type mismatch
|
||||
set a value("nosuchvar")
|
||||
value("nosuchvar") => Undefined variable
|
||||
../tests/test.rem(1612): Undefined variable
|
||||
../tests/test.rem(1614): Undefined variable
|
||||
set a value("nosuchvar", 42)
|
||||
value("nosuchvar", 42) => 42
|
||||
set a value("a", 42)
|
||||
@@ -16495,11 +16504,11 @@ value("a") => 42
|
||||
DEBUG -x
|
||||
|
||||
DEBUG -e
|
||||
../tests/test.rem(1622): eval(): Too many recursive function calls
|
||||
../tests/test.rem(1624): eval(): Too many recursive function calls
|
||||
Base: 1991-02-09
|
||||
Base: 1991-02-09
|
||||
../tests/test.rem(1630): Expired
|
||||
../tests/test.rem(1631): Expired
|
||||
../tests/test.rem(1632): Expired
|
||||
../tests/test.rem(1633): Expired
|
||||
trigvalid = 1; trigdate = 1991-01-14
|
||||
trigvalid = 0; trigdate = 0
|
||||
daysinmon(2, 2000) => 29
|
||||
@@ -16511,36 +16520,36 @@ daysinmon("Feb", 2001) => 28
|
||||
daysinmon("March", 2000) => 31
|
||||
daysinmon("March", 2001) => 31
|
||||
daysinmon("Cabbage", 2001) => Invalid month name
|
||||
../tests/test.rem(1658): daysinmon(): Invalid month name
|
||||
../tests/test.rem(1660): daysinmon(): Invalid month name
|
||||
daysinmon(2000-02-14) => 29
|
||||
daysinmon(2001-02-14) => 28
|
||||
daysinmon(2000-04-14) => 30
|
||||
daysinmon(2001-04-14) => 30
|
||||
date(2020, "April", 15) => 2020-04-15
|
||||
date(2020, "Carrot", 12) => Invalid month name
|
||||
../tests/test.rem(1666): date(): Invalid month name
|
||||
../tests/test.rem(1668): date(): Invalid month name
|
||||
datetime(2020, "April", 13, 04:44) => 2020-04-13@04:44
|
||||
datetime(2020, "April", 13, 4, 44) => 2020-04-13@04:44
|
||||
datetime(2020, "Lettuce", 13, 04:44) => Invalid month name
|
||||
../tests/test.rem(1669): datetime(): Invalid month name
|
||||
../tests/test.rem(1671): datetime(): Invalid month name
|
||||
datetime(2020, "Lettuce", 13, 4, 44) => Invalid month name
|
||||
../tests/test.rem(1670): datetime(): Invalid month name
|
||||
../tests/test.rem(1672): datetime(): Invalid month name
|
||||
wkdaynum("Tue") => 2
|
||||
wkdaynum("Wednesday") => 3
|
||||
wkdaynum("telephone") => Invalid weekday name
|
||||
../tests/test.rem(1674): wkdaynum(): Invalid weekday name
|
||||
../tests/test.rem(1685): Cannot modify system variable: `$NumTrig'
|
||||
../tests/test.rem(1686): POP-VARS without matching PUSH-VARS
|
||||
../tests/test.rem(1676): wkdaynum(): Invalid weekday name
|
||||
../tests/test.rem(1687): Cannot modify system variable: `$NumTrig'
|
||||
../tests/test.rem(1688): POP-VARS without matching PUSH-VARS
|
||||
|
||||
FUNSET a
|
||||
FSET b(x, y) x*y
|
||||
FSET c() 33
|
||||
|
||||
set a a(2)
|
||||
../tests/test.rem(1695): Undefined function: `a'
|
||||
../tests/test.rem(1697): Undefined function: `a'
|
||||
set a b(2)
|
||||
b(?) => Not enough arguments
|
||||
../tests/test.rem(1696): b(): Not enough arguments
|
||||
../tests/test.rem(1698): b(): Not enough arguments
|
||||
set a b(2, 3)
|
||||
Entering UserFN b(2, 3)
|
||||
x => 2
|
||||
@@ -16562,7 +16571,7 @@ Entering UserFN a(2)
|
||||
Leaving UserFN a(2) => 42
|
||||
set a b(2)
|
||||
b(?) => Not enough arguments
|
||||
../tests/test.rem(1707): b(): Not enough arguments
|
||||
../tests/test.rem(1709): b(): Not enough arguments
|
||||
set a b(2, 3)
|
||||
Entering UserFN b(2, 3)
|
||||
x => 2
|
||||
@@ -16577,10 +16586,10 @@ Leaving UserFN c() => 66
|
||||
POP-FUNCS
|
||||
|
||||
set a a(2)
|
||||
../tests/test.rem(1713): Undefined function: `a'
|
||||
../tests/test.rem(1715): Undefined function: `a'
|
||||
set a b(2)
|
||||
b(?) => Not enough arguments
|
||||
../tests/test.rem(1714): b(): Not enough arguments
|
||||
../tests/test.rem(1716): b(): Not enough arguments
|
||||
set a b(2, 3)
|
||||
Entering UserFN b(2, 3)
|
||||
x => 2
|
||||
@@ -16595,7 +16604,7 @@ DEBUG -xe
|
||||
Overridden: subst_colon subst_bang subst_question subst_at subst_hash
|
||||
bad => "ÿ"
|
||||
mbstrlen("ÿ") => Invalid multibyte sequence
|
||||
../tests/test.rem(1734): mbstrlen(): Invalid multibyte sequence
|
||||
../tests/test.rem(1736): mbstrlen(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
strlen("ÿ") => 1
|
||||
faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
@@ -16609,7 +16618,7 @@ index("🙂🙂🙂🙂🙂xyzçççéfoo", "ç") => 24
|
||||
bad => "ÿ"
|
||||
bad => "ÿ"
|
||||
mbindex("ÿ", "ÿ") => Invalid multibyte sequence
|
||||
../tests/test.rem(1742): mbindex(): Invalid multibyte sequence
|
||||
../tests/test.rem(1744): mbindex(): Invalid multibyte sequence
|
||||
faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
mbindex("🙂🙂🙂🙂🙂xyzçççéfoo", "ç", 11) => 11
|
||||
faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
@@ -16628,10 +16637,10 @@ faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
mbsubstr("🙂🙂🙂🙂🙂xyzçççéfoo", 2, 9) => "🙂🙂🙂🙂xyzç"
|
||||
bad => "ÿ"
|
||||
mbsubstr("ÿ", 1) => Invalid multibyte sequence
|
||||
../tests/test.rem(1754): mbsubstr(): Invalid multibyte sequence
|
||||
../tests/test.rem(1756): mbsubstr(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbsubstr("ÿ", 1, 20) => Invalid multibyte sequence
|
||||
../tests/test.rem(1755): mbsubstr(): Invalid multibyte sequence
|
||||
../tests/test.rem(1757): mbsubstr(): Invalid multibyte sequence
|
||||
faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
substr("🙂🙂🙂🙂🙂xyzçççéfoo", 2) => "Ÿ™‚🙂🙂🙂🙂xyzçççéfoo"
|
||||
faces => "🙂🙂🙂🙂🙂xyzçççéfoo"
|
||||
@@ -16641,13 +16650,128 @@ codepoint("🙂🙂🙂🙂🙂xyzçççéfoo") => 128578
|
||||
mbchar(128578, 162, 122) => "🙂¢z"
|
||||
bad => "ÿ"
|
||||
codepoint("ÿ") => Invalid multibyte sequence
|
||||
../tests/test.rem(1762): codepoint(): Invalid multibyte sequence
|
||||
../tests/test.rem(1764): codepoint(): Invalid multibyte sequence
|
||||
codepoint("") => 0
|
||||
mbchar(0) => ""
|
||||
mbchar(0, 120) => Number too low
|
||||
../tests/test.rem(1765): mbchar(): Number too low
|
||||
../tests/test.rem(1767): mbchar(): Number too low
|
||||
mbchar(120, 0) => Number too low
|
||||
../tests/test.rem(1766): mbchar(): Number too low
|
||||
../tests/test.rem(1768): mbchar(): Number too low
|
||||
hebdate(1, "Tishrey") => 1991-09-09
|
||||
hebdate(1, "Tishri") => 1991-09-09
|
||||
hebdate(1, "Tishrei") => 1991-09-09
|
||||
hebdate(1, "תשרי") => 1991-09-09
|
||||
hebdate(1, "Cheshvan") => 1991-10-09
|
||||
hebdate(1, "Kheshvan") => 1991-10-09
|
||||
hebdate(1, "Heshvan") => 1991-10-09
|
||||
hebdate(1, "חשוון") => 1991-10-09
|
||||
hebdate(1, "Kislev") => 1991-11-08
|
||||
hebdate(1, "כסלו") => 1991-11-08
|
||||
hebdate(1, "Tevet") => 1991-12-08
|
||||
hebdate(1, "טבת") => 1991-12-08
|
||||
hebdate(1, "Shvat") => 1992-01-06
|
||||
hebdate(1, "Shevat") => 1992-01-06
|
||||
hebdate(1, "שבט") => 1992-01-06
|
||||
hebdate(1, "Adar A") => 1992-02-05
|
||||
hebdate(1, "Adar 1") => 1992-02-05
|
||||
hebdate(1, "Adar I") => 1992-02-05
|
||||
hebdate(1, "×<>דר ×<>'") => 1992-02-05
|
||||
hebdate(1, "×<>דר ×<>") => 1992-02-05
|
||||
hebdate(1, "×<>דר 1") => 1992-02-05
|
||||
hebdate(1, "×<>דר I") => 1992-02-05
|
||||
hebdate(1, "Adar B") => 1992-03-06
|
||||
hebdate(1, "Adar 2") => 1992-03-06
|
||||
hebdate(1, "Adar II") => 1992-03-06
|
||||
hebdate(1, "×<>דר ב'") => 1992-03-06
|
||||
hebdate(1, "×<>דר ב") => 1992-03-06
|
||||
hebdate(1, "×<>דר 2") => 1992-03-06
|
||||
hebdate(1, "×<>דר II") => 1992-03-06
|
||||
hebdate(1, "Nisan") => 1991-03-16
|
||||
hebdate(1, "× ×™×¡×Ÿ") => 1991-03-16
|
||||
hebdate(1, "Iyar") => 1991-04-15
|
||||
hebdate(1, "Iyyar") => 1991-04-15
|
||||
hebdate(1, "×<>ייר") => 1991-04-15
|
||||
hebdate(1, "Sivan") => 1991-05-14
|
||||
hebdate(1, "סיון") => 1991-05-14
|
||||
hebdate(1, "Tamuz") => 1991-06-13
|
||||
hebdate(1, "Tammuz") => 1991-06-13
|
||||
hebdate(1, "תמוז") => 1991-06-13
|
||||
hebdate(1, "Av") => 1991-07-12
|
||||
hebdate(1, "×<>ב") => 1991-07-12
|
||||
hebdate(1, "Elul") => 1991-08-11
|
||||
hebdate(1, "×<>לול") => 1991-08-11
|
||||
hebdate(1, "Adar") => 1992-03-06
|
||||
hebdate(1, "×<>דר") => 1992-03-06
|
||||
hebmon(1991-09-09) => "Tishrey"
|
||||
ivritmon(1991-09-09) => "תשרי"
|
||||
hebmon(1991-10-09) => "Heshvan"
|
||||
ivritmon(1991-10-09) => "חשוון"
|
||||
hebmon(1991-11-08) => "Kislev"
|
||||
ivritmon(1991-11-08) => "כסלו"
|
||||
hebmon(1991-12-08) => "Tevet"
|
||||
ivritmon(1991-12-08) => "טבת"
|
||||
hebmon(1992-01-06) => "Shvat"
|
||||
ivritmon(1992-01-06) => "שבט"
|
||||
hebmon(1992-02-05) => "Adar A"
|
||||
ivritmon(1992-02-05) => "×<>דר ×<>'"
|
||||
hebmon(1992-03-06) => "Adar B"
|
||||
ivritmon(1992-03-06) => "×<>דר ב'"
|
||||
hebmon(1991-03-16) => "Nisan"
|
||||
ivritmon(1991-03-16) => "× ×™×¡×Ÿ"
|
||||
hebmon(1991-04-15) => "Iyar"
|
||||
ivritmon(1991-04-15) => "×<>ייר"
|
||||
hebmon(1991-05-14) => "Sivan"
|
||||
ivritmon(1991-05-14) => "סיון"
|
||||
hebmon(1991-06-13) => "Tamuz"
|
||||
ivritmon(1991-06-13) => "תמוז"
|
||||
hebmon(1991-07-12) => "Av"
|
||||
ivritmon(1991-07-12) => "×<>ב"
|
||||
hebmon(1991-08-11) => "Elul"
|
||||
ivritmon(1991-08-11) => "×<>לול"
|
||||
mbpad("foo", "bar", 3) => "foo"
|
||||
mbpad("foo", "bar", 3, 1) => "foo"
|
||||
mbpad("foo", "bar", 8) => "barbafoo"
|
||||
mbpad("foo", "bar", 8, 1) => "foobarba"
|
||||
mbpad("foo", "🙂💩", 3) => "foo"
|
||||
mbpad("foo", "🙂💩", 3, 1) => "foo"
|
||||
mbpad("foo", "🙂💩", 8) => "🙂💩🙂💩🙂foo"
|
||||
mbpad("foo", "🙂💩", 8, 1) => "foo🙂💩🙂💩🙂"
|
||||
char(255) => "ÿ"
|
||||
bad => "ÿ"
|
||||
mbpad("foo", "ÿ", 3) => "foo"
|
||||
bad => "ÿ"
|
||||
mbpad("foo", "ÿ", 3, 1) => "foo"
|
||||
bad => "ÿ"
|
||||
mbpad("foo", "ÿ", 8) => Invalid multibyte sequence
|
||||
../tests/test.rem(1886): mbpad(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbpad("foo", "ÿ", 8, 1) => Invalid multibyte sequence
|
||||
../tests/test.rem(1887): mbpad(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbpad("ÿ", "bar", 0) => Invalid multibyte sequence
|
||||
../tests/test.rem(1888): mbpad(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbpad("ÿ", "bar", 0, 1) => Invalid multibyte sequence
|
||||
../tests/test.rem(1889): mbpad(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbpad("ÿ", "bar", 8) => Invalid multibyte sequence
|
||||
../tests/test.rem(1890): mbpad(): Invalid multibyte sequence
|
||||
bad => "ÿ"
|
||||
mbpad("ÿ", "bar", 8, 1) => Invalid multibyte sequence
|
||||
../tests/test.rem(1891): mbpad(): Invalid multibyte sequence
|
||||
]8;;https://dianne.skoll.ca\Hello, linky!
|
||||
]8;;\]8;;https://dianne.skoll.ca\Hello, linky!
|
||||
]8;;\]8;;https://dianne.skoll.ca\Hello, linky!
|
||||
]8;;\../tests/test.rem(1900): Invalid value for system variable
|
||||
../tests/test.rem(1901): Invalid value for system variable
|
||||
../tests/test.rem(1902): Invalid value for system variable
|
||||
../tests/test.rem(1903): Invalid value for system variable
|
||||
../tests/test.rem(1904): Invalid value for system variable
|
||||
mbupper("öÖçÇéôñÑÉÊ") => "ÖÖÇÇÉÔÑÑÉÊ"
|
||||
mblower("öÖçÇéôñÑÉÊ") => "ööççéôññéê"
|
||||
upper("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ"
|
||||
lower("öÖçÇéôñÑÉÊ") => "öÖçÇéôñÑÉÊ"
|
||||
DynBuf Mallocs: 1132 mallocs; 31873408 bytes
|
||||
Variable hash table statistics:
|
||||
Entries: 100146; Buckets: 87719; Non-empty Buckets: 66303
|
||||
Maxlen: 5; Minlen: 0; Avglen: 1.142; Stddev: 0.878; Avg nonempty len: 1.510
|
||||
@@ -16669,7 +16793,7 @@ Expression nodes high-water: 302076
|
||||
Expression nodes leaked: 0
|
||||
Parse level high-water: 34
|
||||
Max expr node evaluations per line: 2001
|
||||
Total expression node evaluations: 106467
|
||||
Total expression node evaluations: 106746
|
||||
|
||||
Test 2
|
||||
|
||||
@@ -20648,7 +20772,7 @@ No reminders.
|
||||
<< /PageSize [612 792] >> setpagedevice
|
||||
% This file was produced by Remind and Rem2PS, written by
|
||||
% Dianne Skoll.
|
||||
% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.
|
||||
% Remind and Rem2PS are Copyright (C) 1992-2026 Dianne Skoll.
|
||||
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
||||
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
||||
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
||||
@@ -21752,7 +21876,7 @@ showpage
|
||||
<< /PageSize [612 792] >> setpagedevice
|
||||
% This file was produced by Remind and Rem2PS, written by
|
||||
% Dianne Skoll.
|
||||
% Remind and Rem2PS are Copyright (C) 1992-2025 Dianne Skoll.
|
||||
% Remind and Rem2PS are Copyright (C) 1992-2026 Dianne Skoll.
|
||||
/ISOLatin1Encoding where { pop save true }{ false } ifelse
|
||||
/ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
|
||||
StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
|
||||
@@ -23707,7 +23831,7 @@ SECURITY: Won't read world-writable file or directory!
|
||||
Error reading include_dir/ww: Can't open file
|
||||
SECURITY: Won't read world-writable file or directory!
|
||||
Error reading include_dir/ww: No files matching *.rem
|
||||
06.01.05
|
||||
06.02.04
|
||||
Enabling test mode: This is meant for the acceptance test.
|
||||
Do not use --test in production.
|
||||
In test mode, the system time is fixed at 2025-01-06@19:00
|
||||
@@ -23905,7 +24029,9 @@ Parsed expression: 1||1
|
||||
Parsed expression: 2
|
||||
=> 2
|
||||
Unparsed: , 3
|
||||
../tests/expr.rem(15): Expecting end-of-line
|
||||
2, 3
|
||||
^-- here
|
||||
../tests/expr.rem(15): Expecting operator or end-of-expression
|
||||
Parsed expression: iif(0, "foo", 0, "bar", 1, "blech", 0, "quux", 1, "borhy", "wacka")
|
||||
=> (Iif 0 "foo" 0 "bar" 1 "blech" 0 "quux" 1 "borhy" "wacka")
|
||||
iif(0, ?, 0, ?, 1, "blech", ?, ?, ?, ?, ?) => "blech"
|
||||
@@ -23923,7 +24049,7 @@ max(6, 9, 50) => 50
|
||||
Parsed expression: max(1,
|
||||
=> Error: Illegal character
|
||||
Unparsed: ,1)
|
||||
,1)
|
||||
max(1,,1)
|
||||
^-- here
|
||||
Parsed expression: 5%0
|
||||
=> (% 5 0)
|
||||
@@ -24263,6 +24389,7 @@ Parsed expression: isany("foo", 1 + 1, 2:00 + 1, '2021-01-01' + 1, '2021-01-01@1
|
||||
"f" + "oo" => "foo"
|
||||
isany("foo", 2, 02:01, 2021-01-02, 2021-01-01@14:01, "foo", ?) => 1
|
||||
No reminders.
|
||||
DynBuf Mallocs: 21 mallocs; 6400 bytes
|
||||
Variable hash table statistics:
|
||||
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||
@@ -24284,7 +24411,7 @@ Expression nodes high-water: 499
|
||||
Expression nodes leaked: 0
|
||||
Parse level high-water: 2001
|
||||
Max expr node evaluations per line: 499
|
||||
Total expression node evaluations: 632
|
||||
Total expression node evaluations: 631
|
||||
-stdin-(14): Unmatched PUSH-OMIT-CONTEXT at -stdin-(7)
|
||||
-stdin-(14): Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT
|
||||
No reminders.
|
||||
@@ -24458,6 +24585,13 @@ Checking ../man/rem.1...
|
||||
Checking ../man/rem2ps.1...
|
||||
Checking ../man/remind.1...
|
||||
Checking ../man/tkremind.1...
|
||||
|
||||
If spellintian is installed, its output (if any) follows...
|
||||
|
||||
|
||||
If hunspell is installed, its output (if any) follows...
|
||||
|
||||
|
||||
# Remind Tokens
|
||||
|
||||
addomit
|
||||
@@ -24470,6 +24604,7 @@ cal
|
||||
clear
|
||||
clear-omit-context
|
||||
complete-through
|
||||
completed-through
|
||||
debug
|
||||
do
|
||||
dump
|
||||
@@ -24638,14 +24773,18 @@ isconst
|
||||
isdst
|
||||
isleap
|
||||
isomitted
|
||||
ivritmon
|
||||
language
|
||||
localtoutc
|
||||
lower
|
||||
max
|
||||
mbchar
|
||||
mbindex
|
||||
mblower
|
||||
mbpad
|
||||
mbstrlen
|
||||
mbsubstr
|
||||
mbupper
|
||||
min
|
||||
minsfromutc
|
||||
minute
|
||||
@@ -24812,6 +24951,7 @@ $PSCal
|
||||
$RunOff
|
||||
$Saturday
|
||||
$September
|
||||
$Shaded
|
||||
$SimpleCal
|
||||
$SortByDate
|
||||
$SortByPrio
|
||||
@@ -24825,6 +24965,7 @@ $T
|
||||
$Tb
|
||||
$Td
|
||||
$TerminalBackground
|
||||
$TerminalHyperlinks
|
||||
$Thursday
|
||||
$TimeSep
|
||||
$TimetIs64bit
|
||||
@@ -24851,6 +24992,7 @@ $WarningLevel
|
||||
$Was
|
||||
$Wednesday
|
||||
No reminders.
|
||||
DynBuf Mallocs: 180071 mallocs; 42974784 bytes
|
||||
Variable hash table statistics:
|
||||
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||
@@ -25053,9 +25195,11 @@ TRANSLATE "MAX-OVERDUE specified twice" ""
|
||||
TRANSLATE "MAX-OVERDUE specified without TODO" ""
|
||||
TRANSLATE "TZ specified twice" ""
|
||||
TRANSLATE "TZ specified for non-timed reminder" ""
|
||||
TRANSLATE "C library does not support multibyte characters" ""
|
||||
TRANSLATE "Invalid multibyte sequence" ""
|
||||
TRANSLATE "Maximum expression complexity exceeded" ""
|
||||
TRANSLATE "Expecting operator or end-of-expression" ""
|
||||
TRANSLATE "Expecting constant, variable, function call or (expression)" ""
|
||||
TRANSLATE "Invalid value for system variable" ""
|
||||
|
||||
# Other Messages
|
||||
TRANSLATE "%s function `%s' defined at %s(%s) does not use its argument" ""
|
||||
@@ -39539,7 +39683,6 @@ trigger(2060-08-01@23:55, 1) => "1 August 2060 AT 19:55"
|
||||
utctolocal(2050-01-01@01:00) => 2049-12-31@20:00
|
||||
localtoutc(2050-12-31@23:44) => 2051-01-01@04:44
|
||||
localtoutc(2050-03-13@00:00) => 2050-03-13@05:00
|
||||
localtoutc(2050-03-13@02:00) => 2050-03-13@07:00
|
||||
localtoutc(2050-11-06@00:00) => 2050-11-06@04:00
|
||||
localtoutc(2050-11-06@02:00) => 2050-11-06@07:00
|
||||
utctolocal(2051-01-01@04:44) => 2050-12-31@23:44
|
||||
@@ -39651,6 +39794,14 @@ Fifth today
|
||||
Sixth on 2025-08-06
|
||||
Eighth on 2025-08-20
|
||||
Ninth today
|
||||
First on 2025-08-01
|
||||
Second on 2022-08-01
|
||||
Third on 2023-08-01
|
||||
Fourth on 2025-08-20
|
||||
Fifth today
|
||||
Sixth on 2025-08-06
|
||||
Eighth on 2025-08-20
|
||||
Ninth today
|
||||
Yup today
|
||||
Yup2 yesterday
|
||||
Yup3 on 2025-08-11
|
||||
@@ -39666,6 +39817,13 @@ Testing TODOS in calendar mode
|
||||
2025/08/01 * * * * First
|
||||
2025/08/01 * * * * Second
|
||||
2025/08/01 * * * * Third
|
||||
2025/08/01 * * * * First
|
||||
2025/08/01 * * * * Second
|
||||
2025/08/01 * * * * Third
|
||||
2025/08/06 * * * * Sixth
|
||||
2025/08/06 * * * * Seventh
|
||||
2025/08/06 * * * * Eighth
|
||||
2025/08/06 * * * * Ninth
|
||||
2025/08/06 * * * * Sixth
|
||||
2025/08/06 * * * * Seventh
|
||||
2025/08/06 * * * * Eighth
|
||||
@@ -39677,10 +39835,18 @@ Testing TODOS in calendar mode
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Eighth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Eighth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Yup
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
2025/08/27 * * * * Eighth
|
||||
2025/08/27 * * * * Ninth
|
||||
2025/08/27 * * * * Eighth
|
||||
2025/08/27 * * * * Ninth
|
||||
|
||||
@@ -39688,6 +39854,10 @@ Testing TODOS in calendar mode with completed todos hidden
|
||||
2025/08/01 * * * * First
|
||||
2025/08/01 * * * * Second
|
||||
2025/08/01 * * * * Third
|
||||
2025/08/01 * * * * First
|
||||
2025/08/01 * * * * Second
|
||||
2025/08/01 * * * * Third
|
||||
2025/08/06 * * * * Sixth
|
||||
2025/08/06 * * * * Sixth
|
||||
2025/08/09 * * * * Nope
|
||||
2025/08/10 * * * * Yup4
|
||||
@@ -39695,26 +39865,41 @@ Testing TODOS in calendar mode with completed todos hidden
|
||||
2025/08/12 * * * * Yup2
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Fifth
|
||||
2025/08/13 * * * * Ninth
|
||||
2025/08/13 * * * * Yup
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
2025/08/20 * * * * Fourth
|
||||
2025/08/20 * * * * Eighth
|
||||
2025/08/20 * * * * Ninth
|
||||
2025/08/27 * * * * Eighth
|
||||
2025/08/27 * * * * Ninth
|
||||
2025/08/27 * * * * Eighth
|
||||
2025/08/27 * * * * Ninth
|
||||
Testing TODOS and JSON mode
|
||||
[
|
||||
{"date":"2025-08-01","filename":"../tests/todos.rem","lineno":4,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-1 ","priority":5000,"body":"First on 2025-08-01"},
|
||||
{"date":"2025-08-01","filename":"../tests/todos.rem","lineno":4,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-01","priority":5000,"body":"First on 2025-08-01"},
|
||||
{"date":"2022-08-01","filename":"../tests/todos.rem","lineno":5,"d":1,"m":8,"is_todo":1,"complete_through":"2022-07-31","priority":5000,"body":"Second on 2022-08-01"},
|
||||
{"date":"2023-08-01","filename":"../tests/todos.rem","lineno":6,"d":1,"m":8,"is_todo":1,"complete_through":"2022-08-01","priority":5000,"body":"Third on 2023-08-01"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":7,"d":20,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-20","priority":5000,"body":"Fourth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":8,"d":13,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-13","priority":5000,"body":"Fifth today"},
|
||||
{"date":"2025-08-06","filename":"../tests/todos.rem","lineno":9,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-6 ","priority":5000,"body":"Sixth on 2025-08-06"},
|
||||
{"date":"2025-08-06","filename":"../tests/todos.rem","lineno":9,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-06","priority":5000,"body":"Sixth on 2025-08-06"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":11,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-13","delta":7,"priority":5000,"body":"Eighth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":12,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-12","delta":7,"priority":5000,"body":"Ninth today"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":15,"d":13,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-13","max_overdue":3,"priority":5000,"body":"Yup today"},
|
||||
{"date":"2025-08-12","filename":"../tests/todos.rem","lineno":16,"d":12,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-12","max_overdue":3,"priority":5000,"body":"Yup2 yesterday"},
|
||||
{"date":"2025-08-11","filename":"../tests/todos.rem","lineno":17,"d":11,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-11","max_overdue":3,"priority":5000,"body":"Yup3 on 2025-08-11"},
|
||||
{"date":"2025-08-10","filename":"../tests/todos.rem","lineno":18,"d":10,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-10","max_overdue":3,"priority":5000,"body":"Yup4 on 2025-08-10"}
|
||||
{"date":"2025-08-01","filename":"../tests/todos.rem","lineno":14,"d":1,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-01","priority":5000,"body":"First on 2025-08-01"},
|
||||
{"date":"2022-08-01","filename":"../tests/todos.rem","lineno":15,"d":1,"m":8,"is_todo":1,"complete_through":"2022-07-31","priority":5000,"body":"Second on 2022-08-01"},
|
||||
{"date":"2023-08-01","filename":"../tests/todos.rem","lineno":16,"d":1,"m":8,"is_todo":1,"complete_through":"2022-08-01","priority":5000,"body":"Third on 2023-08-01"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":17,"d":20,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-20","priority":5000,"body":"Fourth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":18,"d":13,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-13","priority":5000,"body":"Fifth today"},
|
||||
{"date":"2025-08-06","filename":"../tests/todos.rem","lineno":19,"d":6,"m":8,"y":2025,"is_todo":1,"delta":7,"trigbase":"2025-08-06","priority":5000,"body":"Sixth on 2025-08-06"},
|
||||
{"date":"2025-08-20","filename":"../tests/todos.rem","lineno":21,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-13","delta":7,"priority":5000,"body":"Eighth on 2025-08-20"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":22,"wd":["Wednesday"],"is_todo":1,"complete_through":"2025-08-12","delta":7,"priority":5000,"body":"Ninth today"},
|
||||
{"date":"2025-08-13","filename":"../tests/todos.rem","lineno":25,"d":13,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-13","max_overdue":3,"priority":5000,"body":"Yup today"},
|
||||
{"date":"2025-08-12","filename":"../tests/todos.rem","lineno":26,"d":12,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-12","max_overdue":3,"priority":5000,"body":"Yup2 yesterday"},
|
||||
{"date":"2025-08-11","filename":"../tests/todos.rem","lineno":27,"d":11,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-11","max_overdue":3,"priority":5000,"body":"Yup3 on 2025-08-11"},
|
||||
{"date":"2025-08-10","filename":"../tests/todos.rem","lineno":28,"d":10,"m":8,"y":2025,"is_todo":1,"trigbase":"2025-08-10","max_overdue":3,"priority":5000,"body":"Yup4 on 2025-08-10"}
|
||||
]
|
||||
Testing proper redirection of RUN stdout in JSON mode... here's stdout
|
||||
[
|
||||
@@ -39838,6 +40023,7 @@ fib(24) = 46368
|
||||
-stdin-(13): `-': Maximum expression complexity exceeded
|
||||
-stdin-(3): [#0] In function `fib'
|
||||
[remaining call frames omitted]
|
||||
DynBuf Mallocs: 3 mallocs; 192 bytes
|
||||
Variable hash table statistics:
|
||||
Entries: 0; Buckets: 7; Non-empty Buckets: 0
|
||||
Maxlen: 0; Minlen: 0; Avglen: 0.000; Stddev: 0.000; Avg nonempty len: 0.000
|
||||
@@ -39863,6 +40049,7 @@ Total expression node evaluations: 3999940
|
||||
a = 493; hex(a) = 1ED
|
||||
hex(-1) = FFFFFFFF
|
||||
a = 32767; hex(a) = 7FFF
|
||||
DynBuf Mallocs: 5 mallocs; 320 bytes
|
||||
Variable hash table statistics:
|
||||
Entries: 1; Buckets: 7; Non-empty Buckets: 1
|
||||
Maxlen: 1; Minlen: 0; Avglen: 0.143; Stddev: 0.350; Avg nonempty len: 1.000
|
||||
@@ -39918,3 +40105,176 @@ devnull test b
|
||||
|
||||
-stdin-(2): `/': Division by zero
|
||||
No reminders.
|
||||
[
|
||||
{"banner":"Reminders for Wednesday, 1st October, 2025:"},
|
||||
{"date":"2025-10-01","filename":"-stdin-","lineno":3,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst NOT set 2025-10-01"},
|
||||
{"date":"2025-10-01","filename":"-stdin-","lineno":4,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst IS set 2025-10-01"},
|
||||
{"date":"2025-10-01","filename":"-stdin-","lineno":5,"nonconst_expr":1,"d":1,"m":10,"y":2025,"is_todo":0,"trigbase":"2025-10-01","priority":5000,"body":"Nonconst IS set"}
|
||||
]
|
||||
# Nonconst-expr in trigger
|
||||
set $ParseUntriggered 1
|
||||
set a nonconst(1)
|
||||
#!P: Expired: REM 2025-10-01 MSG Nonconst NOT set [today()]
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
#!P: or a relative SCANFROM clause
|
||||
REM 2025 Oct [a] MSG Nonconst IS set [today()]
|
||||
#!P: Next line may have expired, but contains non-constant expression
|
||||
#!P: or a relative SCANFROM clause
|
||||
REM 2025 Oct [a] MSG Nonconst IS set
|
||||
#!P: Next line has expired, but contains expression... please verify
|
||||
#!P: Expired: REM 2025 Oct [1] MSG Expr but not nonconst [today()]
|
||||
#!P: Expired: REM 2025-10-01 MSG No expr seen [1+2]
|
||||
# translations
|
||||
{"LANGID":"en"}
|
||||
# rem2ps begin
|
||||
January 2026 31 4 0
|
||||
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
|
||||
December 31
|
||||
February 28
|
||||
# rem2ps end
|
||||
# translations
|
||||
{"LANGID":"en"}
|
||||
# rem2ps begin
|
||||
January 2026 31 4 0
|
||||
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
|
||||
December 31
|
||||
February 28
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
-stdin-(2): `/': Division by zero
|
||||
# rem2ps end
|
||||
+----------------------------------------------------------------------------+
|
||||
| January 2020‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| Sunday‎ | Monday‎ | Tuesday‎ |Wednesday‎ | Thursday‎ | Friday‎ | Saturday‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| | | |1 ‎ |2 ‎ |3 ‎ |4 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|5 ‎ |6 ‎ |7 ‎ |8 ‎ |9 ‎ |10 ‎ |11 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|12 ‎ |13 ‎ |14 ‎ |15 ‎ |16 ‎ |17 ‎ |18 ‎ |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ |[38;2;255;0;0m]8;;https://dianne.skoll.ca\Hello,]8;;\[0m‎ |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky!]8;;\‎ |]8;;https://dianne.skoll.ca\linky!]8;;\‎ |]8;;https://dianne.skoll.ca\linky!]8;;\‎ |[38;2;255;0;0m]8;;https://dianne.skoll.ca\linky!]8;;\[0m‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|19 ‎ |20 ‎ |21 ‎ |22 ‎ |23 ‎ |24 ‎ |25 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|26 ‎ |27 ‎ |28 ‎ |29 ‎ |30 ‎ |31 ‎ | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
+----------------------------------------------------------------------------+
|
||||
| January 2020‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| Sunday‎ | Monday‎ | Tuesday‎ |Wednesday‎ | Thursday‎ | Friday‎ | Saturday‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| | | |1 ‎ |2 ‎ |3 ‎ |4 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|5 ‎ |6 ‎ |7 ‎ |8 ‎ |9 ‎ |10 ‎ |11 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|12 ‎ |13 ‎ |14 ‎ |15 ‎ |16 ‎ |17 ‎ |18 ‎ |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 1!]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 2!]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 3!]8;;\‎ | | | |
|
||||
| | | |[38;2;255;0;0m]8;;https://dianne.skoll.ca\Hello,]8;;\[0m‎ | | | |
|
||||
| | | |[38;2;255;0;0m]8;;https://dianne.skoll.ca\linky 4!]8;;\[0m‎ | | | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|19 ‎ |20 ‎ |21 ‎ |22 ‎ |23 ‎ |24 ‎ |25 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|26 ‎ |27 ‎ |28 ‎ |29 ‎ |30 ‎ |31 ‎ | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
+----------------------------------------------------------------------------+
|
||||
| January 2020‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| Sunday‎ | Monday‎ | Tuesday‎ |Wednesday‎ | Thursday‎ | Friday‎ | Saturday‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
| | | |1 ‎ |2 ‎ |3 ‎ |4 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|5 ‎ |6 ‎ |7 ‎ |8 ‎ |9 ‎ |10 ‎ |11 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|12 ‎ |13 ‎ |14 ‎ |15 ‎ |16 ‎ |17 ‎ |18 ‎ |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 1!]8;;\‎ | | | |
|
||||
| | | | | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 2!]8;;\‎ | | | |
|
||||
| | | | | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\Hello,]8;;\‎ | | | |
|
||||
| | | |]8;;https://dianne.skoll.ca\linky 3!]8;;\‎ | | | |
|
||||
| | | | | | | |
|
||||
| | | |[38;2;255;0;0m]8;;https://dianne.skoll.ca\Hello,]8;;\[0m‎ | | | |
|
||||
| | | |[38;2;255;0;0m]8;;https://dianne.skoll.ca\linky 4!]8;;\[0m‎ | | | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|19 ‎ |20 ‎ |21 ‎ |22 ‎ |23 ‎ |24 ‎ |25 ‎ |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
|26 ‎ |27 ‎ |28 ‎ |29 ‎ |30 ‎ |31 ‎ | |
|
||||
+----------+----------+----------+----------+----------+----------+----------+
|
||||
# translations
|
||||
{"LANGID":"en"}
|
||||
# rem2ps2 begin
|
||||
February 2026 28 0 0
|
||||
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
|
||||
January 31
|
||||
March 31
|
||||
{"date":"2026-02-01","filename":"../tests/shaded.rem","lineno":10,"passthru":"SHADE","wd":["Sunday"],"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":255,"body":"0 255 255"}
|
||||
{"date":"2026-02-02","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-03","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-04","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
|
||||
{"date":"2026-02-05","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-06","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-07","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-08","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
{"date":"2026-02-09","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-10","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-11","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
|
||||
{"date":"2026-02-12","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
{"date":"2026-02-13","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-14","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-15","filename":"../tests/shaded.rem","lineno":3,"passthru":"SHADE","d":15,"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":0,"body":"0 255 0"}
|
||||
{"date":"2026-02-16","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
{"date":"2026-02-17","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-18","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
|
||||
{"date":"2026-02-19","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-20","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
{"date":"2026-02-21","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-22","filename":"../tests/shaded.rem","lineno":10,"passthru":"SHADE","wd":["Sunday"],"is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":255,"b":255,"body":"0 255 255"}
|
||||
{"date":"2026-02-23","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-24","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
{"date":"2026-02-25","filename":"../tests/shaded.rem","lineno":1,"passthru":"SHADE","wd":["Wednesday"],"is_todo":0,"priority":5000,"r":255,"g":0,"b":0,"body":"255 0 0"}
|
||||
{"date":"2026-02-26","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-27","filename":"../tests/shaded.rem","lineno":14,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":255,"g":255,"b":0,"body":"255 255 0"}
|
||||
{"date":"2026-02-28","filename":"../tests/shaded.rem","lineno":6,"passthru":"SHADE","is_todo":0,"priority":5000,"if_depth":1,"r":0,"g":0,"b":255,"body":"0 0 255"}
|
||||
# rem2ps2 end
|
||||
No reminders.
|
||||
../tests/test-pushpop2.rem(1): POP-VARS at ../tests/test-pushpop2.rem:1 matches PUSH-VARS in different file: ../tests/test-pushpop1.rem:3
|
||||
../tests/test-pushpop2.rem(2): POP-FUNCS at ../tests/test-pushpop2.rem:2 matches PUSH-FUNCS in different file: ../tests/test-pushpop1.rem:2
|
||||
../tests/test-pushpop2.rem(3): POP-OMIT-CONTEXT at ../tests/test-pushpop2.rem:3 matches PUSH-OMIT-CONTEXT in different file: ../tests/test-pushpop1.rem:1
|
||||
No reminders.
|
||||
|
||||
145
tests/test.rem
145
tests/test.rem
@@ -1589,9 +1589,11 @@ dump -c a
|
||||
set a eval("1 +")
|
||||
set a eval("1/0")
|
||||
set a eval("1 / / 2")
|
||||
set a eval("1 / # 2")
|
||||
set a catch(eval("1 +"), 33)
|
||||
set a catch(eval("1/0"), 34)
|
||||
set a catch(eval("1 / / 2"), 35)
|
||||
set a catch(eval("1 / # 2"), 35)
|
||||
|
||||
# Ensure RUN is disabled in eval
|
||||
set a shell("echo foo")
|
||||
@@ -1765,7 +1767,150 @@ set a mbchar(0)
|
||||
set a mbchar(0, 120)
|
||||
set a mbchar(120, 0)
|
||||
|
||||
# Make sure trailing space doesn't cause a diagnostic.
|
||||
set a "foo"
|
||||
|
||||
# Hebrew dates
|
||||
|
||||
SET a hebdate(1, "Tishrey")
|
||||
SET a hebdate(1, "Tishri")
|
||||
SET a hebdate(1, "Tishrei")
|
||||
SET a hebdate(1, "תשרי")
|
||||
|
||||
SET a hebdate(1, "Cheshvan")
|
||||
SET a hebdate(1, "Kheshvan")
|
||||
SET a hebdate(1, "Heshvan")
|
||||
SET a hebdate(1, "חשוון")
|
||||
|
||||
SET a hebdate(1, "Kislev")
|
||||
SET a hebdate(1, "כסלו")
|
||||
|
||||
SET a hebdate(1, "Tevet")
|
||||
SET a hebdate(1, "טבת")
|
||||
|
||||
SET a hebdate(1, "Shvat")
|
||||
SET a hebdate(1, "Shevat")
|
||||
SET a hebdate(1, "שבט")
|
||||
|
||||
SET a hebdate(1, "Adar A")
|
||||
SET a hebdate(1, "Adar 1")
|
||||
SET a hebdate(1, "Adar I")
|
||||
SET a hebdate(1, "אדר א'")
|
||||
SET a hebdate(1, "אדר א")
|
||||
SET a hebdate(1, "אדר 1")
|
||||
SET a hebdate(1, "אדר I")
|
||||
|
||||
SET a hebdate(1, "Adar B")
|
||||
SET a hebdate(1, "Adar 2")
|
||||
SET a hebdate(1, "Adar II")
|
||||
SET a hebdate(1, "אדר ב'")
|
||||
SET a hebdate(1, "אדר ב")
|
||||
SET a hebdate(1, "אדר 2")
|
||||
SET a hebdate(1, "אדר II")
|
||||
|
||||
SET a hebdate(1, "Nisan")
|
||||
SET a hebdate(1, "ניסן")
|
||||
|
||||
SET a hebdate(1, "Iyar")
|
||||
SET a hebdate(1, "Iyyar")
|
||||
SET a hebdate(1, "אייר")
|
||||
|
||||
SET a hebdate(1, "Sivan")
|
||||
SET a hebdate(1, "סיון")
|
||||
|
||||
SET a hebdate(1, "Tamuz")
|
||||
SET a hebdate(1, "Tammuz")
|
||||
SET a hebdate(1, "תמוז")
|
||||
|
||||
SET a hebdate(1, "Av")
|
||||
SET a hebdate(1, "אב")
|
||||
|
||||
SET a hebdate(1, "Elul")
|
||||
SET a hebdate(1, "אלול")
|
||||
|
||||
SET a hebdate(1, "Adar")
|
||||
SET a hebdate(1, "אדר")
|
||||
|
||||
set a hebmon('1991-09-09')
|
||||
set a ivritmon('1991-09-09')
|
||||
|
||||
set a hebmon('1991-10-09')
|
||||
set a ivritmon('1991-10-09')
|
||||
|
||||
set a hebmon('1991-11-08')
|
||||
set a ivritmon('1991-11-08')
|
||||
|
||||
set a hebmon('1991-12-08')
|
||||
set a ivritmon('1991-12-08')
|
||||
|
||||
set a hebmon('1992-01-06')
|
||||
set a ivritmon('1992-01-06')
|
||||
|
||||
set a hebmon('1992-02-05')
|
||||
set a ivritmon('1992-02-05')
|
||||
|
||||
set a hebmon('1992-03-06')
|
||||
set a ivritmon('1992-03-06')
|
||||
|
||||
set a hebmon('1991-03-16')
|
||||
set a ivritmon('1991-03-16')
|
||||
|
||||
set a hebmon('1991-04-15')
|
||||
set a ivritmon('1991-04-15')
|
||||
|
||||
set a hebmon('1991-05-14')
|
||||
set a ivritmon('1991-05-14')
|
||||
|
||||
set a hebmon('1991-06-13')
|
||||
set a ivritmon('1991-06-13')
|
||||
|
||||
set a hebmon('1991-07-12')
|
||||
set a ivritmon('1991-07-12')
|
||||
|
||||
set a hebmon('1991-08-11')
|
||||
set a ivritmon('1991-08-11')
|
||||
|
||||
# mbpad
|
||||
|
||||
set a mbpad("foo", "bar", 3)
|
||||
set a mbpad("foo", "bar", 3, 1)
|
||||
set a mbpad("foo", "bar", 8)
|
||||
set a mbpad("foo", "bar", 8, 1)
|
||||
set a mbpad("foo", "🙂💩", 3)
|
||||
set a mbpad("foo", "🙂💩", 3, 1)
|
||||
set a mbpad("foo", "🙂💩", 8)
|
||||
set a mbpad("foo", "🙂💩", 8, 1)
|
||||
set bad char(255)
|
||||
set a mbpad("foo", bad, 3)
|
||||
set a mbpad("foo", bad, 3, 1)
|
||||
set a mbpad("foo", bad, 8)
|
||||
set a mbpad("foo", bad, 8, 1)
|
||||
set a mbpad(bad, "bar", 0)
|
||||
set a mbpad(bad, "bar", 0, 1)
|
||||
set a mbpad(bad, "bar", 8)
|
||||
set a mbpad(bad, "bar", 8, 1)
|
||||
|
||||
DEBUG -x
|
||||
SET $TerminalHyperlinks 1
|
||||
REM INFO "Url: https://dianne.skoll.ca" MSG Hello, linky!
|
||||
REM INFO "Url: https://dianne.skoll.ca" MSF Hello, linky!
|
||||
REM INFO "Url: https://dianne.skoll.ca" SPECIAL COLOR 255 0 0 Hello, linky!
|
||||
|
||||
# Bad values for system variables
|
||||
SET $Latitude "Cabbage"
|
||||
SET $Longitude "Carrots"
|
||||
SET $TimeSep "FOO"
|
||||
SET $DateSep "BAR"
|
||||
SET $DefaultColor "My oh my, what lovely eyes!"
|
||||
|
||||
# mbupper and mblower
|
||||
DEBUG +x
|
||||
SET a mbupper("öÖçÇéôñÑÉÊ")
|
||||
SET a mblower("öÖçÇéôñÑÉÊ")
|
||||
SET a upper("öÖçÇéôñÑÉÊ")
|
||||
SET a lower("öÖçÇéôñÑÉÊ")
|
||||
DEBUG -x
|
||||
|
||||
# Don't want Remind to queue reminders
|
||||
EXIT
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@ REM TODO COMPLETE-THROUGH 2025-08-06 6 Aug 2025 +7 MSG %"Seventh%" %l
|
||||
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-13 MSG %"Eighth%" %l
|
||||
REM TODO Wed +7 COMPLETE-THROUGH 2025-08-12 MSG %"Ninth%" %l
|
||||
|
||||
REM TODO 1 Aug 2025 MSG %"First%" %l
|
||||
REM TODO 1 Aug COMPLETED-THROUGH 2022-07-31 MSG %"Second%" %l
|
||||
REM TODO 1 Aug COMPLETED-THROUGH 2022-08-01 MSG %"Third%" %l
|
||||
REM TODO 20 Aug 2025 +7 MSG %"Fourth%" %l
|
||||
REM TODO 13 Aug 2025 +7 MSG %"Fifth%" %l
|
||||
REM TODO 6 Aug 2025 +7 MSG %"Sixth%" %l
|
||||
REM TODO COMPLETED-THROUGH 2025-08-06 6 Aug 2025 +7 MSG %"Seventh%" %l
|
||||
REM TODO Wed +7 COMPLETED-THROUGH 2025-08-13 MSG %"Eighth%" %l
|
||||
REM TODO Wed +7 COMPLETED-THROUGH 2025-08-12 MSG %"Ninth%" %l
|
||||
|
||||
# Test MAX-OVERDUE
|
||||
REM TODO 2025-08-13 MAX-OVERDUE 3 MSG %"Yup%" %l
|
||||
REM TODO 2025-08-12 MAX-OVERDUE 3 MSG %"Yup2%" %l
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# Use the output to verify your translations.
|
||||
#
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2025 Dianne Skoll
|
||||
# Copyright (C) 1992-2026 Dianne Skoll
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
10
tests/tz.cmp
10
tests/tz.cmp
@@ -54,26 +54,18 @@ evaltrig("Wednesday at 23:00 TZ Europe/Amsterdam") => 2025-09-03@17:00
|
||||
evaltrig("Wednesday at 23:00 TZ America/Los_Angele"...) => 2025-09-04@02:00
|
||||
evaltrig("Wednesday TZ Europe/Amsterdam") => TZ specified for non-timed reminder
|
||||
-stdin-(11): evaltrig(): TZ specified for non-timed reminder
|
||||
trig("Mon at 00:00 TZ Australia/Sydney", "Tue at 00:00 TZ America/Toronto", "Wed at 00:00 TZ Europe/Amsterdam", "Thu at 00:00 TZ America/Los_Angeles", "Fri at 00:00 TZ Australia/Sydney", "Sat at 00:00 TZ Australia/Sydney", "Sun at 00:00 TZ Australia/Sydney", "at 14:42") => -stdin-(14:21): Trig(tz_adj Australia/Sydney) = Sunday, 31 August, 2025 AT 10:00
|
||||
trig("Mon at 00:00 TZ Australia/Sydney", "Tue at 00:00 TZ America/Toronto", "Wed at 00:00 TZ Europe/Amsterdam", "Thu at 00:00 TZ America/Los_Angeles", "Fri at 00:00 TZ Australia/Sydney", "Sat at 00:00 TZ Australia/Sydney", "Sun at 00:00 TZ Australia/Sydney", "at 14:42") => -stdin-(14:21): Trig = Monday, 8 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Sunday, 7 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig = Monday, 8 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Sunday, 7 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig(tz_adj America/Toronto) = Tuesday, 2 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig = Tuesday, 2 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj America/Toronto) = Tuesday, 2 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Europe/Amsterdam) = Tuesday, 2 September, 2025 AT 18:00
|
||||
-stdin-(14:21): Trig = Wednesday, 3 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Europe/Amsterdam) = Tuesday, 2 September, 2025 AT 18:00
|
||||
-stdin-(14:21): Trig(tz_adj America/Los_Angeles) = Thursday, 4 September, 2025 AT 03:00
|
||||
-stdin-(14:21): Trig = Thursday, 4 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj America/Los_Angeles) = Thursday, 4 September, 2025 AT 03:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Thursday, 4 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig = Friday, 5 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Thursday, 4 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Friday, 5 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig = Saturday, 6 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Friday, 5 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Saturday, 6 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig = Sunday, 7 September, 2025 AT 00:00
|
||||
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Saturday, 6 September, 2025 AT 10:00
|
||||
-stdin-(14:21): Trig = Monday, 1 September, 2025 AT 14:42
|
||||
|
||||
@@ -26,7 +26,9 @@ set a utctolocal('2050-01-01@01:00')
|
||||
set a localtoutc('2050-12-31@23:44')
|
||||
|
||||
set a localtoutc('2050-03-13@00:00')
|
||||
set a localtoutc('2050-03-13@02:00')
|
||||
# This next one fails on MUSL, so it's commented out.
|
||||
# We expect 2050-03-13@07:00 but MUSL gives 2050-03-13@06:00
|
||||
#set a localtoutc('2050-03-13@02:00')
|
||||
set a localtoutc('2050-11-06@00:00')
|
||||
set a localtoutc('2050-11-06@02:00')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Makefile.in for installing WWW server calendar scripts
|
||||
# This file is part of REMIND.
|
||||
# Copyright (C) 1992-2025 by Dianne Skoll
|
||||
# Copyright (C) 1992-2026 by Dianne Skoll
|
||||
|
||||
# The complete path to where the scripts actually live, as seen by
|
||||
# the UNIX operating system.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user