Compare commits

...

67 Commits

Author SHA1 Message Date
Dianne Skoll
948548c73f Update docs. 2022-03-12 12:57:24 -05:00
Dianne Skoll
7495ae1e05 Uniquify lines in error message to avoid overwhelming. 2022-03-12 11:32:26 -05:00
Dianne Skoll
51ae17bd0a Improve the way TkRemind handles errors in the reminder script. 2022-03-12 11:23:54 -05:00
Dianne Skoll
61d665ef7d Turn a bunch of Eprint calls into Wprint calls to indicate warnings instead of errors. 2022-03-12 10:27:58 -05:00
Dianne Skoll
5aaf19ffdb Send LRM sequence in PrintLeft and PrintCentered. 2022-03-12 09:39:28 -05:00
Dianne Skoll
2eb672e380 Add LRM marks in UTF-8 locales. 2022-03-12 09:33:16 -05:00
Dianne Skoll
4a59bf686b Check for langinfo.h 2022-03-12 09:26:41 -05:00
Dianne Skoll
f98ab6f686 Document special behavior of "-cu" 2022-03-11 23:31:04 -05:00
Dianne Skoll
3600cd95cd Add LRM char if we're using Unicode drawing chars 2022-03-11 23:28:03 -05:00
Dianne Skoll
f8bd79fbb2 Fix bug in calendar formatting 2022-03-11 23:18:38 -05:00
Dianne Skoll
4c403047eb Tweaks 2022-03-11 23:10:37 -05:00
Dianne Skoll
25009de417 Update defs.rem 2022-03-11 23:06:24 -05:00
Dianne Skoll
c4588654ec Clean up cruft in defs.rem 2022-03-11 23:02:37 -05:00
Dianne Skoll
c1e5279272 Tweak meeting reminder. 2022-03-11 22:55:51 -05:00
Dianne Skoll
cda8396690 Update copyright date. 2022-03-11 22:52:29 -05:00
Dianne Skoll
c0f79d1e69 Bump mininum remind version. 2022-03-11 22:52:05 -05:00
Dianne Skoll
375a0fb7a2 Update examples to use syntactic sugar. 2022-03-11 22:51:22 -05:00
Dianne Skoll
2069114ef1 More wrap testing. 2022-03-11 22:39:29 -05:00
Dianne Skoll
f6d9e8724d Make test to test wrapping of wide chars 2022-03-11 22:37:40 -05:00
Dianne Skoll
8e55438200 Minor tweak 2022-03-11 22:36:52 -05:00
Dianne Skoll
1ca6feb112 Fix formatting bug when printing calendar with wide spaces. 2022-03-11 22:31:40 -05:00
Dianne Skoll
732ce8283f Update docs. 2022-03-11 21:47:50 -05:00
Dianne Skoll
122bd3e07e Add comment 2022-03-11 21:27:33 -05:00
Dianne Skoll
0ac5cbb837 Properly cope with two of the same moon phase in a given month. 2022-03-11 21:26:22 -05:00
Dianne Skoll
7f3d4812a8 Add Lastday and Lastworkday syntactic sugar 2022-03-11 21:11:16 -05:00
Dianne Skoll
e1fa11c94c Add the First/Second/Third/Fourth/Last syntactic sugar and the
~N/~~N forms of "back"
2022-03-11 20:53:52 -05:00
Dianne Skoll
c06c65acf1 Properly apply options in the right order. 2022-03-11 19:57:20 -05:00
Dianne Skoll
a84fa0bc8f Add canned "Light Theme" and "Dark Theme" buttons. 2022-03-11 19:46:40 -05:00
Dianne Skoll
054648e02b More display tweakage. 2022-03-11 14:35:39 -05:00
Dianne Skoll
9548041334 Tweak display; make keyboard traversal better. 2022-03-11 14:29:07 -05:00
Dianne Skoll
da306f2900 Tweak wording 2022-03-11 13:46:43 -05:00
Dianne Skoll
26587aea02 Give more control over TkRemind colors. 2022-03-11 13:38:11 -05:00
Dianne Skoll
adc86e0f00 Allow setting of "Today" highlight color. 2022-03-10 11:53:00 -05:00
Dianne Skoll
a9ed5f075e Document that trig() and SATISFY should not be mixed. 2022-03-05 11:35:55 -05:00
Dianne Skoll
21e30c980e Test multiple-argument version of trig() 2022-03-04 17:29:23 -05:00
Dianne Skoll
a657b2e55a Update man page. 2022-03-04 15:40:39 -05:00
Dianne Skoll
ff8c55b8b6 Rename "wouldtrig" to just "trig" 2022-03-04 15:38:07 -05:00
Dianne Skoll
eb36c5bca0 Allow wouldtrig() to take an arbitrary number of args; document it. 2022-03-04 15:24:52 -05:00
Dianne Skoll
89173ce1ee Allow logical operators to accept any non-string operands.
Make wouldtrig() return a date.
2022-03-04 14:59:17 -05:00
Dianne Skoll
5d115ba3e3 Document actual behavior of IF command. 2022-03-04 14:58:49 -05:00
Dianne Skoll
7e3adeb9c9 Make wouldtrig return the trigger date (as an INT, coercable to a date)
Update man page.
2022-03-04 12:28:13 -05:00
Dianne Skoll
080cda86fa Document new || and && return values. 2022-03-04 12:12:49 -05:00
Dianne Skoll
6274cbad52 Make || return first true val and && return last val if first val is true. 2022-03-04 12:11:25 -05:00
Dianne Skoll
85c4ad821d Add note about Remind lacking short-circuit logical operators. 2022-03-04 11:45:37 -05:00
Dianne Skoll
b758a2fea8 Tweak formatting. 2022-03-04 11:40:46 -05:00
Dianne Skoll
6619cc7ca4 Add wouldtrig tests. 2022-03-04 11:33:03 -05:00
Dianne Skoll
961f7a8a62 Document wouldtrig() 2022-03-04 11:21:14 -05:00
Dianne Skoll
905287901f Add zero-argument form of wouldtrig. 2022-03-04 11:16:33 -05:00
Dianne Skoll
669be7bf57 Add wouldtrig function. 2022-03-04 11:00:09 -05:00
Dianne Skoll
9b8eb2dc4c Support calling EvalExpr recursively 2022-03-04 10:49:20 -05:00
Dianne Skoll
00ab7b196d Set default of $MaxSatIter to 1000 instead of 150.
Computers are much faster than when Remind was first written;
we can handle a much higher limit.
2022-03-04 08:18:49 -05:00
Dianne Skoll
f616be4bdd Add comment about operator precedence. 2022-03-04 08:16:58 -05:00
Dianne Skoll
8ae9ce8523 Tweak man page. 2022-03-02 15:30:56 -05:00
Dianne Skoll
6d2bbbd7e2 Another diagnostic message. 2022-03-02 15:25:27 -05:00
Dianne Skoll
1453be83b2 Add more diagnostics for bad UNTIL dates. 2022-03-02 15:17:03 -05:00
Dianne Skoll
8659131be2 Use proper keyword in error message. 2022-03-02 14:43:11 -05:00
Dianne Skoll
0276ce322d Diagnose if UNTIL is earlier than start date unless there is a nonconst expr 2022-03-02 09:11:01 -05:00
Dianne Skoll
b36c99a34b Move successful exit to one spot. 2022-03-02 09:01:33 -05:00
Dianne Skoll
ad575f1485 Proper check for overfull box. 2022-03-01 16:15:00 -05:00
Dianne Skoll
a9162f1472 Proper calculation for warning of overfull box. 2022-03-01 16:12:55 -05:00
Dianne Skoll
221e2554a9 Prep for 03.04.01 release. 2022-02-23 11:09:39 -05:00
Dianne Skoll
04ec6c3695 Update TodayDay, TodayMonth and TodayYear in Initialize, in case date has rolled over 2022-02-15 10:04:30 -05:00
Dianne Skoll
b1594980fc Add --disable-perl-build-artifacts flag to configure. 2022-02-13 10:42:50 -05:00
Dianne Skoll
024a8ef38d Double-check that chosen font size for small calendars won't overflow box. 2022-02-13 10:33:21 -05:00
Dianne Skoll
b281051421 Don't overflow small calendar box. 2022-02-12 23:30:08 -05:00
Dianne Skoll
aa1b275b51 Support INSTALL_BASE 2022-02-11 10:55:59 -05:00
Dianne Skoll
c22ca68857 Support INSTALL_BASE env var 2022-02-11 10:39:31 -05:00
34 changed files with 1624 additions and 625 deletions

View File

@@ -20,7 +20,7 @@ install:
@echo "" @echo ""
@$(MAKE) -C src install @$(MAKE) -C src install
@$(MAKE) -C rem2html install @$(MAKE) -C rem2html install
@$(MAKE) -C rem2pdf -f Makefile.top install @$(MAKE) -C rem2pdf -f Makefile.top install INSTALL_BASE=$(INSTALL_BASE)
clean: clean:
find . -name '*~' -exec rm {} \; find . -name '*~' -exec rm {} \;
-$(MAKE) -C src clean -$(MAKE) -C src clean

29
configure vendored
View File

@@ -622,6 +622,7 @@ ac_includes_default="\
ac_header_list= ac_header_list=
ac_subst_vars='LTLIBOBJS ac_subst_vars='LTLIBOBJS
LIBOBJS LIBOBJS
PERLARTIFACTS
VERSION VERSION
EGREP EGREP
GREP GREP
@@ -681,6 +682,7 @@ SHELL'
ac_subst_files='' ac_subst_files=''
ac_user_opts=' ac_user_opts='
enable_option_checking enable_option_checking
enable_perl_build_artifacts
' '
ac_precious_vars='build_alias ac_precious_vars='build_alias
host_alias host_alias
@@ -1305,6 +1307,13 @@ if test -n "$ac_init_help"; then
cat <<\_ACEOF cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-perl-build-artifacts
Disable perllocal.pod and .packlist generation
Some influential environment variables: Some influential environment variables:
CC C compiler command CC C compiler command
CFLAGS C compiler flags CFLAGS C compiler flags
@@ -2292,6 +2301,15 @@ EOF
ac_config_headers="$ac_config_headers src/config.h" ac_config_headers="$ac_config_headers src/config.h"
# Check whether --enable-perl-build-artifacts was given.
if test "${enable_perl_build_artifacts+set}" = set; then :
enableval=$enable_perl_build_artifacts; ac_cv_perlartifacts=$enableval
else
ac_cv_perlartifacts=yes
fi
ac_ext=c ac_ext=c
ac_cpp='$CPP $CPPFLAGS' ac_cpp='$CPP $CPPFLAGS'
@@ -3799,7 +3817,7 @@ _ACEOF
for ac_header in sys/types.h sys/file.h glob.h wctype.h locale.h for ac_header in sys/types.h sys/file.h glob.h wctype.h locale.h langinfo.h
do : do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -3958,6 +3976,12 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes" CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
fi fi
if test "$ac_cv_perlartifacts" = "yes" ; then
PERLARTIFACTS=
else
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
fi
for ac_func in setenv unsetenv glob mbstowcs setlocale initgroups for ac_func in setenv unsetenv glob mbstowcs setlocale initgroups
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -3970,7 +3994,8 @@ _ACEOF
fi fi
done done
VERSION=03.04.00 VERSION=03.04.02
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf" ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf"

View File

@@ -13,6 +13,11 @@ cat <<'EOF'
EOF EOF
AC_CONFIG_HEADER(src/config.h) AC_CONFIG_HEADER(src/config.h)
AC_ARG_ENABLE(perl-build-artifacts,
[ --disable-perl-build-artifacts
Disable perllocal.pod and .packlist generation], ac_cv_perlartifacts=$enableval, ac_cv_perlartifacts=yes)
AH_BOTTOM([#include <custom.h>]) AH_BOTTOM([#include <custom.h>])
dnl Checks for programs. dnl Checks for programs.
@@ -32,7 +37,7 @@ AC_CHECK_SIZEOF(unsigned int)
AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long)
dnl Checks for header files. dnl Checks for header files.
AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h) AC_CHECK_HEADERS(sys/types.h sys/file.h glob.h wctype.h locale.h langinfo.h)
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_STRUCT_TM AC_STRUCT_TM
@@ -45,9 +50,16 @@ if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes" CFLAGS="$CFLAGS -Wall -Wextra -Wstrict-prototypes"
fi fi
if test "$ac_cv_perlartifacts" = "yes" ; then
PERLARTIFACTS=
else
PERLARTIFACTS='NO_PACKLIST=1 NO_PERLLOCAL=1'
fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups) AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale initgroups)
VERSION=03.04.00 VERSION=03.04.02
AC_SUBST(VERSION) AC_SUBST(VERSION)
AC_SUBST(PERL) AC_SUBST(PERL)
AC_SUBST(PERLARTIFACTS)
AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf) AC_OUTPUT(src/Makefile www/Makefile src/version.h rem2html/Makefile rem2pdf/Makefile.PL rem2pdf/Makefile.top rem2pdf/bin/rem2pdf)
chmod a+x rem2pdf/bin/rem2pdf chmod a+x rem2pdf/bin/rem2pdf

View File

@@ -1,5 +1,91 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 3.4 Patch 2 - 2022-??-??
- NEW FEATURE: remind: Add syntactic sugar to simplify some common
types of reminders. See "SYNTACTIC SUGAR FOR REM" in the remind
man page. Based on suggestions from Ian! D. Allen.
- CHANGE: examples/defs.rem: The examples file has been updated to use
the newer syntactic sugar.
- NEW FEATURE: remind: Add the "trig" function to allow more
expressiveness when creating triggers. See man page for details.
- IMPROVEMENT: tkremind: Tweak the calendar display; improve ability to
customize colors, including supplying two built-in themes. Based on
patch and suggestion from Paulo (last name unknown).
- IMPROVEMENT: tkremind: TkRemind handles errors in reminders scripts
much more unobtrusively. Instead of popping up a modal dialog box
with almost-unreadable error output, it discreetly notifies you of
errors with a button that lets you view the specific error messages
in a more readable format.
- CHANGE: remind: Increase $MaxSatIter default to 1000 instead of 150.
Computers are much faster than when I first wrote remind and they
can handle this higher limit easily. The higher limit also enables
certain reasonable reminders that failed in the past because of the
low SATISFY iteration limit.
- CHANGE: remind: The "||" operator now returns the value of the first
non-zero operand rather than just returning 1 or 0. Similarly, "&&"
returns 0 if either operand is false or the value of the last
operand if both operands are true.
NOTE POTENTIAL INCOMPATIBILITY: Remind scripts that depend on ||
and && always returning exactly one of 1 or 0 may need
adjustment.
- CHANGE: The || and && operators can accept any non-STRING type as long
as both operands have the same type. The "false" values are defined
as follows; true values are any other value:
INT: 0
TIME: 00:00
DATE: '1990-01-01' (the Remind epoch)
DATETIME: '1990-01-01@00:00' (the Remind epoch)
- IMPROVEMENT: remind: Issue diagnostics if an UNTIL or THROUGH date
is earlier than any possible trigger date, as well as an UNTIL date
with a fully-specified date and no repeat ("*N"). Suggestion from
Ian! D. Allen.
- BUG FIX: tkremind: If the same moon phase appeared twice in a month,
TkRemind would not display the first occurrence correctly. This has
been fixed.
- BUG FIX: remind: The IF command documentation didn't reflect how it
actually worked; now it does.
- BUG FIX: remind: Use correct UNTIL/THROUGH keyword in error message.
- BUG FIX: rem2pdf: Correct the calculation that warns about an over-full
calendar box. Problem noted by Jonathan Kamens.
- BUG FIX: remind: The "remind -c" output would sometimes be incorrect if
scripts with double-wide characters were used. This has been fixed.
- BUG FIX: remind: The "remind -c" output would sometimes be incorrect
if right-to-left scripts were used in reminders. This has been fixed.
* VERSION 3.4 Patch 1 - 2022-02-23
- MINOR IMPROVEMENT: Support the INSTALL_BASE environment variable for
installing rem2pdf in a non-standard location like your home directory.
This is passed in to rem2pdf's Makefile at build and install time.
- MINOR IMPROVEMENT: ./configure: Add --disable-perl-build-artifacts flag
to avoid installation of perllocal.pod and .packlist files.
- BUG FIX: tkremind: If the system date rolls over, update the display
to correctly highlight the current date. This worked in older versions
of Remind, but was broken by 03.04.00.
- BUG FIX: rem2pdf: The small calendar font would sometimes be scaled
incorrectly so the small calendar overflowed the box. This has been
fixed.
* VERSION 3.4 Patch 0 - 2022-02-10 * VERSION 3.4 Patch 0 - 2022-02-10
- MAJOR CHANGE: Remind and its helpers (except for rem2ps) fully support - MAJOR CHANGE: Remind and its helpers (except for rem2ps) fully support

