Compare commits

...

36 Commits

Author SHA1 Message Date
Dianne Skoll
24e0178d1a Fix tests for 3.3.2 release. 2020-11-08 16:01:57 -05:00
Dianne Skoll
1ede5775f2 Prep for 3.3.2 release. 2020-11-08 16:01:39 -05:00
Dianne Skoll
a5c9b07052 Fix for calendar alignment for reminders with embedded tabs.
Convert all whitespace chars to space in calendar mode.
2020-11-03 08:41:24 -05:00
Dianne Skoll
22353d4833 Fix typo (patch from Yigit Sever) 2020-11-02 08:31:28 -05:00
Dianne Skoll
7499ada891 Properly fix combining-char-word-wrapping. 2020-11-01 12:05:21 -05:00
Dianne Skoll
3f0a4e5c39 Fix another instance of mis-counting display width. 2020-11-01 10:13:51 -05:00
Dianne Skoll
b8d6472974 Add UTF-8 test. 2020-11-01 10:06:48 -05:00
Dianne Skoll
6358297724 Fix column misalignment with UTF-8 text. 2020-11-01 10:03:32 -05:00
Dianne Skoll
4f6dcde980 Upper-case section references.
Prevent potential null pointer dereference.
2020-10-31 16:57:13 -04:00
Dianne Skoll
8a7985c48e Highlight that longitude sign is opposite from the usual convention. 2020-10-12 18:54:26 -04:00
Dianne Skoll
4ddbe54e55 Fix typo 2020-09-25 22:27:48 -04:00
Dianne Skoll
ef0bf73a29 Document MAYBE-UNCOMPUTABLE. 2020-09-25 22:20:16 -04:00
Dianne Skoll
beda9014d8 Add test for MAYBE-UNCOMPUTABLE 2020-09-25 22:11:56 -04:00
Dianne Skoll
498a429b2c Add MAYBE-UNCOMPUTABLE modifier to trigger. 2020-09-25 22:08:49 -04:00
Dianne Skoll
6aa2aa0fb3 Align system vars in output. 2020-09-20 17:43:51 -04:00
Dianne Skoll
1bef88fccd Update released notes. 2020-09-20 17:40:58 -04:00
Dianne Skoll
8308068067 Don't bother aligning "DUMP" output.
It looks ridiculous with 64-char long variable names.
2020-09-20 17:39:33 -04:00
Dianne Skoll
8385c7f1b0 Update custom.h 2020-09-20 17:35:24 -04:00
Dianne Skoll
0537d02fef Increase max variable length from 16 to 64 characters.
Modern computers have plenty of memory, so meh.
2020-09-20 17:32:22 -04:00
Dianne Skoll
c33a1a3b0b Mention that variables are global. 2020-09-20 12:45:29 -04:00
Dianne Skoll
fd39999128 Fix bugs where month numbers with leading zeros are misinterpreted as octal instead of decimal.
Reported by Peter Geddes.
2020-09-13 12:34:27 -04:00
Dianne Skoll
0aa40094fa Make TwentyFourHourMode global. 2020-08-18 15:24:19 -04:00
Dianne Skoll
e3bbbe07be Respect 24-hour mode option. 2020-08-18 15:24:13 -04:00
Dianne Skoll
5633798d33 Document that time is fed to reminder command. 2020-08-18 15:24:09 -04:00
Dianne Skoll
0e7e1b1b75 When feeding reminder on stdin, prefix with "$time: " 2020-08-18 15:24:04 -04:00
Dianne Skoll
4d3790bc1a More tweaking of defs.rem to remove cruft and modernize usage. 2020-08-18 15:24:00 -04:00
Dianne Skoll
2002c7f1f8 Fix up defs.rem. 2020-08-18 15:23:51 -04:00
Dianne Skoll
1be14e99a2 Update docs for -itkremind=1 and -itkprint=1 options in TkRemind. 2020-06-11 15:06:09 -04:00
Dianne Skoll
78efdaf85f Fix bug that broke printing by putting cmdline options in wrong spot. 2020-06-10 10:26:06 -04:00
Dianne Skoll
0e98a1c656 Always set tkremind=1; set tkprint=1 if we're printing. 2020-06-10 10:22:46 -04:00
Dianne Skoll
7aa483e201 Fix bug reported by Jurgen Bollerhey
I have a
"REM Mon SPECIAL WEEK (W[weekno()])"
in my reminders file.
With tkremind -m the week number is displayed on the 2nd column which is
Tuesday and the date of this Tuesday is taken from the monday of the
next week, sometimes of Monday the same week.
2020-03-30 11:29:19 -04:00
Dianne Skoll
a6dbf05af4 Update WHATSNEW. 2020-03-20 09:18:48 -04:00
Dianne Skoll
8ab78fd8be Suppress compile warnings on Ubuntu 18.04 2020-03-19 20:27:45 -04:00
Dianne Skoll
4f119031a4 One more warning to suppress. 2020-03-19 20:24:53 -04:00
Dianne Skoll
19bdd6c2db Avoid warning about ignoring return value of fgets. 2020-03-19 20:24:01 -04:00
Dianne Skoll
f1557b8243 Try to suppress fallthrough warning. 2020-03-19 20:21:29 -04:00
25 changed files with 1810 additions and 414 deletions

2
configure vendored
View File

@@ -3991,7 +3991,7 @@ _ACEOF
fi fi
done done
VERSION=03.03.01 VERSION=03.03.02
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h" ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"

View File

@@ -75,6 +75,6 @@ if test "$GCC" = yes; then
fi fi
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale) AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
VERSION=03.03.01 VERSION=03.03.02
AC_SUBST(VERSION) AC_SUBST(VERSION)
AC_OUTPUT(src/Makefile www/Makefile src/version.h) AC_OUTPUT(src/Makefile www/Makefile src/version.h)

View File

@@ -1,16 +1,42 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 3.3 Patch 1 - 2020-XX-XX * VERSION 3.3 Patch 2 - 2020-11-08
- MINOR NEW FEATURE: Add MAYBE-UNCOMPUTABLE keyword; see the man page
and discussion at
https://dianne.skoll.ca/pipermail/remind-fans/2020/003745.html
- CHANGE: TkRemind always invokes Remind with the "-itkremind=1" option,
even when printing. NOTE INCOMPATIBILITY: This is a behavior change!
When you print from TkRemind, we also invoke Remind with "-itkprint=1"
so you can detect that PostScript is being generated.
- CHANGE: The maxmimum length of a variable name has been increased from
16 characters to 64 characters. Modern computers have plenty of memory.
- BUG FIXES: Minor documentation updates, typo fixes, clarifications, etc.
- BUG FIX: Fix calendar-drawing alignment errors when displaying UTF-8
strings with zero-width combining characters and strings with tabs.
- BUG FIX: TkRemind would mess up placement of the WEEK special if invoked
with the "-m" option. This has been fixed.
- BUG FIX: TkRemind would sometimes fail with an error message when editing
a reminder; this is because it was interpreting months 08 and 09 as
illegal octal numbers. This has been fixed.
* VERSION 3.3 Patch 1 - 2020-03-20
- CHANGE: For overlapping multi-day events, issue a reminder for the - CHANGE: For overlapping multi-day events, issue a reminder for the
most *recent* event rather than the earliest event. NOTE INCOMPATIBILITY: most *recent* event rather than the earliest event. NOTE
This is a behavior change! INCOMPATIBILITY: This is a behavior change!
- CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to recognize - CHANGE: Do not convert 90-99 to 1990-1999 when parsing numbers to
years. NOTE INCOMPATIBILITY: This is a behavior change! recognize years. NOTE INCOMPATIBILITY: This is a behavior change!
- CHANGE: Revert change to -y option that included filename and line number - CHANGE: Revert change to -y option that included filename and line
in the hash. number in the hash.
- CHANGE: Retain newlines (produced by %_) in JSON output. - CHANGE: Retain newlines (produced by %_) in JSON output.
@@ -18,6 +44,8 @@ CHANGES TO REMIND
- FIX: Highlight today's date in "remind -c" output - FIX: Highlight today's date in "remind -c" output
- FIX: Eliminate compiler warnings on Ubuntu 18.04.
- IMPROVEMENT: Allow times to be specified either in 24-hour mode - IMPROVEMENT: Allow times to be specified either in 24-hour mode
(HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.) (HH:MM or HH.MM) or AM/PM mode (HH:MMam; HH:MMpm, etc.)