View File

@@ -16,7 +16,7 @@
# "#PSSTUFF" for nifty PostScript examples # # "#PSSTUFF" for nifty PostScript examples #
# # # #
# This file is part of REMIND. # # This file is part of REMIND. #
# Copyright (C) 1992-2018 Dianne Skoll # # Copyright (C) 1992-2022 Dianne Skoll #
# # # #
############################################################################# #############################################################################
@@ -25,63 +25,14 @@ RUN OFF
################################################ ################################################
# Ensure required version of remind is used... # # Ensure required version of remind is used... #
################################################ ################################################
IF version() < "03.01.10" IF version() < "03.04.02"
ERRMSG This file requires at least version 03.01.10 of Remind.% ERRMSG This file requires at least version 03.01.10 of Remind.%
ERRMSG This version is version [version()]. ERRMSG This version is version [version()].
EXIT EXIT
ENDIF ENDIF
######################################
# Symbolic constants for weekdays... #
######################################
SET Sunday 0
SET Monday 1
SET Tuesday 2
SET Wednesday 3
SET Thursday 4
SET Friday 5
SET Saturday 6
SET Sun 0
SET Mon 1
SET Tue 2
SET Wed 3
SET Thu 4
SET Fri 5
SET Sat 6
#########################################
# Symbolic constants for month names... #
#########################################
SET Jan 1
SET Feb 2
SET Mar 3
SET Apr 4
SET May 5
SET Jun 6
SET Jul 7
SET Aug 8
SET Sep 9
SET Oct 10
SET Nov 11
SET Dec 12
SET January 1
SET February 2
SET March 3
SET April 4
SET May 5
SET June 6
SET July 7
SET August 8
SET September 9
SET October 10
SET November 11
SET December 12
########################################################### ###########################################################
# Other symbolic constants and functions for "pasting"... # # Symbolic constants and functions for "pasting"... #
########################################################### ###########################################################
SET Quote CHAR(34) SET Quote CHAR(34)
@@ -119,50 +70,23 @@ REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
# Here's a tricky problem: The 4th of July is a holiday in the U.S. # Here's a tricky problem: The 4th of July is a holiday in the U.S.
# However, if it falls on a Saturday, the previous Friday is a holiday. # However, if it falls on a Saturday, the previous Friday is a holiday.
# If it falls on a Sunday, the next Monday is a holiday. Here's how # If it falls on a Sunday, the next Monday is a holiday. Here's how
# to do it. NOTE that the following procedure makes the OMIT context # to do it.
# dependent upon the current date. SInce it only depends on the current #
# year, which is not likely to change while producing a calendar, we # For those reminders that update the OMIT context with ADDOMIT, we use
# are fairly safe. However, reminders with huge DELTA or BACK components # SCANFROM -7 for safety; see the man page about moveable OMITs.
# may not operate as expected. In general, any time you make OMIT
# dependent upon the current date, it's tricky and results may not be
# what you expect. You should try to make sure that the OMIT context
# "near" any current reminders will not change during a calendar run.
# The SCANFROM clause will make these OMITs safe.
############################################################################ ############################################################################
# Calculate the weekday of the holiday. # If it falls on a Saturday, bump to previous Friday
REM 4 July SCANFROM -7 SATISFY 1 REM 4 July OMIT SAT SCANFROM -1 BEFORE ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
SET iday $T # If it falls on a Sunday, bump to following Monday
IF WKDAYNUM(iday) == Sat REM 4 July OMIT SUN SCANFROM -7 AFTER ADDOMIT SATISFY [$Td != 4] MSG Independence day (observed)
REM [iday] MSG Independence day (actual)
OMIT [iday-1] MSG Independence day (observed)
ELSE
IF WKDAYNUM(iday) == Sun
REM [iday] MSG Independence day (actual)
OMIT [iday+1] MSG Independence day (observed)
ELSE
OMIT [iday] MSG Independence day
ENDIF
ENDIF
############################################################################ # If it falls on Sat or Sun, note the actual day
# A meeting on the first Monday of every month which is moved to the # REM 4 July SATISFY [$Tw == 0 || $Tw == 6] MSG Independence day (actual)
# second Monday in the event of a holiday. #
############################################################################
# First, the normal meeting. However, the SKIP keyword means this # Otherwise observed and actual is on the 4th
# one won't be triggered if the first Monday is a holiday REM 4 July OMIT SAT SUN SKIP SCANFROM -7 ADDOMIT MSG Independence Day
REM Mon 1 SKIP MSG Meeting
# Now, calculate the "potential" delayed meeting
REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous
# Monday was a holiday
IF ISOMITTED($T-7)
REM [$T] MSG Delayed meeting
ENDIF
########################################################################## ##########################################################################
# # # #
@@ -216,38 +140,38 @@ REM [easter+49] MSG %"Pentecost%"
# which ones are omitted - use the general forms shown below. You'll # which ones are omitted - use the general forms shown below. You'll
# need the Week_n variables defined way up in the file. # need the Week_n variables defined way up in the file.
OMIT Jan 1 MSG %"New Year's%" Day OMIT Jan 1 MSG %"New Year's Day%"
REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%" REM Third Monday in Jan MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%" REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day REM Feb 14 MSG %"Valentine's Day%"
REM Mon Feb [Week_3] SCANFROM -7 ADDOMIT MSG %"President's Day%" REM Third Monday in Feb SCANFROM -7 ADDOMIT MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's%" Day REM Mar 17 MSG %"St. Patrick's Day%"
# The DST rules are accurate for most locations in # The DST rules are accurate for most locations in
# North America # North America
REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b REM Sun Apr 1 ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b REM Sun Mar 8 ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST starts%" %b
REM Sun [_last(Oct)] ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b REM Last Sunday in October ++2 UNTIL 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM Sun 1 Nov ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b REM First Sunday in November ++2 FROM 1 Jan 2007 MSG Daylight Saving Time - %"DST ends%" %b
REM Apr 1 MSG %"April Fool's%" Day REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
REM May 5 MSG %"Cinco de Mayo%" REM May 5 MSG %"Cinco de Mayo%"
REM Sat May [Week_1] MSG %"Kentucky Derby%" REM First Sat in May MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%" REM Second Sun in May MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%" REM Third Sat in May MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM -7 ADDOMIT MSG %"Memorial Day%" REM Last Monday in May SCANFROM -7 ADDOMIT MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%" REM Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%" REM Third Sun in June MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM -7 ADDOMIT MSG %"Labor Day%" REM First Mon in Sep SCANFROM -7 ADDOMIT MSG %"Labor Day%"
REM Mon Oct [Week_2] MSG %"Columbus Day%" REM Second Mon in Oct MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%" REM Nov 11 MSG %"Veterans Day%"
REM Oct 30 MSG %"Mischief Night%" REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%" REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%" REM Tue Nov 2 SCANFROM -7 SATISFY [($Ty % 4) == 0] MSG %"Election Day%"
REM Thu Nov [Week_4] SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%" REM Last Thu in Nov SCANFROM -7 ADDOMIT MSG %"Thanksgiving Day%"
REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%" REM Fri Nov [Week_4+1] SCANFROM -7 ADDOMIT MSG %"Thanksgiving (cont.)%"
OMIT Dec 24 MSG %"Christmas Eve%" OMIT Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day OMIT Dec 25 MSG %"Christmas%" Day
@@ -262,6 +186,24 @@ if $NumTrig > SaveTrig
REM SPECIAL SHADE 220 REM SPECIAL SHADE 220
endif endif
############################################################################
# A meeting on the first Monday of every month which is moved to the #
# second Monday in the event of a holiday. #
############################################################################
# First, the normal meeting. However, the SKIP keyword means this
# one won't be triggered if the first Monday is a holiday
REM First Monday SKIP MSG Meeting
# Now, calculate the "potential" delayed meeting
REM Second Monday SATISFY 1
# But only actually trigger the delayed meeting if the previous
# Monday was a holiday
IF ISOMITTED($T-7)
REM [$T] MSG Delayed meeting
ENDIF
#PSSTUFF2 #PSSTUFF2
########################################################################## ##########################################################################
# # # #
@@ -278,10 +220,10 @@ REM PS Border Border moveto \
([hebday($U)] [hebmon($U)]) show ([hebday($U)] [hebmon($U)]) show
# Fill in the phases of the moon on the PostScript calendar # Fill in the phases of the moon on the PostScript calendar
[moondate(0)] SPECIAL MOON 0 REM [moondate(0)] SPECIAL MOON 0
[moondate(1)] SPECIAL MOON 1 REM [moondate(1)] SPECIAL MOON 1
[moondate(2)] SPECIAL MOON 2 REM [moondate(2)] SPECIAL MOON 2
[moondate(3)] SPECIAL MOON 3 REM [moondate(3)] SPECIAL MOON 3
# The following example puts sunrise and sunset times in PostScript in the # The following example puts sunrise and sunset times in PostScript in the
# calendar - the sizes are hard-coded, however, and work best in landscape. # calendar - the sizes are hard-coded, however, and work best in landscape.

View File

@@ -70,7 +70,10 @@ on terminals that emulate the VT00 line-drawing character set.
.B 'u' .B 'u'
is similar to 'l', but causes \fBRemind\fR to use UNICODE line-drawing is similar to 'l', but causes \fBRemind\fR to use UNICODE line-drawing
characters to draw the calendar. The characters are hard-coded and will characters to draw the calendar. The characters are hard-coded and will
only work on terminals that are set to UTF-8 character encoding. only work on terminals that are set to UTF-8 character encoding. This
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 .TP
.B 'c' .B 'c'
causes \fBRemind\fR to use VT100 escape sequences to approximate causes \fBRemind\fR to use VT100 escape sequences to approximate
@@ -267,7 +270,7 @@ calendar output.
.TP .TP
\fB\-x\fR[\fIn\fR] \fB\-x\fR[\fIn\fR]
Sets the iteration limit for the \fBSATISFY\fR clause of a \fBREM\fR Sets the iteration limit for the \fBSATISFY\fR clause of a \fBREM\fR
command. Defaults to 150. command. Defaults to 1000.
.TP .TP
\fB\-k\fR\fIcmd\fR \fB\-k\fR\fIcmd\fR
Instead of simply printing \fBMSG\fR-type Instead of simply printing \fBMSG\fR-type
@@ -814,7 +817,8 @@ could be specified as:
However, events that do not repeat daily, weekly, monthly or yearly require However, events that do not repeat daily, weekly, monthly or yearly require
another approach. The \fIrepeat\fR component of the \fBREM\fR command another approach. The \fIrepeat\fR component of the \fBREM\fR command
fills this need. To use it, you must completely specify a date (year, month fills this need. To use it, you must completely specify a date (year, month
and day, and optionally weekday.) The \fIrepeat\fR component is an asterisk and day, and optionally weekday); this is the start date of the
repetition period. The \fIrepeat\fR component is an asterisk
followed by a number specifying the repetition period in days. followed by a number specifying the repetition period in days.
.PP .PP
For example, suppose you get paid every second Wednesday, and your For example, suppose you get paid every second Wednesday, and your
@@ -824,12 +828,12 @@ last payday was Wednesday, 28 October, 1992. You can use:
REM 28 Oct 1992 *14 MSG Payday REM 28 Oct 1992 *14 MSG Payday
.fi .fi
.PP .PP
This issues the reminder every 14 days, starting from the calculated trigger This issues the reminder every 14 days, starting from 28 Oct 1992.
date. You can use \fIdelta\fR and \fIback\fR with \fIrepeat.\fR Note, You can use \fIdelta\fR and \fIback\fR with \fIrepeat.\fR Note,
however, that the \fIback\fR is used only to compute the initial however, that the \fIback\fR is used only to compute the starting
trigger date; thereafter, the reminder repeats with the specified date; thereafter, the reminder repeats with the specified
period. Similarly, if you specify a weekday, it is used only to calculate period. Similarly, if you specify a weekday, it is used only to calculate
the initial date, and does not affect the repetition period. the starting date, and does not affect the repetition period.
.PP .PP
.B SCANFROM \fRand\fB FROM .B SCANFROM \fRand\fB FROM
.PP .PP
@@ -1152,6 +1156,84 @@ Note that \fIduration\fR is specified either in hours and minutes as a
duration of 00:00 or 0, then \fBRemind\fR behaves exactly as if no duration of 00:00 or 0, then \fBRemind\fR behaves exactly as if no
\fBDURATION\fR at all had been present. \fBDURATION\fR at all had been present.
.PP
.SH SYNTACTIC SUGAR FOR REM
.PP
The REM command has syntactic sugar to let you express common
reminders. The following pairs of reminders are equivalent:
.PP
.nf
REM First Monday April MSG Foo
REM Mon 1 April MSG Foo
REM Second Monday May MSG Bar
REM Mon 8 May MSG Bar
REM Third Monday MSG Third Monday of every month
REM Mon 15 MSG Third Monday of every month
REM Fourth Sunday June 2025 MSG Fourth Sunday in June 2025
REM Sun 22 June 2025 MSG Fourth Sunday in June 2025
REM Last Monday MSG Last Monday of every month
REM Mon 1 --7 MSG Last Monday of every month
REM Last Monday April MSG Last Monday of every April
REM Mon 1 May --7 MSG Last Monday of every April
REM Last Monday December 2025 MSG Last Monday of Dec 2025
REM Monday 1 Jan 2026 --7 MSG Last Monday of Dec 2025
.fi
.PP
Note that \fBLast\fR effectively adjusts the month and year, if necessary, to
make the reminder trigger on the correct date.
.PP
The keyword \fBIN\fR is completely ignored, so you can write (for example):
.PP
.nf
REM Second Monday in May MSG foo
REM Last Monday in December 2025 MSG Bar
.fi
.PP
An alternate form of \fIback\fR makes writing reminders easier.
The following groups of reminders are equivalent:
.PP
.nf
REM ~~1 MSG Last day of every month
REM Lastday MSG Last day of every month
REM 1 --1 MSG Last day of every month
REM May ~~1 MSG Last day of May
REM Lastday May MSG Last day of May
REM 1 June --1 MSG Last day of May
REM Dec 2025 ~~1 MSG Last day of December 2025
REM Lastday Dec 2025 MSG Last day of December 2025
REM 1 Jan 2026 --1 MSG Last day of December 2025
REM Apr ~1 OMIT SAT SUN MSG Last workday of April
REM Lastworkday April OMIT SAT SUN MSG Last workday of April
REM 1 May -1 OMIT SAT SUN MSG Last workday of April
REM Apr ~~7 MSG Seventh-last day of April
REM 1 May --7 MSG Seventh-last day of April
REM Apr ~2 OMIT SAT SUN MSG Second-last workday of April
REM 1 May -2 OMIT SAT SUN MSG Second-last workday of April
.fi
.PP
As we see, "Lastday" is equivalent to ~~1 and "Lastworkday" to ~1.
.PP
Note that the First/Second/Third/Fourth/Last keywords and the ~ and ~~ form
of \fIback\fR imply a value for the day of the month; as such, they cannot
be combined with a day. Additionally, First/Second/Third/Fourth/Last
must have at least one weekday name. The following are illegal:
.PP
.nf
REM First Monday 3 June MSG Huh?
REM April 3 ~~1 MSG What?
REM Second June MSG Where's the weekday???
.fi
.PP .PP
.SH THE SUBSTITUTION FILTER .SH THE SUBSTITUTION FILTER
.PP .PP
@@ -1853,6 +1935,26 @@ and time separator characters for \fBDATE\fR and \fBTIME\fR constants apply
also to \fBDATETIME\fR constants. also to \fBDATETIME\fR constants.
.RE .RE
.PP .PP
.B ZERO VALUES
.PP
The non-string types all have an associated \fIzero\fR value, which is
treated as "false" by the IF command and the logical operators. The
zero values are:
.PP
.RS
.PP
\fBINT\fR - 0
.PP
\fBDATE\fR - '1990-01-01'
.PP
\fBTIME\fR - 00:00
.PP
\fBDATETIME\fR - '1990-01-01@00:00'
.RE
.PP
Additionally, for the purpose of the IF command (but \fInot\fR the
logical operators) the empty string "" is considered a false value.
.PP
.B OPERATORS .B OPERATORS
.PP .PP
\fBRemind\fR has the following operators. Operators on the same line \fBRemind\fR has the following operators. Operators on the same line
@@ -1976,14 +2078,16 @@ If the operands are not of the same type, == returns 0 and != returns
.RE .RE
.TP .TP
.B && .B &&
This is the logical AND operator. Both of its operands must be of This is the logical AND operator. Both of its operands must be of the
type \fBINT\fR. It returns 1 if both operands are non-zero, and 0 same type and must not be \fBSTRING\fR type. Returns the second
otherwise. operand if both operands are non-zero. Otherwise, returns a zero
of the same type as the operands.
.TP .TP
.B || .B ||
This is the logical OR operator. Both of its operands must be of This is the logical OR operator. Both of its operands must be of
type \fBINT\fR. It returns 1 if either operand is non-zero, and 0 the same type and must not be of \fBSTRING\fR type. It returns
otherwise. the first operand that is non-zero; if both operands are zero, then
returns a zero of the same type as the operands.
.PP .PP
.B NOTES .B NOTES
.PP .PP
@@ -3116,6 +3220,114 @@ 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 date, or a date supplied on the command line, or the date of the
calendar entry currently being computed. calendar entry currently being computed.
.TP .TP
.B trig(s_1 [,s_2, ...])
For each string argument s_\fIn\fR, \fBtrig\fR evaluates s_\fIn\fR
as if it were a REM or IFTRIG trigger
specification. If the trigger would trigger today, then the trigger
date is returned and no further triggers are evaluated. If none
of the triggers would trigger today, then the zero date
1990-01-01 is returned.
.RS
\fBtrig\fR also has a zero-argument form; this returns the trigger
date of the \fImost recent\fR \fBtrig\fR function that returned a
non-zero trigger date.
.PP
\fBtrig\fR can be used to make more sophisticated versions of
\fBIFTRIG\fR. For example, if you have meetings every Monday in
June and July, and you want warnings 3 days in advance, you
could use:
.nf
REM [trig("Mon Jun +3", "Mon July +3")] +3 MSG Meeting %b
.fi
.PP
NOTE: We need to repeat the +3 delta outside of the \fBtrig\fR
function for advance warning to work properly. This is because
\fBtrig\fR returns a date constant (the trigger date) and the
REM command does not know the details of \fBtrig\fR's arguments.
.PP
Note that because \fBRemind\fR does not have short-circuit logical
operators, something like:
.PP
.nf
SET a trig("Mon +7") || trig("Fri +7")
.fi
would set the value of trig() to the date of the following
Thursday. Even though trig("Mon +7") always returns true,
the logical-OR operator still evaluates trig("Fri +7") which
\fIalso\fR returns true and sets \fBtrig()\fR.
.PP
You can work around the lack of a short-circuit logical-OR as follows:
If \fBtrig\fR returns a true value, the specific value it returns
can be coerced to a DATE which is the trigger date. So the following code:
.PP
.nf
SET a trig("Mon +4") || trig("Fri +4")
IF a
REM [a] +4 MSG [wkday($T)] %b.
ENDIF
.fi
.PP
would operate as follows:
.PP
.nf
On Monday: Monday today.
On Tuesday: Friday in 3 days' time.
On Wednesday: Friday in 2 days' time.
On Thursday: Monday in 4 days' time.
On Friday: Monday in 3 days' time.
On Saturday: Monday in 2 days' time.
On Sunday: Monday tomorrow.
.fi
.PP
Compare with the following:
.PP
.nf
SET a trig("Mon +4") || trig("Fri +4")
IF a
REM [trig()] +4 MSG [wkday($T)] %b.
ENDIF
.fi
.PP
which yields:
.PP
.nf
On Monday: Friday in 4 days' time.
On Tuesday: Friday in 3 days' time.
On Wednesday: Friday in 2 days' time.
On Thursday: Friday tomorrow.
On Friday: Friday today.
On Saturday: Monday in 2 days' time.
On Sunday: Monday tomorrow.
.fi
.PP
That is because \fBtrig()\fR returns the trigger date of
the \fIlast\fR trig function that returns true,
whereas the value of \fBa\fR is the trigger date of the \fIfirst\fR
trig function that returns true.
.PP
\fBImportant Note\fR: Because \fBtrig()\fR always returns an absolute
date, it will \fBnot\fR work properly with a \fBSATISFY\fR clause.
Consider this reminder:
.PP
.nf
REM [trig("Mar", "Apr")] SATISFY [$Td == 15] MSG 15 Mar or April
.fi
.PP
If we run \fBRemind\fR on 5 March 2022, we might expect the trigger
date to be calculated as 15 March 2022... but that's not what happens.
Instead, the \fBtrig\fR function is evaluated first, and it returns
2022-03-05. So as far as \fBRemind\fR is concerned, the REM statement
becomes:
.PP
.nf
REM 2022-03-05 SATISFY [$Td == 15] MSG 15 Mar or April
.fi
.PP
and the SATISFY expression is never true. So: \fIDo not mix
trig() and SATISFY\fR.
.RE
.TP
.B trigdate() .B trigdate()
Returns the calculated trigger date of the last \fBREM\fR Returns the calculated trigger date of the last \fBREM\fR
or \fBIFTRIG\fR command. If used or \fBIFTRIG\fR command. If used
@@ -3532,12 +3744,12 @@ Note that the commands are shown indented for clarity. Also, the \fBELSE\fR
portion can be omitted. \fBIF\fR commands can be nested up to a small limit, portion can be omitted. \fBIF\fR commands can be nested up to a small limit,
probably around 8 or 16 levels of nesting, depending on your system. probably around 8 or 16 levels of nesting, depending on your system.
.PP .PP
If the \fIexpr\fR evaluates to a non-zero \fBINT\fR, or a non-null If the \fIexpr\fR evaluates to a non-zero \fBINT\fR, a \fBDATE\fR that
\fBSTRING\fR, then the \fBIF\fR portion is considered true, and the is not 1990-01-01, a \fBTIME\fR that is not 00:00, a \fBDATETIME\fR
\fIt-commands\fR are executed. If \fIexpr\fR evaluates to zero or that is not 1990-01-01@00:00, or a non-null \fBSTRING\fR, then the
null, then the \fIf-commands\fR (if the \fBELSE\fR portion is present) \fBIF\fR portion is considered true, and the \fIt-commands\fR are
are executed. If \fIexpr\fR is not of type \fBINT\fR or \fBSTRING\fR, executed. If \fIexpr\fR evaluates to zero or null, then the
then it is an error. \fIf-commands\fR (if the \fBELSE\fR portion is present) are executed.
.PP .PP
Examples: Examples:
.PP .PP

View File

@@ -173,6 +173,13 @@ it will be underlined when you move the cursor over it, and
you can edit it in a text editor by either left- or right-clicking you can edit it in a text editor by either left- or right-clicking
on the reminder. on the reminder.
.SH ERRORS
If there are any errors in your reminder file, the "Queue..." button
changes to "Errors...". Click on "Errors..." to see the Remind error
output. Click "OK" to close the error window; this makes the button
in the main TkRemind window to revert to "Queue..."
.SH BACKGROUND REMINDERS .SH BACKGROUND REMINDERS
If you create "timed" reminders, \fBTkRemind\fR will queue them in If you create "timed" reminders, \fBTkRemind\fR will queue them in

View File

@@ -29,7 +29,9 @@ install:
if test $$? != 0 ; then echo "Not installing rem2pdf; missing $$m"; exit 0; fi; \ if test $$? != 0 ; then echo "Not installing rem2pdf; missing $$m"; exit 0; fi; \
done; \ done; \
echo "Installing rem2pdf"; \ echo "Installing rem2pdf"; \
if test "$(prefix)" = "/usr" ; then \ if test "$(INSTALL_BASE)" != "" ; then \
$(MAKE) install DESTDIR=$(DESTDIR) "INSTALL_BASE=$(INSTALL_BASE)" && exit 0; \
elif test "$(prefix)" = "/usr" ; then \
$(MAKE) install DESTDIR=$(DESTDIR) INSTALLDIRS=vendor && exit 0; \ $(MAKE) install DESTDIR=$(DESTDIR) INSTALLDIRS=vendor && exit 0; \
else \ else \
$(MAKE) install DESTDIR=$(DESTDIR) && exit 0; \ $(MAKE) install DESTDIR=$(DESTDIR) && exit 0; \
@@ -37,4 +39,4 @@ install:
exit 1; exit 1;
Makefile: Makefile.PL Makefile: Makefile.PL
$(PERL) Makefile.PL || true $(PERL) Makefile.PL @PERLARTIFACTS@ INSTALL_BASE=$(INSTALL_BASE) || true

View File

@@ -637,7 +637,7 @@ sub draw_day
$so_far += $h2; $so_far += $h2;
} }
if ($height) { if ($height) {
if ($entry_height > $height) { if ($h + $entry_height + 2 * $settings->{border_size} > $height) {
print STDERR "WARNING: overfull box at $day " . $self->{monthname} . ' ' . $self->{year} . "\n"; print STDERR "WARNING: overfull box at $day " . $self->{monthname} . ' ' . $self->{year} . "\n";
$entry_height = $height; $entry_height = $height;
} }
@@ -753,24 +753,13 @@ sub draw_small_calendar
$last_day_on_row += 7; $last_day_on_row += 7;
$rows++; $rows++;
} }
my $layout = Pango::Cairo::create_layout($cr); my $font_size = $self->calculate_small_calendar_font_size($cr, $width, $height, $settings, $rows);
my $desc = Pango::FontDescription->from_string($settings->{small_cal_font} . ' ' . '10px');
$layout->set_font_description($desc);
$layout->set_text('88 88 88 88 88 88 88');
my ($wid, $h) = $layout->get_pixel_size();
$h += 1;
$h *= ($rows + 2); # row for month name; row for day names
my $scale = $width / $wid; my $layout = Pango::Cairo::create_layout($cr);
if (($height / $h) < $scale) { my $desc = Pango::FontDescription->from_string($settings->{small_cal_font} . ' ' . $font_size . 'px');
$scale = $height / $h;
}
my $font_size = int($scale * 10);
$layout = Pango::Cairo::create_layout($cr);
$desc = Pango::FontDescription->from_string($settings->{small_cal_font} . ' ' . $font_size . 'px');
$layout->set_font_description($desc); $layout->set_font_description($desc);
$layout->set_text('88 '); $layout->set_text('88 ');
($wid, $h) = $layout->get_pixel_size(); my ($wid, $h) = $layout->get_pixel_size();
$h += 1; $h += 1;
# Month name # Month name
@@ -824,6 +813,43 @@ sub draw_small_calendar
} }
} }
sub calculate_small_calendar_font_size
{
my ($self, $cr, $width, $height, $settings, $rows) = @_;
my $layout = Pango::Cairo::create_layout($cr);
my $desc = Pango::FontDescription->from_string($settings->{small_cal_font} . ' ' . '10px');
$layout->set_font_description($desc);
$layout->set_text('88 88 88 88 88 88 88');
my ($wid, $h) = $layout->get_pixel_size();
$h += 1;
$h *= ($rows + 2); # row for month name; row for day names
my $scale = $width / $wid;
if (($height / $h) < $scale) {
$scale = $height / $h;
}
my $font_size = int($scale * 10);
# Check
$desc = Pango::FontDescription->from_string($settings->{small_cal_font} . ' ' . $font_size . 'px');
$layout->set_font_description($desc);
$layout->set_text('88 88 88 88 88 88 88');
($wid, $h) = $layout->get_pixel_size();
$h += 1;
$h *= ($rows + 2); # row for month name; row for day names
$scale = $width / $wid;
if (($height / $h) < $scale) {
$scale = $height / $h;
}
if ($scale < 1) { # Font size is too big
$font_size--;
}
return $font_size;
}
package Remind::PDF::Multi; package Remind::PDF::Multi;
=head1 NAME =head1 NAME

View File