View File

@@ -26,8 +26,8 @@ RUN OFF
################################################ ################################################
# Ensure required version of remind is used... # # Ensure required version of remind is used... #
################################################ ################################################
IF version() < "03.01.08" IF version() < "03.01.09"
ERRMSG This file requires at least version 03.01.08 of Remind.% ERRMSG This file requires at least version 03.01.09 of Remind.%
ERRMSG This version is version [version()]. ERRMSG This version is version [version()].
EXIT EXIT
ENDIF ENDIF
@@ -84,7 +84,6 @@ SET December 12
########################################################### ###########################################################
# Other symbolic constants and functions for "pasting"... # # Other symbolic constants and functions for "pasting"... #
########################################################### ###########################################################
SET Quote CHAR(34) SET Quote CHAR(34)
# Handy constants/function for specifing week of month... # Handy constants/function for specifing week of month...
@@ -95,29 +94,17 @@ SET Week_4 22
FSET _last(mo) "1 " + MON((mo%12)+1) + " --7" FSET _last(mo) "1 " + MON((mo%12)+1) + " --7"
# Handy function to provide SCANFROM dates... # Handy function to provide SCANFROM dates...
FSET _back(days) TODAY()-days FSET _back(days) $U-days
###########################################################
# Function which returns a string in "am/pm" format based #
# on the time. For example, set a am_pm(NOW())... #
###########################################################
FSET _am_pm(tm) IIF(tm<01:00, tm+12*60+"am", \
tm<12:00, tm+"am", \
tm<13:00, tm+"pm", \
tm-12*60+"pm")
################################################################# #################################################################
# Function which removes a single leading zero from a string... # # Function that removes a single leading zero from a string... #
################################################################# #################################################################
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s) FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
################################################################# #################################################################
# Return the length of the daylight/night portion of a date, # # Return the length of the daylight/night portion of a date, #
# in minutes. # # in minutes. #
################################################################# #################################################################
FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0) FSET _light_len(date) MAX(SUNSET(date)-SUNRISE(date), 0)
FSET _dark_len(date) 1440-_light_len(date) FSET _dark_len(date) 1440-_light_len(date)
@@ -125,26 +112,12 @@ FSET _dark_len(date) 1440-_light_len(date)
# Function to calculate number of years since a given year # # Function to calculate number of years since a given year #
# or number of months since a given month and year... # # or number of months since a given month and year... #
############################################################ ############################################################
FSET _yr_num(yr) ORD($Ty - yr)
FSET _yr_num(yr) ORD(YEAR(TRIGDATE()) - yr) FSET _mo_num(mo, yr) ORD(12 * ($Ty - yr) + $Tm - mo)
FSET _mo_num(mo, yr) ORD(12 * (YEAR(TRIGDATE()) - yr) + \
MONNUM(TRIGDATE()) - mo)
# Here's an example of how to use them: # Here's an example of how to use them:
REM 1 Nov ++12 MSG %"Dean's [_yr_num(1984)] birthday%" is %b. REM 1 Nov ++12 MSG %"John's [_yr_num(1984)] birthday%" is %b.
REM 1 MSG Dean's [_mo_num(11, 1984)] 'monthly' anniversary REM 1 MSG John's [_mo_num(11, 1984)] 'monthly' anniversary
###########################################################
# Function to send mail via elm's "fastmail" (by GMS!)... #
###########################################################
#FSET _mail(from, subj) "mailx -s " + \
# Quote + from + " : " + subj + Quote \
# GETENV("LOGNAME") + " < /dev/null 1>&0"
FSET _mail(from, subj) "fastmail -f " + \
Quote + from + Quote + \
" -s " + Quote + subj + Quote + \
" /dev/null " + GETENV("LOGNAME")
############################################################################# #############################################################################
# Here's a tricky problem: The 4th of July is a holiday in the U.S. # Here's a tricky problem: The 4th of July is a holiday in the U.S.
@@ -158,29 +131,28 @@ FSET _mail(from, subj) "fastmail -f " + \
# dependent upon the current date, it's tricky and results may not be # dependent upon the current date, it's tricky and results may not be
# what you expect. You should try to make sure that the OMIT context # what you expect. You should try to make sure that the OMIT context
# "near" any current reminders will not change during a calendar run. # "near" any current reminders will not change during a calendar run.
# The SCANFROM clause should help make these OMITs very safe. # The SCANFROM clause will make these OMITs safe.
############################################################################ ############################################################################
# Calculate the weekday of the holiday. # Calculate the weekday of the holiday.
REM 4 July SCANFROM [_back(7)] SATISFY 1 REM 4 July SCANFROM [_back(7)] SATISFY 1
IF WKDAYNUM(TRIGDATE()) == Sat SET iday $T
REM [TRIGDATE()] MSG Independence day (actual) IF WKDAYNUM(iday) == Sat
OMIT [TRIGDATE()-1] MSG Independence day (observed) REM [iday] MSG Independence day (actual)
OMIT [iday-1] MSG Independence day (observed)
ELSE ELSE
IF WKDAYNUM(TRIGDATE()) == Sun IF WKDAYNUM(iday) == Sun
REM [TRIGDATE()] MSG Independence day (actual) REM [iday] MSG Independence day (actual)
OMIT [TRIGDATE()+1] MSG Independence day (observed) OMIT [iday+1] MSG Independence day (observed)
ELSE ELSE
OMIT [TRIGDATE()] MSG Independence day OMIT [iday] MSG Independence day
ENDIF ENDIF
ENDIF ENDIF
############################################################################ ############################################################################
# #
# A meeting on the first Monday of every month which is moved to the # # A meeting on the first Monday of every month which is moved to the #
# second Monday in the event of a holiday. # # second Monday in the event of a holiday. #
# #
############################################################################ ############################################################################
# First, the normal meeting. However, the SKIP keyword means this # First, the normal meeting. However, the SKIP keyword means this
@@ -192,68 +164,21 @@ REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous # But only actually trigger the delayed meeting if the previous
# Monday was a holiday # Monday was a holiday
IF ISOMITTED(TRIGDATE()-7) IF ISOMITTED($T-7)
REM [TRIGDATE()] MSG Delayed meeting REM [$T] MSG Delayed meeting
ENDIF ENDIF
############################################################################
# #
# A very complicated reminder sent in by a Remind user. #
# This person gets paid every two weeks, starting from 8 January 1993. #
# If a pay date occurs before the twelfth of a month, then that #
# he pays his mortgage on that pay date. Otherwise, he pays the mortgage #
# on the previous pay date. Furthermore, he has to schedule his #
# mortgage payment six days before it is due. He wants to be reminded #
# a further four days before the scheduling deadline. He also #
# wants to be mailed a notice two weeks before the scheduling deadline. #
# #
# Here's the solution - if you can follow this, consider yourself a #
# Remind programmer extraordinaire! #
# #
############################################################################
# A function to determine whether or not a pay-date is a mortgage-date.
FSET _IsMortDate(x) DAY(x) < 12 || (DAY(x+14) >= 12 && DAY(x+14) <= 14)
# Paydays - for reference
REM 8 Jan 1993 *14 MSG Payday
# Calculate the mortgage payment six days ahead of time. Note that this
# is done "implicitly" by subtracting 6 from the starting date - we start
# on 2 Jan rather than 8 Jan. We add 6 to TRIGDATE() in _IsMortDate to
# compensate.
REM 2 Jan 1993 *14 ++4 SATISFY [_IsMortDate(TRIGDATE()+6)] \
MSG %"Schedule mortgage payment%" for %a.
# Now the mail reminder two weeks before the payment date - because two
# weeks before a payment date is also a payment date, no pre-compensation
# in the starting date of 8 Jan is necessary - convince yourself of this!
# This uses the _mail() function defined earlier.
REM ONCE 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE()+14)] \
RUN [_mail("Decatur Federal", \
"Pay mortgage by the " + ORD(DAY(TRIGDATE()+14)))]
# Make an entry on the calendar when the mortgage should be paid
REM 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE())] \
CAL Mortgage payment
########################################################################## ##########################################################################
# # # #
# On our UNIX system, I run a program which queries the university # # On our UNIX system, I run a program that queries the university #
# library and creates a file called ".booksdue". This file is # # library and creates a file called ".booksdue". This file is #
# a REMIND script to tell me when my library books are due. Here's # # a REMIND script to tell me when my library books are due. Here's #
# an example from my reminder file - it shows the use of filedate(). # # an example from my reminder file - it shows the use of filedate(). #
# When the .booksdue file is at least 7 days old, I create a new version # # When the .booksdue file is at least 7 days old, I create a new version #
# by querying the library computer. Note the use of realtoday() rather # # by querying the library computer. Note the use of realtoday() rather #
# than today. # # than today(). #
# # # #
########################################################################## ##########################################################################
IF !$RunOff && !$CalMode && !$SimpleCal IF !$RunOff && !$CalMode && !$SimpleCal
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7 IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
REM RUN /home/dfs/bilge/library/getbooks REM RUN /home/dfs/bilge/library/getbooks
@@ -283,7 +208,7 @@ REM Sat Sun SPECIAL SHADE 220
############################################################################# #############################################################################
SET SaveTrig $NumTrig SET SaveTrig $NumTrig
SET easter EASTERDATE(YEAR(TODAY())) SET easter EASTERDATE($Uy)
REM [easter-46] MSG %"Ash Wednesday%" REM [easter-46] MSG %"Ash Wednesday%"
REM [easter-7] MSG %"Palm Sunday%" REM [easter-7] MSG %"Palm Sunday%"
OMIT [easter-2] MSG %"Good Friday%" OMIT [easter-2] MSG %"Good Friday%"
@@ -301,7 +226,7 @@ REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%" REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day REM Feb 14 MSG %"Valentine's%" Day
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1 REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"President's Day%" OMIT [$T] MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's%" Day REM Mar 17 MSG %"St. Patrick's%" Day
# The DST rules are accurate for most locations in # The DST rules are accurate for most locations in
@@ -319,23 +244,23 @@ REM Sat May [Week_1] MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%" REM Sun May [Week_2] MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%" REM Sat May [Week_3] MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1 REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Memorial Day%" OMIT [$T] MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%" REM Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%" REM Sun Jun [Week_3] MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1 REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Labor Day%" OMIT [$T] MSG %"Labor Day%"
REM Mon Oct [Week_2] MSG %"Columbus Day%" REM Mon Oct [Week_2] MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%" REM Nov 11 MSG %"Veterans Day%"
REM Oct 30 MSG %"Mischief Night%" REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%" REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM [_back(7)] \ REM Tue Nov 2 SCANFROM [_back(7)] \
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \ SATISFY [($Ty % 4) == 0] \
MSG %"Election%" Day MSG %"Election%" Day
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1 REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" Day OMIT [$T] MSG %"Thanksgiving%" Day
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1 REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
OMIT [trigdate()] MSG %"Thanksgiving%" (cont.) OMIT [$T] MSG %"Thanksgiving%" (cont.)
OMIT Dec 24 MSG %"Christmas Eve%" OMIT Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day OMIT Dec 25 MSG %"Christmas%" Day
@@ -350,13 +275,6 @@ if $NumTrig > SaveTrig
REM SPECIAL SHADE 220 REM SPECIAL SHADE 220
endif endif
# Seasons (valid from 1992 to 2000)...
REM Mar 20 MSG %"Spring%" begins
REM Jun [IIF(YEAR(TODAY())%4, 21, 20)] MSG %"Summer%" begins
REM Sep [CHOOSE(YEAR(TODAY())-1991, 22,22,23,23,22,22,22,23,22)] \
MSG %"Fall%" begins
REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
#PSSTUFF2 #PSSTUFF2
########################################################################## ##########################################################################
# # # #
@@ -370,7 +288,7 @@ REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
# example, I recommend that you use the -sd 10 option for Rem2PS. # example, I recommend that you use the -sd 10 option for Rem2PS.
REM PS Border Border moveto \ REM PS Border Border moveto \
/DayFont findfont DaySize scalefont setfont \ /DayFont findfont DaySize scalefont setfont \
([hebday(today())] [hebmon(today())]) show ([hebday($U)] [hebmon($U)]) show
# Fill in the phases of the moon on the PostScript calendar # Fill in the phases of the moon on the PostScript calendar
[moondate(0)] SPECIAL MOON 0 [moondate(0)] SPECIAL MOON 0
@@ -382,7 +300,7 @@ REM PS Border Border moveto \
# calendar - the sizes are hard-coded, however, and work best in landscape. # calendar - the sizes are hard-coded, however, and work best in landscape.
REM PS Border Border 5 sub moveto \ REM PS Border Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \ /SmallFont findfont 4 scalefont setfont \
(Sunrise: [sunrise(trigdate())] Sunset: [sunset(trigdate())]) show (Sunrise: [sunrise($T)] Sunset: [sunset($T)]) show
# The next one puts the day number (1-366) and days left in the year at the # The next one puts the day number (1-366) and days left in the year at the
# bottom of the post-script calendar. Again, the hard-coded sizes work best # bottom of the post-script calendar. Again, the hard-coded sizes work best
@@ -390,7 +308,7 @@ REM PS Border Border 5 sub moveto \
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1) FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \ REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \ /SmallFont findfont 4 scalefont setfont \
([_DayOfYear(today())]([365+isleap(today())-_DayOfYear(today())])) show ([_DayOfYear($U)]([365+isleap($U)-_DayOfYear($U)])) show
#JHOLS #JHOLS
########################################################################## ##########################################################################
@@ -430,7 +348,7 @@ SET Reform 0
# Convenient function definition to save typing # Convenient function definition to save typing
FSET _h(x, y) HEBDATE(x,y) FSET _h(x, y) HEBDATE(x,y)
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7) FSET _h2(x, y) HEBDATE(x, y, $U-7)
FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1) FSET _PastSat(x, y) IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1)
FSET _PastSun(x, y) IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1) FSET _PastSun(x, y) IIF(WKDAYNUM(_h2(x,y))!=0, _h2(x,y), _h2(x,y)+1)
FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1) FSET _PastMon(x, y) IIF(WKDAYNUM(_h2(x,y))!=1, _h2(x,y), _h2(x,y)+1)
@@ -464,7 +382,7 @@ ELSE
ENDIF ENDIF
# Because Kislev can change length, we must be more careful about Chanukah # Because Kislev can change length, we must be more careful about Chanukah
FSET _chan(x) HEBDATE(24, "Kislev", today()-9)+x FSET _chan(x) HEBDATE(24, "Kislev", $U-9)+x
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b. [_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%" [_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%" [_chan(3)] MSG %"Chanukah 3%"
@@ -553,9 +471,9 @@ ENDIF
# Counting the omer - do the whole spiel, i.e: # Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer." # "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here! # Nice Remind programming example here!
SET ostart HEBDATE(16, "Nisan", TODAY()-50) SET ostart HEBDATE(16, "Nisan", $U-50)
IF ostart <= TODAY() && (TODAY() - ostart < 49) IF ostart <= $U && ($U - ostart < 49)
SET odays TODAY()-ostart+1 SET odays $U-ostart+1
IF odays < 7 IF odays < 7
MSG %"%"Today is the [ORD(odays)] day of the Omer. MSG %"%"Today is the [ORD(odays)] day of the Omer.
ELSE ELSE
@@ -573,8 +491,8 @@ ENDIF
### for Friday and Saturday. Note: You must set your latitude, longitude ### for Friday and Saturday. Note: You must set your latitude, longitude
### and possibly time zone for these to work properly! ### and possibly time zone for these to work properly!
REM Friday CAL Candle lighting at [sunset(trigdate())-18] REM Friday CAL Candle lighting at [sunset($T)-18]
REM Saturday CAL Havdalah at [sunset(trigdate())+42] REM Saturday CAL Havdalah at [sunset($T)+42]
#COLORS #COLORS
########################################################################## ##########################################################################

View File

@@ -26,7 +26,7 @@ Anything after the __EOF__ marker is completely ignored.
.SH OPTIONS .SH OPTIONS
\fBRemind\fR has a slew of options. If you're new to the program, \fBRemind\fR has a slew of options. If you're new to the program,
ignore them for now and skip to the section "Reminder Files". ignore them for now and skip to the section "REMINDER FILES".
.TP .TP
.B \-n .B \-n
The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence The \fB\-n\fR option causes \fBRemind\fR to print the \fBnext\fR occurrence
@@ -248,7 +248,7 @@ encountered in the reminder script. The \fB\-g\fR option cause
\fBRemind\fR to sort reminders by date and time prior to issuing them. \fBRemind\fR to sort reminders by date and time prior to issuing them.
The optional \fBa\fR and \fBd\fR characters specify the sort order The optional \fBa\fR and \fBd\fR characters specify the sort order
(ascending or descending) for the date, time and priority fields. See (ascending or descending) for the date, time and priority fields. See
the section "Sorting Reminders" for more information. the section "SORTING REMINDERS" for more information.
.TP .TP
\fB\-b\fR[\fIn\fR] \fB\-b\fR[\fIn\fR]
@@ -323,7 +323,7 @@ TAG clause.
\fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR \fB\-i\fR\fIvar\fR\fB=\fR\fIexpr\fR
Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR Sets the value of the specified \fIvar\fR to \fIexpr\fR, and \fBpreserves\fR
\fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the \fIvar\fR. \fIExpr\fR can be any valid \fBRemind\fR expression. See the
section "Initializing Variables on the Command Line" for more details. section "INITIALIZING VARIABLES ON THE COMMAND LINE" for more details.
.TP .TP
\fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR \fB\-i\fR\fIfunc\fR(\fIargs\fR)=\fIdefinition\fR
Allows you to define a function on the command line. Allows you to define a function on the command line.
@@ -352,7 +352,7 @@ In addition, you can supply a \fIrepeat\fR parameter, which has the
form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times, form *\fInum\fR. This causes \fBRemind\fR to be run \fInum\fR times,
with the date incrementing on each iteration. You may have to enclose with the date incrementing on each iteration. You may have to enclose
the parameter in quotes to avoid shell expansion. See the subsection the parameter in quotes to avoid shell expansion. See the subsection
"Repeated Execution" in the section "Calendar Mode" for more "Repeated Execution" in the section "CALENDAR MODE" for more
information. information.
.SH REMINDER FILES .SH REMINDER FILES
.PP .PP
@@ -439,7 +439,7 @@ These keywords denote the \fItype\fR
of the reminder. (\fBSATISFY\fR is more complicated and will be explained of the reminder. (\fBSATISFY\fR is more complicated and will be explained
later.) A \fBMSG\fR-type reminder normally prints a message to the standard later.) A \fBMSG\fR-type reminder normally prints a message to the standard
output, after passing the \fIbody\fR through a special substitution filter, output, after passing the \fIbody\fR through a special substitution filter,
described in the section "The Substitution Filter." However, if you have described in the section "THE SUBSTITUTION FILTER." However, if you have
used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are used the \fB\-k\fR command-line option, then \fBMSG\fR-type reminders are
passed to the appropriate program. Note that the options \fB\-c\fR, passed to the appropriate program. Note that the options \fB\-c\fR,
\fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option. \fB\-s\fR, \fB\-p\fR and \fB\-n\fR disable the \fB\-k\fR option.
@@ -457,7 +457,7 @@ The \fBMSF\fR keyword is almost the same as the \fBMSG\fR keyword,
except that the reminder is formatted to fit into a paragraph-like except that the reminder is formatted to fit into a paragraph-like
format. Three system variables control the formatting of \fBMSF\fR-type format. Three system variables control the formatting of \fBMSF\fR-type
reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and reminders - they are \fB$FirstIndent\fR, \fB$SubsIndent\fR and
\fB$FormWidth\fR. They are discussed in the section "System Variables." \fB$FormWidth\fR. They are discussed in the section "SYSTEM VARIABLES."
The \fBMSF\fR keyword causes the spacing of your reminder to be altered - The \fBMSF\fR keyword causes the spacing of your reminder to be altered -
extra spaces are discarded, and two spaces are placed after periods and extra spaces are discarded, and two spaces are placed after periods and
other characters, as specified by the system variables \fB$EndSent\fR and other characters, as specified by the system variables \fB$EndSent\fR and
@@ -815,7 +815,7 @@ the initial date, and does not affect the repetition period.
.B SCANFROM \fRand\fB FROM .B SCANFROM \fRand\fB FROM
.PP .PP
The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers The \fBSCANFROM\fR and \fBFROM\fR keywords are for advanced \fBRemind\fR programmers
only, and will be explained in the section "Details about Trigger Computation" only, and will be explained in the section "DETAILS ABOUT TRIGGER COMPUTATION"
near the end of this manual. Note that \fBSCANFROM\fR is available only near the end of this manual. Note that \fBSCANFROM\fR is available only
in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only in versions of \fBRemind\fR from 03.00.04 up. \fBFROM\fR is available only
from 03.01.00 and later. from 03.01.00 and later.
@@ -827,7 +827,7 @@ It is used in calendar mode and when sorting reminders. If two reminders
have the same trigger date and time, then they are sorted by priority. have the same trigger date and time, then they are sorted by priority.
If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000 If the \fBPRIORITY\fR keyword is not supplied, a default priority of 5000
is used. (This default can be changed by adjusting the system variable is used. (This default can be changed by adjusting the system variable
\fB$DefaultPrio\fR. See the section "System Variables" for more \fB$DefaultPrio\fR. See the section "SYSTEM VARIABLES" for more
information.) information.)
.PP .PP
.B EXPIRY DATES .B EXPIRY DATES
@@ -968,7 +968,7 @@ it terminates the search after the \fBSATISFY\fR iteration limit
.PP .PP
Timed reminders are those that have an \fBAT\fR keyword followed Timed reminders are those that have an \fBAT\fR keyword followed
by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR by a \fItime\fR and optional \fItdelta\fR and \fItrepeat\fR. The \fItime\fR
mau be specified in 24-hour format, with 0:00 representing midnight, may be specified in 24-hour format, with 0:00 representing midnight,
12:00 representing noon, and 23:59 representing one minute to midnight. 12:00 representing noon, and 23:59 representing one minute to midnight.
Alternatively, it may be specified in common "AM/PM" format; in this case, Alternatively, it may be specified in common "AM/PM" format; in this case,
the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm the hour must range from 1 to 12. 12:00am represents midnight, 12:00pm
@@ -1061,7 +1061,7 @@ of timed reminders, and the \fBWARN\fR keyword allows precise control
over the advance triggering of all types of reminders. over the advance triggering of all types of reminders.
However, discussion must be deferred until after However, discussion must be deferred until after
expressions and user-defined functions are explained. See the subsection expressions and user-defined functions are explained. See the subsection
"Precise Scheduling" further on. "PRECISE SCHEDULING" further on.
.PP .PP
.B TAG AND DURATION .B TAG AND DURATION
.PP .PP
@@ -1323,7 +1323,7 @@ is similar to \fB%3\fR but displays the current time.
used by the substitution filter, used by the substitution filter,
but is used to tell \fBRemind\fR which text to include in a calendar but is used to tell \fBRemind\fR which text to include in a calendar
entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen. entry when the \fB\-c\fR, \fB\-s\fR or \fB\-p\fR option is chosen.
See "Calendar Mode" See "CALENDAR MODE"
.PP .PP
Notes: Notes:
.TP .TP
@@ -1900,6 +1900,9 @@ variable. Examples:
Note that variables themselves have no type. They take on the type of Note that variables themselves have no type. They take on the type of
whatever you store in them. whatever you store in them.
.PP .PP
Variables set with SET or on the command-line with \fB\-i\fR\fIvar\fB=\fR\fIexpr\fR
have global scope.
.PP
To delete a variable, use the \fBUNSET\fR command: To delete a variable, use the \fBUNSET\fR command:
.PP .PP
\fBUNSET\fR \fIvar\fR [\fIvar\fR...] \fBUNSET\fR \fIvar\fR [\fIvar\fR...]
@@ -2059,8 +2062,13 @@ the latitude and longitude system variables.
These specify the longitude of your location. \fB$LongDeg\fR can These specify the longitude of your location. \fB$LongDeg\fR can
range from \-180 to 180. Western longitudes are positive; eastern range from \-180 to 180. Western longitudes are positive; eastern
ones are negative. Note that all three components should have the ones are negative. Note that all three components should have the
same sign: All positive for Western longitudes and all negative same sign: All positive for Western longitudes and all negative for
for Eastern longitudes. Eastern longitudes. Note that for historical reasons, the sign for
longitude is \fIdifferent\fR from the usual convention! If you find
the longitude of your location from a search engine, you will most
likely \fIneed to invert the sign to have it work correctly with
Remind.\fR
.RS .RS
.PP .PP
The latitude and longitude information is required for the functions The latitude and longitude information is required for the functions
@@ -2486,16 +2494,16 @@ variables are generally case-sensitive; thus, getenv("HOME") is not
the same as getenv("home"). the same as getenv("home").
.TP .TP
.B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]]) .B hebdate(i_day, s_hebmon [,idq_yrstart [,i_jahr [,i_aflag]]])
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebday(dq_date) .B hebday(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebmon(dq_date) .B hebmon(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hebyear(dq_date) .B hebyear(dq_date)
Support for Hebrew dates - see the section "The Hebrew Calendar" Support for Hebrew dates - see the section "THE HEBREW CALENDAR"
.TP .TP
.B hour(tq_time) .B hour(tq_time)
Returns the hour component of \fItime\fR. Returns the hour component of \fItime\fR.
@@ -3624,7 +3632,7 @@ However, when \fBRemind\fR gets around to calculating the trigger
for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be for Tuesday, 8 September, 1992, the \fBOMIT\fR command will now be
omitting Labour Day for 1993, and the "Mon AFTER" command omitting Labour Day for 1993, and the "Mon AFTER" command
will not be triggered. (But see the description of \fBSCANFROM\fR will not be triggered. (But see the description of \fBSCANFROM\fR
in the section "Details about Trigger Computation.") in the section "DETAILS ABOUT TRIGGER COMPUTATION.")
.PP .PP
It is probably best to stay away from computing \fBOMIT\fR It is probably best to stay away from computing \fBOMIT\fR
trigger dates unless you keep these pitfalls in mind. trigger dates unless you keep these pitfalls in mind.
@@ -3660,6 +3668,35 @@ Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner same problem, though in different ways. Sometimes a \fBSATISFY\fR is cleaner
and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer. and sometimes an \fBOMITFUNC\fR; experiment and use whichever seems clearer.
.PP .PP
.SH POSSIBLY-UNCOMPUTABLE TRIGGERS
.PP
Occasionally, you may wish to suppress the "Can't compute trigger" warnings
for reminders for which a trigger date cannot be compute. For example,
the following reminder is triggered on a Monday that is not a holiday
if the following Tuesday is a holiday:
.PP
.nf
REM Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
However, if there are no Mondays after today's date that satisfy the
condition, Remind will print the "Can't compute trigger" error. To
suppress this, use the \fBMAYBE-UNCOMPUTABLE\fR keyword:
.PP
.nf
REM MAYBE-UNCOMPUTABLE Mon SKIP SATISFY [isomitted($T+1)] MSG Work between holidays
.fi
.PP
It's almost never appropriate to use \fBMAYBE-UNCOMPUTABLE\fR, but it is
provided for those rare occasions when it makes sense. If you use
\fBMAYBE-UNCOMPUTABLE\fR inside the \fBevaltrig()\fR function, then
untriggerable triggers return -1. For example:
.PP
.nf
SET a evaltrig("MAYBE-UNCOMPUTABLE Mon SKIP OMIT Mon")
.fi
.PP
will set a to -1.
.SH DEBUGGING REMINDER SCRIPTS .SH DEBUGGING REMINDER SCRIPTS
.PP .PP
Although the command-line \fB\-d\fR option is useful for debugging, it Although the command-line \fB\-d\fR option is useful for debugging, it

View File

@@ -125,10 +125,11 @@ Select the appropriate paper size and orientation. Activate
be the normal case unless you have many reminders in a particular be the normal case unless you have many reminders in a particular
day. (See the \fBRem2PS\fR documentation.) day. (See the \fBRem2PS\fR documentation.)
Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Finally, click \fBPrint\fR to print or \fBCancel\fR to cancel. Note
Note that during printing, \fBRemind\fR is \fInot\fR called with that during printing, \fBRemind\fR is called with the
the \fB-itkremind=1\fR option, because it is operated in normal \fB-itkremind=1\fR option and also an additional \fB-itkprint=1\fR
PostScript-producing mode. option.
.SH EDITING REMINDERS .SH EDITING REMINDERS
@@ -210,7 +211,8 @@ background reminder pops up.
.TP .TP
.B Feed popped-up reminder to command's standard input .B Feed popped-up reminder to command's standard input
If selected, feeds the text of the reminder to the command described If selected, feeds the text of the reminder to the command described
above. above. The text of the reminder is prefixed by "HH:MM ", where HH:MM
is the time of the reminder.
.TP .TP
.B E-mail reminders here if popup not dismissed .B E-mail reminders here if popup not dismissed

View File

@@ -265,7 +265,7 @@ proc Initialize {} {
global MondayFirst TwentyFourHourMode ReminderFileModTime global MondayFirst TwentyFourHourMode ReminderFileModTime
global Option global Option
set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA" set CommandLine "|$Remind -itkremind=1 -pp -y -l EXTRA"
set PSCmd "$Remind -pp -l EXTRA" set PSCmd "$Remind -itkremind=1 -itkprint=1 -pp -l EXTRA"
set i 0 set i 0
while {$i < $argc} { while {$i < $argc} {
if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} { if {[regexp -- {-[bgxim].*} [lindex $argv $i]]} {
@@ -962,7 +962,8 @@ proc FillCalWindow {} {
"WEEK" { "WEEK" {
set stuff [string trimleft $stuff] set stuff [string trimleft $stuff]
set stuff [string trimright $stuff] set stuff [string trimright $stuff]
set label [expr $firstWkday + $day - 1] set offset [CalEntryOffset $firstWkday]
set label [expr $offset + $day]
.cal.l$label configure -text "$day $stuff" .cal.l$label configure -text "$day $stuff"
continue continue
} }
@@ -2340,8 +2341,12 @@ proc BrowseForFileRead {w {dir ""}} {
# Starts a background Remind daemon to handle timed reminders # Starts a background Remind daemon to handle timed reminders
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
proc StartBackgroundRemindDaemon {} { proc StartBackgroundRemindDaemon {} {
global Remind DaemonFile ReminderFile Option global Remind DaemonFile ReminderFile Option TwentyFourHourMode
set problem [catch { set DaemonFile [open "|$Remind -z0 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err] if {$TwentyFourHourMode} {
set problem [catch { set DaemonFile [open "|$Remind -b1 -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
} else {
set problem [catch { set DaemonFile [open "|$Remind -z0 -itkremind=1 $Option(ExtraRemindArgs) $ReminderFile" "r+"] } err]
}
if {$problem} { if {$problem} {
tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK tk_dialog .error Error "Can't start Remind daemon in background: $err" error 0 OK
} else { } else {
@@ -2559,7 +2564,7 @@ proc IssueBackgroundReminder { file time now tag } {
} }
if {$Option(RunCmd) != ""} { if {$Option(RunCmd) != ""} {
if {$Option(FeedReminder)} { if {$Option(FeedReminder)} {
FeedReminderToCommand $Option(RunCmd) $msg FeedReminderToCommand $Option(RunCmd) "$time: $msg"
} else { } else {
exec "/bin/sh" "-c" $Option(RunCmd) "&" exec "/bin/sh" "-c" $Option(RunCmd) "&"
} }
@@ -2705,9 +2710,11 @@ proc ReadTaggedOptions { tag date } {
lappend ans -text-day2 $d lappend ans -text-day2 $d
} }
if {[dict exists $obj m]} { if {[dict exists $obj m]} {
lappend ans -text-mon1 [lindex $MonthNames [expr [dict get $obj m] -1]] set mm [dict get $obj m]
lappend ans -text-mon2 [lindex $MonthNames [expr [dict get $obj m] -1]] set mm [string trimleft $m 0]
lappend ans -text-mon3 [lindex $MonthNames [expr [dict get $obj m] -1]] lappend ans -text-mon1 [lindex $MonthNames [expr $mm -1]]
lappend ans -text-mon2 [lindex $MonthNames [expr $mm -1]]
lappend ans -text-mon3 [lindex $MonthNames [expr $mm -1]]
} else { } else {
lappend ans -text-mon1 {every month} lappend ans -text-mon1 {every month}
lappend ans -text-mon2 {every month} lappend ans -text-mon2 {every month}
@@ -2746,7 +2753,8 @@ proc ReadTaggedOptions { tag date } {
lappend ans -text-ordinal Last lappend ans -text-ordinal Last
# Adjust month down and possibly year? # Adjust month down and possibly year?
if {[dict exists $obj m]} { if {[dict exists $obj m]} {
set idx [expr [dict get $obj m] -1] set mm [string trimleft [dict get $obj m] 0]
set idx [expr $mm -1]
if {$idx <= 0} { if {$idx <= 0} {
set idx 12 set idx 12
} }
@@ -2792,15 +2800,18 @@ proc ReadTaggedOptions { tag date } {
if {[dict exists $obj until]} { if {[dict exists $obj until]} {
set u [dict get $obj until] set u [dict get $obj until]
regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $u all yu mu du regexp {^([0-9][0-9][0-9][0-9]).([0-9][0-9]).([0-9][0-9])} $u all yu mu du
# Trim leading zeros, or Tcl complains
set mu [string trimleft $mu 0]
lappend ans -global-expbut 1 lappend ans -global-expbut 1
lappend ans -text-expday $du lappend ans -text-expday $du
lappend ans -text-expmon [lindex $MonthNames [expr $mu-1]] lappend ans -text-expmon [lindex $MonthNames [expr $mu-1]]
lappend ans -text-expyear $yu lappend ans -text-expyear $yu
} else { } else {
set mm [string trimleft $m 0]
lappend ans -global-expbut 0 lappend ans -global-expbut 0
lappend ans -text-expday $d lappend ans -text-expday $d
lappend ans -text-expmon [lindex $MonthNames [expr $m-1]] lappend ans -text-expmon [lindex $MonthNames [expr $mm-1]]
lappend ans -text-expyear $y lappend ans -text-expyear $y
} }
@@ -3428,7 +3439,10 @@ proc ShowTodaysReminders {} {
# Grab the reminders # Grab the reminders
set stuff "" set stuff ""
set cmdline "|$Remind -g -q -r " set cmdline "|$Remind -itkremind=1 -g -q -r "
if {$TwentyFourHourMode} {
append cmdline "-b1 "
}
append cmdline $Option(ExtraRemindArgs); append cmdline $Option(ExtraRemindArgs);
append cmdline " $ReminderFile 2>/dev/null" append cmdline " $ReminderFile 2>/dev/null"
set f [open $cmdline r] set f [open $cmdline r]

View File

@@ -9,6 +9,7 @@
/* */ /* */
/***************************************************************/ /***************************************************************/
#define _XOPEN_SOURCE
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
@@ -21,6 +22,7 @@
#ifdef REM_USE_WCHAR #ifdef REM_USE_WCHAR
#include <wctype.h> #include <wctype.h>
#include <wchar.h>
#endif #endif
#include "types.h" #include "types.h"
@@ -356,6 +358,7 @@ static int make_wchar_versions(CalEntry *e)
if (!buf) return 0; if (!buf) return 0;
(void) mbstowcs(buf, e->text, len+1); (void) mbstowcs(buf, e->text, len+1);
buf[len] = 0;
e->wc_text = buf; e->wc_text = buf;
e->wc_pos = buf; e->wc_pos = buf;
return 1; return 1;
@@ -881,11 +884,21 @@ static void PrintCentered(char const *s, int width, char *pad)
for (i=0; i<d; i++) fputs(pad, stdout); for (i=0; i<d; i++) fputs(pad, stdout);
for (i=0; i<width; i++) { for (i=0; i<width; i++) {
if (*s) PutChar(*s++); else break; if (*s) {
if (isspace(*s)) {
PutChar(' ');
s++;
} else {
PutChar(*s++);
}
} else {
break;
}
} }
for (i=d+len; i<width; i++) fputs(pad, stdout); for (i=d+len; i<width; i++) fputs(pad, stdout);
#else #else
size_t len = mbstowcs(NULL, s, 0); size_t len = mbstowcs(NULL, s, 0);
int display_len;
int i; int i;
wchar_t static_buf[128]; wchar_t static_buf[128];
wchar_t *buf; wchar_t *buf;
@@ -909,11 +922,25 @@ static void PrintCentered(char const *s, int width, char *pad)
} }
} }
(void) mbstowcs(buf, s, len+1); (void) mbstowcs(buf, s, len+1);
d = (width - len) / 2; display_len = wcswidth(buf, len+1);
d = (width - display_len) / 2;
if (d < 0) d = 0;
ws = buf; ws = buf;
for (i=0; i<d; i++) fputs(pad, stdout); for (i=0; i<d; i++) fputs(pad, stdout);
for (i=0; i<width; i++) { for (i=0; i<width; i++) {
if (*ws) PutWideChar(*ws++); else break; if (*ws) {
PutWideChar(*ws++);
if (wcwidth(*ws) == 0) {
/* Don't count this character... it's zero-width */
i--;
}
} else {
break;
}
}
/* Mop up any potential combining characters */
while (*ws && wcwidth(*ws) == 0) {
PutWideChar(*ws++);
} }
for (i=d+len; i<width; i++) fputs(pad, stdout); for (i=d+len; i<width; i++) fputs(pad, stdout);
if (buf != static_buf) free(buf); if (buf != static_buf) free(buf);
@@ -967,6 +994,7 @@ static int WriteOneColLine(int col)
#ifdef REM_USE_WCHAR #ifdef REM_USE_WCHAR
wchar_t const *ws; wchar_t const *ws;
wchar_t const *wspace; wchar_t const *wspace;
int width;
#endif #endif
int numwritten = 0; int numwritten = 0;
@@ -991,9 +1019,18 @@ static int WriteOneColLine(int col)
} }
/* Find the last space char within the column. */ /* Find the last space char within the column. */
while (ws - e->wc_pos <= ColSpaces) { width = 0;
if (!*ws) {wspace = ws; break;} while (width <= ColSpaces) {
if (iswspace(*ws)) wspace = ws; if (!*ws) {
wspace = ws;
break;
}
if (iswspace(*ws)) {
wspace = ws;
}
if (wcwidth(*ws)) {
width++;
}
ws++; ws++;
} }
@@ -1006,16 +1043,30 @@ static int WriteOneColLine(int col)
if (!wspace) { if (!wspace) {
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) { for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) {
if (!*ws) break; if (!*ws) break;
numwritten++; if (iswspace(*ws)) {
PutWideChar(*ws); PutChar(' ');
numwritten++;
} else {
if (wcwidth(*ws) > 0) {
numwritten += wcwidth(*ws);
}
PutWideChar(*ws);
}
} }
e->wc_pos = ws; e->wc_pos = ws;
} else { } else {
/* We found a space - print everything before it. */ /* We found a space - print everything before it. */
for (ws = e->wc_pos; ws<wspace; ws++) { for (ws = e->wc_pos; ws<wspace; ws++) {
if (!*ws) break; if (!*ws) break;
numwritten++; if (iswspace(*ws)) {
PutWideChar(*ws); PutChar(' ');
numwritten++;
} else {
if (wcwidth(*ws) > 0) {
numwritten += wcwidth(*ws);
}
PutWideChar(*ws);
}
} }
} }
@@ -1065,7 +1116,7 @@ static int WriteOneColLine(int col)
/* Find the last space char within the column. */ /* Find the last space char within the column. */
while (s - e->pos <= ColSpaces) { while (s - e->pos <= ColSpaces) {
if (!*s) {space = s; break;} if (!*s) {space = s; break;}
if (*s == ' ') space = s; if (isspace(*s)) space = s;
s++; s++;
} }
@@ -1079,7 +1130,11 @@ static int WriteOneColLine(int col)
for (s = e->pos; s - e->pos < ColSpaces; s++) { for (s = e->pos; s - e->pos < ColSpaces; s++) {
if (!*s) break; if (!*s) break;
numwritten++; numwritten++;
PutChar(*s); if (isspace(*s)) {
PutChar(' ');
} else {
PutChar(*s);
}
} }
e->pos = s; e->pos = s;
} else { } else {
@@ -1087,7 +1142,11 @@ static int WriteOneColLine(int col)
for (s = e->pos; s<space; s++) { for (s = e->pos; s<space; s++) {
if (!*s) break; if (!*s) break;
numwritten++; numwritten++;
PutChar(*s); if (isspace(*s)) {
PutChar(' ');
} else {
PutChar(*s);
}
} }
} }
@@ -1100,7 +1159,7 @@ static int WriteOneColLine(int col)
while(numwritten++ < ColSpaces) PutChar(' '); while(numwritten++ < ColSpaces) PutChar(' ');
/* Skip any spaces before next word */ /* Skip any spaces before next word */
while (*s == ' ') s++; while (isspace(*s)) s++;
/* If done, free memory if no next entry. */ /* If done, free memory if no next entry. */
if (!*s && !e->next) { if (!*s && !e->next) {
@@ -1325,6 +1384,9 @@ static int DoCalRem(ParsePtr p, int col)
if (trig.typ == SAT_TYPE) { if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, &tim, p); r=DoSatRemind(&trig, &tim, p);
if (r) { if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
if (r == E_EXPIRED) return OK; if (r == E_EXPIRED) return OK;
return r; return r;
@@ -1369,6 +1431,9 @@ static int DoCalRem(ParsePtr p, int col)
/* Calculate the trigger date */ /* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1); jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) { if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
return r; return r;
} }
@@ -1599,6 +1664,7 @@ static int DoCalRem(ParsePtr p, int col)
if(!e->filename) { if(!e->filename) {
if (e->text) free(e->text); if (e->text) free(e->text);
if (e->raw_text) free(e->raw_text); if (e->raw_text) free(e->raw_text);
if (e->wc_text) free(e->wc_text);
free(e); free(e);
return E_NO_MEM; return E_NO_MEM;
} }

View File

@@ -146,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */ /* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */ /* any less than 12. */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16 #define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */ /* MAX_PRT_LEN: The maximum number of characters to print when */

View File

@@ -146,7 +146,7 @@
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */ /* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */ /* any less than 12. */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 16 #define VAR_NAME_LEN 64
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */ /* MAX_PRT_LEN: The maximum number of characters to print when */

View File

@@ -81,6 +81,9 @@ int DoRem(ParsePtr p)
PurgeEchoLine("%s\n", CurLine); PurgeEchoLine("%s\n", CurLine);
r=DoSatRemind(&trig, &tim, p); r=DoSatRemind(&trig, &tim, p);
if (r) { if (r) {
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
if (r == E_EXPIRED) return OK; if (r == E_EXPIRED) return OK;
return r; return r;
@@ -134,6 +137,9 @@ int DoRem(ParsePtr p)
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]); PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
PurgeEchoLine("%s\n", CurLine); PurgeEchoLine("%s\n", CurLine);
} }
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = OK;
}
FreeTrig(&trig); FreeTrig(&trig);
return r; return r;
} }
@@ -219,6 +225,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->duration_days = 0; trig->duration_days = 0;
trig->eventstart = NO_TIME; trig->eventstart = NO_TIME;
trig->eventduration = NO_TIME; trig->eventduration = NO_TIME;
trig->maybe_uncomputable = 0;
DBufInit(&(trig->tags)); DBufInit(&(trig->tags));
trig->passthru[0] = 0; trig->passthru[0] = 0;
tim->ttime = NO_TIME; tim->ttime = NO_TIME;
@@ -276,6 +283,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
trig->m = tok.val; trig->m = tok.val;
break; break;
case T_MaybeUncomputable:
trig->maybe_uncomputable = 1;
break;
case T_Skip: case T_Skip:
DBufFree(&buf); DBufFree(&buf);
if (trig->skip != NO_SKIP) return E_SKIP_ERR; if (trig->skip != NO_SKIP) return E_SKIP_ERR;
@@ -987,7 +998,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
break; break;
case RUN_TYPE: case RUN_TYPE:
system(DBufValue(&buf)); System(DBufValue(&buf));
break; break;
default: /* Unknown/illegal type? */ default: /* Unknown/illegal type? */
@@ -1257,7 +1268,7 @@ int DoMsgCommand(char const *cmd, char const *msg)
} }
r = OK; r = OK;
system(DBufValue(&execBuffer)); System(DBufValue(&execBuffer));
finished: finished:
DBufFree(&buf); DBufFree(&buf);

View File

@@ -150,7 +150,9 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
we can usually save some unnecessary copying */ we can usually save some unnecessary copying */
*(dbuf->buffer) = 0; *(dbuf->buffer) = 0;
fgets(dbuf->buffer, dbuf->allocatedLen, fp); if (fgets(dbuf->buffer, dbuf->allocatedLen, fp) == NULL) {
return OK;
}
if (!*(dbuf->buffer)) return OK; if (!*(dbuf->buffer)) return OK;
dbuf->len = strlen(dbuf->buffer); dbuf->len = strlen(dbuf->buffer);
l = dbuf->len - 1; l = dbuf->len - 1;
@@ -162,7 +164,7 @@ int DBufGets(DynamicBuffer *dbuf, FILE *fp)
while(busy) { while(busy) {
*tmp = 0; *tmp = 0;
fgets(tmp, 256, fp); if (fgets(tmp, 256, fp) == NULL) return OK;
if (!*tmp) return OK; if (!*tmp) return OK;
l = strlen(tmp) - 1; l = strlen(tmp) - 1;
if (tmp[l] == '\n') { if (tmp[l] == '\n') {

View File

@@ -366,12 +366,12 @@ static int CacheFile(char const *fname)
cl = NULL; cl = NULL;
/* Create a file header */ /* Create a file header */
cf = NEW(CachedFile); cf = NEW(CachedFile);
cf->cache = NULL;
if (!cf) { if (!cf) {
ShouldCache = 0; ShouldCache = 0;
FCLOSE(fp); FCLOSE(fp);
return E_NO_MEM; return E_NO_MEM;
} }
cf->cache = NULL;
cf->filename = StrDup(fname); cf->filename = StrDup(fname);
if (!cf->filename) { if (!cf->filename) {
ShouldCache = 0; ShouldCache = 0;

View File

@@ -2917,6 +2917,10 @@ FEvalTrig(func_info *info)
} }
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0); jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
} }
if (r == E_CANT_TRIG && trig.maybe_uncomputable) {
r = 0;
jul = -1;
}
FreeTrig(&trig); FreeTrig(&trig);
if (r) return r; if (r) return r;
if (jul < 0) { if (jul < 0) {

View File

@@ -213,7 +213,7 @@ static int new_value (json_state * state,
} }
#define whitespace \ #define whitespace \
case '\n': ++ state.cur_line; state.cur_col = 0; \ case '\n': ++ state.cur_line; state.cur_col = 0; /* FALLTHRU */ \
case ' ': case '\t': case '\r' case ' ': case '\t': case '\r'
#define string_add(b) \ #define string_add(b) \

View File

@@ -813,9 +813,11 @@ int DoIfTrig(ParsePtr p)
if (trig.typ != NO_TYPE) return E_PARSE_ERR; if (trig.typ != NO_TYPE) return E_PARSE_ERR;
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1); jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
if (r) { if (r) {
if (!Hush || r != E_RUN_DISABLED) { if (r != E_CANT_TRIG || !trig.maybe_uncomputable) {
Eprint("%s", ErrMsg[r]); if (!Hush || r != E_RUN_DISABLED) {
} Eprint("%s", ErrMsg[r]);
}
}
syndrome = IF_TRUE | BEFORE_ELSE; syndrome = IF_TRUE | BEFORE_ELSE;
} }
else { else {
@@ -1392,3 +1394,14 @@ SaveLastTimeTrig(TimeTrig const *t)
{ {
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig)); memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
} }
/* Wrapper to ignore warnings about ignoring return value of system() */
void
System(char const *cmd)
{
int r;
r = system(cmd);
if (r == 0) {
r = 1;
}
}

View File

@@ -160,3 +160,4 @@ void PrintJSONKeyPairString(char const *name, char const *val);
void PrintJSONKeyPairDate(char const *name, int jul); void PrintJSONKeyPairDate(char const *name, int jul);
void PrintJSONKeyPairDateTime(char const *name, int dt); void PrintJSONKeyPairDateTime(char const *name, int dt);
void PrintJSONKeyPairTime(char const *name, int t); void PrintJSONKeyPairTime(char const *name, int t);
void System(char const *cmd);

View File

@@ -150,7 +150,7 @@ void IssueSortedReminders(void)
break; break;
case RUN_TYPE: case RUN_TYPE:
system(cur->text); System(cur->text);
break; break;
} }

View File

@@ -67,6 +67,7 @@ Token TokArray[] = {
{ "june", 3, T_Month, 5 }, { "june", 3, T_Month, 5 },
{ "march", 3, T_Month, 2 }, { "march", 3, T_Month, 2 },
{ "may", 3, T_Month, 4 }, { "may", 3, T_Month, 4 },
{ "maybe-uncomputable", 5, T_MaybeUncomputable, 0},
{ "monday", 3, T_WkDay, 0 }, { "monday", 3, T_WkDay, 0 },
{ "msf", 3, T_RemType, MSF_TYPE }, { "msf", 3, T_RemType, MSF_TYPE },
{ "msg", 3, T_RemType, MSG_TYPE }, { "msg", 3, T_RemType, MSG_TYPE },

View File

@@ -73,6 +73,7 @@ typedef struct {
int duration_days; /* Duration converted to days to search */ int duration_days; /* Duration converted to days to search */
int eventstart; /* Original event start (datetime) */ int eventstart; /* Original event start (datetime) */
int eventduration; /* Original event duration (minutes) */ int eventduration; /* Original event duration (minutes) */
int maybe_uncomputable; /* Suppress "can't compute trigger" warnings */
char sched[VAR_NAME_LEN+1]; /* Scheduling function */ char sched[VAR_NAME_LEN+1]; /* Scheduling function */
char warn[VAR_NAME_LEN+1]; /* Warning function */ char warn[VAR_NAME_LEN+1]; /* Warning function */
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */ char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
@@ -171,7 +172,8 @@ enum TokTypes
T_Duration, T_Duration,
T_LongTime, T_LongTime,
T_OmitFunc, T_OmitFunc,
T_Through T_Through,
T_MaybeUncomputable
}; };
/* The structure of a token */ /* The structure of a token */

View File

@@ -475,17 +475,17 @@ int DoDump(ParsePtr p)
DumpVarTable(); DumpVarTable();
return OK; return OK;
} }
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE); fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
while(1) { while(1) {
if (*DBufValue(&buf) == '$') { if (*DBufValue(&buf) == '$') {
DumpSysVarByName(DBufValue(&buf)+1); DumpSysVarByName(DBufValue(&buf)+1);
} else { } else {
v = FindVar(DBufValue(&buf), 0); v = FindVar(DBufValue(&buf), 0);
DBufValue(&buf)[VAR_NAME_LEN] = 0; DBufValue(&buf)[VAR_NAME_LEN] = 0;
if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN, if (!v) fprintf(ErrFp, "%s %s\n",
DBufValue(&buf), UNDEF); DBufValue(&buf), UNDEF);
else { else {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name); fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp); PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n"); fprintf(ErrFp, "\n");
} }
@@ -513,12 +513,12 @@ void DumpVarTable(void)
register Var *v; register Var *v;
register int i; register int i;
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE); fprintf(ErrFp, "%s %s\n\n", VARIABLE, VALUE);
for (i=0; i<VAR_HASH_SIZE; i++) { for (i=0; i<VAR_HASH_SIZE; i++) {
v = VHashTbl[i]; v = VHashTbl[i];
while(v) { while(v) {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name); fprintf(ErrFp, "%s ", v->name);
PrintValue(&(v->v), ErrFp); PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n"); fprintf(ErrFp, "\n");
v = v->next; v = v->next;
@@ -835,7 +835,7 @@ static void DumpSysVar(char const *name, const SysVar *v)
return; return;
} }
if (name) strcat(buffer, name); else strcat(buffer, v->name); if (name) strcat(buffer, name); else strcat(buffer, v->name);
fprintf(ErrFp, "%*s ", VAR_NAME_LEN+1, buffer); fprintf(ErrFp, "%16s ", buffer);
if (v) { if (v) {
if (v->type == SPECIAL_TYPE) { if (v->type == SPECIAL_TYPE) {
Value val; Value val;

View File

@@ -289,6 +289,9 @@ rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
EOF EOF
export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8
../src/remind -w128 -c ../tests/utf-8.rem 1 Nov 2019 >> ../tests/test.out
cmp -s ../tests/test.out ../tests/test.cmp cmp -s ../tests/test.out ../tests/test.cmp
if [ "$?" = "0" ]; then if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED" echo "Remind: Acceptance test PASSED"

File diff suppressed because it is too large Load Diff

View File

@@ -376,6 +376,14 @@ set a133 trigduration()
set a134 trigeventstart() set a134 trigeventstart()
set a135 trigeventduration() set a135 trigeventduration()
# These will issue errors
REM Mon OMIT Mon SKIP MSG Never ever ever...
REM Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
# These will just silently not trigger
REM MAYBE-UNCOMPUTABLE Mon OMIT Mon SKIP MSG Never ever ever...
REM MAYBE-UNCOMPUTABLE Mon SATISFY [wkdaynum($T) == 3] MSG Nope nope...
dump dump
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OMIT 2010-09-03 THROUGH 2010-09-15 OMIT 2010-09-03 THROUGH 2010-09-15

4
tests/utf-8.rem Normal file
View File

@@ -0,0 +1,4 @@
MSG ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский ру́сский
MSG עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית עִבְרִית
Wed MSG With tabs and spaces