@@ -127,6 +127,12 @@ set OptDescr(BackgroundColor) "Default background color of calendar boxes"
set Option(TextColor) "#000000" set Option(TextColor) "#000000"
set OptDescr(TextColor) "Default text color in calendar boxes" set OptDescr(TextColor) "Default text color in calendar boxes"
set Option(TodayColor) "#00C0C0"
set OptDescr(TodayColor) "Background color for today heading"
set Option(LineColor) "#000000"
set OptDescr(LineColor) "Color of gridlines on calendar"
set Option(LabelColor) "#000000" set Option(LabelColor) "#000000"
set OptDescr(LabelColor) "Default label color for headings" set OptDescr(LabelColor) "Default label color for headings"
@@ -165,6 +171,9 @@ set EditorPid -1
# Inotify file # Inotify file
set InotifyFP "" set InotifyFP ""
# Errors from last remind run
set RemindErrors ""
# Reminder file to append to -- default # Reminder file to append to -- default
set AppendFile {NOSUCHFILE} set AppendFile {NOSUCHFILE}
catch {set AppendFile $ReminderFile} catch {set AppendFile $ReminderFile}
@@ -282,7 +291,17 @@ proc is_warning_header { line } {
proc Initialize {} { proc Initialize {} {
global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd global DayNames argc argv CommandLine ReminderFile AppendFile Remind PSCmd
global MondayFirst TwentyFourHourMode ReminderFileModTime global MondayFirst TwentyFourHourMode ReminderFileModTime
global TodayDay TodayMonth TodayYear
global Option ConfigFile global Option ConfigFile
# In case date has rolled over, recalculate Today* values
set now [clock seconds]
set TodayMonth [expr [string trim [clock format $now -format %N]] - 1]
set TodayYear [clock format $now -format %Y]
set TodayDay [string trim [clock format $now -format %e]]
set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA" set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA"
set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp -l EXTRA" set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp -l EXTRA"
set i 0 set i 0
@@ -449,7 +468,7 @@ proc CreateCalFrame { w dayNames } {
} }
global MondayFirst global MondayFirst
frame $w -background $Option(WinBackground) frame $w -background $Option(LineColor)
for {set i 0} {$i < 7} {incr i} { for {set i 0} {$i < 7} {incr i} {
if {$MondayFirst} { if {$MondayFirst} {
set index [expr ($i+1)%7] set index [expr ($i+1)%7]
@@ -457,28 +476,31 @@ proc CreateCalFrame { w dayNames } {
set index $i set index $i
} }
label $w.day$i -border 1 -text [lindex $dayNames $index] -justify center -font HeadingFont -foreground $Option(LabelColor) -background $Option(WinBackground) label $w.day$i -bd 0 -text [lindex $dayNames $index] -justify center -font HeadingFont -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
grid configure $w.day$i -row 0 -column $i -sticky ew grid configure $w.day$i -row 0 -column $i -sticky ew -padx 1 -pady 1
} }
for {set i 0} {$i < 6} {incr i} { for {set i 0} {$i < 6} {incr i} {
set n [expr $i*7] set n [expr $i*7]
for {set j 0} {$j < 7} {incr j} { for {set j 0} {$j < 7} {incr j} {
set f [expr $n+$j] set f [expr $n+$j]
button $w.l$f -text "" -justify center -command "" \ button $w.l$f -text "" -justify center -command "" \
-state disabled -relief flat -border 0 -padx 0 -pady 0 -font HeadingFont -state disabled -relief flat -bd 0 -padx 0 -pady 0 -font HeadingFont -highlightthickness 1
text $w.t$f -width 12 -height $h -border 1 -spacing3 3 -wrap word -relief flat \ text $w.t$f -width 12 -height $h -bd 0 -spacing3 3 -wrap word -relief flat \
-state disabled -takefocus 0 -cursor {} -font CalboxFont -foreground $Option(TextColor) -background $Option(BackgroundColor) -state disabled -takefocus 0 -cursor {} -font CalboxFont -foreground $Option(TextColor) -background $Option(BackgroundColor) \
-highlightthickness 0
frame $w.f$f -padx 0 -pady 0 -highlightthickness 0 -relief flat -bd 0
$w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f" $w.t$f tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$f"
$w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f" $w.t$f tag bind REM <ButtonPress-3> "FireEditor $w.t$f"
grid configure $w.l$f -row [expr $i*2+1] -column $j -sticky ew pack $w.l$f -in $w.f$f -side top -expand 0 -fill x
grid configure $w.t$f -row [expr $i*2+2] -column $j -sticky nsew pack $w.t$f -in $w.f$f -side top -expand 1 -fill both
grid configure $w.f$f -row [expr $i+1] -column $j -sticky nsew -padx 1 -pady 1
} }
} }
for {set i 0} {$i < 7} {incr i} { for {set i 0} {$i < 7} {incr i} {
grid columnconfigure $w $i -weight 1 grid columnconfigure $w $i -weight 1
} }
for {set i 2} {$i < 14} {incr i 2} { for {set i 1} {$i < 7} {incr i} {
grid rowconfigure $w $i -weight 1 grid rowconfigure $w $i -weight 1
} }
} }
@@ -504,8 +526,12 @@ proc ConfigureCalFrame { w firstDay numDays } {
set last [expr $offset+$numDays] set last [expr $offset+$numDays]
for {set i 0} {$i < $first} {incr i} { for {set i 0} {$i < $first} {incr i} {
grid $w.l$i $w.t$i grid $w.f$i
$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
raise $w.l$i
raise $w.t$i
$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
$w.l$i configure -state disabled $w.l$i configure -state disabled
balloon_add_help $w.l$i "" balloon_add_help $w.l$i ""
$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground) $w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
@@ -515,13 +541,17 @@ proc ConfigureCalFrame { w firstDay numDays } {
} }
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i" $w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled -takefocus 0
} }
for {set i $first} {$i <= $last} {incr i} { for {set i $first} {$i <= $last} {incr i} {
grid $w.l$i $w.t$i grid $w.f$i
pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
raise $w.l$i
raise $w.t$i
set d [expr $i-$first+1] set d [expr $i-$first+1]
$w.l$i configure -text $d -state normal -relief flat \ $w.l$i configure -text $d -state normal -relief flat \
-command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground) -command "ModifyDay $d $firstDay" -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help $w.l$i "Add a reminder..." balloon_add_help $w.l$i "Add a reminder..."
$w.t$i configure -relief sunken -takefocus 1 -state normal -foreground $Option(TextColor) -background $Option(BackgroundColor) $w.t$i configure -relief sunken -takefocus 1 -state normal -foreground $Option(TextColor) -background $Option(BackgroundColor)
$w.t$i delete 1.0 end $w.t$i delete 1.0 end
@@ -530,23 +560,27 @@ proc ConfigureCalFrame { w firstDay numDays } {
} }
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i" $w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled -takefocus 0
} }
set forgetIt 0 set forgetIt 0
for {set i [expr $last+1]} {$i < 42} {incr i} { for {set i [expr $last+1]} {$i < 42} {incr i} {
if {$i%7 == 0} { if {$i%7 == 0} {
set forgetIt 1 set forgetIt 1
} }
set row [expr ($i/7)*2+1] set row [expr ($i/7)+1]
if {$forgetIt} { if {$forgetIt} {
grid remove $w.l$i $w.t$i grid remove $w.f$i
grid rowconfigure $w $row -weight 0 grid rowconfigure $w $row -weight 0
grid rowconfigure $w [expr $row+1] -weight 0 grid rowconfigure $w [expr $row+1] -weight 0
} else { } else {
grid $w.l$i $w.t$i grid $w.f$i
pack $w.l$i -in $w.f$i -side top -expand 0 -fill x
pack $w.t$i -in $w.f$i -side top -expand 1 -fill both
raise $w.l$i
raise $w.t$i
grid rowconfigure $w [expr $row+1] -weight 1 grid rowconfigure $w [expr $row+1] -weight 1
} }
$w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) $w.l$i configure -text "" -command "" -state normal -relief flat -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
$w.l$i configure -state disabled $w.l$i configure -state disabled
balloon_add_help $w.l$i "" balloon_add_help $w.l$i ""
$w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground) $w.t$i configure -relief flat -takefocus 0 -state normal -background $Option(WinBackground)
@@ -556,11 +590,11 @@ proc ConfigureCalFrame { w firstDay numDays } {
} }
$w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i" $w.t$i tag bind TAGGED <ButtonPress-1> "EditTaggedReminder $w.t$i"
$w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i" $w.t$i tag bind REM <ButtonPress-3> "FireEditor $w.t$i"
$w.t$i configure -state disabled $w.t$i configure -state disabled -takefocus 0
} }
if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } { if { $CurMonth == $TodayMonth && $CurYear == $TodayYear } {
set n [expr $TodayDay + $offset] set n [expr $TodayDay + $offset]
$w.l$n configure -background "#00c0c0" $w.l$n configure -background $Option(TodayColor)
} }
} }
@@ -577,36 +611,36 @@ proc DoQueue {} {
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
proc CreateCalWindow { dayNames } { proc CreateCalWindow { dayNames } {
global Option global Option
frame .h -background $Option(WinBackground); frame .h -background $Option(LineColor)
label .h.title -text "" -justify center -pady 1 -border 1 -relief raised -font HeadingFont -background $Option(WinBackground) -foreground $Option(LabelColor) label .h.title -text "" -justify center -pady 2 -bd 0 -relief flat -font HeadingFont -background $Option(WinBackground) -foreground $Option(LabelColor)
pack .h.title -side top -fill x pack .h.title -side top -fill x -pady 1 -padx 1
pack .h -side top -expand 0 -fill x pack .h -side top -expand 0 -fill x
. configure -background $Option(LineColor)
CreateCalFrame .cal $dayNames CreateCalFrame .cal $dayNames
frame .b -background $Option(WinBackground); frame .b -background $Option(LineColor)
button .b.prev -text "\u2b9c" -command {MoveMonth -1} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.prev -text "\u2b9c" -command {MoveMonth -1} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.prev "Go to previous month" balloon_add_help .b.prev "Go to previous month"
button .b.this -text {Today} -command {ThisMonth} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.this -text {Today} -command {ThisMonth} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.this "Go to this month" balloon_add_help .b.this "Go to this month"
button .b.next -text "\u2b9e" -command {MoveMonth 1} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.next -text "\u2b9e" -command {MoveMonth 1} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.next "Go to next month" balloon_add_help .b.next "Go to next month"
button .b.goto -text {Go To Date...} -command {GotoDialog} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.goto -text {Go To Date...} -command {GotoDialog} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.goto "Go to a specific date" balloon_add_help .b.goto "Go to a specific date"
button .b.print -text {Print...} -command {DoPrint} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.print -text {Print...} -command {DoPrint} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.print "Print a PostScript calendar" balloon_add_help .b.print "Print a PostScript or PDF calendar"
button .b.queue -text {Queue...} -command {DoQueue} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.options -text {Options...} -command EditOptions -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
balloon_add_help .b.queue "See the queue of pending reminders (debugging purposes only)"
button .b.quit -text {Quit} -command {Quit} -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground)
balloon_add_help .b.quit "Quit TkRemind"
button .b.options -text {Options...} -command EditOptions -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground)
balloon_add_help .b.options "Set TkRemind options" balloon_add_help .b.options "Set TkRemind options"
label .b.status -text "" -width 25 -relief sunken -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) button .b.queue -text {Queue...} -command {DoQueue} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
label .b.nqueued -text "" -width 20 -relief sunken -border 1 -foreground $Option(LabelColor) -background $Option(WinBackground) balloon_add_help .b.queue "See the queue of pending reminders (debugging purposes only)"
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.queue .b.quit -side left -fill both button .b.quit -text {Quit} -command {Quit} -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 1 -highlightcolor $Option(LineColor) -highlightbackground $Option(WinBackground)
pack .b.status -side left -fill both -expand 1 balloon_add_help .b.quit "Quit TkRemind"
pack .b.nqueued -side left -fill both label .b.status -text "" -width 25 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
pack .b -side bottom -fill x -expand 0 label .b.nqueued -text "" -width 20 -relief flat -bd 0 -foreground $Option(LabelColor) -background $Option(WinBackground) -highlightthickness 0
pack .b.prev .b.this .b.next .b.goto .b.print .b.options .b.queue .b.quit -side left -fill both -padx 1
pack .b.status -side left -fill both -expand 1 -padx 1
pack .b.nqueued -side left -fill both -padx 1
pack .b -side bottom -fill x -expand 0 -pady 1
pack .cal -side top -fill both -expand 1 pack .cal -side top -fill both -expand 1
wm title . "TkRemind" wm title . "TkRemind"
wm iconname . "" wm iconname . ""
@@ -689,7 +723,7 @@ proc EditOptions {} {
pack $w.cmd -in $w.rf -side left -expand 1 -fill x pack $w.cmd -in $w.rf -side left -expand 1 -fill x
$w.cmd insert 0 $tmpOpt(RunCmd) $w.cmd insert 0 $tmpOpt(RunCmd)
frame $w.sep3 -border 1 -relief sunken frame $w.sep3 -bd 1 -relief sunken
# E-mail reminder if popup not dismissed # E-mail reminder if popup not dismissed
frame $w.eml frame $w.eml
label $w.lab_email_address -text "E-mail reminders here if popup not dismissed:" -anchor w -justify left label $w.lab_email_address -text "E-mail reminders here if popup not dismissed:" -anchor w -justify left
@@ -734,6 +768,12 @@ proc EditOptions {} {
label $w.bgcolor -text " Background color:" label $w.bgcolor -text " Background color:"
button $w.bbgcolor -background $Option(BackgroundColor) -command [list PickColor BackgroundColor $w.bbgcolor] -text ... button $w.bbgcolor -background $Option(BackgroundColor) -command [list PickColor BackgroundColor $w.bbgcolor] -text ...
label $w.tbgcolor -text "Color for highlighting \"today\":"
button $w.tbbgcolor -background $Option(TodayColor) -command [list PickColor TodayColor $w.tbbgcolor] -text ...
label $w.gridcolor -text " Gridline color:"
button $w.gridbcolor -background $Option(LineColor) -command [list PickColor LineColor $w.gridbcolor] -text ...
grid $w.textcolor $w.btextcolor $w.bgcolor $w.bbgcolor -in $w.colors1 grid $w.textcolor $w.btextcolor $w.bgcolor $w.bbgcolor -in $w.colors1
grid $w.bgcolor $w.bbgcolor -in $w.colors1 grid $w.bgcolor $w.bbgcolor -in $w.colors1
@@ -742,11 +782,12 @@ proc EditOptions {} {
label $w.wincolor -text " Window color:" label $w.wincolor -text " Window color:"
button $w.bwincolor -background $Option(WinBackground) -command [list PickColor WinBackground $w.bwincolor] -text ... button $w.bwincolor -background $Option(WinBackground) -command [list PickColor WinBackground $w.bwincolor] -text ...
grid $w.headcolor $w.bheadcolor $w.wincolor $w.bwincolor -in $w.colors1 grid $w.headcolor $w.bheadcolor $w.wincolor $w.bwincolor -in $w.colors1
grid $w.tbgcolor $w.tbbgcolor $w.gridcolor $w.gridbcolor -in $w.colors1
grid columnconfigure $w.colors1 0 -weight 1 grid columnconfigure $w.colors1 0 -weight 1
grid columnconfigure $w.colors1 2 -weight 1 grid columnconfigure $w.colors1 2 -weight 1
frame $w.sep1 -border 1 -relief sunken frame $w.sep1 -bd 1 -relief sunken
frame $w.sep2 -border 1 -relief sunken frame $w.sep2 -bd 1 -relief sunken
checkbutton $w.feed \ checkbutton $w.feed \
-text "Feed popped-up reminder to command's standard input" \ -text "Feed popped-up reminder to command's standard input" \
@@ -770,10 +811,12 @@ proc EditOptions {} {
pack $w.colors1 -in $w.f -side top -expand 0 -fill x pack $w.colors1 -in $w.f -side top -expand 0 -fill x
pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1 pack $w.sep2 -in $w.f -side top -expand 0 -fill x -ipady 1
button $w.default -text "Light Theme" -command [list set_default_colors $w]
button $w.dark -text "Dark Theme" -command [list set_dark_colors $w]
button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w" button $w.save -text "Save Options" -command "SaveOptions $w; destroy $w"
button $w.cancel -text "Cancel" -command "CancelOptions; destroy $w" button $w.cancel -text "Cancel" -command "CancelOptions; destroy $w"
wm protocol $w WM_DELETE_WINDOW "CancelOptions; destroy $w" wm protocol $w WM_DELETE_WINDOW "CancelOptions; destroy $w"
pack $w.save $w.cancel -in $w.b -side left -expand 0 -fill x pack $w.default $w.dark $w.save $w.cancel -in $w.b -side left -expand 0 -fill x
CenterWindow $w . CenterWindow $w .
} }
@@ -845,6 +888,10 @@ proc SaveOptions { w } {
.b.queue configure -foreground $Option(LabelColor) -background $Option(WinBackground) .b.queue configure -foreground $Option(LabelColor) -background $Option(WinBackground)
.b.quit configure -foreground $Option(LabelColor) -background $Option(WinBackground) .b.quit configure -foreground $Option(LabelColor) -background $Option(WinBackground)
.b.options configure -foreground $Option(LabelColor) -background $Option(WinBackground) .b.options configure -foreground $Option(LabelColor) -background $Option(WinBackground)
. configure -background $Option(LineColor);
.h configure -background $Option(LineColor);
.cal configure -background $Option(LineColor)
.b configure -background $Option(LineColor)
} }
proc WriteOptionsToFile {} { proc WriteOptionsToFile {} {
@@ -939,11 +986,12 @@ proc ConfigureCalWindow { month year firstDay numDays } {
proc FillCalWindow {} { proc FillCalWindow {} {
set FileName "" set FileName ""
set LineNo 0 set LineNo 0
global DayNames CurYear CurMonth MonthNames CommandLine Option TagToObj global DayNames CurYear CurMonth MonthNames CommandLine Option TagToObj RemindErrors
array unset TagToObj array unset TagToObj
Status "Firing off Remind..." Status "Firing off Remind..."
set_button_to_queue
set month [lindex $MonthNames $CurMonth] set month [lindex $MonthNames $CurMonth]
set cmd [regsub EXTRA $CommandLine $Option(ExtraRemindArgs)] set cmd [regsub EXTRA $CommandLine $Option(ExtraRemindArgs)]
@@ -1032,7 +1080,7 @@ proc FillCalWindow {} {
continue continue
} }
"MOON" { "MOON" {
DoMoonSpecial $n $stuff $fntag DoMoonSpecial $n $stuff $fntag $day
continue continue
} }
"COLOUR" - "COLOUR" -
@@ -1057,7 +1105,7 @@ proc FillCalWindow {} {
set extratags "clr$color" set extratags "clr$color"
.cal.t$n configure -state normal .cal.t$n configure -state normal
.cal.t$n tag configure $extratags -foreground "#$color" .cal.t$n tag configure $extratags -foreground "#$color"
.cal.t$n configure -state disabled .cal.t$n configure -state disabled -takefocus 0
set stuff $rest set stuff $rest
set type "COLOR" set type "COLOR"
} }
@@ -1083,16 +1131,27 @@ proc FillCalWindow {} {
} }
} }
.cal.t$n insert end "\n" .cal.t$n insert end "\n"
.cal.t$n configure -state disabled .cal.t$n configure -state disabled -takefocus 0
} }
set problem [catch { close $file } errmsg] set problem [catch { close $file } errmsg]
if {$problem} { if {$problem} {
tk_dialog .error Error "There was a problem running Remind: $errmsg" error 0 OK set RemindErrors [unique_lines $errmsg]
set_button_to_errors
} }
DisplayTime DisplayTime
} }
proc unique_lines { s } {
set l [split $s "\n"]
foreach line $l {
if {"$line" != ""} {
dict set d $line 1
}
}
return [join [dict keys $d] "\n"]
}
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# MoveMonth -- move by +1 or -1 months # MoveMonth -- move by +1 or -1 months
# Arguments: # Arguments:
@@ -1152,13 +1211,13 @@ proc DoPrint {} {
toplevel .p toplevel .p
wm title .p "TkRemind Print..." wm title .p "TkRemind Print..."
wm iconname .p "Print..." wm iconname .p "Print..."
frame .p.f1 -relief sunken -border 2 frame .p.f1 -relief sunken -bd 2
frame .p.f11 frame .p.f11
frame .p.f12 frame .p.f12
frame .p.f2 -relief sunken -border 2 frame .p.f2 -relief sunken -bd 2
frame .p.f2a -relief sunken -border 2 frame .p.f2a -relief sunken -bd 2
frame .p.f3 -relief sunken -border 2 frame .p.f3 -relief sunken -bd 2
frame .p.f3a -relief sunken -border 2 frame .p.f3a -relief sunken -bd 2
frame .p.f4 frame .p.f4
radiobutton .p.tofile -text "To file: " -variable Option(PrintDest) -value file radiobutton .p.tofile -text "To file: " -variable Option(PrintDest) -value file
@@ -1169,7 +1228,7 @@ proc DoPrint {} {
.p.command insert end "lpr" .p.command insert end "lpr"
if { $HaveRem2PDF } { if { $HaveRem2PDF } {
frame .p.ff -relief sunken -border 2 frame .p.ff -relief sunken -bd 2
label .p.format -text "Output Format:" label .p.format -text "Output Format:"
radiobutton .p.pdf -text "PDF" -variable Option(PrintFormat) -value pdf radiobutton .p.pdf -text "PDF" -variable Option(PrintFormat) -value pdf
radiobutton .p.ps -text "PostScript" -variable Option(PrintFormat) -value ps radiobutton .p.ps -text "PostScript" -variable Option(PrintFormat) -value ps
@@ -1451,16 +1510,16 @@ proc CreateModifyDialog {w day firstDay args} {
set month [lindex $MonthNames $CurMonth] set month [lindex $MonthNames $CurMonth]
set wkday [lindex $EnglishDayNames [expr ($day+$firstDay-1) % 7]] set wkday [lindex $EnglishDayNames [expr ($day+$firstDay-1) % 7]]
frame $w.o -border 4 -relief ridge frame $w.o -bd 4 -relief ridge
frame $w.o1 -border 4 frame $w.o1 -bd 4
frame $w.o2 -border 4 frame $w.o2 -bd 4
frame $w.o3 -border 4 frame $w.o3 -bd 4
frame $w.exp -border 4 frame $w.exp -bd 4
frame $w.adv -border 4 frame $w.adv -bd 4
frame $w.weekend -border 4 frame $w.weekend -bd 4
frame $w.durationbox -border 4 frame $w.durationbox -bd 4
frame $w.time -border 4 frame $w.time -bd 4
frame $w.hol -border 4 frame $w.hol -bd 4
frame $w.msg frame $w.msg
frame $w.buttons frame $w.buttons
pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o pack $w.o1 $w.o2 $w.o3 -side top -anchor w -in $w.o
@@ -3530,7 +3589,7 @@ proc DoShadeSpecial { n r g b } {
# %DESCRIPTION: # %DESCRIPTION:
# Handles the "MOON" special -- draws a moon symbol # Handles the "MOON" special -- draws a moon symbol
#*********************************************************************** #***********************************************************************
proc DoMoonSpecial { n stuff fntag } { proc DoMoonSpecial { n stuff fntag day } {
set msg "" set msg ""
set num [scan $stuff "%d %d %d %s" phase junk1 junk2 msg] set num [scan $stuff "%d %d %d %s" phase junk1 junk2 msg]
if {$num < 1} { if {$num < 1} {
@@ -3539,11 +3598,27 @@ proc DoMoonSpecial { n stuff fntag } {
if {$phase < 0 || $phase > 3} { if {$phase < 0 || $phase > 3} {
return return
} }
switch -exact -- $phase {
0 { set win .moon_new } # We need two sets of moon phase windows. There can be
1 { set win .moon_first } # two of a given phase in the same month, but Tk does
2 { set win .moon_full } # not allow the same embedded window in two separate
3 { set win .moon_last } # text boxes. So we use this hack to make sure
# we use a different window if the same moon phase
# happens twice in a month.
if { $day < 16 } {
switch -exact -- $phase {
0 { set win .moon_new }
1 { set win .moon_first }
2 { set win .moon_full }
3 { set win .moon_last }
}
} else {
switch -exact -- $phase {
0 { set win .moon_new2 }
1 { set win .moon_first2 }
2 { set win .moon_full2 }
3 { set win .moon_last2 }
}
} }
.cal.t$n configure -state normal .cal.t$n configure -state normal
.cal.t$n window create 1.0 -window $win .cal.t$n window create 1.0 -window $win
@@ -3569,7 +3644,7 @@ proc DoMoonSpecial { n stuff fntag } {
.cal.t$n tag bind $fntag <ButtonPress-1> "FireEditor .cal.t$n $fntag" .cal.t$n tag bind $fntag <ButtonPress-1> "FireEditor .cal.t$n $fntag"
} }
} }
.cal.t$n configure -state disabled .cal.t$n configure -state disabled -takefocus 0
} }
#*********************************************************************** #***********************************************************************
# %PROCEDURE: DisplayTime # %PROCEDURE: DisplayTime
@@ -3607,6 +3682,11 @@ proc CreateMoonWindows {} {
catch { destroy .moon_full } catch { destroy .moon_full }
catch { destroy .moon_last } catch { destroy .moon_last }
catch { destroy .moon_new2 }
catch { destroy .moon_first2}
catch { destroy .moon_full2 }
catch { destroy .moon_last2 }
set extra 1 set extra 1
#set wid [font measure CalboxFont 0] #set wid [font measure CalboxFont 0]
set wid [font metrics CalboxFont -ascent] set wid [font metrics CalboxFont -ascent]
@@ -3633,10 +3713,29 @@ proc CreateMoonWindows {} {
.moon_last create oval $extra $extra $w $w -outline $Option(TextColor) -width 1 .moon_last create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
.moon_last create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 270 -extent 180 -outline {} .moon_last create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 270 -extent 180 -outline {}
canvas .moon_new2 -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
.moon_new2 create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
canvas .moon_first2 -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
.moon_first2 create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
.moon_first2 create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 90 -extent 180 -outline {}
canvas .moon_full2 -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
.moon_full2 create oval $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -width 1
canvas .moon_last2 -background $Option(BackgroundColor) -width $wid -height $wid -borderwidth 0 -highlightthickness 0
.moon_last2 create oval $extra $extra $w $w -outline $Option(TextColor) -width 1
.moon_last2 create arc $extra $extra $w $w -outline $Option(TextColor) -fill $Option(TextColor) -start 270 -extent 180 -outline {}
balloon_add_help .moon_new "New Moon" balloon_add_help .moon_new "New Moon"
balloon_add_help .moon_first "First Quarter" balloon_add_help .moon_first "First Quarter"
balloon_add_help .moon_full "Full Moon" balloon_add_help .moon_full "Full Moon"
balloon_add_help .moon_last "Last Quarter" balloon_add_help .moon_last "Last Quarter"
balloon_add_help .moon_new2 "New Moon"
balloon_add_help .moon_first2 "First Quarter"
balloon_add_help .moon_full2 "Full Moon"
balloon_add_help .moon_last2 "Last Quarter"
} }
#*********************************************************************** #***********************************************************************
@@ -3996,4 +4095,72 @@ proc FindConfigFile {} {
set ConfigFile "~/.tkremindrc" set ConfigFile "~/.tkremindrc"
} }
proc set_default_colors { w } {
global tmpOpt
set tmpOpt(BackgroundColor) "#d9d9d9"
set tmpOpt(LabelColor) "#000000"
set tmpOpt(LineColor) "#000000"
set tmpOpt(TextColor) "#000000"
set tmpOpt(TodayColor) "#00C0C0"
set tmpOpt(WinBackground) "#d9d9d9"
update_color_buttons $w
}
proc set_dark_colors { w } {
global tmpOpt
set tmpOpt(BackgroundColor) "#000000"
set tmpOpt(LabelColor) "#00ffff"
set tmpOpt(LineColor) "#0080fc"
set tmpOpt(TextColor) "#ffffff"
set tmpOpt(TodayColor) "#b000b6"
set tmpOpt(WinBackground) "#000000"
update_color_buttons $w
}
proc update_color_buttons { w } {
global tmpOpt
$w.bbgcolor configure -background $tmpOpt(BackgroundColor)
$w.bheadcolor configure -background $tmpOpt(LabelColor)
$w.gridbcolor configure -background $tmpOpt(LineColor)
$w.btextcolor configure -background $tmpOpt(TextColor)
$w.tbbgcolor configure -background $tmpOpt(TodayColor)
$w.bwincolor configure -background $tmpOpt(WinBackground)
}
proc set_button_to_queue {} {
.b.queue configure -text {Queue...} -command {DoQueue}
}
proc set_button_to_errors {} {
.b.queue configure -text {Errors...} -command {ShowErrors}
}
proc ShowErrors {} {
global RemindErrors
set w ".errors"
catch { destroy $w }
toplevel $w
text $w.t -width 80 -height 30 -wrap word -yscrollcommand "$w.sb set"
scrollbar $w.sb -orient vertical -command "$w.t yview"
button $w.ok -text OK -command DoneShowingErrors
grid $w.t -row 0 -column 0 -sticky nsew
grid $w.sb -row 0 -column 1 -sticky ns
grid $w.ok -row 1 -column 0 -stick w
grid columnconfigure $w 0 -weight 1
grid columnconfigure $w 1 -weight 0
grid rowconfigure $w 0 -weight 1
grid rowconfigure $w 1 -weight 0
$w.t insert end $RemindErrors
$w.t configure -state disabled
CenterWindow $w .
}
proc DoneShowingErrors {} {
global RemindErrors
set RemindErrors {}
set_button_to_queue
destroy .errors
}
# Rem2PS program to execute -- supply full path if you want
main main

View File

@@ -15,6 +15,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
@@ -26,6 +27,10 @@
#include <wchar.h> #include <wchar.h>
#endif #endif
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#include "types.h" #include "types.h"
#include "protos.h" #include "protos.h"
#include "expr.h" #include "expr.h"
@@ -75,6 +80,8 @@ static struct line_drawing VT100Drawing = {
"\x6c", "\x74", "\x6a", "\x71" "\x6c", "\x74", "\x6a", "\x71"
}; };
static int encoding_is_utf8 = 0;
static struct line_drawing UTF8Drawing = { static struct line_drawing UTF8Drawing = {
"", "", "", "",
"\xe2\x94\xb4", "\xe2\x94\xb4",
@@ -248,6 +255,17 @@ static void WriteBottomCalLine (void);
static void WriteIntermediateCalLine (void); static void WriteIntermediateCalLine (void);
static void WriteCalDays (void); static void WriteCalDays (void);
static void
send_lrm(void)
{
/* Send a lrm control sequence if UseUTF8Chars is enabled
or char encoding is UTF-8
*/
if (UseUTF8Chars || encoding_is_utf8) {
printf("\xE2\x80\x8E");
}
}
static char const * static char const *
despace(char const *s) despace(char const *s)
{ {
@@ -587,6 +605,14 @@ void ProduceCalendar(void)
{ {
int y, m, d; int y, m, d;
/* Check if current locale is UTF-8, if we have langinfo.h */
#ifdef HAVE_LANGINFO_H
char const *encoding = nl_langinfo(CODESET);
if (!strcasecmp(encoding, "utf-8")) {
encoding_is_utf8 = 1;
}
#endif
if (UseUTF8Chars) { if (UseUTF8Chars) {
linestruct = &UTF8Drawing; linestruct = &UTF8Drawing;
} else if (UseVTChars) { } else if (UseVTChars) {
@@ -975,6 +1001,10 @@ static void PrintLeft(char const *s, int width, char pad)
while (*ws && wcwidth(*ws) == 0) { while (*ws && wcwidth(*ws) == 0) {
PutWideChar(*ws++); PutWideChar(*ws++);
} }
/* Possibly send lrm control sequence */
send_lrm();
for (i=display_len; i<width; i++) fputc(pad, stdout); for (i=display_len; i<width; i++) fputc(pad, stdout);
if (buf != static_buf) free(buf); if (buf != static_buf) free(buf);
#endif #endif
@@ -1055,6 +1085,9 @@ static void PrintCentered(char const *s, int width, char *pad)
while (*ws && wcwidth(*ws) == 0) { while (*ws && wcwidth(*ws) == 0) {
PutWideChar(*ws++); PutWideChar(*ws++);
} }
/* Possibly send lrm control sequence */
send_lrm();
for (i=d+display_len; i<width; i++) fputs(pad, stdout); for (i=d+display_len; i<width; i++) fputs(pad, stdout);
if (buf != static_buf) free(buf); if (buf != static_buf) free(buf);
#endif #endif
@@ -1089,7 +1122,6 @@ static int WriteOneCalLine(void)
return done; return done;
} }
/***************************************************************/ /***************************************************************/
/* */ /* */
/* WriteOneColLine */ /* WriteOneColLine */
@@ -1140,9 +1172,14 @@ static int WriteOneColLine(int col)
} }
if (iswspace(*ws)) { if (iswspace(*ws)) {
wspace = ws; wspace = ws;
}
if (wcwidth(*ws)) {
width++; width++;
} else {
if (wcwidth(*ws)) {
width += wcwidth(*ws);
if (width > ColSpaces) {
break;
}
}
} }
ws++; ws++;
} }
@@ -1154,13 +1191,16 @@ static int WriteOneColLine(int col)
/* If we couldn't find a space char, print what we have. */ /* If we couldn't find a space char, print what we have. */
if (!wspace) { if (!wspace) {
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) { for (ws = e->wc_pos; numwritten < ColSpaces; ws++) {
if (!*ws) break; if (!*ws) break;
if (iswspace(*ws)) { if (iswspace(*ws)) {
putchar(' '); putchar(' ');
numwritten++; numwritten++;
} else { } else {
if (wcwidth(*ws) > 0) { if (wcwidth(*ws) > 0) {
if (numwritten + wcwidth(*ws) > ColSpaces) {
break;
}
numwritten += wcwidth(*ws); numwritten += wcwidth(*ws);
} }
PutWideChar(*ws); PutWideChar(*ws);
@@ -1188,6 +1228,9 @@ static int WriteOneColLine(int col)
printf("%s", Decolorize(e->r, e->g, e->b)); printf("%s", Decolorize(e->r, e->g, e->b));
} }
/* Possibly send lrm control sequence */
send_lrm();
/* Flesh out the rest of the column */ /* Flesh out the rest of the column */
while(numwritten++ < ColSpaces) putchar(' '); while(numwritten++ < ColSpaces) putchar(' ');

View File

@@ -20,6 +20,8 @@
#undef HAVE_LOCALE_H #undef HAVE_LOCALE_H
#undef HAVE_LANGINFO_H
#undef HAVE_GLOB #undef HAVE_GLOB
#undef HAVE_SETENV #undef HAVE_SETENV

View File

@@ -116,7 +116,7 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */ /* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAL_STACK_SIZE 500 #define VAL_STACK_SIZE 1000
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */ /* INCLUDE_NEST: How many nested INCLUDES do we handle? */

View File

@@ -116,7 +116,7 @@
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */ /* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAL_STACK_SIZE 500 #define VAL_STACK_SIZE 1000
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */ /* INCLUDE_NEST: How many nested INCLUDES do we handle? */

View File

@@ -28,7 +28,7 @@ static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
static int ParseLocalOmit (ParsePtr s, Trigger *t); static int ParseLocalOmit (ParsePtr s, Trigger *t);
static int ParseScanFrom (ParsePtr s, Trigger *t, int type); static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
static int ParsePriority (ParsePtr s, Trigger *t); static int ParsePriority (ParsePtr s, Trigger *t);
static int ParseUntil (ParsePtr s, Trigger *t); static int ParseUntil (ParsePtr s, Trigger *t, int type);
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err); static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
static int ComputeTrigDuration(TimeTrig *t); static int ComputeTrigDuration(TimeTrig *t);
@@ -237,11 +237,15 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
tim->delta = DefaultTDelta; tim->delta = DefaultTDelta;
tim->rep = NO_REP; tim->rep = NO_REP;
tim->duration = NO_TIME; tim->duration = NO_TIME;
trig->need_wkday = 0;
trig->adj_for_last = 0;
if (save_in_globals) { if (save_in_globals) {
LastTriggerTime = NO_TIME; LastTriggerTime = NO_TIME;
} }
while(1) { int parsing = 1;
while(parsing) {
/* Read space-delimited string */ /* Read space-delimited string */
r = ParseToken(s, &buf); r = ParseToken(s, &buf);
if (r) return r; if (r) return r;
@@ -249,6 +253,25 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
/* Figure out what we've got */ /* Figure out what we've got */
FindToken(DBufValue(&buf), &tok); FindToken(DBufValue(&buf), &tok);
switch(tok.type) { switch(tok.type) {
case T_In:
/* Completely ignored */
DBufFree(&buf);
break;
case T_Ordinal:
DBufFree(&buf);
if (trig->d != NO_DAY) return E_DAY_TWICE;
if (tok.val < 0) {
if (trig->back != NO_BACK) return E_BACK_TWICE;
trig->back = -7;
trig->d = 1;
trig->adj_for_last = 1;
} else {
trig->d = 1 + 7 * tok.val;
}
trig->need_wkday = 1;
break;
case T_Date: case T_Date:
DBufFree(&buf); DBufFree(&buf);
if (trig->d != NO_DAY) return E_DAY_TWICE; if (trig->d != NO_DAY) return E_DAY_TWICE;
@@ -322,7 +345,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
DBufFree(&buf); DBufFree(&buf);
trig->typ = tok.val; trig->typ = tok.val;
if (s->isnested) return E_CANT_NEST_RTYPE; if (s->isnested) return E_CANT_NEST_RTYPE;
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
if (trig->typ == PASSTHRU_TYPE) { if (trig->typ == PASSTHRU_TYPE) {
r = ParseToken(s, &buf); r = ParseToken(s, &buf);
if (r) return r; if (r) return r;
@@ -332,19 +354,20 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
} }
StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN); StrnCpy(trig->passthru, DBufValue(&buf), PASSTHRU_LEN);
} }
return OK; parsing = 0;
break;
case T_Through: case T_Through:
DBufFree(&buf); DBufFree(&buf);
if (trig->rep != NO_REP) return E_REP_TWICE; if (trig->rep != NO_REP) return E_REP_TWICE;
trig->rep = 1; trig->rep = 1;
r = ParseUntil(s, trig); r = ParseUntil(s, trig, tok.type);
if (r) return r; if (r) return r;
break; break;
case T_Until: case T_Until:
DBufFree(&buf); DBufFree(&buf);
r=ParseUntil(s, trig); r=ParseUntil(s, trig, tok.type);
if (r) return r; if (r) return r;
break; break;
@@ -378,6 +401,15 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->back = tok.val; trig->back = tok.val;
break; break;
case T_BackAdj:
DBufFree(&buf);
if (trig->back != NO_BACK) return E_BACK_TWICE;
if (trig->d != NO_DAY) return E_DAY_TWICE;
trig->back = tok.val;
trig->d = 1;
trig->adj_for_last = 1;
break;
case T_Once: case T_Once:
DBufFree(&buf); DBufFree(&buf);
if (trig->once != NO_ONCE) return E_ONCE_TWICE; if (trig->once != NO_ONCE) return E_ONCE_TWICE;
@@ -392,7 +424,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
case T_Omit: case T_Omit:
DBufFree(&buf); DBufFree(&buf);
if (trig->omitfunc[0]) { if (trig->omitfunc[0]) {
Eprint("Warning: OMIT is ignored if you use OMITFUNC"); Wprint("Warning: OMIT is ignored if you use OMITFUNC");
} }
r = ParseLocalOmit(s, trig); r = ParseLocalOmit(s, trig);
@@ -401,12 +433,12 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
case T_Empty: case T_Empty:
DBufFree(&buf); DBufFree(&buf);
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; parsing = 0;
return OK; break;
case T_OmitFunc: case T_OmitFunc:
if (trig->localomit) { if (trig->localomit) {
Eprint("Warning: OMIT is ignored if you use OMITFUNC"); Wprint("Warning: OMIT is ignored if you use OMITFUNC");
} }
r=ParseToken(s, &buf); r=ParseToken(s, &buf);
if (r) return r; if (r) return r;
@@ -474,10 +506,58 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
DBufFree(&buf); DBufFree(&buf);
trig->typ = MSG_TYPE; trig->typ = MSG_TYPE;
if (s->isnested) return E_CANT_NEST_RTYPE; if (s->isnested) return E_CANT_NEST_RTYPE;
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday; parsing = 0;
return OK; break;
} }
} }
if (trig->need_wkday && trig->wd == NO_WD) {
Eprint("Weekday name(s) required");
return E_PARSE_ERR;
}
/* Adjust month and possibly year */
if (trig->adj_for_last) {
if (trig->m != NO_MON) {
trig->m++;
if (trig->m >= 12) {
trig->m = 0;
if (trig->y != NO_YR) {
trig->y++;
}
}
}
trig->adj_for_last = 0;
}
/* Check for some warning conditions */
if (!s->nonconst_expr) {
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL) {
if (Julian(trig->y, trig->m, trig->d) > trig->until) {
Wprint("Warning: UNTIL/THROUGH date earlier than start date");
}
}
if (trig->from != NO_DATE) {
if (trig->until != NO_UNTIL && trig->until < trig->from) {
Wprint("Warning: UNTIL/THROUGH date earlier than FROM date");
}
} else if (trig->scanfrom != NO_DATE) {
if (trig->until != NO_UNTIL && trig->until < trig->scanfrom) {
Wprint("Warning: UNTIL/THROUGH date earlier than SCANFROM date");
}
}
}
if (trig->y != NO_YR && trig->m != NO_MON && trig->d != NO_DAY && trig->until != NO_UNTIL && trig->rep == NO_REP) {
Wprint("Warning: Useless use of UNTIL with fully-specified date and no *rep");
}
/* Set scanfrom to default if not set explicitly */
if (trig->scanfrom == NO_DATE) {
trig->scanfrom = JulianToday;
}
return OK;
} }
/***************************************************************/ /***************************************************************/
@@ -568,12 +648,18 @@ static int ParseLocalOmit(ParsePtr s, Trigger *t)
/* ParseUntil - parse the UNTIL portion of a reminder */ /* ParseUntil - parse the UNTIL portion of a reminder */
/* */ /* */
/***************************************************************/ /***************************************************************/
static int ParseUntil(ParsePtr s, Trigger *t) static int ParseUntil(ParsePtr s, Trigger *t, int type)
{ {
int y = NO_YR, int y = NO_YR,
m = NO_MON, m = NO_MON,
d = NO_DAY; d = NO_DAY;
char const *which;
if (type == T_Until) {
which = "UNTIL";
} else {
which = "THROUGH";
}
Token tok; Token tok;
int r; int r;
DynamicBuffer buf; DynamicBuffer buf;
@@ -589,7 +675,7 @@ static int ParseUntil(ParsePtr s, Trigger *t)
case T_Year: case T_Year:
DBufFree(&buf); DBufFree(&buf);
if (y != NO_YR) { if (y != NO_YR) {
Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]); Eprint("%s: %s", which, ErrMsg[E_YR_TWICE]);
return E_YR_TWICE; return E_YR_TWICE;
} }
y = tok.val; y = tok.val;
@@ -598,7 +684,7 @@ static int ParseUntil(ParsePtr s, Trigger *t)
case T_Month: case T_Month:
DBufFree(&buf); DBufFree(&buf);
if (m != NO_MON) { if (m != NO_MON) {
Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]); Eprint("%s: %s", which, ErrMsg[E_MON_TWICE]);
return E_MON_TWICE; return E_MON_TWICE;
} }
m = tok.val; m = tok.val;
@@ -607,7 +693,7 @@ static int ParseUntil(ParsePtr s, Trigger *t)
case T_Day: case T_Day:
DBufFree(&buf); DBufFree(&buf);
if (d != NO_DAY) { if (d != NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]); Eprint("%s: %s", which, ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE; return E_DAY_TWICE;
} }
d = tok.val; d = tok.val;
@@ -616,15 +702,15 @@ static int ParseUntil(ParsePtr s, Trigger *t)
case T_Date: case T_Date:
DBufFree(&buf); DBufFree(&buf);
if (y != NO_YR) { if (y != NO_YR) {
Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]); Eprint("%s: %s", which, ErrMsg[E_YR_TWICE]);
return E_YR_TWICE; return E_YR_TWICE;
} }
if (m != NO_MON) { if (m != NO_MON) {
Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]); Eprint("%s: %s", which, ErrMsg[E_MON_TWICE]);
return E_MON_TWICE; return E_MON_TWICE;
} }
if (d != NO_DAY) { if (d != NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]); Eprint("%s: %s", which, ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE; return E_DAY_TWICE;
} }
FromJulian(tok.val, &y, &m, &d); FromJulian(tok.val, &y, &m, &d);
@@ -632,7 +718,7 @@ static int ParseUntil(ParsePtr s, Trigger *t)
default: default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) { if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]); Eprint("%s: %s", which, ErrMsg[E_INCOMPLETE]);
DBufFree(&buf); DBufFree(&buf);
return E_INCOMPLETE; return E_INCOMPLETE;
} }

View File

@@ -44,21 +44,32 @@ static int MakeValue (char const *s, Value *v, Var *locals, ParsePtr p);
/* Binary operators - all left-associative */ /* Binary operators - all left-associative */
/* Operator precedence:
* Highest: Unary - Unary !
* / %
* + -
* < <= > >=
* == !=
* &&
* Lowest: ||
*
*/
/* Make SURE they are sorted lexically... this may die on an EBCDIC /* Make SURE they are sorted lexically... this may die on an EBCDIC
system... */ system... */
Operator BinOp[] = { Operator BinOp[] = {
{ "!=", 15, BIN_OP, NotEqual }, { "!=", 15, BIN_OP, NotEqual },
{ "%", 20, BIN_OP, Mod }, { "%", 20, BIN_OP, Mod },
{ "&&", 14, BIN_OP, LogAND }, { "&&", 14, BIN_OP, LogAND },
{ "*", 20, BIN_OP, Multiply }, { "*", 20, BIN_OP, Multiply },
{ "+", 18, BIN_OP, Add }, { "+", 18, BIN_OP, Add },
{ "-", 18, BIN_OP, Subtract }, { "-", 18, BIN_OP, Subtract },
{ "/", 20, BIN_OP, Divide }, { "/", 20, BIN_OP, Divide },
{ "<", 16, BIN_OP, LessThan }, { "<", 16, BIN_OP, LessThan },
{ "<=", 16, BIN_OP, LessOrEqual }, { "<=", 16, BIN_OP, LessOrEqual },
{ "==", 15, BIN_OP, EqualTo }, { "==", 15, BIN_OP, EqualTo },
{ ">", 16, BIN_OP, GreaterThan }, { ">", 16, BIN_OP, GreaterThan },
{ ">=", 16, BIN_OP, GreaterOrEqual }, { ">=", 16, BIN_OP, GreaterOrEqual },
{ "||", 12, BIN_OP, LogOR }, { "||", 12, BIN_OP, LogOR },
}; };
@@ -66,8 +77,8 @@ Operator BinOp[] = {
/* These ones must be sorted too. */ /* These ones must be sorted too. */
Operator UnOp[] = { Operator UnOp[] = {
{ "!", 22, UN_OP, LogNot }, { "!", 22, UN_OP, LogNot },
{ "-", 22, UN_OP, UnMinus }, { "-", 22, UN_OP, UnMinus },
}; };
#define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator)) #define NUM_UN_OPS (sizeof(UnOp) / sizeof(Operator))
@@ -75,7 +86,8 @@ extern BuiltinFunc Func[];
Operator OpStack[OP_STACK_SIZE]; Operator OpStack[OP_STACK_SIZE];
Value ValStack[VAL_STACK_SIZE]; Value ValStack[VAL_STACK_SIZE];
int OpStackPtr, ValStackPtr; int OpStackPtr = 0;
int ValStackPtr = 0;
/***************************************************************/ /***************************************************************/
/* */ /* */
@@ -115,12 +127,13 @@ static int DebugPerform(Operator *op)
/* Clean the stack after an error occurs. */ /* Clean the stack after an error occurs. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static void CleanStack(void) static void CleanStack(int old_op_stack_ptr, int old_val_stack_ptr)
{ {
int i; int i;
for (i=0; i<ValStackPtr; i++) DestroyValue(ValStack[i]); for (i=old_val_stack_ptr; i<ValStackPtr; i++) DestroyValue(ValStack[i]);
ValStackPtr = 0; ValStackPtr = old_val_stack_ptr;
OpStackPtr = old_op_stack_ptr;
} }
/***************************************************************/ /***************************************************************/
@@ -306,8 +319,8 @@ int EvalExpr(char const **e, Value *v, ParsePtr p)
{ {
int r; int r;
OpStackPtr = 0; int old_op_stack_ptr = OpStackPtr;
ValStackPtr = 0; int old_val_stack_ptr = ValStackPtr;
r = Evaluate(e, NULL, p); r = Evaluate(e, NULL, p);
@@ -316,11 +329,15 @@ int EvalExpr(char const **e, Value *v, ParsePtr p)
DBufFree(&ExprBuf); DBufFree(&ExprBuf);
if (r) { if (r) {
CleanStack(); CleanStack(old_op_stack_ptr, old_val_stack_ptr);
/* fprintf(stderr, "O=%d V=%d\n", OpStackPtr, ValStackPtr); */
return r; return r;
} }
*v = *ValStack; OpStackPtr = old_op_stack_ptr;
ValStack[0].type = ERR_TYPE; ValStackPtr = old_val_stack_ptr;
*v = ValStack[old_val_stack_ptr];
ValStack[old_val_stack_ptr].type = ERR_TYPE;
/* fprintf(stderr, "O=%d V=%d\n", OpStackPtr, ValStackPtr); */
return r; return r;
} }
@@ -1108,13 +1125,16 @@ static int LogOR(void)
return r; return r;
} }
if (v1.type == INT_TYPE && v2.type == INT_TYPE) { if (v1.type != v2.type || v1.type == STR_TYPE || v2.type == STR_TYPE) {
v1.v.val = (v1.v.val || v2.v.val) ? 1 : 0; DestroyValue(v1); DestroyValue(v2);
PushValStack(v1); return E_BAD_TYPE;
return OK;
} }
DestroyValue(v1); DestroyValue(v2);
return E_BAD_TYPE; if (v1.v.val == 0) {
v1.v.val = v2.v.val;
}
PushValStack(v1);
return OK;
} }
/***************************************************************/ /***************************************************************/
@@ -1135,13 +1155,15 @@ static int LogAND(void)
return r; return r;
} }
if (v1.type == INT_TYPE && v2.type == INT_TYPE) { if (v1.type != v2.type || v1.type == STR_TYPE || v2.type == STR_TYPE) {
v1.v.val = (v1.v.val && v2.v.val) ? 1 : 0; DestroyValue(v1); DestroyValue(v2);
PushValStack(v1); return E_BAD_TYPE;
return OK;
} }
DestroyValue(v1); DestroyValue(v2); if (v1.v.val != 0) {
return E_BAD_TYPE; v1.v.val = v2.v.val;
}
PushValStack(v1);
return OK;
} }
/***************************************************************/ /***************************************************************/

View File

@@ -58,6 +58,7 @@ static int FADusk (func_info *);
static int FAbs (func_info *); static int FAbs (func_info *);
static int FAccess (func_info *); static int FAccess (func_info *);
static int FAmpm (func_info *); static int FAmpm (func_info *);
static int FTrig (func_info *);
static int FIsAny (func_info *); static int FIsAny (func_info *);
static int FArgs (func_info *); static int FArgs (func_info *);
static int FAsc (func_info *); static int FAsc (func_info *);
@@ -126,6 +127,7 @@ static int FSunset (func_info *);
static int FTime (func_info *); static int FTime (func_info *);
static int FTimepart (func_info *); static int FTimepart (func_info *);
static int FToday (func_info *); static int FToday (func_info *);
static int FTrig (func_info *);
static int FTrigback (func_info *); static int FTrigback (func_info *);
static int FTrigdate (func_info *); static int FTrigdate (func_info *);
static int FTrigdatetime (func_info *); static int FTrigdatetime (func_info *);
@@ -279,6 +281,7 @@ BuiltinFunc Func[] = {
{ "time", 2, 2, 1, FTime }, { "time", 2, 2, 1, FTime },
{ "timepart", 1, 1, 1, FTimepart }, { "timepart", 1, 1, 1, FTimepart },
{ "today", 0, 0, 0, FToday }, { "today", 0, 0, 0, FToday },
{ "trig", 0, NO_MAX, 0, FTrig },
{ "trigback", 0, 0, 0, FTrigback }, { "trigback", 0, 0, 0, FTrigback },
{ "trigdate", 0, 0, 0, FTrigdate }, { "trigdate", 0, 0, 0, FTrigdate },
{ "trigdatetime", 0, 0, 0, FTrigdatetime }, { "trigdatetime", 0, 0, 0, FTrigdatetime },
@@ -2411,8 +2414,7 @@ static int FPsshade(func_info *info)
if (!psshade_warned) { if (!psshade_warned) {
psshade_warned = 1; psshade_warned = 1;
Eprint("psshade() is deprecated; use SPECIAL SHADE instead."); Wprint("psshade() is deprecated; use SPECIAL SHADE instead.");
FreshLine = 1;
} }
sprintf(s, "/_A LineWidth 2 div def "); sprintf(s, "/_A LineWidth 2 div def ");
@@ -2467,8 +2469,7 @@ static int FPsmoon(func_info *info)
} }
if (!psmoon_warned) { if (!psmoon_warned) {
psmoon_warned = 1; psmoon_warned = 1;
Eprint("psmoon() is deprecated; use SPECIAL MOON instead."); Wprint("psmoon() is deprecated; use SPECIAL MOON instead.");
FreshLine = 1;
} }
if (size > 0) { if (size > 0) {
sprintf(sizebuf, "%d", size); sprintf(sizebuf, "%d", size);
@@ -2971,8 +2972,12 @@ FEvalTrig(func_info *info)
CreateParser(ARGSTR(0), &p); CreateParser(ARGSTR(0), &p);
p.allownested = 0; p.allownested = 0;
r = ParseRem(&p, &trig, &tim, 0); r = ParseRem(&p, &trig, &tim, 0);
if (r) return r; if (r) {
DestroyParser(&p);
return r;
}
if (trig.typ != NO_TYPE) { if (trig.typ != NO_TYPE) {
DestroyParser(&p);
FreeTrig(&trig); FreeTrig(&trig);
return E_PARSE_ERR; return E_PARSE_ERR;
} }
@@ -2981,7 +2986,7 @@ FEvalTrig(func_info *info)
} else { } else {
/* Hokey... */ /* Hokey... */
if (trig.scanfrom != JulianToday) { if (trig.scanfrom != JulianToday) {
Eprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()"); Wprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()");
} }
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0); jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
} }
@@ -2990,6 +2995,7 @@ FEvalTrig(func_info *info)
jul = -1; jul = -1;
} }
FreeTrig(&trig); FreeTrig(&trig);
DestroyParser(&p);
if (r) return r; if (r) return r;
if (jul < 0) { if (jul < 0) {
RetVal.type = INT_TYPE; RetVal.type = INT_TYPE;
@@ -3003,3 +3009,59 @@ FEvalTrig(func_info *info)
} }
return OK; return OK;
} }
static int LastTrig = 0;
static int
FTrig(func_info *info)
{
Parser p;
Trigger trig;
TimeTrig tim;
int jul;
int r;
int i;
RetVal.type = DATE_TYPE;
if (Nargs == 0) {
RETVAL = LastTrig;
return OK;
}
for (i=0; i<Nargs; i++) {
ASSERT_TYPE(i, STR_TYPE);
}
RETVAL = 0;
for (i=0; i<Nargs; i++) {
CreateParser(ARGSTR(i), &p);
p.allownested = 0;
r = ParseRem(&p, &trig, &tim, 0);
if (r) {
DestroyParser(&p);
return r;
}
if (trig.typ != NO_TYPE) {
DestroyParser(&p);
FreeTrig(&trig);
return E_PARSE_ERR;
}
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
if (r == E_CANT_TRIG) {
DestroyParser(&p);
FreeTrig(&trig);
continue;
}
if (ShouldTriggerReminder(&trig, &tim, jul, &r)) {
LastTrig = jul;
RETVAL = jul;
DestroyParser(&p);
FreeTrig(&trig);
return OK;
}
DestroyParser(&p);
FreeTrig(&trig);
}
return OK;
}

View File

@@ -88,7 +88,7 @@ EXTERN INIT( int DefaultColorB, -1);
EXTERN INIT( int DefaultColorG, -1); EXTERN INIT( int DefaultColorG, -1);
EXTERN INIT( int SynthesizeTags, 0); EXTERN INIT( int SynthesizeTags, 0);
EXTERN INIT( int ScFormat, SC_AMPM); EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 150); EXTERN INIT( int MaxSatIter, 1000);
EXTERN INIT( int MaxStringLen, MAX_STR_LEN); EXTERN INIT( int MaxStringLen, MAX_STR_LEN);
EXTERN INIT( char *FileName, NULL); EXTERN INIT( char *FileName, NULL);
EXTERN INIT( int UseStdin, 0); EXTERN INIT( int UseStdin, 0);

View File

@@ -698,7 +698,7 @@ void Usage(void)
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline f=tracefiles\n"); fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline f=tracefiles\n");
fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n"); fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n"); fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n"); fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=1000)\n");
fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\n"); fprintf(ErrFp, " -kcmd Run `cmd' for MSG-type reminders\n");
fprintf(ErrFp, " -g[dddd] Sort reminders by date, time, priority, and 'timedness'\n"); fprintf(ErrFp, " -g[dddd] Sort reminders by date, time, priority, and 'timedness'\n");
fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n"); fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");

View File

@@ -283,7 +283,7 @@ void Usage(void)
fprintf(ErrFp, " -d... Virheenetsintä: e=echo x=expr-eval t=trig v=dumpvars l=showline\n"); fprintf(ErrFp, " -d... Virheenetsintä: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n"); fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n");
fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n"); fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n");
fprintf(ErrFp, " -x[n] SATISFY-lauseen toistoraja (oletus 150)\n"); fprintf(ErrFp, " -x[n] SATISFY-lauseen toistoraja (oletus 1000)\n");
fprintf(ErrFp, " -kcmd Suorita 'cmd' MSG-tyyppisille viesteille\n"); fprintf(ErrFp, " -kcmd Suorita 'cmd' MSG-tyyppisille viesteille\n");
fprintf(ErrFp, " -g[ddd] Lajittele viestit päiväyksen, ajan ja tärkeyden mukaan\n"); fprintf(ErrFp, " -g[ddd] Lajittele viestit päiväyksen, ajan ja tärkeyden mukaan\n");
fprintf(ErrFp, " -ivar=val Alusta muuttuja var arvolla val ja säilytä var\n"); fprintf(ErrFp, " -ivar=val Alusta muuttuja var arvolla val ja säilytä var\n");

View File

@@ -258,7 +258,7 @@ void Usage(void)
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n"); fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Envoyer les messages de stderr à stdout\n"); fprintf(ErrFp, " -e Envoyer les messages de stderr à stdout\n");
fprintf(ErrFp, " -b[n] Formats de l'heure pour le calendrier: 0=am/pm, 1=24hr, 2=aucun\n"); fprintf(ErrFp, " -b[n] Formats de l'heure pour le calendrier: 0=am/pm, 1=24hr, 2=aucun\n");
fprintf(ErrFp, " -x[n] Limite d'itérations pour la clause SATISFY (def=150)\n"); fprintf(ErrFp, " -x[n] Limite d'itérations pour la clause SATISFY (def=1000)\n");
fprintf(ErrFp, " -kcmd Exécuter 'cmd' pour les rappels de type MSG\n"); fprintf(ErrFp, " -kcmd Exécuter 'cmd' pour les rappels de type MSG\n");
fprintf(ErrFp, " -g[ddd] Trier les rappels par date, heure et priorité avant d'émettre\n"); fprintf(ErrFp, " -g[ddd] Trier les rappels par date, heure et priorité avant d'émettre\n");
fprintf(ErrFp, " -ivar=val Initialiser var à val et conserver var\n"); fprintf(ErrFp, " -ivar=val Initialiser var à val et conserver var\n");

View File

@@ -270,7 +270,7 @@ void Usage(void)
fprintf(ErrFp, " -d... Odpluskwianie: e=echo x=expr-eval t=trig v=dumpvars l=showline\n"); fprintf(ErrFp, " -d... Odpluskwianie: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Komunikaty o błędach skieruj na stdout\n"); fprintf(ErrFp, " -e Komunikaty o błędach skieruj na stdout\n");
fprintf(ErrFp, " -b[n] Format czasu: 0=am/pm, 1=24godz., 2=żaden\n"); fprintf(ErrFp, " -b[n] Format czasu: 0=am/pm, 1=24godz., 2=żaden\n");
fprintf(ErrFp, " -x[n] Limit powtórzeń klauzuli SATISFY (domyślnie=150)\n"); fprintf(ErrFp, " -x[n] Limit powtórzeń klauzuli SATISFY (domyślnie=1000)\n");
fprintf(ErrFp, " -kcmd Wywołaj 'cmd' dla przypomnień typu MSG\n"); fprintf(ErrFp, " -kcmd Wywołaj 'cmd' dla przypomnień typu MSG\n");
fprintf(ErrFp, " -g[ddd] Sortuj przypomnienia według daty, czasu i priorytetu\n"); fprintf(ErrFp, " -g[ddd] Sortuj przypomnienia według daty, czasu i priorytetu\n");
fprintf(ErrFp, " -ivar=val Zainicjuj zmienną var wartościa val i zachowaj ja\n"); fprintf(ErrFp, " -ivar=val Zainicjuj zmienną var wartościa val i zachowaj ja\n");

View File

@@ -283,7 +283,7 @@ void Usage(void)
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trigger v=dumpvars l=showline\n"); fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trigger v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Desvia mensagens normalmente enviadas a stderr para stdout\n"); fprintf(ErrFp, " -e Desvia mensagens normalmente enviadas a stderr para stdout\n");
fprintf(ErrFp, " -b[n] Formato da hora para o cal: 0=am/pm, 1=24hr, 2=nenhum\n"); fprintf(ErrFp, " -b[n] Formato da hora para o cal: 0=am/pm, 1=24hr, 2=nenhum\n");
fprintf(ErrFp, " -x[n] Limite de iteracoes para a clausula SATISFY (default=150)\n"); fprintf(ErrFp, " -x[n] Limite de iteracoes para a clausula SATISFY (default=1000)\n");
fprintf(ErrFp, " -kcmd Executa `cmd' para os compromissos com MSG\n"); fprintf(ErrFp, " -kcmd Executa `cmd' para os compromissos com MSG\n");
fprintf(ErrFp, " -g[ddd] Classifica compromissos por data, hora e prioridade antes de exibir\n"); fprintf(ErrFp, " -g[ddd] Classifica compromissos por data, hora e prioridade antes de exibir\n");
fprintf(ErrFp, " -ivar=val Inicializa (e preserva) variavel var com val\n"); fprintf(ErrFp, " -ivar=val Inicializa (e preserva) variavel var com val\n");

View File

@@ -568,6 +568,29 @@ int EvaluateExpr(ParsePtr p, Value *v)
return OK; return OK;
} }
/***************************************************************/
/* */
/* Wprint - print a warning message. */
/* */
/***************************************************************/
void Wprint(char const *fmt, ...)
{
va_list argptr;
if (FileName) {
if (strcmp(FileName, "-"))
(void) fprintf(ErrFp, "%s(%d): ", FileName, LineNo);
else
(void) fprintf(ErrFp, "-stdin-(%d): ", LineNo);
}
va_start(argptr, fmt);
(void) vfprintf(ErrFp, fmt, argptr);
(void) fputc('\n', ErrFp);
va_end(argptr);
return;
}
/***************************************************************/ /***************************************************************/
/* */ /* */
/* Eprint - print an error message. */ /* Eprint - print an error message. */

View File

@@ -463,7 +463,7 @@ DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
end = Julian(yend, mend, dend); end = Julian(yend, mend, dend);
if (end < start) { if (end < start) {
Eprint("Warning: Swapping dates on OMIT ... THROUGH ... line"); Wprint("Warning: Swapping dates on OMIT ... THROUGH ... line");
tmp = start; tmp = start;
start = end; start = end;
end = tmp; end = tmp;

View File

@@ -62,6 +62,7 @@ int EvaluateExpr (ParsePtr p, Value *v);
int Evaluate (char const **s, Var *locals, ParsePtr p); int Evaluate (char const **s, Var *locals, ParsePtr p);
int FnPopValStack (Value *val); int FnPopValStack (Value *val);
void Eprint (char const *fmt, ...); void Eprint (char const *fmt, ...);
void Wprint (char const *fmt, ...);
void OutputLine (FILE *fp); void OutputLine (FILE *fp);
void CreateParser (char const *s, ParsePtr p); void CreateParser (char const *s, ParsePtr p);
void DestroyParser (ParsePtr p); void DestroyParser (ParsePtr p);

View File

@@ -43,30 +43,36 @@ Token TokArray[] = {
{ "at", 2, T_At, 0 }, { "at", 2, T_At, 0 },
{ "august", 3, T_Month, 7 }, { "august", 3, T_Month, 7 },
{ "banner", 3, T_Banner, 0 }, { "banner", 3, T_Banner, 0 },
{ "before", 3, T_Skip, BEFORE_SKIP }, { "before", 3, T_Skip, BEFORE_SKIP },
{ "cal", 3, T_RemType, CAL_TYPE }, { "cal", 3, T_RemType, CAL_TYPE },
{ "clear-omit-context", 5, T_Clr, 0 }, { "clear-omit-context", 5, T_Clr, 0 },
{ "debug", 5, T_Debug, 0 }, { "debug", 5, T_Debug, 0 },
{ "december", 3, T_Month, 11 }, { "december", 3, T_Month, 11 },
{ "do", 2, T_IncludeR, 0 }, { "do", 2, T_IncludeR, 0 },
{ "dumpvars", 4, T_Dumpvars, 0 }, { "dumpvars", 4, T_Dumpvars, 0 },
{ "duration", 3, T_Duration, 0 }, { "duration", 3, T_Duration, 0 },
{ "else", 4, T_Else, 0 }, { "else", 4, T_Else, 0 },
{ "endif", 5, T_EndIf, 0 }, { "endif", 5, T_EndIf, 0 },
{ "errmsg", 6, T_ErrMsg, 0 }, { "errmsg", 6, T_ErrMsg, 0 },
{ "exit", 4, T_Exit, 0 }, { "exit", 4, T_Exit, 0 },
{ "february", 3, T_Month, 1 }, { "february", 3, T_Month, 1 },
{ "first", 5, T_Ordinal, 0 },
{ "flush", 5, T_Flush, 0 }, { "flush", 5, T_Flush, 0 },
{ "fourth", 6, T_Ordinal, 3 },
{ "friday", 3, T_WkDay, 4 }, { "friday", 3, T_WkDay, 4 },
{ "from", 4, T_Scanfrom, FROM_TYPE }, { "from", 4, T_Scanfrom, FROM_TYPE },
{ "fset", 4, T_Fset, 0 }, { "fset", 4, T_Fset, 0 },
{ "if", 2, T_If, 0 }, { "if", 2, T_If, 0 },
{ "iftrig", 6, T_IfTrig, 0 }, { "iftrig", 6, T_IfTrig, 0 },
{ "in", 2, T_In, 0 },
{ "include", 3, T_Include, 0 }, { "include", 3, T_Include, 0 },
{ "includecmd", 10, T_IncludeCmd, 0 }, { "includecmd", 10, T_IncludeCmd, 0 },
{ "january", 3, T_Month, 0 }, { "january", 3, T_Month, 0 },
{ "july", 3, T_Month, 6 }, { "july", 3, T_Month, 6 },
{ "june", 3, T_Month, 5 }, { "june", 3, T_Month, 5 },
{ "last", 4, T_Ordinal, -1 },
{ "lastday", 7, T_BackAdj, -1 },
{ "lastworkday", 11, T_BackAdj, 1 },
{ "march", 3, T_Month, 2 }, { "march", 3, T_Month, 2 },
{ "may", 3, T_Month, 4 }, { "may", 3, T_Month, 4 },
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0}, { "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
@@ -90,12 +96,14 @@ Token TokArray[] = {
{ "saturday", 3, T_WkDay, 5 }, { "saturday", 3, T_WkDay, 5 },
{ "scanfrom", 4, T_Scanfrom, SCANFROM_TYPE }, { "scanfrom", 4, T_Scanfrom, SCANFROM_TYPE },
{ "sched", 5, T_Sched, 0 }, { "sched", 5, T_Sched, 0 },
{ "second", 6, T_Ordinal, 1 },
{ "september", 3, T_Month, 8 }, { "september", 3, T_Month, 8 },
{ "set", 3, T_Set, 0 }, { "set", 3, T_Set, 0 },
{ "skip", 3, T_Skip, SKIP_SKIP }, { "skip", 3, T_Skip, SKIP_SKIP },
{ "special", 7, T_RemType, PASSTHRU_TYPE }, { "special", 7, T_RemType, PASSTHRU_TYPE },
{ "sunday", 3, T_WkDay, 6 }, { "sunday", 3, T_WkDay, 6 },
{ "tag", 3, T_Tag, 0 }, { "tag", 3, T_Tag, 0 },
{ "third", 5, T_Ordinal, 2 },
{ "through", 7, T_Through, 0 }, { "through", 7, T_Through, 0 },
{ "thursday", 3, T_WkDay, 3 }, { "thursday", 3, T_WkDay, 3 },
{ "tuesday", 3, T_WkDay, 1 }, { "tuesday", 3, T_WkDay, 1 },
@@ -325,6 +333,14 @@ void FindNumericToken(char const *s, Token *t)
t->type = T_Back; t->type = T_Back;
t->val *= mult; t->val *= mult;
return; return;
} else if (*s == '~') {
s++;
if (*s == '~') { mult = -1; s++; }
PARSENUM(t->val, s);
if (*s) return; /* Illegal token if followed by non-numeric char */
t->type = T_BackAdj;
t->val *= mult;
return;
} }
return; /* Unknown token type */ return; /* Unknown token type */
} }

View File

@@ -69,6 +69,8 @@ typedef struct {
int once; int once;
int scanfrom; int scanfrom;
int from; int from;
int adj_for_last; /* Adjust month/year for use of LAST */
int need_wkday; /* Set if we *need* a weekday */
int priority; int priority;
int duration_days; /* Duration converted to days to search */ int duration_days; /* Duration converted to days to search */
int eventstart; /* Original event start (datetime) */ int eventstart; /* Original event start (datetime) */
@@ -157,7 +159,8 @@ enum TokTypes
T_AddOmit, T_AddOmit,
T_WkDay, T_WkDay,
T_Month, T_Time, T_Date, T_DateTime, T_Month, T_Time, T_Date, T_DateTime,
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta, T_Back, T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta,
T_Back, T_BackAdj,
T_Once, T_Once,
T_Empty, T_Empty,
T_Comment, T_Comment,
@@ -175,7 +178,10 @@ enum TokTypes
T_LongTime, T_LongTime,
T_OmitFunc, T_OmitFunc,
T_Through, T_Through,
T_MaybeUncomputable T_MaybeUncomputable,
T_Ordinal,
T_In,
T_LastBack
}; };
/* The structure of a token */ /* The structure of a token */

View File

@@ -167,7 +167,7 @@ int DoFset(ParsePtr p)
/* Add the function definition */ /* Add the function definition */
FSet(func); FSet(func);
if (orig_namelen > VAR_NAME_LEN) { if (orig_namelen > VAR_NAME_LEN) {
Eprint("Warning: Function name `%s...' truncated to `%s'", Wprint("Warning: Function name `%s...' truncated to `%s'",
func->name, func->name); func->name, func->name);
} }
return OK; return OK;

View File

@@ -43,8 +43,7 @@ typedef int (*SysVarFunc)(int, Value *);
static void deprecated_var(char const *var, char const *instead) static void deprecated_var(char const *var, char const *instead)
{ {
if (DebugFlag & DB_PRTLINE) { if (DebugFlag & DB_PRTLINE) {
Eprint("%s is deprecated; use %s instead", var, instead); Wprint("%s is deprecated; use %s instead", var, instead);
FreshLine = 1;
} }
} }
@@ -508,7 +507,7 @@ int DoSet (Parser *p)
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v); if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
else r = SetVar(DBufValue(&buf), &v); else r = SetVar(DBufValue(&buf), &v);
if (buf.len > VAR_NAME_LEN) { if (buf.len > VAR_NAME_LEN) {
Eprint("Warning: Variable name `%.*s...' truncated to `%.*s'", Wprint("Warning: Variable name `%.*s...' truncated to `%.*s'",
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf)); VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
} }
DBufFree(&buf); DBufFree(&buf);
@@ -908,9 +907,7 @@ int GetSysVar(char const *name, Value *val)
/* In "verbose" mode, print attempts to test $RunOff */ /* In "verbose" mode, print attempts to test $RunOff */
if (DebugFlag & DB_PRTLINE) { if (DebugFlag & DB_PRTLINE) {
if (v->value == (void *) &RunDisabled) { if (v->value == (void *) &RunDisabled) {
Eprint("(Security note: $RunOff variable tested.)"); Wprint("(Security note: $RunOff variable tested.)");
/* Allow further messages from this line */
FreshLine = 1;
} }
} }
return OK; return OK;

View File

@@ -27,7 +27,7 @@ SET $December "दिसंबर"
REM 1 MSG Përkujtues REM 1 MSG Përkujtues
REM 2 SPECIAL SHADE 192 192 255 REM 2 SPECIAL SHADE 192 192 255
REM 2 MSG تذكير REM 2 MSG تذكير
REM 3 MSG 提醒 REM 3 MSG 提醒提醒提醒提醒提醒提醒提醒提醒
REM 4 MSG રીમાઇન્ડર REM 4 MSG રીમાઇન્ડર
REM 5 MSG Emlékeztető REM 5 MSG Emlékeztető
REM 6 MSG Áminning REM 6 MSG Áminning
@@ -57,6 +57,7 @@ REM 24 MSG リマインダー
REM 25 MSG Искә төшерү REM 25 MSG Искә төшерү
REM 26 MSG Напомняне REM 26 MSG Напомняне
REM 27 MSG ഓർമ്മപ്പെടുത്തൽ REM 27 MSG ഓർമ്മപ്പെടുത്തൽ
REM 28 MSG リaリaaリaaリaaリaaリaaリaaリaaリaaリaaリa
REM 1 SPECIAL SHADE 192 255 192 REM 1 SPECIAL SHADE 192 255 192
REM 14 SPECIAL SHADE 255 192 192 REM 14 SPECIAL SHADE 255 192 192
REM 14 SPECIAL PANGO <span face="Zapf Chancery" size="15000">This is so <span foreground="blue">fancy</span></span> REM 14 SPECIAL PANGO <span face="Zapf Chancery" size="15000">This is so <span foreground="blue">fancy</span></span>

View File

@@ -321,7 +321,8 @@ if test -z "$LC_ALL" ; then
fi fi
if test "$OK" = 0 ; then if test "$OK" = 0 ; then
export LC_ALL=en_US.utf-8 export LC_ALL=C.UTF-8
export LANG=C.UTF-8
fi fi
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out ../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out

File diff suppressed because it is too large Load Diff

View File

@@ -524,6 +524,22 @@ msg [$Uw]%
msg [$Uy]% msg [$Uy]%
msg [$Wednesday]% msg [$Wednesday]%
# Diagnose until before start date, only for non-constant expressions and
# fully-specified start date
REM Mon 1992 UNTIL 1991-01-01 MSG Not diagnosed - not fully-specified start
REM 1992-01-01 *1 UNTIL 1991-12-31 MSG Diagnosed
set x '1992-01-01'
REM [x] *1 UNTIL 1991-12-31 MSG Not diagnosed - nonconst expression
REM MON FROM 1992-01-01 UNTIL 1991-12-31 Diagnosed
REM MON SCANFROM 1992-01-01 UNTIL 1991-12-31 Diagnosed
REM MON FROM [x] UNTIL 1991-12-31 Not diagnosed
REM MON SCANFROM [x] UNTIL 1991-12-31 Not diagnosed
REM 1992-01-01 UNTIL 1992-02-02 MSG Diagnosed
REM [x] UNTIL 1992-02-02 MSG Diagnosed
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OMIT 2010-09-03 THROUGH 2010-09-15 OMIT 2010-09-03 THROUGH 2010-09-15
OMIT December 25 MSG X OMIT December 25 MSG X
@@ -714,6 +730,66 @@ msg [a]
set x psshade(50) set x psshade(50)
set x psmoon(0) set x psmoon(0)
# Trig
IF trig("sun +1") || trig("thu +1")
REM [trig()] +1 MSG Foo %b
ENDIF
# Trig with a bad warnfunc
FSET w(x) x/0
IF trig("sun warn w") || trig("thu warn w")
REM [trig()] +1 MSG Foo %b
ENDIF
# Trig with a good warnfunc
FSET w(x) choose(x, 5, 3, 1, 0)
# Ugh. This is where short-circuit logical operators
# would really come in handy.
IF trig("sun warn w") || trig("thu warn w")
REM [trig()] +5 MSG Foo %b
ENDIF
REM [trig("Mon", "Tue", "Wed", "Sat")] MSG foo
REM [trig("Mon", "Tue", "Wed")] MSG bar
# The new syntactic sugar
REM First Monday January MSG x
REM Second Tuesday in April MSG x
REM Third Wednesday in October MSG x
REM Fourth Friday in July MSG x
REM Last Tuesday in August MSG x
REM Last Sunday in December MSG x
REM First Monday January 2000 MSG x
REM Second Tuesday in April 2000 MSG x
REM Third Wednesday in October 2000 MSG x
REM Fourth Friday in July 2000 MSG x
REM Last Tuesday in August 2000 MSG x
REM Last Sunday in December 2000 MSG x
REM January ~~1 MSG y
REM February ~~1 MSG y
REM February ~~2 MSG y
REM February ~~3 MSG y
REM February ~~8 MSG y
REM February ~~20 MSG y
PUSH
OMIT 31 March
REM March ~1 MSG y
REM March ~~1 MSG y
REM Lastday March MSG y
REM Lastworkday March MSG y
POP
REM Dec 2000 ~~1 MSG y
REM Dec 2000 ~~2 MSG y
REM Dec 2000 ~~3 MSG y
REM Dec 2000 ~~7 MSG y
REM Jan 2001 ~~1 MSG y
REM Lastday April 2022 OMIT SAT SUN MSG foo
REM Lastworkday April 2022 OMIT SAT SUN MSG foo
# Don't want Remind to queue reminders # Don't want Remind to queue reminders
EXIT EXIT