Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
405c7d9ed0 | ||
|
|
ac5b641d93 | ||
|
|
06a79989c0 | ||
|
|
671db64436 | ||
|
|
33344cefe6 | ||
|
|
5ef0341537 | ||
|
|
6abca08189 | ||
|
|
35670ce651 | ||
|
|
e230d53d84 | ||
|
|
88537a3471 | ||
|
|
7c9d74da73 | ||
|
|
3b582935ee | ||
|
|
508fafb875 | ||
|
|
6f718f0fe5 | ||
|
|
53acbf2052 | ||
|
|
1606dbbe77 | ||
|
|
adced3ac6c | ||
|
|
14f207140a | ||
|
|
d2da32de6c | ||
|
|
e5d6a36f05 | ||
|
|
68ecfcf876 | ||
|
|
fcb14b9dfe | ||
|
|
6a4b4257a6 | ||
|
|
385b57e269 | ||
|
|
a8e81e3984 | ||
|
|
46c5f0e752 | ||
|
|
454d859fdd | ||
|
|
57134a182c | ||
|
|
5801e143ea | ||
|
|
4e0d0ff98b | ||
|
|
d4ac1849ae | ||
|
|
c16ac1bd8c | ||
|
|
16222ac3bc | ||
|
|
8d88931fb1 | ||
|
|
63f0356e70 | ||
|
|
786b0dee6f | ||
|
|
e7ef9dc295 | ||
|
|
f59461b95d | ||
|
|
566a86b9fd | ||
|
|
8589a3730d | ||
|
|
c05fd366df | ||
|
|
fc9fd1e53c | ||
|
|
a5e6eb9f7c | ||
|
|
a9430fea5f | ||
|
|
828a0d6589 | ||
|
|
32601da748 | ||
|
|
ac50f119cf | ||
|
|
7622ebaa0a | ||
|
|
a586d5cd37 | ||
|
|
edbc88bd19 | ||
|
|
94f99f3414 | ||
|
|
fd4f84349e | ||
|
|
f86350b2ff | ||
|
|
564b72066a | ||
|
|
2890c52090 | ||
|
|
c1d45485c1 | ||
|
|
8b2a69cf8d | ||
|
|
034c1341b3 | ||
|
|
29bbf1a030 | ||
|
|
be6661d6be | ||
|
|
3f876e792c | ||
|
|
f2457b90ff | ||
|
|
e999e9009b | ||
|
|
46326c001b | ||
|
|
b84c2c403c | ||
|
|
861ad72187 | ||
|
|
7dbbc34ccc | ||
|
|
4ea45d1d14 | ||
|
|
c1b9243e2f | ||
|
|
a41c40c7a4 | ||
|
|
318d4547ef | ||
|
|
6f98b60a6a | ||
|
|
baa8f7f3c4 | ||
|
|
6297622072 | ||
|
|
9f3ba0bf2b | ||
|
|
9591dec708 | ||
|
|
ee2d0b7518 | ||
|
|
2d46749c58 | ||
|
|
494664d1b6 | ||
|
|
49686210ae | ||
|
|
ddfa44188b | ||
|
|
73cf93d27b | ||
|
|
60d1a34bf0 | ||
|
|
6f80986801 | ||
|
|
2078f087b2 | ||
|
|
68d110826e | ||
|
|
9fb04c54ae | ||
|
|
d82314594b | ||
|
|
ad169a5248 | ||
|
|
a9bab81226 | ||
|
|
fa63a9ba51 | ||
|
|
1e7a630737 | ||
|
|
de1afce8da | ||
|
|
ac3cb19c26 | ||
|
|
af0479d11d | ||
|
|
0d9c04707f | ||
|
|
c2218f133b | ||
|
|
1ad0645fab | ||
|
|
3c16f6839a | ||
|
|
e8bac1e469 | ||
|
|
b3b69596f4 | ||
|
|
6a7bcb0956 | ||
|
|
f18a0704c1 | ||
|
|
d6f24b7c1e | ||
|
|
e2c9bbf94c | ||
|
|
f53aa4f656 | ||
|
|
a7ab9b8bf8 | ||
|
|
4448271166 | ||
|
|
4861b535a2 | ||
|
|
167f0100c7 | ||
|
|
b0367c7a5c | ||
|
|
4ae8ad52f5 | ||
|
|
dbd64828ab | ||
|
|
158ca882ba | ||
|
|
623ed44608 | ||
|
|
f13b867626 | ||
|
|
ff85325886 | ||
|
|
aa830116ea | ||
|
|
1a4504ba28 | ||
|
|
20365c4627 | ||
|
|
fae8f89ed6 | ||
|
|
a0689999fe | ||
|
|
a42a0ab032 | ||
|
|
b66eb5d3ec | ||
|
|
8b4bc0f56e | ||
|
|
c9d984983f | ||
|
|
47125b051a | ||
|
|
e5e6ff6031 | ||
|
|
9f0aedb608 | ||
|
|
08af33ece5 | ||
|
|
9b421d0b94 | ||
|
|
7bd8d2dd25 | ||
|
|
a7c4879a0a | ||
|
|
8b3585a6b8 | ||
|
|
a223149aee | ||
|
|
9185341b0c | ||
|
|
bf2d707e13 | ||
|
|
f081e5c54d | ||
|
|
18a3db0f31 | ||
|
|
d2c115127d | ||
|
|
c12e7e1b8f | ||
|
|
d3495ab3aa | ||
|
|
b93a7a6195 | ||
|
|
e5519a8498 | ||
|
|
eb2256f873 | ||
|
|
637b137b1c | ||
|
|
e2d14e73bf | ||
|
|
fbbffb4672 | ||
|
|
422e098727 | ||
|
|
87347e30b2 | ||
|
|
3314ce9823 | ||
|
|
402c1fe614 | ||
|
|
1d57856aa8 | ||
|
|
c027c215d6 | ||
|
|
fa0428b9fe | ||
|
|
b01c499ce5 | ||
|
|
4e5033dd24 | ||
|
|
00863f3830 | ||
|
|
2d4b35e8b9 | ||
|
|
6e4f2b9466 | ||
|
|
9a6fc0253b | ||
|
|
3180c781ed | ||
|
|
632152e8b6 | ||
|
|
1048f7e98d | ||
|
|
3de265216e | ||
|
|
2bdcadc7ab | ||
|
|
421ddfc68e |
1
.gitignore
vendored
@@ -13,3 +13,4 @@ tests/test.out
|
||||
*~
|
||||
src/rem2ps
|
||||
src/version.h
|
||||
TAGS
|
||||
|
||||
8
Makefile
@@ -8,7 +8,7 @@ all: src/Makefile
|
||||
@echo "* *"
|
||||
@echo "*******************"
|
||||
@echo ""
|
||||
@cd src; $(MAKE) all LANGDEF=$(LANGDEF)
|
||||
@cd src && $(MAKE) all LANGDEF=$(LANGDEF)
|
||||
|
||||
install:
|
||||
@echo ""
|
||||
@@ -18,14 +18,14 @@ install:
|
||||
@echo "* *"
|
||||
@echo "*********************"
|
||||
@echo ""
|
||||
cd src; $(MAKE) install
|
||||
@cd src && $(MAKE) install
|
||||
|
||||
clean:
|
||||
find . -name '*~' -exec rm {} \;
|
||||
cd src; $(MAKE) clean
|
||||
cd src && $(MAKE) clean
|
||||
|
||||
test:
|
||||
@cd src && $(MAKE) test
|
||||
@cd src && $(MAKE) -s test
|
||||
|
||||
distclean: clean
|
||||
rm -f config.cache config.log config.status src/Makefile src/config.h tests/test.out www/Makefile
|
||||
|
||||
2
configure
vendored
@@ -3991,7 +3991,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.17
|
||||
VERSION=03.03.00
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
@@ -75,6 +75,6 @@ if test "$GCC" = yes; then
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||
VERSION=03.01.17
|
||||
VERSION=03.03.00
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
REMIND version 3.1 for UNIX
|
||||
REMIND version 3.2 for UNIX
|
||||
|
||||
REMIND is a sophisticated alarm/calendar program. Details are given
|
||||
in the man page, "remind.1".
|
||||
@@ -6,16 +6,16 @@ in the man page, "remind.1".
|
||||
INSTALLING REMIND:
|
||||
-----------------
|
||||
|
||||
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X Windows:
|
||||
--------------------------------------------------------------
|
||||
If you have Tcl/Tk (wish 4.1 or higher) installed and are running X11:
|
||||
----------------------------------------------------------------------
|
||||
|
||||
1) Type: wish ./build.tk from the top-level Remind directory.
|
||||
Fill in the various options and hit "Build Remind"
|
||||
|
||||
2) Type: "make install" -- you may need to be root to do this.
|
||||
|
||||
If you do NOT have Tcl/Tk or are NOT running X Windows:
|
||||
-------------------------------------------------------
|
||||
If you do NOT have Tcl/Tk or are NOT running X11:
|
||||
-------------------------------------------------
|
||||
|
||||
1) Edit the file "src/custom.h" according to your preferences.
|
||||
|
||||
@@ -73,12 +73,12 @@ RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
|
||||
|
||||
1. POPUP REMINDERS
|
||||
|
||||
If you're running under X-Windows and you have the TCL tools,
|
||||
you can create simple pop-up reminders by creating the following
|
||||
TCL script called 'popup'. It pops a message on to the screen and
|
||||
waits for you to press the 'OK' button. If you don't press the OK button
|
||||
within 15 seconds, it exits anyway. To use it, you can use the '-k' option
|
||||
for Remind as follows:
|
||||
If you're running under X11 and you have the Tcl tools, you can create
|
||||
simple pop-up reminders by creating the following Tcl script called
|
||||
'popup'. It pops a message on to the screen and waits for you to
|
||||
press the 'OK' button. If you don't press the OK button within 15
|
||||
seconds, it exits anyway. To use it, you can use the '-k' option for
|
||||
Remind as follows:
|
||||
|
||||
remind "-kpopup '%s'&" .reminders
|
||||
|
||||
@@ -93,7 +93,7 @@ Norman Walsh.
|
||||
#!/usr/local/bin/wish
|
||||
wm withdraw .
|
||||
after 15000 { destroy . ; exit }
|
||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
||||
tk_dialog .d { Message } $argv warning 0 { OK }
|
||||
destroy .
|
||||
exit
|
||||
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
|
||||
|
||||
@@ -1,5 +1,82 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.3 Patch 0 - 2020-01-31
|
||||
|
||||
- FIX: rem2ps: Add a %%PageBoundingBox: document structuring convention
|
||||
comment.
|
||||
|
||||
- FIX: rem2ps: Ignore unknown SPECIAL-type reminders.
|
||||
|
||||
- IMPROVEMENT: In calendar mode ("-c" option), Remind automatically adjusts
|
||||
the width of the calendar to fit the terminal window if standard output
|
||||
is a TTY.
|
||||
|
||||
- IMPROVEMENT: Add JSON-based output with "remind -pp" and "remind -ppp"
|
||||
The JSON-based intermediate format preserves a lot more information
|
||||
about the original reminder, allowing back-ends more insight into
|
||||
the intent of the reminder, the recurrence used, etc. See the documentation
|
||||
in "man rem2ps"
|
||||
|
||||
- IMPROVEMENT: TkRemind can "reverse-engineer" reminders that it creates
|
||||
using the additional information in the "remind -pp" format, so it
|
||||
doesn't create or use ugly comment blocks to delimit the reminders
|
||||
it creates.
|
||||
|
||||
- IMPROVEMENT: TkRemind: Add popup help to most buttons and controls.
|
||||
|
||||
- NEW FEATURE: Add support for $DefaultColor system variable, suggested
|
||||
by Tim Chase.
|
||||
|
||||
- NEW FEATURE: The "-@[n][,m]" command-line option allows colored reminders
|
||||
in Agenda Mode as well as in Calendar Mode. It also adds support for
|
||||
terminal emulators that can handle the xterm 256-color escape sequences
|
||||
as well as the true 24-bit color escape sequences.
|
||||
|
||||
- CHANGE: SPECIALs are now case-insensitive. Before, only SPECIAL COLOR
|
||||
would work. Now you can use Special Color, special color, etc.
|
||||
|
||||
* Version 3.2 Patch 0 - 2020-01-03
|
||||
|
||||
- IMPROVEMENT: Add support for events spanning multiple days (with AT
|
||||
and DURATION). Add trigeventstart() and trigeventduration()
|
||||
introspection functions; see "MULTI-DAY EVENTS" in the man page.
|
||||
|
||||
- IMPROVEMENT: Add introspection functions trigback(), trigdelta(),
|
||||
trigduration(), trigfrom(), trigpriority(), trigrep(),
|
||||
trigscanfrom(), trigtimedelta(), trigtimerep(), and triguntil(). See
|
||||
man page for details; thanks to Tim Chase for the suggestion.
|
||||
|
||||
- IMPROVEMENT: TkRemind: Use PNG images for the next month / previous
|
||||
month buttons rather than -> and <-. Also use nice anti-aliased
|
||||
moon phase images instead of ugly blocky bitmaps.
|
||||
|
||||
- CHANGE: Modify addition so that previously-illegal combinations
|
||||
TIME + TIME, TIME + DATETIME and DATETIME + TIME are now allowed.
|
||||
Also allow DATETIME - TIME. If t1 and t2 are expressions of type TIME
|
||||
and dt is an expression of type DATETIME, then the following are now
|
||||
equivalent (before, the expressions on the left-hand side would fail
|
||||
with a "Type mismatch" error.)
|
||||
|
||||
t1 + t2 == t1 + coerce("INT", t2)
|
||||
dt + t2 == dt + coerce("INT", t2)
|
||||
t1 + dt == coerce("INT", t1) + dt
|
||||
dt - t2 == dt - coerce("INT", t2)
|
||||
|
||||
- DOC FIX: Document previously-undocumented $MaxStringLen system variable
|
||||
|
||||
- DOC FIX: Various minor documentation fixes.
|
||||
|
||||
- BUG FIX: Specifying a DURATION without an AT clause results in an error.
|
||||
Before, it would be accepted but not do anything useful.
|
||||
|
||||
- BUG FIX: Catch potential date overflow in slide() function
|
||||
|
||||
- BUG FIX: Fix compile error when compiling Romanian version; eliminate
|
||||
compiler warning when compiling non-English versions.
|
||||
|
||||
- BUG FIX: TkRemind: Fix startup failure of TkRemind if options are at
|
||||
default. :(
|
||||
|
||||
* Version 3.1 Patch 17 - 2019-11-15
|
||||
|
||||
- IMPROVEMENT: Add "Extra Remind Options" setting to TkRemind.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH REM 1 "30 August 2007"
|
||||
.TH REM 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rem \- Invoke Remind with a default filename
|
||||
|
||||
262
man/rem2ps.1
@@ -1,13 +1,13 @@
|
||||
.TH REM2PS 1 "11 April 2005"
|
||||
.TH REM2PS 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
rem2ps \- draw a PostScript calendar from Remind output
|
||||
.SH SYNOPSIS
|
||||
.B rem2ps [\fIoptions\fR]
|
||||
.SH DESCRIPTION
|
||||
\fBRem2ps\fR reads the standard input, which should be the results of running
|
||||
\fBRemind\fR with the \fB\-p\fR option. It emits PostScript code (which
|
||||
draws a calendar) to the standard output.
|
||||
\fBRem2ps\fR reads the standard input, which should be the results of
|
||||
running \fBRemind\fR with the \fB\-p\fR or \fB\-pp\fR option. It
|
||||
emits PostScript code (which draws a calendar) to the standard output.
|
||||
.PP
|
||||
See the section "Rem2PS Input Format" for details about the \fB\-p\fR
|
||||
data. This may be useful if you wish to create other \fBRemind\fR
|
||||
@@ -267,7 +267,7 @@ hold:
|
||||
.TP
|
||||
o
|
||||
The PostScript origin is at the bottom left-hand corner of the page, and
|
||||
PostScript units of 1/72" are in effect.
|
||||
PostScript units of 1/72 inch are in effect.
|
||||
.TP
|
||||
o
|
||||
The variables MinX, MinY, MaxX and MaxY define the bounding box within
|
||||
@@ -313,7 +313,13 @@ Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
|
||||
with the year and month in large grey letters in the background of the
|
||||
calendar.
|
||||
.PP
|
||||
.SH REM2PS INPUT FORMAT
|
||||
.SH REM2PS INPUT FORMAT (-P OPTION)
|
||||
The \fB\-p\fR option is an older, simpler interchange format used by
|
||||
\fBRemind\fR to communicate with back-ends. New back-ends are
|
||||
encoraged to support the new \fB\-pp\fR format preferably, though they
|
||||
are encouraged to support the older \fB\-p\fR format as well if the
|
||||
older format contains enough information for them to work properly.
|
||||
.PP
|
||||
\fBRemind \-p\fR sends the following lines to standard output.
|
||||
The information is designed to be easily parsed by back-end programs:
|
||||
.TP
|
||||
@@ -375,6 +381,9 @@ was provided.
|
||||
.PP
|
||||
\fIbody\fR is the body of the reminder.
|
||||
.PP
|
||||
Future versions of \fBRemind\fR may add additional keys to the JSON
|
||||
object. Back-ends \fImust\fR ignore keys they don't recognize.
|
||||
.PP
|
||||
After a month's worth of reminders have been emitted, \fBRemind\fR
|
||||
emits the line:
|
||||
.PP
|
||||
@@ -393,6 +402,247 @@ the line number and file name of the file containing the reminder. Back-ends
|
||||
that don't care about this information should ignore lines starting with
|
||||
"#" (except, of course, for the # rem2ps lines.)
|
||||
.PP
|
||||
.SH REM2PS PARTIAL JSON INPUT FORMAT (-PP OPTION)
|
||||
\fBRemind \-pp\fR sends the following lines to standard output. They
|
||||
are designed to be easily parsed, but contain much more information
|
||||
than the old-style \fBremind -p\fR output. The extra information
|
||||
contains a representation of the parsed "REM" statement, which could
|
||||
allow converters to better preserve semantics of a reminder. For
|
||||
example, this format passes enough information to allow a back-end to
|
||||
(in many cases) determine a reminder's recurrence rather than just treating
|
||||
each reminder as a one-off event.
|
||||
.PP
|
||||
The lines emitted by \fBremind \-pp\fR are as follows:
|
||||
.TP
|
||||
.B # rem2ps2 begin
|
||||
This line signifies the start of calendar data. Back-ends can search
|
||||
for it to verify they are being fed correct information. Note the
|
||||
"2" after "rem2ps", which distinguishes this format from the older \fB\-p\fR
|
||||
format.
|
||||
.TP
|
||||
\fImonth_name year num_days first_day monday_first\fR
|
||||
Same as the \fB\-p\fR format
|
||||
.TP
|
||||
\fIsun mon tue wed thu fri sat\fR
|
||||
Same as the \fB\-p\fR format
|
||||
.TP
|
||||
\fInext_mon next_days\fR
|
||||
Same as the \fB\-p\fR format
|
||||
.TP
|
||||
\fIprev_mon prev_days\fR
|
||||
Same as the \fB\-p\fR format
|
||||
.PP
|
||||
.B CALENDAR ENTRIES
|
||||
.PP
|
||||
The remaining data consists of calendar entries expressed as a JSON object
|
||||
on a single line. Each such line will begin with "{" and will be a well-formed
|
||||
JSON object. The keys that may be present in the JSON object are as
|
||||
follows:
|
||||
.TP
|
||||
.B date \fIYYYY-MM-DD\fR
|
||||
The \fbdate\fR key will \fIalways\fR be present; it is the trigger date
|
||||
of the reminder expressed as a string in the format \fIYYYY-MM-DD\fR
|
||||
.TP
|
||||
.B filename \fIf\fR
|
||||
The filename in which the reminder was found.
|
||||
.TP
|
||||
.B lineno \fIn\fR
|
||||
The line number within the file on which the reminder was found.
|
||||
.TP
|
||||
.B nonconst_expr 1
|
||||
If the reminder contained a non-constant expression that had to be evaluated
|
||||
to determine the trigger date, this key will be present with the value 1.
|
||||
If this key is present, then it is unsafe for a back-end to rely on
|
||||
recurrence semantics or even the semantics of any part of the parsed
|
||||
reminder, as they may have been computed in a way that cannot be expressed
|
||||
in JSON.
|
||||
.TP
|
||||
.B if_depth \fIn\fR
|
||||
If the reminder is inside one or more IF or ELSE statements, this key
|
||||
will be present and the value will be the number of nested IFs from
|
||||
the top-level to the reminder. Back-ends should be wary of
|
||||
interpreting recurrence semantics of reminders within an IF or ELSE
|
||||
block.
|
||||
.TP
|
||||
.B passthru \fIspecial\fR
|
||||
If the reminder was a SPECIAL reminder, the \fBpassthru\fR key will be
|
||||
present and the value will be the type of SPECIAL (such as SHADE, COLOR,
|
||||
MOON, etc.)
|
||||
.TP
|
||||
.B tags \fIdata\fR
|
||||
If any TAG clauses are present, the \fBtag\fR key will be present and consist
|
||||
of a comma-separated list of tags.
|
||||
.TP
|
||||
.B time \fIt\fR
|
||||
If an AT clause was present, this key will contain the time of the AT clause
|
||||
in minutes after midnight.
|
||||
.TP
|
||||
.B tdelta \fIn\fR
|
||||
If a time delta (+n after an AT clause) was present, this key contains the
|
||||
delta value in minutes.
|
||||
.TP
|
||||
.B trep \fIn\fR
|
||||
If a time repeat (*n after an AT clause) was present, this key contains the
|
||||
repeat value in minutes.
|
||||
.TP
|
||||
.B eventduration \fIn\fR
|
||||
If a DURATION clause was present, this key contains the event duration in
|
||||
minutes.
|
||||
.TP
|
||||
.B duration \fIn\fR
|
||||
If a DURATION clause was present, this key contains today's duration in
|
||||
minutes. See the \fBremind(1)\fR man page, "MULTI-DAY EVENTS", for a
|
||||
discussion of duration vs. event duration.
|
||||
.TP
|
||||
.B eventstart \fIdt\fR
|
||||
If an AT clause was present, this key contains the event start time in
|
||||
the format \fIYYYY-MM-DDTHH:MM\fR.
|
||||
.TP
|
||||
.B back \fIn\fR
|
||||
If the reminder contained a "back" clause (\-n or \-\-n), this key
|
||||
contains the back value. If the "back" value was \-n, the value will
|
||||
be positive; if it was \-\-n, the value will be negative.
|
||||
.TP
|
||||
.B delta \fIn\fR
|
||||
If the reminder contained a "delta" clause (\+n or \+\+n), this key
|
||||
contains the delta value. If the "delta" value was \+n, the value will
|
||||
be positive; if it was \+\+n, the value will be negative.
|
||||
.TP
|
||||
.B rep \fIn\fR
|
||||
If the reminder contained a "repeat" clause (*n), this key contains
|
||||
the repeat value.
|
||||
.TP
|
||||
.B skip \fItype\fR
|
||||
If the reminder contained a SKIP, BEFORE or AFTER keyword, then this
|
||||
key will contain that keyword.
|
||||
.TP
|
||||
.B localomit \fIarray\fR
|
||||
If the reminder contains a local OMIT keyword, this key will be present.
|
||||
Its value will be an array of English day names that are OMITted.
|
||||
.TP
|
||||
.B wd \fIarray\fR
|
||||
If the reminder contains one or more weekdays, this key will be present.
|
||||
Its value will be an array of English day names that are present.
|
||||
.TP
|
||||
.B d \fIn\fR
|
||||
If a day-of-month is present in the reminder specification, this key
|
||||
will be present and its value will be the day number.
|
||||
.TP
|
||||
.B m \fIn\fR
|
||||
If a month is present in the reminder specification, this key
|
||||
will be present and its value will be the month number.
|
||||
.TP
|
||||
.B y \fIn\fR
|
||||
If a year is present in the reminder specification, this key
|
||||
will be present and its value will be the year.
|
||||
.TP
|
||||
.B until \fIYYYY-MM-DD\fR
|
||||
If the reminder contains an UNTIL or THROUGH clause, this key
|
||||
will be present. Its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B once 1
|
||||
If the reminder contains a ONCE keyword, this key will be present
|
||||
with a value of 1.
|
||||
.TP
|
||||
.B scanfrom \fIYYYY-MM-DD\fR
|
||||
If the reminder contains a SCANFROM keyword, this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B from \fIYYYY-MM-DD\fR
|
||||
If the reminder contains a FROM keyword, this key will be present
|
||||
and its value will be a string of the form YYYY-MM-DD.
|
||||
.TP
|
||||
.B priority \fIn\fR
|
||||
The priority of the reminder. Always present; if no PRIORITY keyword
|
||||
is specified, then a reminder has a default priority of 5000.
|
||||
.TP
|
||||
.B r \fIn\fR
|
||||
For a SHADE or COLOR special, the red color component.
|
||||
.TP
|
||||
.B g \fIn\fR
|
||||
For a SHADE or COLOR special, the green color component.
|
||||
.TP
|
||||
.B b \fIn\fR
|
||||
For a SHADE or COLOR special, the blue color component.
|
||||
.TP
|
||||
.B body \fIbody\fR
|
||||
The body of the reminder to issue. Always present.
|
||||
.TP
|
||||
.B rawbody \fIraw\fR
|
||||
The "raw" body of the reminder, before any expression-pasting or
|
||||
substitution-sequence processing. If the raw body would be the same
|
||||
as the processed body, then this key is not present.
|
||||
.PP
|
||||
After a month's worth of reminders have been emitted, \fBRemind\fR
|
||||
emits the line:
|
||||
.PP
|
||||
\fB# rem2ps2 end
|
||||
.PP
|
||||
However, back-ends should keep reading until EOF in case more data for
|
||||
subsequent months is forthcoming.
|
||||
.PP
|
||||
|
||||
.SH REM2PS PURE JSON INPUT FORMAT (-PPP OPTION)
|
||||
\fBRemind \-ppp\fR emits \fIpure JSON\fR output. The format is
|
||||
as follows:
|
||||
.PP
|
||||
\fBRemind\fR outputs a JSON array. Each element of the array is a
|
||||
\fImonth descriptor\fR.
|
||||
.PP
|
||||
Each month descriptor is a JSON object with the following elements:
|
||||
.TP
|
||||
.B monthname \fIname\fR
|
||||
The name of the month.
|
||||
.TP
|
||||
.B year \fIyyyy\fR
|
||||
The year.
|
||||
.TP
|
||||
.B daysinmonnth \fIn\fR
|
||||
The number of days in the current month.
|
||||
.TP
|
||||
.B firstwkday \fIn\fR
|
||||
The weekday of the first day of the month (0 = Sunday, 1 = Monday, 6 = Saturday).
|
||||
.TP
|
||||
.B mondayfirst \fIn\fR
|
||||
An indicator of whether or not the calendar week should start with
|
||||
Sunday (n=0) or Monday (n=1).
|
||||
.TP
|
||||
.B daynames \fR[\fIdays\fR]
|
||||
A seven-element array of day names; each element is a string representing
|
||||
the names of the days from Sunday through Saturday.
|
||||
.TP
|
||||
.B prevmonthname \fIname\fR
|
||||
The name of the previous month.
|
||||
.TP
|
||||
.B daysinprevmonth \fIn\fR
|
||||
The number of days in the previous month.
|
||||
.TP
|
||||
.B prevmonthyear \fIyyyy\fR
|
||||
The year of the previous month. (The same as \fByear\fR unless the current
|
||||
month is January.)
|
||||
.TP
|
||||
.B nextmonthname \fIname\fR
|
||||
The name of the following month.
|
||||
.TP
|
||||
.B daysinnextmonth \fIn\fR
|
||||
The number of days in the following month.
|
||||
.TP
|
||||
.B nextmonthyear \fIyyyy\fR
|
||||
The year of the following month. (The same as \fByear\fR unless the
|
||||
current month is December.)
|
||||
.TP
|
||||
.B entries \fR[\fIarray\fR]
|
||||
The \fBentries\fR key consists of an array of calendar entries; each
|
||||
entry is a JSON object that has the same format as described in the
|
||||
\fBCALENDAR ENTRIES\fR section in the \fB\-PP FORMAT\fR section,
|
||||
\fIwith the following difference\fR: In \fB\-PP\fR mode, if a reminder
|
||||
has \fB%"\fR markers, only the text between the markers
|
||||
is included in the \fBbody\fR element. In \fB\-PPP\fR mode, the
|
||||
entire text \fIincluding\fR the \fB%"\fR markers is included and it's up to
|
||||
the back-end to extract the portion between the markers if that
|
||||
is desired.
|
||||
|
||||
|
||||
.SH AUTHOR
|
||||
Rem2PS was written by Dianne Skoll <dianne@skoll.ca>
|
||||
.SH BUGS
|
||||
|
||||
335
man/remind.1
@@ -1,4 +1,4 @@
|
||||
.TH REMIND 1 "31 August 2008"
|
||||
.TH REMIND 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
remind \- a sophisticated reminder service
|
||||
@@ -46,7 +46,8 @@ The \fB\-c\fR option causes \fBRemind\fR to produce a calendar that is
|
||||
sent to standard output. If you supply a number \fIn\fR, then a
|
||||
calendar will be generated for \fIn\fR months, starting with the
|
||||
current month. By default, a calendar for only the current month is
|
||||
produced.
|
||||
produced.
|
||||
.RS
|
||||
.PP
|
||||
You can precede \fIn\fR (if any) with a set of flags. The flags
|
||||
are as follows:
|
||||
@@ -72,24 +73,54 @@ only work on terminals that are set to UTF-8 character encoding.
|
||||
.TP
|
||||
.B 'c'
|
||||
causes \fBRemind\fR to use VT100 escape sequences to approximate
|
||||
SPECIAL COLOR reminders. The approximation is (of necessity) very
|
||||
SPECIAL COLOR reminders. Note that this flag is kept for
|
||||
backwards-compatibility; you should use the \fB\-@\fI[n][,m]\fR
|
||||
command-line option instead.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B \-@\fR[\fIn\fR][,\fIm\fR]
|
||||
Tells \fBRemind\fR to approximate SPECIAL COLOR reminders using VT100
|
||||
escape sequences. The approximation is (of necessity) very
|
||||
coarse, because the VT100 only has eight different color sequences,
|
||||
each with one of two brightnesses. A color component greater than
|
||||
64 is considered "on", and if any of the three color components is
|
||||
greater than 128, the color is considered "bright".
|
||||
|
||||
.RS
|
||||
.PP
|
||||
If you supply the optional numeric parameters, the have the following
|
||||
meanings: \fIn\fR=0 tells \fBRemind\fR to use the standard 16 VT100
|
||||
colors. \fIn\fR=1 tells it to use an extended 256-color palette supported
|
||||
by many terminal emulators such as xterm. And \fIn\fR=2 tells it to
|
||||
use escape sequences that support true 24-bit colors, again supported
|
||||
by many terminal emulators such as xterm.
|
||||
.PP
|
||||
If the optional \fIm\fR parameter is supplied following a comma,
|
||||
then \fIm\fR=0 tells \fBRemind\fR that the terminal background is dark,
|
||||
and \fBRemind\fR will brighten up dark colors to make them visible. If
|
||||
\fIm\fR=1, then \fBRemind\fR assumes the terminal background is light
|
||||
and it will darken bright colors to make them visible. If no \fIm\fR
|
||||
is supplied, then \fBRemind\fR does not perform any adjustments, and
|
||||
some reminders may be hard or impossible to see if the color is too close
|
||||
to the terminal background color.
|
||||
.RE
|
||||
.TP
|
||||
.B \-w\fR\fIcol\fR[,\fIpad\fR[,\fIspc\fR]]]
|
||||
The \fB\-w\fR option specifies the output width, padding and spacing
|
||||
of the formatted calendar output. \fICol\fR specifies the number of
|
||||
columns in the output device, and defaults to 80. \fIPad\fR specifies
|
||||
how many lines to use to "pad" empty calendar boxes. This defaults to
|
||||
5. If you have many reminders on certain days that make your calendar
|
||||
too large to fit on a page, you can try reducing \fIpad\fR to make the
|
||||
empty boxes smaller. \fISpc\fR specifies how many blank lines to leave
|
||||
between the day number and the first reminder entry. It defaults to 1.
|
||||
columns in the output device. If not specified, or specified as 0,
|
||||
it defaults to the larger of 71 or the actual width of your terminal,
|
||||
or to 80 if standard output is not a terminal.
|
||||
.RS
|
||||
.PP
|
||||
\fIPad\fR specifies how many lines
|
||||
to use to "pad" empty calendar boxes. This defaults to 5. If you
|
||||
have many reminders on certain days that make your calendar too large
|
||||
to fit on a page, you can try reducing \fIpad\fR to make the empty
|
||||
boxes smaller. \fISpc\fR specifies how many blank lines to leave
|
||||
between the day number and the first reminder entry. It defaults to
|
||||
1.
|
||||
.PP
|
||||
Any of \fIcol\fR, \fIpad\fR or \fIspc\fR can be omitted, providing you
|
||||
provide the correct number of commas. Don't use any spaces in the option.
|
||||
.RE
|
||||
@@ -106,17 +137,27 @@ If you immediately follow the \fBs\fR with the letter
|
||||
day they actually occur \fIas well as\fR on any preceding days specified
|
||||
by the reminder's \fIdelta\fR.
|
||||
.TP
|
||||
.B \-p\fR[\fBa\fR]\fIn\fR
|
||||
.B \-p\fR[\fBa\fR][\fBp\fR][\fBp\fR]\fIn\fR
|
||||
The \fB\-p\fR option is very similar to the \fB\-s\fR option, except
|
||||
that the output contains additional information for use by the
|
||||
\fBRem2PS\fR program, which creates a PostScript calendar. For this
|
||||
\fBRem2PS\fR program, which creates a PostScript calendar, and various
|
||||
other back-end programs. For this
|
||||
option, \fIn\fR cannot start with "+"; it must specify a number of months.
|
||||
The format of the \fB\-p\fR output is described in the \fBrem2ps(1)\fR
|
||||
man page. If you immediately follow the \fBp\fR with the letter
|
||||
\fBa\fR, then \fBRemind\fR displays reminders on the calendar on the
|
||||
day they actually occur \fIas well as\fR on any preceding days specified
|
||||
by the reminder's \fIdelta\fR.
|
||||
|
||||
by the reminder's \fIdelta\fR. If you follow the \fBp\fR with another
|
||||
\fBp\fR, then \fBRemind\fR uses a more comprehensive JSON-based
|
||||
format rather than the "simple calendar" format. This format is
|
||||
also documented in the \fBrem2ps(1)\fR man page. Finally, if you use
|
||||
three p's, as in \fB\-ppp\fR, then \fBRemind\fR uses a pure JSON
|
||||
format, again documented in \fBrem2ps(1)\fR.
|
||||
.RS
|
||||
.PP
|
||||
Note that the \fB\-pp\fR or \fB\-ppp\fR options also enable the \fB\-l\fR
|
||||
option.
|
||||
.RE
|
||||
.TP
|
||||
.B \-l
|
||||
If you use the \-l option in conjunction with the \-p option, then
|
||||
@@ -448,7 +489,8 @@ of a special reminder depends on the back-end. For the \fBRem2PS\fR
|
||||
back-end, \fBSPECIAL PostScript\fR is equivalent to a \fBPS\fR-type
|
||||
reminder, and \fBSPECIAL PSFile\fR is equivalent to a \fBPSFILE\fR-type
|
||||
reminder. The body of a \fBSPECIAL\fR reminder is obviously dependent
|
||||
upon the back-end.
|
||||
upon the back-end. A back-end \fImust\fR ignore a \fBSPECIAL\fR that
|
||||
it does not recognize.
|
||||
.PP
|
||||
.B DATE SPECIFICATIONS
|
||||
.PP
|
||||
@@ -1033,17 +1075,17 @@ by the hexadecimal representation of the MD5 sum of the REM
|
||||
command line. This lets you give a more-or-less unique identifier
|
||||
to each distinct REM command.
|
||||
.PP
|
||||
The \fBDURATION\fR keyword makes sense only for timed reminders;
|
||||
it specifies the duration of an event. Currently, this is not
|
||||
used, but it may be used in future by back-ends or scheduling
|
||||
systems built around \fBRemind\fR. For example, if you have
|
||||
a 90-minute meeting starting at 1:00pm, you could use:
|
||||
The \fBDURATION\fR keyword makes sense only for timed reminders; it
|
||||
specifies the duration of an event. For example, if you have a
|
||||
90-minute meeting starting at 1:00pm, you could use:
|
||||
.PP
|
||||
.nf
|
||||
REM 5 March 1999 AT 13:00 DURATION 1:30 MSG Meeting
|
||||
.fi
|
||||
.PP
|
||||
Note that \fIduration\fR is specified in hours and minutes.
|
||||
Note that \fIduration\fR is specified in hours and minutes. If you
|
||||
specify a duration of 00:00, then \fBRemind\fR behaves exactly as if
|
||||
no \fBDURATION\fR at all had been present.
|
||||
.PP
|
||||
.SH THE SUBSTITUTION FILTER
|
||||
.PP
|
||||
@@ -1709,7 +1751,12 @@ Has several uses. These are:
|
||||
.PP
|
||||
\fBINT\fR + \fBTIME\fR or \fBTIME\fR + \fBINT\fR - returns a \fBTIME\fR
|
||||
obtained by adding
|
||||
\fBINT\fR minutes to the original \fBTIME\fR.
|
||||
\fBINT\fR minutes to the original \fBTIME\fR. The result will always
|
||||
range from 00:00 through 23:59.
|
||||
.PP
|
||||
\fBTIME\fR + \fBTIME\fR treats the second \fBTIME\fR parameter as a
|
||||
duration, converting it to an integer number of minutes past midnight,
|
||||
and then performs addition as with \fBTIME\fR + \fBINT\fR.
|
||||
.PP
|
||||
\fBINT\fR + \fBDATE\fR or \fBDATE\fR + \fBINT\fR - returns a \fBDATE\fR
|
||||
obtained by adding \fBINT\fR days to the original \fBDATE\fR.
|
||||
@@ -1718,6 +1765,11 @@ obtained by adding \fBINT\fR days to the original \fBDATE\fR.
|
||||
\fBDATETIME\fR obtained by adding \fBINT\fR minutes to the original
|
||||
\fBDATETIME\fR.
|
||||
.PP
|
||||
\fBDATETIME\fR + \fBTIME\fR or \fBTIME\fR + \fBDATETIME\fR
|
||||
treats the \fBTIME\fR parameter as a
|
||||
duration, converting it to an integer number of minutes past midnight,
|
||||
and then performs addition as with \fBDATETIME\fR + \fBINT\fR.
|
||||
.PP
|
||||
\fBSTRING\fR + \fBSTRING\fR - returns a \fBSTRING\fR that is the
|
||||
concatenation of the two original
|
||||
\fBSTRING\fRs.
|
||||
@@ -1751,9 +1803,11 @@ the original \fBDATE\fR.
|
||||
earlier
|
||||
than the original \fBTIME\fR.
|
||||
.PP
|
||||
\fBDATETIME\fR - \fBINT\fR - returns a \fBDATETIME\fR that is \fBINT\fR minutes
|
||||
earlier
|
||||
than the original \fBDATETIME\fR.
|
||||
\fBDATETIME\fR - \fBINT\fR - returns a \fBDATETIME\fR that is
|
||||
\fBINT\fR minutes earlier than the original \fBDATETIME\fR.
|
||||
.PP
|
||||
\fBDATETIME\fR - \fBTIME\fR - coerces the \fBTIME\fR to an \fBINT\fR
|
||||
and then performs subtraction as above.
|
||||
.RE
|
||||
.TP
|
||||
.B <, <=, >, and >=
|
||||
@@ -1883,6 +1937,22 @@ This variable can be set only to "/" or "-". It holds the character
|
||||
used to separate portions of a date when \fBRemind\fR prints a DATE or
|
||||
DATETIME value.
|
||||
.TP
|
||||
.B $DefaultColor
|
||||
This variable can be set to a string that has the form of three
|
||||
space-separated numbers. Each number must be an integer from 0 to
|
||||
255, or all three numbers must be -1. The default value of
|
||||
\fB$DefaultColor\fR is "-1 -1 -1", which suppresses default coloring
|
||||
of MSG-type reminders. If you set \fB$DefaultColor\fR to any other
|
||||
value, then all MSG-, MSF- and CAL-type reminders are effectively
|
||||
converted into SPECIAL COLOR reminders whose color value is specified
|
||||
by \fB$DefaultColor\fR.
|
||||
.RS
|
||||
.PP
|
||||
Unlike other system variables, the value of \fB$DefaultColor\fR is
|
||||
\fInot\fR preserved between calendar iterations; rather, it is reset
|
||||
to "-1 -1 -1" at the start of each iteration.
|
||||
.RE
|
||||
.TP
|
||||
.B $DefaultPrio
|
||||
The default priority assigned to reminders without a \fBPRIORITY\fR
|
||||
clause. You can set this as required to adjust the priorities of
|
||||
@@ -1986,6 +2056,10 @@ start of your reminder scripts.
|
||||
The maximum number of iterations for the \fBSATISFY\fR clause
|
||||
(described later.) Must be at least 10.
|
||||
.TP
|
||||
.B $MaxStringLen
|
||||
A limit on the longest string that \fBRemind\fR will allow you
|
||||
to create. The default is 65535.
|
||||
.TP
|
||||
.B $MinsFromUTC
|
||||
The number of minutes between Universal Time Coordinated and local time. If
|
||||
\fB$CalcUTC\fR is non-zero, this is calculated upon startup of \fBRemind\fR.
|
||||
@@ -2791,10 +2865,77 @@ date, returns the integer 0.
|
||||
Similar to trigdate(), but returns a \fBDATETIME\fR if the most recent
|
||||
triggerable \fBREM\fR command had an \fBAT\fR clause. If there was no
|
||||
\fBAT\fR clause, returns a \fBDATE\fR. If no trigger could be computed,
|
||||
returns the integer 0.
|
||||
returns the integer 0. See "MULTI-DAY EVENTS" for more information.
|
||||
.TP
|
||||
.B trigeventstart()
|
||||
Returns a \fBDATETIME\fR representing the start of the most recent
|
||||
triggerable \fBREM\fR command that had an \fBAT\fR clause. For events
|
||||
without a \fBDURATION\fR or that do not span multiple days, returns
|
||||
the same as \fBtrigdatetime()\fR. If the \fBREM\fR command did not
|
||||
have an \fBAT\fR clause, returns the integer -1 (and differs from
|
||||
\fBtrigdatetime()\fR in this respect.) See "MULTI-DAY EVENTS" for more
|
||||
information.
|
||||
.TP
|
||||
.B trigeventduration()
|
||||
Returns a \fBTIME\fR representing the duration of the most recent
|
||||
triggerable \fBREM\fR command that had an \fBAT\fR and a
|
||||
\fBDURATION\fR clause. If the event does not span multiple days,
|
||||
returns the same thing as \fBtrigduration()\fR. If the \fBREM\fR
|
||||
command lacked an \fBAT\fR or \fBDURATION\fR clause, returns -1. See
|
||||
"MULTI-DAY EVENTS" for more information.
|
||||
.TP
|
||||
.B trigback()
|
||||
Returns the "back" amount of the last \fBREM\fR or \fBIFTRIG\fR command.
|
||||
Returns a positive integer N if the "back" is of the form -N, or a negative
|
||||
integer if it is of the form --N. If there is no "back", then returns 0.
|
||||
.TP
|
||||
.B trigdelta()
|
||||
Returns the "delta" amount of the last \fBREM\fR or \fBIFTRIG\fR command.
|
||||
Returns a positive integer N if the "delta" is of the form +N, or a negative
|
||||
integer if it is of the form ++N. If there is no "delta", then returns 0.
|
||||
.TP
|
||||
.B trigtimedelta()
|
||||
Similar to \fBtrigdelta()\fR, but returns the delta used in the
|
||||
\fBAT\fR clause of a timed reminder.
|
||||
.TP
|
||||
.B trigrep()
|
||||
Returns the "repeat" amount of the last \fBREM\fR or \fBIFTRIG\fR
|
||||
command. Returns a positive integer N if the "repeat" is of the form
|
||||
*N. If there is no "repeat", then returns 0.
|
||||
.TP
|
||||
.B trigtimerep()
|
||||
Similar to \fBtrigrep()\fR, but returns the repeat used in the \fBAT\fR clause
|
||||
of a timed reminder.
|
||||
.TP
|
||||
.B trigduration()
|
||||
Returns (as a TIME type) the \fBDURATION\fR parameter of a timed
|
||||
reminder. If there is no \fBDURATION\fR parameter, returns the
|
||||
integer -1. See "MULTI-DAY EVENTS" for more information.
|
||||
.TP
|
||||
.B trigpriority()
|
||||
Returns the \fBPRIORITY\fR of the last \fBREM\fR or \fBIFTRIG\fR command.
|
||||
.TP
|
||||
.B triguntil()
|
||||
Returns (as a \fBDATE\fR type) the \fBUNTIL\fR parameter of the last
|
||||
\fBREM\fR or \fBIFTRIG\fR command. If there was no \fBUNTIL\fR
|
||||
parameter, returns the integer -1. If there is a \fBTHROUGH\fR parameter,
|
||||
that will be returned by \fBtriguntil()\fR since "THROUGH yyyy-mm-dd" is simply
|
||||
syntactic sugar for "*1 UNTIL yyyy-mm-dd".
|
||||
.TP
|
||||
.B trigscanfrom()
|
||||
Returns (as a \fBDATE\fR type) the \fBSCANFROM\fR parameter of the last \fBREM\fR
|
||||
or \fBIFTRIG\fR command. If there was no \fBSCANFROM\fR parameter, returns
|
||||
the integer -1. Note that \fBFROM\fR and \fBSCANFROM\fR interact; a reminder that
|
||||
has a "FROM yyyy-mm-dd" parameter will act as if it has a \fBSCANFROM\fR parameter
|
||||
whose value is the maximum of "yyyy-mm-dd" and today.
|
||||
.TP
|
||||
.B trigfrom()
|
||||
Returns (as a \fBDATE\fR type) the \fBFROM\fR parameter of the last \fBREM\fR or
|
||||
\fBIFTRIG\fR command. If there was no \fBFROM\fR parameter, returns the integer -1.
|
||||
|
||||
.TP
|
||||
.B trigger(d_date [,t_time [,i_utcflag]]) \fRor\fB trigger(q_datetime [,i_utcflag])
|
||||
Returns a string suitable for use in a \fBREM\fR command or a SCANFROM
|
||||
Returns a string suitable for use in a \fBREM\fR command or a \fBSCANFROM\fR
|
||||
or UNTIL clause, allowing you to calculate trigger dates in advance.
|
||||
Note that in earlier versions of \fBRemind\fR, \fBtrigger\fR was
|
||||
required to convert a date into something the \fBREM\fR command could
|
||||
@@ -2827,9 +2968,11 @@ The value for your time zone may differ.
|
||||
.RE
|
||||
.TP
|
||||
.B trigtime()
|
||||
Returns the time of the last \fBREM\fR command with an \fBAT\fR clause.
|
||||
If the last \fBREM\fR did not have an \fBAT\fR clause, returns the integer
|
||||
0.
|
||||
Returns the time of the last \fBREM\fR command with an \fBAT\fR
|
||||
clause. If the last \fBREM\fR did not have an \fBAT\fR clause,
|
||||
returns the integer 0. If a \fBREM\fR command has an \fBAT\fR clause
|
||||
with a \fBDURATION\fR, then you can compute the end time as
|
||||
\fBtrigtime() + trigduration()\fR.
|
||||
.TP
|
||||
.B trigvalid()
|
||||
Returns 1 if the value returned by \fBtrigdate()\fR is valid for the most
|
||||
@@ -2909,6 +3052,99 @@ Returns a number from 0 to 6 representing the day-of-week of the specified
|
||||
.TP
|
||||
.B year(dq_date)
|
||||
Returns a \fBINT\fR that is the year component of \fIdate\fR.
|
||||
|
||||
.SH MULTI-DAY EVENTS
|
||||
|
||||
If you specify a start time with \fBAT\fR and a duration with
|
||||
\fBDURATION\fR, you can create events that span multiple days.
|
||||
Consider these two REM statements:
|
||||
.PP
|
||||
.nf
|
||||
REM 1991-02-13 AT 16:00 DURATION 72:00 MSG 72-hour event
|
||||
REM 1991-02-13 THROUGH 1991-02-16 AT 16:00 MSG Four events
|
||||
.fi
|
||||
.PP
|
||||
The first statement creates a \fIsingle\fR event that starts on
|
||||
13 February 1991 at 16:00 and runs through 16 February 1991 at 16:00
|
||||
.PP
|
||||
The second statements creates \fIfour separate\fR events that start
|
||||
at 16:00 on 13, 14, 15 and 16 February 1991 and have indefinite duration.
|
||||
.PP
|
||||
Remind handles multi-day events specially. These are the rules:
|
||||
.PP
|
||||
On the \fIfirst\fR day of a multi-day event, \fBtrigdatetime()\fR will
|
||||
return the starting date and time of the event, and \fBtrigduration()\fR
|
||||
will return the original DURATION.
|
||||
.PP
|
||||
On each \fIsubsequent\fR day of a multi-day event, \fBtrigdatetime()\fR
|
||||
will return midnight on the day in question, and \fBtrigduration()\fR
|
||||
will return the \fIremaining\fR duration. Consider this example:
|
||||
.PP
|
||||
.nf
|
||||
#!/bin/sh
|
||||
remind - 12 feb 1991 '*6' <<'EOF'
|
||||
BANNER %
|
||||
REM 1991-02-13 AT 16:00 DURATION 72:00 SATISFY 1
|
||||
set a trigdatetime()
|
||||
set b trigduration()
|
||||
set c trigeventstart()
|
||||
set d trigeventduration()
|
||||
MSG now=[today()] dt=[a] dur=[b] estart=[c] edur=[d]%
|
||||
EOF
|
||||
.fi
|
||||
.PP
|
||||
The output is:
|
||||
.PP
|
||||
.nf
|
||||
now=1991-02-12 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
|
||||
now=1991-02-13 dt=1991-02-13@16:00 dur=72:00 estart=1991-02-13@16:00 edur=72:00
|
||||
now=1991-02-14 dt=1991-02-14@00:00 dur=64:00 estart=1991-02-13@16:00 edur=72:00
|
||||
now=1991-02-15 dt=1991-02-15@00:00 dur=40:00 estart=1991-02-13@16:00 edur=72:00
|
||||
now=1991-02-16 dt=1991-02-16@00:00 dur=16:00 estart=1991-02-13@16:00 edur=72:00
|
||||
now=1991-02-17 dt=1991-02-13@16:00 dur=72:00 estart=-1 edur=-1
|
||||
.fi
|
||||
.PP
|
||||
As you see, the \fBtrigdatetime()\fR and \fBtrigduration()\fR functions
|
||||
return the start time and duration of the \fIremaining\fR portion of
|
||||
a multi-day event, whereas \fBtrigeventstart\fR and \fBtrigeventduration\fR
|
||||
always return the original start and duration of the multi-day event. Note also
|
||||
that the return value for expired reminders is not reliable; the fact
|
||||
that \fBtrigeventstart\fR and \fBtrigeventduration\fR return -1 in that case
|
||||
is an implementation artifact.
|
||||
.PP
|
||||
.B SELF-OVERLAPPING EVENTS
|
||||
.PP
|
||||
A multi-day event has the possibility of "overlapping itself". When this
|
||||
happens, \fBRemind\fR prefers the \fIearlier\fR event (only one copy of
|
||||
an event is ever triggered for a given date.) Consider this example:
|
||||
.PP
|
||||
.nf
|
||||
#!/bin/sh
|
||||
remind - '*4' 11 Feb 1991 <<'EOF'
|
||||
|
||||
BANNER %
|
||||
REM MON at 0:00 DURATION 192:0 MSG [today()] [trigeventstart()] [trigduration()]%
|
||||
|
||||
EOF
|
||||
.fi
|
||||
.PP
|
||||
The output is:
|
||||
.PP
|
||||
.nf
|
||||
1991-02-11 1991-02-04@00:00 24:00
|
||||
1991-02-12 1991-02-11@00:00 168:00
|
||||
1991-02-13 1991-02-11@00:00 144:00
|
||||
1991-02-14 1991-02-11@00:00 120:00
|
||||
.fi
|
||||
.PP
|
||||
Although 1991-02-11 is a Monday (which should cause the event to be
|
||||
triggered, the 8-day-long event that started on 1991-02-04 \fIhas not
|
||||
finished yet\fR, so that is the one that is triggered. The next day,
|
||||
the event starting on 1991-02-04 \fIhas\fR finished, so the 1991-02-11
|
||||
event triggers, with a remaining duration of 168:00, or 7 days.
|
||||
.PP
|
||||
I do not recommend constructing self-overlapping multi-day events.
|
||||
.PP
|
||||
.SH EXPRESSION PASTING
|
||||
.PP
|
||||
An extremely powerful feature of \fBRemind\fR is its macro capability,
|
||||
@@ -2984,7 +3220,7 @@ three commands are equivalent:
|
||||
o
|
||||
You cannot use expression-pasting to determine the type (\fBMSG\fR,
|
||||
\fBCAL\fR, etc.) of a \fBREM\fR command. You can paste expressions
|
||||
before and after the \fBMSG\fR, etc keywords, but cannot do something like
|
||||
before and after the \fBMSG\fR, etc. keywords, but cannot do something like
|
||||
this:
|
||||
.PP
|
||||
.nf
|
||||
@@ -3080,8 +3316,10 @@ to true if a corresponding \fBREM\fR command would trigger. Examples:
|
||||
.PP
|
||||
Note that the \fBIFTRIG\fR command computes a trigger date, which can
|
||||
be retrieved with the \fBtrigdate()\fR function. You can use all of
|
||||
the normal trigger components, such as \fBUNTIL\fR, \fIdelta\fR, etc in the
|
||||
\fBIFTRIG\fR command.
|
||||
the normal trigger components, such as \fBUNTIL\fR, \fIdelta\fR, etc. in the
|
||||
\fBIFTRIG\fR command. However, you cannot use a type specifier such
|
||||
as \fBCAL\fR, \fBMSG\fR or \fBSATISFY\fR; attempting to do so
|
||||
yields a parse error.
|
||||
.PP
|
||||
.SH USER-DEFINED FUNCTIONS
|
||||
.PP
|
||||
@@ -3279,12 +3517,12 @@ ends. Otherwise, \fBRemind\fR computes the next trigger date, and re-tests
|
||||
or non-null, or until the iteration limit specified with the \fB\-x\fR
|
||||
command-line option is reached.
|
||||
.PP
|
||||
If \fIexpr\fR is not satisfied, then \fBtrigvalid()\fR is set to 0.
|
||||
Otherwise, \fBtrigvalid()\fR is set to 1. In any event, no error message
|
||||
is issued.
|
||||
If \fIexpr\fR is not satisfied, then \fBtrigvalid()\fR is set to 0 and
|
||||
the error message "Can't compute trigger" is issued. Otherwise,
|
||||
\fBtrigvalid()\fR is set to 1.
|
||||
.PP
|
||||
This is really useful only if \fIexpr\fR involves a call to the
|
||||
\fBtrigdate()\fR function; otherwise, \fIexpr\fR will not change as
|
||||
\fBtrigdate()\fR or related functions; otherwise, \fIexpr\fR will not change as
|
||||
\fBRemind\fR iterates.
|
||||
.PP
|
||||
An example of the usefulness of \fBSATISFY\fR: Suppose you wish to
|
||||
@@ -3307,6 +3545,12 @@ more complicated sequence:
|
||||
ENDIF
|
||||
.fi
|
||||
.PP
|
||||
You can write the REM statement a little more concisely:
|
||||
.PP
|
||||
.nf
|
||||
REM 13 SATISFY $Tw == 5
|
||||
.fi
|
||||
.PP
|
||||
Let's see how this works. The \fBSATISFY\fR clause iterates through
|
||||
all the 13ths of successive months, until a trigger date is found whose
|
||||
day-of-week is Friday (== 5). If a valid date was found, we use the
|
||||
@@ -3361,7 +3605,7 @@ follows:
|
||||
.fi
|
||||
.PP
|
||||
Note that for this case only, the \fIexpr\fR after \fBSATISFY\fR
|
||||
\fImust\fR be enclosed in braces. It must come after all the other
|
||||
\fImust\fR be enclosed in square brackets. It must come after all the other
|
||||
components of the trigger, and immediately before the \fBMSG\fR,
|
||||
\fBRUN\fR, etc. keyword. If \fIexpr\fR cannot be satisfied, then
|
||||
the reminder is not triggered.
|
||||
@@ -3369,16 +3613,14 @@ the reminder is not triggered.
|
||||
Thus, the "Friday the 13th" example can be expressed more compactly as:
|
||||
.PP
|
||||
.nf
|
||||
REM 13 +2 SATISFY [wkdaynum(trigdate()) == 5] \\
|
||||
MSG Friday the 13th is %b.
|
||||
REM 13 +2 SATISFY [$Tw == 5] MSG Friday the 13th is %b.
|
||||
.fi
|
||||
.PP
|
||||
And you can trigger a reminder on Mondays, Wednesdays and Thursdays
|
||||
occurring on odd-numbered days of the month with the following:
|
||||
.PP
|
||||
.nf
|
||||
REM Mon Wed Thu SATISFY [day(trigdate())%2] \\
|
||||
MSG Here it is!!!
|
||||
REM Mon Wed Thu SATISFY [$Td %2 ] MSG Here it is!!!
|
||||
.fi
|
||||
.PP
|
||||
Note that \fBSATISFY\fR and \fBOMITFUNC\fR can often be used to solve the
|
||||
@@ -3547,7 +3789,7 @@ iterations. On the next iteration, the commands are skipped, since
|
||||
initialized has remained defined. Thus, time-consuming operations that
|
||||
do not depend on the value of \fBtoday()\fR are done only once.
|
||||
.PP
|
||||
System variables (those whose names start with '$') are automatically
|
||||
Most system variables (those whose names start with '$') are automatically
|
||||
preserved between calendar iterations.
|
||||
.PP
|
||||
Note that for efficiency, \fBRemind\fR caches the reminder script
|
||||
@@ -4136,7 +4378,7 @@ They are used only when piping data from a \fBremind \-p\fR line.
|
||||
equivalent of MSG in \fBremind's\fR normal mode of operation.)
|
||||
.PP
|
||||
The various \fBSPECIAL\fRs recognized are particular for each
|
||||
backend; however, there are three \fBSPECIAL\fRs that all backends
|
||||
backend; however, there are four \fBSPECIAL\fRs that all backends
|
||||
should attempt to support. They are currently supported by
|
||||
\fBRem2PS\fR, \fBtkremind\fR and \fBrem2html\fR.
|
||||
.PP
|
||||
@@ -4199,9 +4441,12 @@ The rest of the line is the text to put in the calendar.
|
||||
.PP
|
||||
The COLOR special is "doubly special", because in its normal operating
|
||||
mode, \fBremind\fR treats a COLOR special just like a MSG-type reminder.
|
||||
Also, if you invoke \fBRemind\fR with \fB\-cc\fR..., then it approximates
|
||||
Also, if you invoke \fBRemind\fR with \fB\-@\fR[\fIn\fR], then it approximates
|
||||
SPECIAL COLOR reminders on your terminal.
|
||||
.PP
|
||||
See also the documentation of the \fB$DefaultColor\fR system variable
|
||||
in the section "SYSTEM VARIABLES".
|
||||
.PP
|
||||
The \fBWEEK\fR special lets you place annotations such as the week
|
||||
number in the calendar. For example, this would number each Monday
|
||||
with the ISO 8601 week number. The week number is shown like this:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH TKREMIND 1 "15 February 1998"
|
||||
.TH TKREMIND 1 "1 January 2020"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
tkremind \- graphical front-end to Remind calendar program
|
||||
@@ -360,7 +360,7 @@ This line is emitted in response to a \fBSTATUS\fR command. The number
|
||||
.SH AUTHOR
|
||||
TkRemind was written by Dianne Skoll <dianne@skoll.ca>
|
||||
|
||||
\fBTkRemind\fR is Copyright 1996-2018 by Dianne Skoll.
|
||||
\fBTkRemind\fR is Copyright 1996-2020 by Dianne Skoll.
|
||||
|
||||
.SH FILES
|
||||
|
||||
|
||||
830
scripts/tkremind
@@ -43,8 +43,10 @@ test: remind
|
||||
.c.o:
|
||||
@CC@ -c @CPPFLAGS@ @CFLAGS@ @DEFS@ $(CEXTRA) $(LANGDEF) -I. -I$(srcdir) $<
|
||||
|
||||
rem2ps: rem2ps.o dynbuf.o
|
||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o
|
||||
$(REMINDOBJS): $(REMINDHDRS)
|
||||
|
||||
rem2ps: rem2ps.o dynbuf.o json.o
|
||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o rem2ps rem2ps.o dynbuf.o json.o -lm
|
||||
|
||||
remind: $(REMINDOBJS)
|
||||
@CC@ @LDFLAGS@ $(LDEXTRA) -o remind $(REMINDOBJS) @LIBS@
|
||||
@@ -72,7 +74,7 @@ clobber:
|
||||
rm -f *.o *~ remind rem2ps test.out core *.bak
|
||||
|
||||
depend:
|
||||
gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c
|
||||
gccmakedep @DEFS@ $(REMINDSRCS) rem2ps.c json.c
|
||||
|
||||
# The next targets are not very useful to you. I use them to build
|
||||
# distributions, etc.
|
||||
@@ -86,6 +88,7 @@ distro:
|
||||
beta-tgz:
|
||||
cd .. && git archive --worktree-attributes --format=tar --prefix=remind-$(VERSION)/ HEAD > src/remind-$(VERSION)-BETA-$(BETA).tar
|
||||
gzip -f -v -9 remind-$(VERSION)-BETA-$(BETA).tar
|
||||
gpg --detach-sign -u dianne@skoll.ca remind-$(VERSION)-BETA-$(BETA).tar.gz
|
||||
|
||||
#---------------- Stuff after this added by "make depend" -----------------
|
||||
|
||||
|
||||
715
src/calendar.c
@@ -5,7 +5,7 @@
|
||||
/* The code for generating a calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
#include <wctype.h>
|
||||
@@ -31,10 +33,11 @@
|
||||
/* Data structures used by the calendar */
|
||||
typedef struct cal_entry {
|
||||
struct cal_entry *next;
|
||||
char const *text;
|
||||
char *text;
|
||||
char *raw_text;
|
||||
char const *pos;
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *wc_text;
|
||||
wchar_t *wc_text;
|
||||
wchar_t const *wc_pos;
|
||||
#endif
|
||||
int is_color;
|
||||
@@ -44,8 +47,12 @@ typedef struct cal_entry {
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
int duration;
|
||||
char const *filename;
|
||||
char *filename;
|
||||
int lineno;
|
||||
Trigger trig;
|
||||
TimeTrig tt;
|
||||
int nonconst_expr;
|
||||
int if_depth;
|
||||
} CalEntry;
|
||||
|
||||
/* Line-drawing sequences */
|
||||
@@ -132,13 +139,92 @@ static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
static struct line_drawing *linestruct;
|
||||
#define DRAW(x) fputs(linestruct->x, stdout)
|
||||
|
||||
struct xterm256_colors {
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
};
|
||||
|
||||
/* Xterm support 256 different colors, numbered from 0 to 255. The following
|
||||
table is a list of the [r, g, b] components of each Xterm color. The
|
||||
data was obtained from https://jonasjacek.github.io/colors/ */
|
||||
static struct xterm256_colors XTerm256Colors[] =
|
||||
{
|
||||
{ 0, 0, 0}, {128, 0, 0}, { 0, 128, 0}, {128, 128, 0},
|
||||
{ 0, 0, 128}, {128, 0, 128}, { 0, 128, 128}, {192, 192, 192},
|
||||
{128, 128, 128}, {255, 0, 0}, { 0, 255, 0}, {255, 255, 0},
|
||||
{ 0, 0, 255}, {255, 0, 255}, { 0, 255, 255}, {255, 255, 255},
|
||||
{ 0, 0, 0}, { 0, 0, 95}, { 0, 0, 135}, { 0, 0, 175},
|
||||
{ 0, 0, 215}, { 0, 0, 255}, { 0, 95, 0}, { 0, 95, 95},
|
||||
{ 0, 95, 135}, { 0, 95, 175}, { 0, 95, 215}, { 0, 95, 255},
|
||||
{ 0, 135, 0}, { 0, 135, 95}, { 0, 135, 135}, { 0, 135, 175},
|
||||
{ 0, 135, 215}, { 0, 135, 255}, { 0, 175, 0}, { 0, 175, 95},
|
||||
{ 0, 175, 135}, { 0, 175, 175}, { 0, 175, 215}, { 0, 175, 255},
|
||||
{ 0, 215, 0}, { 0, 215, 95}, { 0, 215, 135}, { 0, 215, 175},
|
||||
{ 0, 215, 215}, { 0, 215, 255}, { 0, 255, 0}, { 0, 255, 95},
|
||||
{ 0, 255, 135}, { 0, 255, 175}, { 0, 255, 215}, { 0, 255, 255},
|
||||
{ 95, 0, 0}, { 95, 0, 95}, { 95, 0, 135}, { 95, 0, 175},
|
||||
{ 95, 0, 215}, { 95, 0, 255}, { 95, 95, 0}, { 95, 95, 95},
|
||||
{ 95, 95, 135}, { 95, 95, 175}, { 95, 95, 215}, { 95, 95, 255},
|
||||
{ 95, 135, 0}, { 95, 135, 95}, { 95, 135, 135}, { 95, 135, 175},
|
||||
{ 95, 135, 215}, { 95, 135, 255}, { 95, 175, 0}, { 95, 175, 95},
|
||||
{ 95, 175, 135}, { 95, 175, 175}, { 95, 175, 215}, { 95, 175, 255},
|
||||
{ 95, 215, 0}, { 95, 215, 95}, { 95, 215, 135}, { 95, 215, 175},
|
||||
{ 95, 215, 215}, { 95, 215, 255}, { 95, 255, 0}, { 95, 255, 95},
|
||||
{ 95, 255, 135}, { 95, 255, 175}, { 95, 255, 215}, { 95, 255, 255},
|
||||
{135, 0, 0}, {135, 0, 95}, {135, 0, 135}, {135, 0, 175},
|
||||
{135, 0, 215}, {135, 0, 255}, {135, 95, 0}, {135, 95, 95},
|
||||
{135, 95, 135}, {135, 95, 175}, {135, 95, 215}, {135, 95, 255},
|
||||
{135, 135, 0}, {135, 135, 95}, {135, 135, 135}, {135, 135, 175},
|
||||
{135, 135, 215}, {135, 135, 255}, {135, 175, 0}, {135, 175, 95},
|
||||
{135, 175, 135}, {135, 175, 175}, {135, 175, 215}, {135, 175, 255},
|
||||
{135, 215, 0}, {135, 215, 95}, {135, 215, 135}, {135, 215, 175},
|
||||
{135, 215, 215}, {135, 215, 255}, {135, 255, 0}, {135, 255, 95},
|
||||
{135, 255, 135}, {135, 255, 175}, {135, 255, 215}, {135, 255, 255},
|
||||
{175, 0, 0}, {175, 0, 95}, {175, 0, 135}, {175, 0, 175},
|
||||
{175, 0, 215}, {175, 0, 255}, {175, 95, 0}, {175, 95, 95},
|
||||
{175, 95, 135}, {175, 95, 175}, {175, 95, 215}, {175, 95, 255},
|
||||
{175, 135, 0}, {175, 135, 95}, {175, 135, 135}, {175, 135, 175},
|
||||
{175, 135, 215}, {175, 135, 255}, {175, 175, 0}, {175, 175, 95},
|
||||
{175, 175, 135}, {175, 175, 175}, {175, 175, 215}, {175, 175, 255},
|
||||
{175, 215, 0}, {175, 215, 95}, {175, 215, 135}, {175, 215, 175},
|
||||
{175, 215, 215}, {175, 215, 255}, {175, 255, 0}, {175, 255, 95},
|
||||
{175, 255, 135}, {175, 255, 175}, {175, 255, 215}, {175, 255, 255},
|
||||
{215, 0, 0}, {215, 0, 95}, {215, 0, 135}, {215, 0, 175},
|
||||
{215, 0, 215}, {215, 0, 255}, {215, 95, 0}, {215, 95, 95},
|
||||
{215, 95, 135}, {215, 95, 175}, {215, 95, 215}, {215, 95, 255},
|
||||
{215, 135, 0}, {215, 135, 95}, {215, 135, 135}, {215, 135, 175},
|
||||
{215, 135, 215}, {215, 135, 255}, {215, 175, 0}, {215, 175, 95},
|
||||
{215, 175, 135}, {215, 175, 175}, {215, 175, 215}, {215, 175, 255},
|
||||
{215, 215, 0}, {215, 215, 95}, {215, 215, 135}, {215, 215, 175},
|
||||
{215, 215, 215}, {215, 215, 255}, {215, 255, 0}, {215, 255, 95},
|
||||
{215, 255, 135}, {215, 255, 175}, {215, 255, 215}, {215, 255, 255},
|
||||
{255, 0, 0}, {255, 0, 95}, {255, 0, 135}, {255, 0, 175},
|
||||
{255, 0, 215}, {255, 0, 255}, {255, 95, 0}, {255, 95, 95},
|
||||
{255, 95, 135}, {255, 95, 175}, {255, 95, 215}, {255, 95, 255},
|
||||
{255, 135, 0}, {255, 135, 95}, {255, 135, 135}, {255, 135, 175},
|
||||
{255, 135, 215}, {255, 135, 255}, {255, 175, 0}, {255, 175, 95},
|
||||
{255, 175, 135}, {255, 175, 175}, {255, 175, 215}, {255, 175, 255},
|
||||
{255, 215, 0}, {255, 215, 95}, {255, 215, 135}, {255, 215, 175},
|
||||
{255, 215, 215}, {255, 215, 255}, {255, 255, 0}, {255, 255, 95},
|
||||
{255, 255, 135}, {255, 255, 175}, {255, 255, 215}, {255, 255, 255},
|
||||
{ 8, 8, 8}, { 18, 18, 18}, { 28, 28, 28}, { 38, 38, 38},
|
||||
{ 48, 48, 48}, { 58, 58, 58}, { 68, 68, 68}, { 78, 78, 78},
|
||||
{ 88, 88, 88}, { 98, 98, 98}, {108, 108, 108}, {118, 118, 118},
|
||||
{128, 128, 128}, {138, 138, 138}, {148, 148, 148}, {158, 158, 158},
|
||||
{168, 168, 168}, {178, 178, 178}, {188, 188, 188}, {198, 198, 198},
|
||||
{208, 208, 208}, {218, 218, 218}, {228, 228, 228}, {238, 238, 238}
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
static CalEntry *CalColumn[7];
|
||||
|
||||
static int ColSpaces;
|
||||
|
||||
static void Colorize(CalEntry const *e);
|
||||
static void Decolorize(void);
|
||||
static int DidAMonth;
|
||||
static int DidADay;
|
||||
|
||||
static void ColorizeEntry(CalEntry const *e);
|
||||
static void SortCol (CalEntry **col);
|
||||
static void DoCalendarOneWeek (int nleft);
|
||||
static void DoCalendarOneMonth (void);
|
||||
@@ -159,6 +245,76 @@ static void WriteBottomCalLine (void);
|
||||
static void WriteIntermediateCalLine (void);
|
||||
static void WriteCalDays (void);
|
||||
|
||||
static void PrintJSONString(char const *s)
|
||||
{
|
||||
while (*s) {
|
||||
switch(*s) {
|
||||
case '\b': printf("\\b"); break;
|
||||
case '\f': printf("\\f"); break;
|
||||
case '\n': printf("\\n"); break;
|
||||
case '\r': printf("\\r"); break;
|
||||
case '\t': printf("\\t"); break;
|
||||
case '"': printf("\\\""); break;
|
||||
case '\\': printf("\\\\"); break;
|
||||
default: printf("%c", *s);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintJSONKeyPairInt(char const *name, int val)
|
||||
{
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":%d, ", val);
|
||||
}
|
||||
|
||||
static void PrintJSONKeyPairString(char const *name, char const *val)
|
||||
{
|
||||
/* If value is blank, skip it! */
|
||||
if (!val || !*val) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"");
|
||||
PrintJSONString(val);
|
||||
printf("\", ");
|
||||
}
|
||||
|
||||
static void PrintJSONKeyPairDate(char const *name, int jul)
|
||||
{
|
||||
int y, m, d;
|
||||
if (jul == NO_DATE) {
|
||||
/* Skip it! */
|
||||
return;
|
||||
}
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
||||
|
||||
}
|
||||
|
||||
static void PrintJSONKeyPairDateTime(char const *name, int dt)
|
||||
{
|
||||
int y, m, d, h, i, k;
|
||||
if (dt == NO_TIME) {
|
||||
/* Skip it! */
|
||||
return;
|
||||
}
|
||||
i = dt / MINUTES_PER_DAY;
|
||||
FromJulian(i, &y, &m, &d);
|
||||
k = dt % MINUTES_PER_DAY;
|
||||
h = k / 60;
|
||||
i = k % 60;
|
||||
printf("\"");
|
||||
PrintJSONString(name);
|
||||
printf("\":\"%04d-%02d-%02dT%02d:%02d\", ", y, m+1, d, h, i);
|
||||
|
||||
}
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static void PutWideChar(wchar_t const wc)
|
||||
{
|
||||
@@ -202,26 +358,146 @@ static void goff(void)
|
||||
printf("%s", linestruct->graphics_off);
|
||||
}
|
||||
|
||||
static void Decolorize(void)
|
||||
static void
|
||||
ClampColor(int *r, int *g, int *b)
|
||||
{
|
||||
printf("%s", "\x1B[0m");
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_UNKNOWN) {
|
||||
/* No special clamping if terminal background is unknown */
|
||||
return;
|
||||
}
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
|
||||
if (*r <= 64 && *g <= 64 && *b <= 64) {
|
||||
int max = *r;
|
||||
double factor;
|
||||
if (*g > max) max = *g;
|
||||
if (*b > max) max = *b;
|
||||
if (max == 0) {
|
||||
*r = 65;
|
||||
*g = 65;
|
||||
*b = 65;
|
||||
return;
|
||||
}
|
||||
factor = 65.0 / (double) max;
|
||||
*r = (int) (factor * (double) *r);
|
||||
*g = (int) (factor * (double) *g);
|
||||
*b = (int) (factor * (double) *b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
|
||||
if (*r > 191 && *g > 191 && *b > 191) {
|
||||
int min = *r;
|
||||
if (*g < min) min = *g;
|
||||
if (*b < min) min = *b;
|
||||
double factor = 192.0 / (double) min;
|
||||
*r = (int) (factor * (double) *r);
|
||||
*g = (int) (factor * (double) *g);
|
||||
*b = (int) (factor * (double) *b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Colorize(CalEntry const *e)
|
||||
char const *
|
||||
Decolorize(int r, int g, int b)
|
||||
{
|
||||
int bright = 0;
|
||||
int r, g, b;
|
||||
if (e->r > 128 || e->g > 128 || e->b > 128) {
|
||||
bright = 1;
|
||||
}
|
||||
if (e->r > 64) r = 1;
|
||||
else r = 0;
|
||||
if (e->g > 64) g = 1;
|
||||
else g = 0;
|
||||
if (e->b > 64) b = 1;
|
||||
else b = 0;
|
||||
if (!strcmp(Colorize(r, g, b), "")) {
|
||||
return "";
|
||||
}
|
||||
return "\x1B[0m";
|
||||
}
|
||||
|
||||
printf("%s", VT100Colors[bright][r][g][b]);
|
||||
static char const *
|
||||
Colorize256(int r, int g, int b)
|
||||
{
|
||||
static char buf[40];
|
||||
int best = -1;
|
||||
int best_dist = 0;
|
||||
int dist;
|
||||
struct xterm256_colors *cur;
|
||||
size_t i;
|
||||
|
||||
ClampColor(&r, &g, &b);
|
||||
for (i=0; i<(sizeof(XTerm256Colors) / sizeof(XTerm256Colors[0])); i++) {
|
||||
cur = &XTerm256Colors[i];
|
||||
dist = ((r - cur->r) * (r - cur->r)) +
|
||||
((b - cur->b) * (b - cur->b)) +
|
||||
((g - cur->g) * (g - cur->g));
|
||||
if (best == -1 || dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = (int) i;
|
||||
}
|
||||
}
|
||||
cur = &XTerm256Colors[best];
|
||||
sprintf(buf, "\x1B[38;5;%dm", best);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char const *
|
||||
ColorizeTrue(int r, int g, int b)
|
||||
{
|
||||
static char buf[40];
|
||||
ClampColor(&r, &g, &b);
|
||||
sprintf(buf, "\x1B[38;2;%d;%d;%dm", r, g, b);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char const *
|
||||
Colorize(int r, int g, int b)
|
||||
{
|
||||
int bright = 0;
|
||||
|
||||
if (UseTrueColors) {
|
||||
return ColorizeTrue(r, g, b);
|
||||
}
|
||||
|
||||
if (Use256Colors) {
|
||||
return Colorize256(r, g, b);
|
||||
}
|
||||
if (r > 128 || g > 128 || b > 128) {
|
||||
bright = 1;
|
||||
}
|
||||
if (r > 64) r = 1;
|
||||
else r = 0;
|
||||
if (g > 64) g = 1;
|
||||
else g = 0;
|
||||
if (b > 64) b = 1;
|
||||
else b = 0;
|
||||
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_DARK) {
|
||||
/* Convert black-on-black to grey */
|
||||
if (!r && !g && !b) return VT100Colors[1][0][0][0];
|
||||
}
|
||||
if (TerminalBackground == TERMINAL_BACKGROUND_LIGHT) {
|
||||
/* Convert white-on-white to grey */
|
||||
if (r && g && b) return VT100Colors[1][0][0][0];
|
||||
}
|
||||
return VT100Colors[bright][r][g][b];
|
||||
}
|
||||
|
||||
static void ColorizeEntry(CalEntry const *e)
|
||||
{
|
||||
printf("%s", Colorize(e->r, e->g, e->b));
|
||||
}
|
||||
|
||||
static int
|
||||
ComputeCalWidth(int x)
|
||||
{
|
||||
struct winsize w;
|
||||
if (x >= 71) {
|
||||
/* Has been set with -w option */
|
||||
return x;
|
||||
}
|
||||
if (!isatty(STDOUT_FILENO)) {
|
||||
/* Output is not a TTY... assume 80 */
|
||||
return 80;
|
||||
}
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) {
|
||||
return 80;
|
||||
}
|
||||
if (w.ws_col < 71) {
|
||||
return 80;
|
||||
}
|
||||
return w.ws_col;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -244,14 +520,25 @@ void ProduceCalendar(void)
|
||||
}
|
||||
ShouldCache = 1;
|
||||
|
||||
CalWidth = ComputeCalWidth(CalWidth);
|
||||
|
||||
ColSpaces = (CalWidth - 9) / 7;
|
||||
CalWidth = 7*ColSpaces + 8;
|
||||
|
||||
if (CalMonths) {
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
JulianToday = Julian(y, m, 1);
|
||||
while (CalMonths--)
|
||||
DidAMonth = 0;
|
||||
if (PsCal == PSCAL_LEVEL3) {
|
||||
printf("[\n");
|
||||
}
|
||||
while (CalMonths--) {
|
||||
DoCalendarOneMonth();
|
||||
DidAMonth = 1;
|
||||
}
|
||||
if (PsCal == PSCAL_LEVEL3) {
|
||||
printf("\n]\n");
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (MondayFirst) JulianToday -= (JulianToday%7);
|
||||
@@ -373,30 +660,74 @@ static void DoCalendarOneMonth(void)
|
||||
|
||||
if (!DoSimpleCalendar) WriteCalHeader();
|
||||
|
||||
DidADay = 0;
|
||||
|
||||
if (PsCal) {
|
||||
FromJulian(JulianToday, &y, &m, &d);
|
||||
printf("%s\n", PSBEGIN);
|
||||
printf("%s %d %d %d %d\n",
|
||||
MonthName[m], y, DaysInMonth(m, y), (JulianToday+1) % 7,
|
||||
MondayFirst);
|
||||
printf("%s %s %s %s %s %s %s\n",
|
||||
DayName[6], DayName[0], DayName[1], DayName[2],
|
||||
DayName[3], DayName[4], DayName[5]);
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
printf("%s\n", PSBEGIN);
|
||||
} else if (PsCal == PSCAL_LEVEL2) {
|
||||
printf("%s\n", PSBEGIN2);
|
||||
} else {
|
||||
if (DidAMonth) {
|
||||
printf(",\n");
|
||||
}
|
||||
printf("{\n");
|
||||
}
|
||||
if (PsCal < PSCAL_LEVEL3) {
|
||||
printf("%s %d %d %d %d\n",
|
||||
MonthName[m], y, DaysInMonth(m, y), (JulianToday+1) % 7,
|
||||
MondayFirst);
|
||||
printf("%s %s %s %s %s %s %s\n",
|
||||
DayName[6], DayName[0], DayName[1], DayName[2],
|
||||
DayName[3], DayName[4], DayName[5]);
|
||||
} else {
|
||||
PrintJSONKeyPairString("monthname", MonthName[m]);
|
||||
PrintJSONKeyPairInt("year", y);
|
||||
PrintJSONKeyPairInt("daysinmonth", DaysInMonth(m, y));
|
||||
PrintJSONKeyPairInt("firstwkday", (JulianToday+1) % 7);
|
||||
PrintJSONKeyPairInt("mondayfirst", MondayFirst);
|
||||
printf("\"daynames\":[\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"],",
|
||||
DayName[6], DayName[0], DayName[1], DayName[2],
|
||||
DayName[3], DayName[4], DayName[5]);
|
||||
}
|
||||
mm = m-1;
|
||||
if (mm<0) {
|
||||
mm = 11; yy = y-1;
|
||||
} else yy=y;
|
||||
|
||||
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
|
||||
if (PsCal < PSCAL_LEVEL3) {
|
||||
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
|
||||
} else {
|
||||
PrintJSONKeyPairString("prevmonthname", MonthName[mm]);
|
||||
PrintJSONKeyPairInt("daysinprevmonth", DaysInMonth(mm, yy));
|
||||
PrintJSONKeyPairInt("prevmonthyear", yy);
|
||||
}
|
||||
mm = m+1;
|
||||
if (mm>11) {
|
||||
mm = 0; yy = y+1;
|
||||
} else yy=y;
|
||||
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
|
||||
if (PsCal < PSCAL_LEVEL3) {
|
||||
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
|
||||
} else {
|
||||
PrintJSONKeyPairString("nextmonthname", MonthName[mm]);
|
||||
PrintJSONKeyPairInt("daysinnextmonth", DaysInMonth(mm, yy));
|
||||
PrintJSONKeyPairInt("nextmonthyear", yy);
|
||||
printf("\"entries\":[\n");
|
||||
}
|
||||
}
|
||||
while (WriteCalendarRow()) continue;
|
||||
|
||||
if (PsCal) printf("%s\n", PSEND);
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
printf("%s\n", PSEND);
|
||||
} else if (PsCal == PSCAL_LEVEL2) {
|
||||
printf("%s\n", PSEND2);
|
||||
} else if (PsCal == PSCAL_LEVEL3){
|
||||
if (DidADay) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("]\n}");
|
||||
}
|
||||
if (!DoSimpleCalendar) WriteCalTrailer();
|
||||
}
|
||||
|
||||
@@ -631,9 +962,10 @@ static int WriteOneColLine(int col)
|
||||
if (!*ws && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
@@ -647,7 +979,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
ColorizeEntry(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
@@ -669,7 +1001,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
printf("%s", Decolorize(e->r, e->g, e->b));
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
@@ -681,9 +1013,10 @@ static int WriteOneColLine(int col)
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*ws && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
free(e);
|
||||
} else {
|
||||
e->wc_pos = ws;
|
||||
@@ -699,11 +1032,12 @@ static int WriteOneColLine(int col)
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
free(e->text);
|
||||
free(e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e->raw_text);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
@@ -717,7 +1051,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
ColorizeEntry(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
@@ -739,7 +1073,7 @@ static int WriteOneColLine(int col)
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
printf("%s", Decolorize(e->r, e->g, e->b));
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
@@ -751,11 +1085,12 @@ static int WriteOneColLine(int col)
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
free(e->text);
|
||||
free(e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
free(e->raw_text);
|
||||
free(e);
|
||||
} else {
|
||||
e->pos = s;
|
||||
@@ -781,10 +1116,7 @@ static void GenerateCalEntries(int col)
|
||||
Parser p;
|
||||
|
||||
/* Do some initialization first... */
|
||||
ClearGlobalOmits();
|
||||
DestroyOmitContexts();
|
||||
DestroyVars(0);
|
||||
NumTriggered = 0;
|
||||
PerIterationInit();
|
||||
|
||||
r=IncludeFile(InitialFile);
|
||||
if (r) {
|
||||
@@ -930,14 +1262,16 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
CalEntry *CurCol = CalColumn[col];
|
||||
CalEntry *e;
|
||||
char const *s, *s2;
|
||||
DynamicBuffer buf, obuf, pre_buf;
|
||||
DynamicBuffer buf, obuf, pre_buf, raw_buf;
|
||||
Token tok;
|
||||
int nonconst_expr = 0;
|
||||
|
||||
int is_color, col_r, col_g, col_b;
|
||||
|
||||
is_color = 0;
|
||||
DBufInit(&buf);
|
||||
DBufInit(&pre_buf);
|
||||
DBufInit(&raw_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
@@ -945,6 +1279,20 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (trig.typ == MSG_TYPE ||
|
||||
trig.typ == CAL_TYPE ||
|
||||
trig.typ == MSF_TYPE) {
|
||||
is_color = (
|
||||
DefaultColorR != -1
|
||||
&& DefaultColorG != -1
|
||||
&& DefaultColorB != -1);
|
||||
if (is_color) {
|
||||
col_r = DefaultColorR;
|
||||
col_g = DefaultColorG;
|
||||
col_b = DefaultColorB;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't include timed reminders in calendar if -a option supplied. */
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) {
|
||||
FreeTrig(&trig);
|
||||
@@ -955,7 +1303,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
r=DoSatRemind(&trig, p);
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
@@ -999,13 +1347,15 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save nonconst_expr flag */
|
||||
nonconst_expr = p->nonconst_expr;
|
||||
/* Convert PS and PSF to PASSTHRU */
|
||||
if (trig.typ == PS_TYPE) {
|
||||
strcpy(trig.passthru, "PostScript");
|
||||
@@ -1014,13 +1364,27 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
strcpy(trig.passthru, "PSFile");
|
||||
trig.typ = PASSTHRU_TYPE;
|
||||
}
|
||||
|
||||
/* If it's a plain reminder but we have a default color, add the
|
||||
three colors to the prebuf and change passthru to "COLOR" */
|
||||
if (trig.typ == MSG_TYPE ||
|
||||
trig.typ == CAL_TYPE ||
|
||||
trig.typ == MSF_TYPE) {
|
||||
if (PsCal && is_color) {
|
||||
char cbuf[24];
|
||||
sprintf(cbuf, "%d %d %d ", col_r, col_g, col_b);
|
||||
DBufPuts(&pre_buf, cbuf);
|
||||
strcpy(trig.passthru, "COLOR");
|
||||
/* Don't change trig.typ or next if() will trigger! */
|
||||
}
|
||||
}
|
||||
if (trig.typ == PASSTHRU_TYPE) {
|
||||
if (!PsCal && strcmp(trig.passthru, "COLOR") && strcmp(trig.passthru, "COLOUR")) {
|
||||
if (!PsCal && StrCmpi(trig.passthru, "COLOR") && StrCmpi(trig.passthru, "COLOUR")) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (!strcmp(trig.passthru, "COLOR") ||
|
||||
!strcmp(trig.passthru, "COLOUR")) {
|
||||
if (!StrCmpi(trig.passthru, "COLOR") ||
|
||||
!StrCmpi(trig.passthru, "COLOUR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
@@ -1069,20 +1433,31 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
ShouldTriggerReminder(&trig, &tim, jul, &err))) {
|
||||
NumTriggered++;
|
||||
|
||||
/* The parse_ptr should not be nested, but just in case... */
|
||||
if (!p->isnested) {
|
||||
if (DBufPuts(&raw_buf, p->pos) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
if (DoSimpleCalendar || tim.ttime != NO_TIME) {
|
||||
/* Suppress time if it's not today or if it's a non-COLOR special */
|
||||
if (jul != JulianToday ||
|
||||
(trig.typ == PASSTHRU_TYPE &&
|
||||
strcmp(trig.passthru, "COLOUR") &&
|
||||
strcmp(trig.passthru, "COLOR"))) {
|
||||
StrCmpi(trig.passthru, "COLOUR") &&
|
||||
StrCmpi(trig.passthru, "COLOR"))) {
|
||||
if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) {
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
@@ -1100,6 +1475,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&obuf, v.v.str) != OK) {
|
||||
DestroyValue(v);
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
@@ -1121,12 +1497,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (r) {
|
||||
DBufFree(&pre_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&raw_buf);
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (DBufLen(&obuf) <= oldLen) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
DBufFree(&raw_buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
@@ -1140,6 +1518,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (DBufPuts(&obuf, v.v.str) != OK) {
|
||||
DestroyValue(v);
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
@@ -1156,10 +1535,15 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
e = NEW(CalEntry);
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->nonconst_expr = nonconst_expr;
|
||||
e->if_depth = NumIfs;
|
||||
e->trig = trig;
|
||||
e->tt = tim;
|
||||
#ifdef REM_USE_WCHAR
|
||||
e->wc_pos = NULL;
|
||||
e->wc_text = NULL;
|
||||
@@ -1169,9 +1553,13 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
e->g = col_g;
|
||||
e->b = col_b;
|
||||
e->text = StrDup(s);
|
||||
e->raw_text = StrDup(DBufValue(&raw_buf));
|
||||
DBufFree(&raw_buf);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
if (!e->text) {
|
||||
if (!e->text || !e->raw_text) {
|
||||
if (e->text) free(e->text);
|
||||
if (e->raw_text) free(e->raw_text);
|
||||
free(e);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
@@ -1189,12 +1577,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
e->priority = trig.priority;
|
||||
e->filename = StrDup(FileName);
|
||||
if(!e->filename) {
|
||||
if (e->text) free(e->text);
|
||||
if (e->raw_text) free(e->raw_text);
|
||||
free(e);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->lineno = LineNo;
|
||||
|
||||
if (trig.typ == PASSTHRU_TYPE) {
|
||||
if (trig.typ == PASSTHRU_TYPE || is_color) {
|
||||
StrnCpy(e->passthru, trig.passthru, PASSTHRU_LEN);
|
||||
} else {
|
||||
e->passthru[0] = 0;
|
||||
@@ -1212,23 +1602,8 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* WriteSimpleEntries */
|
||||
/* */
|
||||
/* Write entries in 'simple calendar' format. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void WriteSimpleEntries(int col, int jul)
|
||||
static void WriteSimpleEntryProtocol1(CalEntry *e)
|
||||
{
|
||||
CalEntry *e = CalColumn[col];
|
||||
CalEntry *n;
|
||||
int y, m, d;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
while(e) {
|
||||
if (DoPrefixLineNo) printf("# fileinfo %d %s\n", e->lineno, e->filename);
|
||||
printf("%04d/%02d/%02d", y, m+1, d);
|
||||
if (e->passthru[0]) {
|
||||
printf(" %s", e->passthru);
|
||||
} else {
|
||||
@@ -1250,10 +1625,186 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
printf("* ");
|
||||
}
|
||||
printf("%s\n", e->text);
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
}
|
||||
|
||||
|
||||
static void WriteSimpleEntryProtocol2(CalEntry *e, int today)
|
||||
{
|
||||
int done = 0;
|
||||
if (DoPrefixLineNo) {
|
||||
PrintJSONKeyPairString("filename", e->filename);
|
||||
PrintJSONKeyPairInt("lineno", e->lineno);
|
||||
}
|
||||
PrintJSONKeyPairString("passthru", e->passthru);
|
||||
PrintJSONKeyPairString("tags", DBufValue(&(e->tags)));
|
||||
if (e->duration != NO_TIME) {
|
||||
PrintJSONKeyPairInt("duration", e->duration);
|
||||
}
|
||||
if (e->time != NO_TIME) {
|
||||
PrintJSONKeyPairInt("time", e->time);
|
||||
if (e->tt.delta) {
|
||||
PrintJSONKeyPairInt("tdelta", e->tt.delta);
|
||||
}
|
||||
if (e->tt.rep) {
|
||||
PrintJSONKeyPairInt("trep", e->tt.rep);
|
||||
}
|
||||
}
|
||||
if (e->trig.eventduration != NO_TIME) {
|
||||
PrintJSONKeyPairInt("eventduration", e->trig.eventduration);
|
||||
}
|
||||
/* wd is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (e->trig.wd != NO_WD) {
|
||||
printf("\"wd\":[");
|
||||
done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (e->trig.wd & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("], ");
|
||||
}
|
||||
if (e->trig.d != NO_DAY) {
|
||||
PrintJSONKeyPairInt("d", e->trig.d);
|
||||
}
|
||||
if (e->trig.m != NO_MON) {
|
||||
PrintJSONKeyPairInt("m", e->trig.m+1);
|
||||
}
|
||||
if (e->trig.y != NO_YR) {
|
||||
PrintJSONKeyPairInt("y", e->trig.y);
|
||||
}
|
||||
PrintJSONKeyPairDateTime("eventstart", e->trig.eventstart);
|
||||
if (e->trig.back) {
|
||||
PrintJSONKeyPairInt("back", e->trig.back);
|
||||
}
|
||||
if (e->trig.delta) {
|
||||
PrintJSONKeyPairInt("delta", e->trig.delta);
|
||||
}
|
||||
if (e->trig.rep) {
|
||||
PrintJSONKeyPairInt("rep", e->trig.rep);
|
||||
}
|
||||
if (e->nonconst_expr) {
|
||||
PrintJSONKeyPairInt("nonconst_expr", e->nonconst_expr);
|
||||
}
|
||||
if (e->if_depth) {
|
||||
PrintJSONKeyPairInt("if_depth", e->if_depth);
|
||||
}
|
||||
switch(e->trig.skip) {
|
||||
case SKIP_SKIP:
|
||||
PrintJSONKeyPairString("skip", "SKIP");
|
||||
break;
|
||||
case BEFORE_SKIP:
|
||||
PrintJSONKeyPairString("skip", "BEFORE");
|
||||
break;
|
||||
case AFTER_SKIP:
|
||||
PrintJSONKeyPairString("skip", "AFTER");
|
||||
break;
|
||||
}
|
||||
/* Local omit is an array of days from 0=monday to 6=sunday.
|
||||
We convert to array of strings */
|
||||
if (e->trig.localomit != NO_WD) {
|
||||
printf("\"localomit\":[");
|
||||
done = 0;
|
||||
int i;
|
||||
for (i=0; i<7; i++) {
|
||||
if (e->trig.localomit & (1 << i)) {
|
||||
if (done) {
|
||||
printf(",");
|
||||
}
|
||||
done = 1;
|
||||
printf("\"%s\"", EnglishDayName[i]);
|
||||
}
|
||||
}
|
||||
printf("], ");
|
||||
}
|
||||
PrintJSONKeyPairDate("until", e->trig.until);
|
||||
if (e->trig.once != NO_ONCE) {
|
||||
PrintJSONKeyPairInt("once", e->trig.once);
|
||||
}
|
||||
if (e->trig.scanfrom != today) {
|
||||
PrintJSONKeyPairDate("scanfrom", e->trig.scanfrom);
|
||||
}
|
||||
PrintJSONKeyPairDate("from", e->trig.from);
|
||||
PrintJSONKeyPairInt("priority", e->trig.priority);
|
||||
|
||||
if (e->is_color) {
|
||||
PrintJSONKeyPairInt("r", e->r);
|
||||
PrintJSONKeyPairInt("g", e->g);
|
||||
PrintJSONKeyPairInt("b", e->b);
|
||||
} else if (!StrCmpi(e->passthru, "SHADE")) {
|
||||
int r, g, b, n;
|
||||
n = sscanf(e->text, "%d %d %d", &r, &g, &b);
|
||||
if (n < 3) {
|
||||
g = r;
|
||||
b = r;
|
||||
}
|
||||
if (r < 0) r = 0;
|
||||
else if (r > 255) r = 255;
|
||||
if (g < 0) g = 0;
|
||||
else if (g > 255) g = 255;
|
||||
if (b < 0) b = 0;
|
||||
else if (b > 255) b = 255;
|
||||
PrintJSONKeyPairInt("r", r);
|
||||
PrintJSONKeyPairInt("g", g);
|
||||
PrintJSONKeyPairInt("b", b);
|
||||
}
|
||||
/* Only print rawbody if it differs from body */
|
||||
if (strcmp(e->raw_text, e->text)) {
|
||||
PrintJSONKeyPairString("rawbody", e->raw_text);
|
||||
}
|
||||
printf("\"body\":\"");
|
||||
PrintJSONString(e->text);
|
||||
printf("\"");
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* WriteSimpleEntries */
|
||||
/* */
|
||||
/* Write entries in 'simple calendar' format. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void WriteSimpleEntries(int col, int jul)
|
||||
{
|
||||
CalEntry *e = CalColumn[col];
|
||||
CalEntry *n;
|
||||
int y, m, d;
|
||||
|
||||
FromJulian(jul, &y, &m, &d);
|
||||
while(e) {
|
||||
if (DoPrefixLineNo) {
|
||||
if (PsCal != PSCAL_LEVEL2 && PsCal != PSCAL_LEVEL3) {
|
||||
printf("# fileinfo %d %s\n", e->lineno, e->filename);
|
||||
}
|
||||
}
|
||||
if (PsCal >= PSCAL_LEVEL2) {
|
||||
if (PsCal == PSCAL_LEVEL3) {
|
||||
if (DidADay) {
|
||||
printf(",\n");
|
||||
}
|
||||
}
|
||||
DidADay = 1;
|
||||
printf("{\"date\":\"%04d-%02d-%02d\", ", y, m+1, d);
|
||||
WriteSimpleEntryProtocol2(e, jul);
|
||||
printf("}");
|
||||
if (PsCal != PSCAL_LEVEL3) {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
printf("%04d/%02d/%02d", y, m+1, d);
|
||||
WriteSimpleEntryProtocol1(e);
|
||||
}
|
||||
|
||||
free(e->text);
|
||||
free(e->raw_text);
|
||||
free(e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
if (e->wc_text) free(e->wc_text);
|
||||
#endif
|
||||
n = e->next;
|
||||
free(e);
|
||||
@@ -1530,6 +2081,8 @@ char const *SynthesizeTag(void)
|
||||
unsigned char buf[16];
|
||||
static char out[128];
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (unsigned char *) FileName, strlen(FileName));
|
||||
MD5Update(&ctx, (unsigned char *) &LineNo, sizeof(LineNo));
|
||||
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
||||
MD5Final(buf, &ctx);
|
||||
sprintf(out, "__syn__%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -220,6 +220,9 @@
|
||||
#define PSBEGIN "# rem2ps begin"
|
||||
#define PSEND "# rem2ps end"
|
||||
|
||||
#define PSBEGIN2 "# rem2ps2 begin"
|
||||
#define PSEND2 "# rem2ps2 end"
|
||||
|
||||
#ifdef BROKEN_PUTC
|
||||
#define Putc SafePutc
|
||||
#define PutChar SafePutChar
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* which you can customize. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -220,6 +220,9 @@
|
||||
#define PSBEGIN "# rem2ps begin"
|
||||
#define PSEND "# rem2ps end"
|
||||
|
||||
#define PSBEGIN2 "# rem2ps2 begin"
|
||||
#define PSEND2 "# rem2ps2 end"
|
||||
|
||||
#ifdef BROKEN_PUTC
|
||||
#define Putc SafePutc
|
||||
#define PutChar SafePutChar
|
||||
|
||||
127
src/dorem.c
@@ -7,7 +7,7 @@
|
||||
/* commands. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
@@ -34,6 +34,17 @@ static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
|
||||
static int ParsePriority (ParsePtr s, Trigger *t);
|
||||
static int ParseUntil (ParsePtr s, Trigger *t);
|
||||
static int ShouldTriggerBasedOnWarn (Trigger *t, int jul, int *err);
|
||||
static int ComputeTrigDuration(TimeTrig *t);
|
||||
|
||||
static int
|
||||
ComputeTrigDuration(TimeTrig *t)
|
||||
{
|
||||
if (t->ttime == NO_TIME ||
|
||||
t->duration == NO_TIME) {
|
||||
return 0;
|
||||
}
|
||||
return (t->ttime + t->duration - 1) / MINUTES_PER_DAY;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -68,7 +79,7 @@ int DoRem(ParsePtr p)
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
PurgeEchoLine("%s\n", "#!P: Cannot purge SATISFY-type reminders");
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
r=DoSatRemind(&trig, p);
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
@@ -117,7 +128,7 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (PurgeMode) {
|
||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||
@@ -200,10 +211,14 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->once = NO_ONCE;
|
||||
trig->typ = NO_TYPE;
|
||||
trig->scanfrom = NO_DATE;
|
||||
trig->from = NO_DATE;
|
||||
trig->priority = DefaultPrio;
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->duration_days = 0;
|
||||
trig->eventstart = NO_TIME;
|
||||
trig->eventduration = NO_TIME;
|
||||
DBufInit(&(trig->tags));
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
@@ -245,6 +260,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
tim->ttime = (tok.val % MINUTES_PER_DAY);
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -276,6 +292,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
DBufFree(&buf);
|
||||
r=ParseTimeTrig(s, tim, save_in_globals);
|
||||
if (r) return r;
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
|
||||
case T_Scanfrom:
|
||||
@@ -372,6 +389,10 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
r=ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->omitfunc, DBufValue(&buf), VAR_NAME_LEN);
|
||||
|
||||
/* An OMITFUNC counts as a nonconst_expr! */
|
||||
s->expr_happened = 1;
|
||||
s->nonconst_expr = 1;
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
@@ -396,7 +417,15 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
switch(tok.type) {
|
||||
case T_Time:
|
||||
case T_LongTime:
|
||||
tim->duration = tok.val;
|
||||
if (tok.val != 0) {
|
||||
tim->duration = tok.val;
|
||||
} else {
|
||||
tim->duration = NO_TIME;
|
||||
}
|
||||
if (save_in_globals) {
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
trig->duration_days = ComputeTrigDuration(tim);
|
||||
break;
|
||||
default:
|
||||
return E_BAD_TIME;
|
||||
@@ -468,6 +497,7 @@ static int ParseTimeTrig(ParsePtr s, TimeTrig *tim, int save_in_globals)
|
||||
/* Save trigger time in global variable */
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
}
|
||||
PushToken(DBufValue(&buf), s);
|
||||
DBufFree(&buf);
|
||||
@@ -702,9 +732,12 @@ static int ParseScanFrom(ParsePtr s, Trigger *t, int type)
|
||||
}
|
||||
t->scanfrom = Julian(y, m, d);
|
||||
if (type == FROM_TYPE) {
|
||||
t->from = t->scanfrom;
|
||||
if (t->scanfrom < JulianToday) {
|
||||
t->scanfrom = JulianToday;
|
||||
}
|
||||
} else {
|
||||
t->from = NO_DATE;
|
||||
}
|
||||
|
||||
PushToken(DBufValue(&buf), s);
|
||||
@@ -730,20 +763,24 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
char const *s;
|
||||
Value v;
|
||||
|
||||
int red = -1, green = -1, blue = -1;
|
||||
int is_color = 0;
|
||||
|
||||
DBufInit(&buf);
|
||||
DBufInit(&calRow);
|
||||
DBufInit(&pre_buf);
|
||||
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
|
||||
if ((t->typ == PASSTHRU_TYPE && strcmp(t->passthru, "COLOR") && strcmp(t->passthru, "COLOUR")) ||
|
||||
if ((t->typ == PASSTHRU_TYPE && StrCmpi(t->passthru, "COLOR") && StrCmpi(t->passthru, "COLOUR")) ||
|
||||
t->typ == CAL_TYPE ||
|
||||
t->typ == PS_TYPE ||
|
||||
t->typ == PSF_TYPE)
|
||||
return OK;
|
||||
|
||||
/* Handle COLOR types */
|
||||
if (t->typ == PASSTHRU_TYPE && (!strcmp(t->passthru, "COLOR") || !strcmp(t->passthru, "COLOUR"))) {
|
||||
if (t->typ == PASSTHRU_TYPE && (!StrCmpi(t->passthru, "COLOR") || !StrCmpi(t->passthru, "COLOUR"))) {
|
||||
/* Strip off three tokens */
|
||||
r = ParseToken(p, &buf);
|
||||
sscanf(DBufValue(&buf), "%d", &red);
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
@@ -751,6 +788,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
sscanf(DBufValue(&buf), "%d", &green);
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
@@ -758,6 +796,7 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r = ParseToken(p, &buf);
|
||||
sscanf(DBufValue(&buf), "%d", &blue);
|
||||
if (!NextMode) {
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
@@ -841,6 +880,23 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Correct colors */
|
||||
if (UseVTColors) {
|
||||
if (red == -1 && green == -1 && blue == -1) {
|
||||
if (DefaultColorR != -1 && DefaultColorG != -1 && DefaultColorB != -1) {
|
||||
red = DefaultColorR;
|
||||
green = DefaultColorG;
|
||||
blue = DefaultColorB;
|
||||
}
|
||||
}
|
||||
if (red >= 0 && green >= 0 && blue >= 0) {
|
||||
is_color = 1;
|
||||
if (red > 255) red = 255;
|
||||
if (green > 255) green = 255;
|
||||
if (blue > 255) blue = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the substituted string into the substitution buffer */
|
||||
|
||||
/* Don't use msgprefix() on RUN-type reminders */
|
||||
@@ -851,6 +907,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (is_color) {
|
||||
DBufPuts(&buf, Colorize(red, green, blue));
|
||||
}
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
@@ -862,6 +921,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_color) {
|
||||
DBufPuts(&buf, Colorize(red, green, blue));
|
||||
}
|
||||
if ( (r=DoSubst(p, &buf, t, tim, jul, NORMAL_MODE)) ) return r;
|
||||
if (t->typ != RUN_TYPE) {
|
||||
if (UserFuncExists("msgsuffix") == 1) {
|
||||
@@ -870,6 +932,9 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
r = EvalExpr(&s, &v, NULL);
|
||||
if (!r) {
|
||||
if (!DoCoerce(STR_TYPE, &v)) {
|
||||
if (is_color) {
|
||||
DBufPuts(&buf, Colorize(red, green, blue));
|
||||
}
|
||||
if (DBufPuts(&buf, v.v.str) != OK) {
|
||||
DBufFree(&buf);
|
||||
DestroyValue(v);
|
||||
@@ -881,6 +946,10 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
}
|
||||
}
|
||||
|
||||
if (is_color) {
|
||||
DBufPuts(&buf, Decolorize(red, green, blue));
|
||||
}
|
||||
|
||||
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
|
||||
if (DBufPutc(&buf, '\n') != OK) {
|
||||
DBufFree(&buf);
|
||||
@@ -1019,18 +1088,18 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
/* Do the "satisfying..." remind calculation. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int DoSatRemind(Trigger *trig, ParsePtr p)
|
||||
int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
|
||||
{
|
||||
int iter, jul, r;
|
||||
int iter, jul, r, start;
|
||||
Value v;
|
||||
char const *s;
|
||||
char const *t;
|
||||
|
||||
t = p->pos;
|
||||
iter = 0;
|
||||
jul = trig->scanfrom;
|
||||
start = trig->scanfrom;
|
||||
while (iter++ < MaxSatIter) {
|
||||
jul = ComputeTrigger(jul, trig, &r, 1);
|
||||
jul = ComputeTriggerNoAdjustDuration(start, trig, tt, &r, 1);
|
||||
if (r) {
|
||||
if (r == E_CANT_TRIG) return OK; else return r;
|
||||
}
|
||||
@@ -1042,14 +1111,42 @@ int DoSatRemind(Trigger *trig, ParsePtr p)
|
||||
t = p->pos;
|
||||
if (r) return r;
|
||||
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (v.type == INT_TYPE && v.v.val) return OK;
|
||||
if (v.type == STR_TYPE && *v.v.str) return OK;
|
||||
if ((v.type == INT_TYPE && v.v.val) ||
|
||||
(v.type == STR_TYPE && *v.v.str)) {
|
||||
AdjustTriggerForDuration(trig->scanfrom, jul, trig, tt, 1);
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
int y, m, d;
|
||||
FromJulian(LastTriggerDate, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(satisfied) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[LastTriggerDate % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tt->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tt->ttime / 60),
|
||||
(tt->ttime % 60));
|
||||
if (tt->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tt->duration / 60),
|
||||
(tt->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
p->pos = s;
|
||||
jul++;
|
||||
if (jul+trig->duration_days < start) {
|
||||
start++;
|
||||
} else {
|
||||
start = jul+trig->duration_days+1;
|
||||
}
|
||||
}
|
||||
p->pos = t;
|
||||
LastTrigValid = 0;
|
||||
return OK;
|
||||
return E_CANT_TRIG;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* reminders are triggered. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
|
||||
#define UPPER(c) (islower(c) ? toupper(c) : (c))
|
||||
@@ -656,8 +656,13 @@ int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul,
|
||||
break;
|
||||
|
||||
case '"':
|
||||
if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
|
||||
has_quote = 1;
|
||||
if (PsCal != PSCAL_LEVEL3) {
|
||||
if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
|
||||
has_quote = 1;
|
||||
} else {
|
||||
if (DBufPutc(dbuf, '%') != OK) return E_NO_MEM;
|
||||
if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* buffers. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Declaration of functions for manipulating dynamic buffers */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Error definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
#define E_NO_MATCHING_REMS 100
|
||||
#define E_STRING_TOO_LONG 101
|
||||
#define E_TIME_TWICE 102
|
||||
#define E_DURATION_NO_AT 103
|
||||
#ifdef MK_GLOBALS
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
@@ -234,7 +235,8 @@ EXTERN char *ErrMsg[]
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
}
|
||||
#endif /* MK_GLOBALS */
|
||||
;
|
||||
|
||||
34
src/expr.c
@@ -5,7 +5,7 @@
|
||||
/* This file contains routines to parse and evaluate */
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* Copyright 1992-2018 by Dianne Skoll */
|
||||
/* Copyright 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#define LE 4
|
||||
#define NE 5
|
||||
|
||||
static char CoerceBuf[512];
|
||||
extern int NumFuncs;
|
||||
|
||||
static int Multiply(void), Divide(void), Mod(void), Add(void),
|
||||
@@ -578,6 +577,8 @@ int DoCoerce(char type, Value *v)
|
||||
int h, d, m, y, i, k;
|
||||
char const *s;
|
||||
|
||||
char coerce_buf[128];
|
||||
|
||||
/* Do nothing if value is already the right type */
|
||||
if (type == v->type) return OK;
|
||||
|
||||
@@ -605,12 +606,12 @@ int DoCoerce(char type, Value *v)
|
||||
}
|
||||
case STR_TYPE:
|
||||
switch(v->type) {
|
||||
case INT_TYPE: sprintf(CoerceBuf, "%d", v->v.val); break;
|
||||
case TIME_TYPE: sprintf(CoerceBuf, "%02d%c%02d", v->v.val / 60,
|
||||
case INT_TYPE: sprintf(coerce_buf, "%d", v->v.val); break;
|
||||
case TIME_TYPE: sprintf(coerce_buf, "%02d%c%02d", v->v.val / 60,
|
||||
TimeSep, v->v.val % 60);
|
||||
break;
|
||||
case DATE_TYPE: FromJulian(v->v.val, &y, &m, &d);
|
||||
sprintf(CoerceBuf, "%04d%c%02d%c%02d",
|
||||
sprintf(coerce_buf, "%04d%c%02d%c%02d",
|
||||
y, DateSep, m+1, DateSep, d);
|
||||
break;
|
||||
case DATETIME_TYPE:
|
||||
@@ -619,13 +620,13 @@ int DoCoerce(char type, Value *v)
|
||||
k = v->v.val % MINUTES_PER_DAY;
|
||||
h = k / 60;
|
||||
i = k % 60;
|
||||
sprintf(CoerceBuf, "%04d%c%02d%c%02d%c%02d%c%02d",
|
||||
sprintf(coerce_buf, "%04d%c%02d%c%02d%c%02d%c%02d",
|
||||
y, DateSep, m+1, DateSep, d, DateTimeSep, h, TimeSep, i);
|
||||
break;
|
||||
default: return E_CANT_COERCE;
|
||||
}
|
||||
v->type = STR_TYPE;
|
||||
v->v.str = StrDup(CoerceBuf);
|
||||
v->v.str = StrDup(coerce_buf);
|
||||
if (!v->v.str) {
|
||||
v->type = ERR_TYPE;
|
||||
return E_NO_MEM;
|
||||
@@ -765,9 +766,9 @@ static int Add(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a datetime plus an int, add 'em */
|
||||
if ((v1.type == DATETIME_TYPE && v2.type == INT_TYPE) ||
|
||||
(v1.type == INT_TYPE && v2.type == DATETIME_TYPE)) {
|
||||
/* If it's a datetime plus an int or a time, add 'em */
|
||||
if ((v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) ||
|
||||
((v1.type == INT_TYPE || v1.type == TIME_TYPE) && v2.type == DATETIME_TYPE)) {
|
||||
v1.v.val += v2.v.val;
|
||||
if (v1.v.val < 0) return E_DATE_OVER;
|
||||
v1.type = DATETIME_TYPE;
|
||||
@@ -775,9 +776,11 @@ static int Add(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a time plus an int, add 'em mod MINUTES_PER_DAY */
|
||||
/* If it's a time plus an int or a time plus a time,
|
||||
add 'em mod MINUTES_PER_DAY */
|
||||
if ((v1.type == TIME_TYPE && v2.type == INT_TYPE) ||
|
||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE)) {
|
||||
(v1.type == INT_TYPE && v2.type == TIME_TYPE) ||
|
||||
(v1.type == TIME_TYPE && v2.type == TIME_TYPE)) {
|
||||
v1.v.val = (v1.v.val + v2.v.val) % MINUTES_PER_DAY;
|
||||
if (v1.v.val < 0) v1.v.val += MINUTES_PER_DAY;
|
||||
v1.type = TIME_TYPE;
|
||||
@@ -808,7 +811,7 @@ static int Add(void)
|
||||
return E_NO_MEM;
|
||||
}
|
||||
strcpy(v3.v.str, v1.v.str);
|
||||
strcat(v3.v.str, v2.v.str);
|
||||
strcpy(v3.v.str+l1, v2.v.str);
|
||||
DestroyValue(v1); DestroyValue(v2);
|
||||
PushValStack(v3);
|
||||
return OK;
|
||||
@@ -851,8 +854,9 @@ static int Subtract(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* If it's a datetime minus an int, do subtraction, checking for underflow */
|
||||
if (v1.type == DATETIME_TYPE && v2.type == INT_TYPE) {
|
||||
/* If it's a datetime minus an int or a time, do subtraction,
|
||||
* checking for underflow */
|
||||
if (v1.type == DATETIME_TYPE && (v2.type == INT_TYPE || v2.type == TIME_TYPE)) {
|
||||
v1.v.val -= v2.v.val;
|
||||
if (v1.v.val < 0) return E_DATE_OVER;
|
||||
PushValStack(v1);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Contains a few definitions used by expression evaluator. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* files. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
358
src/funcs.c
@@ -6,7 +6,7 @@
|
||||
/* expressions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -53,94 +53,107 @@
|
||||
#define RetVal (info->retval)
|
||||
|
||||
/* Function prototypes */
|
||||
static int FCurrent (func_info *);
|
||||
static int FNonomitted (func_info *);
|
||||
static int FTimepart(func_info *);
|
||||
static int FDatepart(func_info *);
|
||||
static int FRealCurrent(func_info *);
|
||||
static int FAbs (func_info *);
|
||||
static int FAccess (func_info *);
|
||||
static int FArgs (func_info *);
|
||||
static int FAsc (func_info *);
|
||||
static int FBaseyr (func_info *);
|
||||
static int FChar (func_info *);
|
||||
static int FChoose (func_info *);
|
||||
static int FCoerce (func_info *);
|
||||
static int FDate (func_info *);
|
||||
static int FDateTime (func_info *);
|
||||
static int FDay (func_info *);
|
||||
static int FDaysinmon (func_info *);
|
||||
static int FDefined (func_info *);
|
||||
static int FDosubst (func_info *);
|
||||
static int FEasterdate (func_info *);
|
||||
static int FEvalTrig (func_info *);
|
||||
static int FFiledate (func_info *);
|
||||
static int FFiledatetime (func_info *);
|
||||
static int FFiledir (func_info *);
|
||||
static int FFilename (func_info *);
|
||||
static int FGetenv (func_info *);
|
||||
static int FHebdate (func_info *);
|
||||
static int FHebday (func_info *);
|
||||
static int FHebmon (func_info *);
|
||||
static int FHebyear (func_info *);
|
||||
static int FHour (func_info *);
|
||||
static int FIif (func_info *);
|
||||
static int FIndex (func_info *);
|
||||
static int FIsdst (func_info *);
|
||||
static int FIsomitted (func_info *);
|
||||
static int FSlide (func_info *);
|
||||
static int FLanguage (func_info *);
|
||||
static int FMax (func_info *);
|
||||
static int FMin (func_info *);
|
||||
static int FMinute (func_info *);
|
||||
static int FMinsfromutc (func_info *);
|
||||
static int FMoondate (func_info *);
|
||||
static int FMoondatetime (func_info *);
|
||||
static int FMoonphase (func_info *);
|
||||
static int FMoontime (func_info *);
|
||||
static int FMon (func_info *);
|
||||
static int FMonnum (func_info *);
|
||||
static int FOrd (func_info *);
|
||||
static int FOstype (func_info *);
|
||||
static int FPlural (func_info *);
|
||||
static int FSgn (func_info *);
|
||||
static int FPsmoon (func_info *);
|
||||
static int FPsshade (func_info *);
|
||||
static int FShell (func_info *);
|
||||
static int FStrlen (func_info *);
|
||||
static int FSubstr (func_info *);
|
||||
static int FADawn (func_info *);
|
||||
static int FADusk (func_info *);
|
||||
static int FNDawn (func_info *);
|
||||
static int FNDusk (func_info *);
|
||||
static int FDawn (func_info *);
|
||||
static int FDusk (func_info *);
|
||||
static int FSunset (func_info *);
|
||||
static int FSunrise (func_info *);
|
||||
static int FTime (func_info *);
|
||||
static int FTrigdate (func_info *);
|
||||
static int FTrigdatetime (func_info *);
|
||||
static int FTrigtime (func_info *);
|
||||
static int FTrigvalid (func_info *);
|
||||
static int FTypeof (func_info *);
|
||||
static int FUpper (func_info *);
|
||||
static int FValue (func_info *);
|
||||
static int FVersion (func_info *);
|
||||
static int FWkday (func_info *);
|
||||
static int FWkdaynum (func_info *);
|
||||
static int FYear (func_info *);
|
||||
static int FIsleap (func_info *);
|
||||
static int FLower (func_info *);
|
||||
static int FNow (func_info *);
|
||||
static int FRealnow (func_info *);
|
||||
static int FRealtoday (func_info *);
|
||||
static int FToday (func_info *);
|
||||
static int FTrigger (func_info *);
|
||||
static int FTzconvert (func_info *);
|
||||
static int FWeekno (func_info *);
|
||||
static int CheckArgs (BuiltinFunc *f, int nargs);
|
||||
static int CleanUpAfterFunc (func_info *);
|
||||
static int SunStuff (int rise, double cosz, int jul);
|
||||
static int FADawn (func_info *);
|
||||
static int FADusk (func_info *);
|
||||
static int FAbs (func_info *);
|
||||
static int FAccess (func_info *);
|
||||
static int FArgs (func_info *);
|
||||
static int FAsc (func_info *);
|
||||
static int FBaseyr (func_info *);
|
||||
static int FChar (func_info *);
|
||||
static int FChoose (func_info *);
|
||||
static int FCoerce (func_info *);
|
||||
static int FCurrent (func_info *);
|
||||
static int FDate (func_info *);
|
||||
static int FDateTime (func_info *);
|
||||
static int FDatepart (func_info *);
|
||||
static int FDawn (func_info *);
|
||||
static int FDay (func_info *);
|
||||
static int FDaysinmon (func_info *);
|
||||
static int FDefined (func_info *);
|
||||
static int FDosubst (func_info *);
|
||||
static int FDusk (func_info *);
|
||||
static int FEasterdate (func_info *);
|
||||
static int FEvalTrig (func_info *);
|
||||
static int FFiledate (func_info *);
|
||||
static int FFiledatetime (func_info *);
|
||||
static int FFiledir (func_info *);
|
||||
static int FFilename (func_info *);
|
||||
static int FGetenv (func_info *);
|
||||
static int FHebdate (func_info *);
|
||||
static int FHebday (func_info *);
|
||||
static int FHebmon (func_info *);
|
||||
static int FHebyear (func_info *);
|
||||
static int FHour (func_info *);
|
||||
static int FIif (func_info *);
|
||||
static int FIndex (func_info *);
|
||||
static int FIsdst (func_info *);
|
||||
static int FIsleap (func_info *);
|
||||
static int FIsomitted (func_info *);
|
||||
static int FLanguage (func_info *);
|
||||
static int FLower (func_info *);
|
||||
static int FMax (func_info *);
|
||||
static int FMin (func_info *);
|
||||
static int FMinsfromutc (func_info *);
|
||||
static int FMinute (func_info *);
|
||||
static int FMon (func_info *);
|
||||
static int FMonnum (func_info *);
|
||||
static int FMoondate (func_info *);
|
||||
static int FMoondatetime (func_info *);
|
||||
static int FMoonphase (func_info *);
|
||||
static int FMoontime (func_info *);
|
||||
static int FNDawn (func_info *);
|
||||
static int FNDusk (func_info *);
|
||||
static int FNonomitted (func_info *);
|
||||
static int FNow (func_info *);
|
||||
static int FOrd (func_info *);
|
||||
static int FOstype (func_info *);
|
||||
static int FPlural (func_info *);
|
||||
static int FPsmoon (func_info *);
|
||||
static int FPsshade (func_info *);
|
||||
static int FRealCurrent (func_info *);
|
||||
static int FRealnow (func_info *);
|
||||
static int FRealtoday (func_info *);
|
||||
static int FSgn (func_info *);
|
||||
static int FShell (func_info *);
|
||||
static int FSlide (func_info *);
|
||||
static int FStrlen (func_info *);
|
||||
static int FSubstr (func_info *);
|
||||
static int FSunrise (func_info *);
|
||||
static int FSunset (func_info *);
|
||||
static int FTime (func_info *);
|
||||
static int FTimepart (func_info *);
|
||||
static int FToday (func_info *);
|
||||
static int FTrigback (func_info *);
|
||||
static int FTrigdate (func_info *);
|
||||
static int FTrigdatetime (func_info *);
|
||||
static int FTrigdelta (func_info *);
|
||||
static int FTrigduration (func_info *);
|
||||
static int FTrigeventduration(func_info *);
|
||||
static int FTrigeventstart (func_info *);
|
||||
static int FTrigfrom (func_info *);
|
||||
static int FTrigger (func_info *);
|
||||
static int FTrigpriority (func_info *);
|
||||
static int FTrigrep (func_info *);
|
||||
static int FTrigscanfrom (func_info *);
|
||||
static int FTrigtime (func_info *);
|
||||
static int FTrigtimedelta (func_info *);
|
||||
static int FTrigtimerep (func_info *);
|
||||
static int FTriguntil (func_info *);
|
||||
static int FTrigvalid (func_info *);
|
||||
static int FTypeof (func_info *);
|
||||
static int FTzconvert (func_info *);
|
||||
static int FUpper (func_info *);
|
||||
static int FValue (func_info *);
|
||||
static int FVersion (func_info *);
|
||||
static int FWeekno (func_info *);
|
||||
static int FWkday (func_info *);
|
||||
static int FWkdaynum (func_info *);
|
||||
static int FYear (func_info *);
|
||||
|
||||
static int CleanUpAfterFunc (func_info *);
|
||||
static int CheckArgs (BuiltinFunc *f, int nargs);
|
||||
static int SunStuff (int rise, double cosz, int jul);
|
||||
|
||||
/* "Overload" the struct Operator definition */
|
||||
#define NO_MAX 127
|
||||
@@ -260,10 +273,22 @@ BuiltinFunc Func[] = {
|
||||
{ "time", 2, 2, 1, FTime },
|
||||
{ "timepart", 1, 1, 1, FTimepart },
|
||||
{ "today", 0, 0, 0, FToday },
|
||||
{ "trigback", 0, 0, 0, FTrigback },
|
||||
{ "trigdate", 0, 0, 0, FTrigdate },
|
||||
{ "trigdatetime", 0, 0, 0, FTrigdatetime },
|
||||
{ "trigdelta", 0, 0, 0, FTrigdelta },
|
||||
{ "trigduration", 0, 0, 0, FTrigduration },
|
||||
{ "trigeventduration", 0, 0, 0, FTrigeventduration },
|
||||
{ "trigeventstart", 0, 0, 0, FTrigeventstart },
|
||||
{ "trigfrom", 0, 0, 0, FTrigfrom },
|
||||
{ "trigger", 1, 3, 0, FTrigger },
|
||||
{ "trigpriority", 0, 0, 0, FTrigpriority },
|
||||
{ "trigrep", 0, 0, 0, FTrigrep },
|
||||
{ "trigscanfrom", 0, 0, 0, FTrigscanfrom },
|
||||
{ "trigtime", 0, 0, 0, FTrigtime },
|
||||
{ "trigtimedelta",0, 0, 0, FTrigtimedelta },
|
||||
{ "trigtimerep", 0, 0, 0, FTrigtimerep },
|
||||
{ "triguntil", 0, 0, 0, FTriguntil },
|
||||
{ "trigvalid", 0, 0, 0, FTrigvalid },
|
||||
{ "typeof", 1, 1, 1, FTypeof },
|
||||
{ "tzconvert", 2, 3, 0, FTzconvert },
|
||||
@@ -1137,6 +1162,120 @@ static int FTrigdate(func_info *info)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigback(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.back;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigdelta(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.delta;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigtimedelta(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTimeTrig.delta;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigtimerep(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTimeTrig.rep;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigeventduration(func_info *info)
|
||||
{
|
||||
if (LastTrigger.eventduration == NO_TIME) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = TIME_TYPE;
|
||||
RETVAL = LastTrigger.eventduration;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigeventstart(func_info *info)
|
||||
{
|
||||
if (LastTrigger.eventstart == NO_TIME) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = DATETIME_TYPE;
|
||||
RETVAL = LastTrigger.eventstart;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigduration(func_info *info)
|
||||
{
|
||||
if (LastTimeTrig.duration == NO_TIME) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = TIME_TYPE;
|
||||
RETVAL = LastTimeTrig.duration;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigrep(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.rep;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigpriority(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = LastTrigger.priority;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTriguntil(func_info *info)
|
||||
{
|
||||
if (LastTrigger.until == NO_UNTIL) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = LastTrigger.until;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigscanfrom(func_info *info)
|
||||
{
|
||||
if (LastTrigger.scanfrom == NO_DATE) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = LastTrigger.scanfrom;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigfrom(func_info *info)
|
||||
{
|
||||
if (LastTrigger.from == NO_DATE) {
|
||||
RetVal.type = INT_TYPE;
|
||||
RETVAL = -1;
|
||||
} else {
|
||||
RetVal.type = DATE_TYPE;
|
||||
RETVAL = LastTrigger.from;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int FTrigvalid(func_info *info)
|
||||
{
|
||||
RetVal.type = INT_TYPE;
|
||||
@@ -1880,7 +2019,7 @@ static int SunStuff(int rise, double cosz, int jul)
|
||||
+ (double) LongSec / 3600.0;
|
||||
|
||||
latitude = DEGRAD * ((double) LatDeg + (double) LatMin / 60.0
|
||||
+ (double) LatSec / 3600.0);
|
||||
+ (double) LatSec / 3600.0);
|
||||
|
||||
|
||||
FromJulian(jul, &year, &mon, &day);
|
||||
@@ -1919,10 +2058,10 @@ static int SunStuff(int rise, double cosz, int jul)
|
||||
/* Sine of sun's declination */
|
||||
sinDelta = 0.39782 * sin(DEGRAD*L);
|
||||
cosDelta = sqrt(1 - sinDelta*sinDelta);
|
||||
|
||||
|
||||
/* Cosine of sun's local hour angle */
|
||||
cosH = (cosz - sinDelta * sin(latitude)) / (cosDelta * cos(latitude));
|
||||
|
||||
|
||||
if (cosH < -1.0) { /* Summer -- permanent daylight */
|
||||
if (rise) return NO_TIME;
|
||||
else return -NO_TIME;
|
||||
@@ -1940,9 +2079,9 @@ static int SunStuff(int rise, double cosz, int jul)
|
||||
|
||||
if (T >= 24.0) T -= 24.0;
|
||||
else if (T < 0.0) T+= 24.0;
|
||||
|
||||
|
||||
UT = T + longdeg / 15.0;
|
||||
|
||||
|
||||
|
||||
local = UT + (double) mins / 60.0;
|
||||
if (local < 0.0) local += 24.0;
|
||||
@@ -1953,7 +2092,7 @@ static int SunStuff(int rise, double cosz, int jul)
|
||||
|
||||
hours = (int) local;
|
||||
mins = (int) ((local - hours) * 60.0);
|
||||
|
||||
|
||||
/* Sometimes, we get roundoff error. Check for "reasonableness" of
|
||||
answer. */
|
||||
if (rise) {
|
||||
@@ -2422,16 +2561,16 @@ static int tz_set_tz(char const *tz)
|
||||
unsetenv("TZ");
|
||||
r = 0;
|
||||
} else {
|
||||
r = setenv("TZ", tz, 1);
|
||||
r = setenv("TZ", tz, 1);
|
||||
}
|
||||
tzset();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int tz_convert(int year, int month, int day,
|
||||
int hour, int minute,
|
||||
char const *src_tz, char const *tgt_tz,
|
||||
struct tm *tm)
|
||||
int hour, int minute,
|
||||
char const *src_tz, char const *tgt_tz,
|
||||
struct tm *tm)
|
||||
{
|
||||
int r;
|
||||
time_t t;
|
||||
@@ -2452,28 +2591,28 @@ static int tz_convert(int year, int month, int day,
|
||||
/* backup old TZ env var */
|
||||
old_tz = getenv("TZ");
|
||||
if (tgt_tz == NULL) {
|
||||
tgt_tz = old_tz;
|
||||
tgt_tz = old_tz;
|
||||
}
|
||||
|
||||
/* set source TZ */
|
||||
r = tz_set_tz(src_tz);
|
||||
if (r == -1) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create timestamp in UTC */
|
||||
t = mktime(tm);
|
||||
|
||||
if (t == (time_t) -1) {
|
||||
tz_set_tz(old_tz);
|
||||
return -1;
|
||||
tz_set_tz(old_tz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set target TZ */
|
||||
r = tz_set_tz(tgt_tz);
|
||||
if (r == -1) {
|
||||
tz_set_tz(old_tz);
|
||||
return -1;
|
||||
tz_set_tz(old_tz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert to target TZ */
|
||||
@@ -2484,9 +2623,9 @@ static int tz_convert(int year, int month, int day,
|
||||
|
||||
/* return result */
|
||||
if (res == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2557,6 +2696,7 @@ FSlide(func_info *info)
|
||||
} else {
|
||||
while(amt) {
|
||||
d--;
|
||||
if (d < 0) return E_DATE_OVER;
|
||||
r = IsOmitted(d, localomit, NULL,&omit);
|
||||
if (r) return r;
|
||||
if (!omit) amt++;
|
||||
@@ -2697,13 +2837,13 @@ FEvalTrig(func_info *info)
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (scanfrom == NO_DATE) {
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 0);
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 0);
|
||||
} else {
|
||||
/* Hokey... */
|
||||
if (trig.scanfrom != JulianToday) {
|
||||
Eprint("Warning: SCANFROM is ignored in two-argument form of evaltrig()");
|
||||
}
|
||||
jul = ComputeTrigger(scanfrom, &trig, &r, 0);
|
||||
jul = ComputeTrigger(scanfrom, &trig, &tim, &r, 0);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
if (r) return r;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* globals.h and err.h */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* MK_GLOBALS. Also contains useful macro definitions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -46,7 +46,7 @@ EXTERN INIT( int DoPrefixLineNo, 0);
|
||||
EXTERN INIT( int MondayFirst, 0);
|
||||
EXTERN INIT( int Iterations, 1);
|
||||
EXTERN INIT( int PsCal, 0);
|
||||
EXTERN INIT( int CalWidth, 80);
|
||||
EXTERN INIT( int CalWidth, -1);
|
||||
EXTERN INIT( int CalWeeks, 0);
|
||||
EXTERN INIT( int CalMonths, 0);
|
||||
EXTERN INIT( int Hush, 0);
|
||||
@@ -73,6 +73,9 @@ EXTERN INIT( int Daemon, 0);
|
||||
EXTERN INIT( char DateSep, DATESEP);
|
||||
EXTERN INIT( char TimeSep, TIMESEP);
|
||||
EXTERN INIT( char DateTimeSep, DATETIMESEP);
|
||||
EXTERN INIT( int DefaultColorR, -1);
|
||||
EXTERN INIT( int DefaultColorB, -1);
|
||||
EXTERN INIT( int DefaultColorG, -1);
|
||||
EXTERN INIT( int SynthesizeTags, 0);
|
||||
EXTERN INIT( int ScFormat, SC_AMPM);
|
||||
EXTERN INIT( int MaxSatIter, 150);
|
||||
@@ -85,8 +88,10 @@ EXTERN FILE *ErrFp;
|
||||
EXTERN INIT( FILE *PurgeFP, NULL);
|
||||
EXTERN INIT( int NumIfs, 0);
|
||||
EXTERN INIT( unsigned int IfFlags, 0);
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
EXTERN INIT( int LastTrigValid, 0);
|
||||
EXTERN Trigger LastTrigger;
|
||||
EXTERN TimeTrig LastTimeTrig;
|
||||
EXTERN INIT( int LastTriggerDate, 0);
|
||||
EXTERN INIT( int LastTriggerTime, 0);
|
||||
EXTERN INIT( int ShouldCache, 0);
|
||||
EXTERN char const *CurLine;
|
||||
@@ -98,6 +103,9 @@ EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseUTF8Chars, 0);
|
||||
EXTERN INIT( int UseVTColors, 0);
|
||||
EXTERN INIT( int Use256Colors, 0);
|
||||
EXTERN INIT( int UseTrueColors, 0);
|
||||
EXTERN INIT( int TerminalBackground, TERMINAL_BACKGROUND_UNKNOWN);
|
||||
|
||||
/* Latitude and longitude */
|
||||
EXTERN INIT( int LatDeg, LAT_DEG);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Hebrew calendar */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/* Derived from code written by Amos Shapir in 1978; revised */
|
||||
/* 1985. */
|
||||
|
||||
53
src/init.c
@@ -7,7 +7,7 @@
|
||||
/* in normal mode. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2019 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
* simple calendar format.
|
||||
* -r = Disallow RUN mode
|
||||
* -c[n] = Produce a calendar for n months (default = 1)
|
||||
* -@[n,m] = Colorize n=0 VT100 n=1 85 n=2 True m=0 dark terminal m=1 light
|
||||
* -w[n,n,n] = Specify output device width, padding and spacing
|
||||
* -s[n] = Produce calendar in "simple calendar" format
|
||||
* -p[n] = Produce calendar in format compatible with rem2ps
|
||||
@@ -135,7 +136,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
int InvokedAsRem = 0;
|
||||
char const *s;
|
||||
int weeks;
|
||||
|
||||
int x;
|
||||
int jul;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@@ -190,6 +191,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
|
||||
/* Parse the command-line options */
|
||||
i = 1;
|
||||
|
||||
while (i < argc) {
|
||||
arg = argv[i];
|
||||
if (*arg != '-') break; /* Exit the loop if it's not an option */
|
||||
@@ -204,6 +206,27 @@ void InitRemind(int argc, char const *argv[])
|
||||
while (*arg) {
|
||||
switch(*arg++) {
|
||||
|
||||
case '@':
|
||||
UseVTColors = 1;
|
||||
if (*arg) {
|
||||
PARSENUM(x, arg);
|
||||
if (x == 1) {
|
||||
Use256Colors = 1;
|
||||
} else if (x == 2) {
|
||||
UseTrueColors = 1;
|
||||
}
|
||||
}
|
||||
if (*arg == ',') {
|
||||
arg++;
|
||||
PARSENUM(x, arg);
|
||||
if (x == 0) {
|
||||
TerminalBackground = TERMINAL_BACKGROUND_DARK;
|
||||
} else if (x == 1) {
|
||||
TerminalBackground = TERMINAL_BACKGROUND_LIGHT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
case 'J':
|
||||
PurgeMode = 1;
|
||||
@@ -400,9 +423,21 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'p':
|
||||
case 'P':
|
||||
DoSimpleCalendar = 1;
|
||||
PsCal = 1;
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
PsCal = PSCAL_LEVEL1;
|
||||
while (*arg == 'a' || *arg == 'A' ||
|
||||
*arg == 'p' || *arg == 'P') {
|
||||
if (*arg == 'a' || *arg == 'A') {
|
||||
DoSimpleCalDelta = 1;
|
||||
} else if (*arg == 'p' || *arg == 'P') {
|
||||
/* JSON interchange formats always include
|
||||
file and line number info */
|
||||
DoPrefixLineNo = 1;
|
||||
if (PsCal == PSCAL_LEVEL1) {
|
||||
PsCal = PSCAL_LEVEL2;
|
||||
} else {
|
||||
PsCal = PSCAL_LEVEL3;
|
||||
}
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
PARSENUM(CalMonths, arg);
|
||||
@@ -418,7 +453,10 @@ void InitRemind(int argc, char const *argv[])
|
||||
case 'W':
|
||||
if (*arg != ',') {
|
||||
PARSENUM(CalWidth, arg);
|
||||
if (CalWidth < 71) CalWidth = 71;
|
||||
if (CalWidth != 0 && CalWidth < 71) CalWidth = 71;
|
||||
if (CalWidth == 0) {
|
||||
CalWidth = -1;
|
||||
}
|
||||
}
|
||||
if (*arg == ',') {
|
||||
arg++;
|
||||
@@ -599,7 +637,7 @@ void InitRemind(int argc, char const *argv[])
|
||||
#ifndef L_USAGE_OVERRIDE
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2019 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
@@ -607,6 +645,7 @@ void Usage(void)
|
||||
fprintf(ErrFp, "Options:\n");
|
||||
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
|
||||
fprintf(ErrFp, " -r Disable RUN directives\n");
|
||||
fprintf(ErrFp, " -@[n,m] Colorize COLOR reminders\n");
|
||||
fprintf(ErrFp, " -c[a][n] Produce a calendar for n (default 1) months\n");
|
||||
fprintf(ErrFp, " -c[a]+[n] Produce a calendar for n (default 1) weeks\n");
|
||||
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
|
||||
|
||||
1045
src/json.c
Normal file
280
src/json.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H
|
||||
#define _JSON_H
|
||||
|
||||
#ifndef json_char
|
||||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (* mem_alloc) (size_t, int zero, void * user_data);
|
||||
void (* mem_free) (void *, void * user_data);
|
||||
|
||||
void * user_data; /* will be passed to mem_alloc and mem_free */
|
||||
|
||||
size_t value_extra; /* how much extra space to allocate for values? */
|
||||
|
||||
} json_settings;
|
||||
|
||||
#define json_enable_comments 0x01
|
||||
|
||||
typedef enum
|
||||
{
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
|
||||
} json_type;
|
||||
|
||||
extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_object_entry
|
||||
{
|
||||
json_char * name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value * value;
|
||||
|
||||
} json_object_entry;
|
||||
|
||||
typedef struct _json_value
|
||||
{
|
||||
struct _json_value * parent;
|
||||
|
||||
json_type type;
|
||||
|
||||
union
|
||||
{
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
json_char * ptr; /* null terminated */
|
||||
|
||||
} string;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
json_object_entry * values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} object;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
struct _json_value ** values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} array;
|
||||
|
||||
} u;
|
||||
|
||||
union
|
||||
{
|
||||
struct _json_value * next_alloc;
|
||||
void * object_mem;
|
||||
|
||||
} _reserved;
|
||||
|
||||
#ifdef JSON_TRACK_SOURCE
|
||||
|
||||
/* Location of the value in the source JSON
|
||||
*/
|
||||
unsigned int line, col;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value ()
|
||||
{ memset (this, 0, sizeof (_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const
|
||||
{
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int) index) >= u.array.length)
|
||||
{
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
return *u.array.values [index];
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (const char * index) const
|
||||
{
|
||||
if (type != json_object)
|
||||
return json_value_none;
|
||||
|
||||
for (unsigned int i = 0; i < u.object.length; ++ i)
|
||||
if (!strcmp (u.object.values [i].name, index))
|
||||
return *u.object.values [i].value;
|
||||
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
inline operator const char * () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
|
||||
default:
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
inline operator json_int_t () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t) u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
inline operator bool () const
|
||||
{
|
||||
if (type != json_boolean)
|
||||
return false;
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return (double) u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} json_value;
|
||||
|
||||
json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
|
||||
void json_value_free (json_value *);
|
||||
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Header file for language support for various languages. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* Further corrections by Erik-Jan Vens */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the English language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993-1998 by Mikko Silvonen. */
|
||||
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -302,7 +302,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#elif IBMEXTENDED
|
||||
"Ok",
|
||||
@@ -407,7 +408,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#else
|
||||
"Ok",
|
||||
@@ -512,7 +514,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
|
||||
#endif
|
||||
@@ -524,7 +527,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1993 by Laurent Duperval and */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
@@ -242,7 +242,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
|
||||
#else /* ISOLATIN1 */
|
||||
"Ok",
|
||||
@@ -347,7 +348,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
@@ -357,7 +359,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* I don't speak German. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Support for the Icelandic language. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* Translated by Björn Davíðsson (bjossi@snerpa.is) */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* This file is part of REMIND. */
|
||||
/* It is Copyright (C) 1996 by Valerio Aimale */
|
||||
/* */
|
||||
/* Remind is copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Remind is copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* This file is Copyright (C) 1993 by Trygve Randen. */
|
||||
/* Remind is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Remind is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* Polish. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -281,7 +281,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#else /* ISOLATIN1 */
|
||||
"OK",
|
||||
"Brakujacy ']'",
|
||||
@@ -385,7 +386,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
#endif /* ISOLATIN1 */
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
@@ -395,7 +397,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996 by Marco Paganini and */
|
||||
/* Dianne Skoll. */
|
||||
/* */
|
||||
@@ -247,7 +247,8 @@ EXTERN char *ErrMsg[] =
|
||||
"Can't convert between time zones",
|
||||
"No files matching *.rem",
|
||||
"String too long",
|
||||
"Time specified twice"
|
||||
"Time specified twice",
|
||||
"Cannot specify DURATION without specifying AT"
|
||||
};
|
||||
#endif /* MK_GLOBALS */
|
||||
|
||||
@@ -256,7 +257,7 @@ EXTERN char *ErrMsg[] =
|
||||
#define L_USAGE_OVERRIDE 1
|
||||
void Usage(void)
|
||||
{
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2018 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
fprintf(ErrFp, "\nREMIND %s (versao %s) (C) 1992-2020 Dianne Skoll\n", VERSION, L_LANGNAME);
|
||||
#ifdef BETA
|
||||
fprintf(ErrFp, ">>>> VERSAO BETA <<<<\n");
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
!/***************************************************************/
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ROMANIAN.H */
|
||||
/* */
|
||||
@@ -8,7 +8,7 @@
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* */
|
||||
/* REMIND is Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* REMIND is Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* This file is Copyright (C) 1996-1998 by Liviu Daia */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* Author: Rafa Couto <rafacouto@biogate.com> */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
78
src/main.c
@@ -6,7 +6,7 @@
|
||||
/* routines, etc. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -63,14 +63,16 @@ int main(int argc, char *argv[])
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
ErrFp = stderr;
|
||||
|
||||
/* Set up global vars */
|
||||
/* Set up global vars */
|
||||
ArgC = argc;
|
||||
ArgV = (char const **) argv;
|
||||
|
||||
InitRemind(argc, (char const **) argv);
|
||||
ClearLastTriggers();
|
||||
|
||||
if (DoCalendar || (DoSimpleCalendar && (!NextMode || PsCal))) {
|
||||
ProduceCalendar();
|
||||
return 0;
|
||||
@@ -125,10 +127,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
if (Iterations) {
|
||||
ClearGlobalOmits();
|
||||
DestroyOmitContexts();
|
||||
DestroyVars(0);
|
||||
NumTriggered = 0;
|
||||
PerIterationInit();
|
||||
JulianToday++;
|
||||
}
|
||||
}
|
||||
@@ -146,6 +145,19 @@ void PurgeEchoLine(char const *fmt, ...)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
PerIterationInit(void)
|
||||
{
|
||||
ClearGlobalOmits();
|
||||
DestroyOmitContexts();
|
||||
DestroyVars(0);
|
||||
DefaultColorR = -1;
|
||||
DefaultColorG = -1;
|
||||
DefaultColorB = -1;
|
||||
NumTriggered = 0;
|
||||
ClearLastTriggers();
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoReminders */
|
||||
@@ -799,8 +811,13 @@ int DoIfTrig(ParsePtr p)
|
||||
else {
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &tim, &r, 1);
|
||||
if (r) {
|
||||
if (!Hush || r != E_RUN_DISABLED) {
|
||||
Eprint("%s", ErrMsg[r]);
|
||||
}
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
}
|
||||
else {
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
syndrome = IF_TRUE | BEFORE_ELSE;
|
||||
@@ -1322,3 +1339,46 @@ FreeTrig(Trigger *t)
|
||||
{
|
||||
DBufFree(&(t->tags));
|
||||
}
|
||||
|
||||
void
|
||||
ClearLastTriggers(void)
|
||||
{
|
||||
LastTrigger.expired = 0;
|
||||
LastTrigger.wd = NO_WD;
|
||||
LastTrigger.d = NO_DAY;
|
||||
LastTrigger.m = NO_MON;
|
||||
LastTrigger.y = NO_YR;
|
||||
LastTrigger.back = NO_BACK;
|
||||
LastTrigger.delta = NO_DELTA;
|
||||
LastTrigger.rep = NO_REP;
|
||||
LastTrigger.localomit = NO_WD;
|
||||
LastTrigger.skip = NO_SKIP;
|
||||
LastTrigger.until = NO_UNTIL;
|
||||
LastTrigger.typ = NO_TYPE;
|
||||
LastTrigger.once = NO_ONCE;
|
||||
LastTrigger.scanfrom = NO_DATE;
|
||||
LastTrigger.from = NO_DATE;
|
||||
LastTrigger.priority = DefaultPrio;
|
||||
LastTrigger.sched[0] = 0;
|
||||
LastTrigger.warn[0] = 0;
|
||||
LastTrigger.omitfunc[0] = 0;
|
||||
LastTrigger.passthru[0] = 0;
|
||||
|
||||
LastTimeTrig.ttime = NO_TIME;
|
||||
LastTimeTrig.delta = NO_DELTA;
|
||||
LastTimeTrig.rep = NO_REP;
|
||||
LastTimeTrig.duration = NO_TIME;
|
||||
}
|
||||
|
||||
void
|
||||
SaveLastTrigger(Trigger const *t)
|
||||
{
|
||||
memcpy(&LastTrigger, t, sizeof(LastTrigger));
|
||||
DBufInit(&(LastTrigger.tags));
|
||||
}
|
||||
|
||||
void
|
||||
SaveLastTimeTrig(TimeTrig const *t)
|
||||
{
|
||||
memcpy(&LastTimeTrig, t, sizeof(LastTimeTrig));
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Calculations for figuring out moon phases. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* the data structures for OMITted dates. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
15
src/protos.h
@@ -5,7 +5,7 @@
|
||||
/* Function Prototypes. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -88,7 +88,10 @@ void HandleQueuedReminders (void);
|
||||
char const *FindInitialToken (Token *tok, char const *s);
|
||||
void FindToken (char const *s, Token *tok);
|
||||
void FindNumericToken (char const *s, Token *t);
|
||||
int ComputeTrigger (int today, Trigger *trig, int *err, int save_in_globals);
|
||||
int ComputeTrigger (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
||||
int ComputeTriggerNoAdjustDuration (int today, Trigger *trig, TimeTrig *tim, int *err, int save_in_globals);
|
||||
int AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals);
|
||||
int ComputeScanStart(int today, Trigger *trig, TimeTrig *tt);
|
||||
char *StrnCpy (char *dest, char const *source, int n);
|
||||
int StrMatch (char const *s1, char const *s2, int n);
|
||||
int StrinCmp (char const *s1, char const *s2, int n);
|
||||
@@ -105,7 +108,7 @@ void DumpVarTable (void);
|
||||
void DestroyVars (int all);
|
||||
int PreserveVar (char const *name);
|
||||
int DoPreserve (Parser *p);
|
||||
int DoSatRemind (Trigger *trig, ParsePtr p);
|
||||
int DoSatRemind (Trigger *trig, TimeTrig *tt, ParsePtr p);
|
||||
int DoMsgCommand (char const *cmd, char const *msg);
|
||||
int ParseNonSpaceChar (ParsePtr p, int *err, int peek);
|
||||
unsigned int HashVal (char const *str);
|
||||
@@ -142,3 +145,9 @@ void PurgeEchoLine(char const *fmt, ...);
|
||||
void FreeTrig(Trigger *t);
|
||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||
char const *SynthesizeTag(void);
|
||||
void ClearLastTriggers(void);
|
||||
void SaveLastTrigger(Trigger const *t);
|
||||
void SaveLastTimeTrig(TimeTrig const *t);
|
||||
void PerIterationInit(void);
|
||||
char const *Decolorize(int r, int g, int b);
|
||||
char const *Colorize(int r, int g, int b);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Queue up reminders for subsequent execution. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "globals.h"
|
||||
#include "err.h"
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
|
||||
@@ -43,6 +43,7 @@ typedef struct queuedrem {
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
char sched[VAR_NAME_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
Trigger t;
|
||||
TimeTrig tt;
|
||||
} QueuedRem;
|
||||
|
||||
@@ -91,6 +92,8 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->typ = trig->typ;
|
||||
strcpy(qelem->passthru, trig->passthru);
|
||||
qelem->tt = *tim;
|
||||
qelem->t = *trig;
|
||||
DBufInit(&(qelem->t.tags));
|
||||
qelem->next = QueueHead;
|
||||
qelem->RunDisabled = RunDisabled;
|
||||
qelem->ntrig = 0;
|
||||
@@ -246,6 +249,8 @@ void HandleQueuedReminders(void)
|
||||
LastTriggerDate = JulianToday;
|
||||
LastTriggerTime = q->tt.ttime;
|
||||
LastTrigValid = 1;
|
||||
SaveLastTrigger(&(q->t));
|
||||
SaveLastTimeTrig(&(q->tt));
|
||||
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
|
||||
if (Daemon < 0) {
|
||||
printf("NOTE endreminder\n");
|
||||
|
||||
286
src/rem2ps.c
@@ -5,7 +5,7 @@
|
||||
/* Print a PostScript calendar. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "rem2ps.h"
|
||||
#include "json.h"
|
||||
|
||||
#define NEW(type) (malloc(sizeof(type)))
|
||||
|
||||
@@ -30,6 +31,7 @@
|
||||
#define SPECIAL_COLOR 4
|
||||
#define SPECIAL_WEEK 5
|
||||
#define SPECIAL_SHADE 6
|
||||
#define SPECIAL_UNKNOWN 7
|
||||
|
||||
/* Array holding how specials sort */
|
||||
static int SpecialSortOrder[] = {
|
||||
@@ -46,6 +48,7 @@ typedef struct calentry {
|
||||
struct calentry *next;
|
||||
int special;
|
||||
char *entry;
|
||||
int daynum;
|
||||
} CalEntry;
|
||||
|
||||
typedef struct {
|
||||
@@ -137,6 +140,172 @@ void WriteOneEntry (CalEntry *c);
|
||||
void GetSmallLocations (void);
|
||||
char const *EatToken(char const *in, char *out, int maxlen);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* StrCmpi */
|
||||
/* */
|
||||
/* Compare strings, case insensitive. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int StrCmpi(char const *s1, char const *s2)
|
||||
{
|
||||
int r;
|
||||
while (*s1 && *s2) {
|
||||
r = toupper(*s1) - toupper(*s2);
|
||||
if (r) return r;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return toupper(*s1) - toupper(*s2);
|
||||
}
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* Parse the new-style JSON intermediate format */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static CalEntry *
|
||||
JSONToCalEntry(DynamicBuffer *buf)
|
||||
{
|
||||
CalEntry *c;
|
||||
json_value *val;
|
||||
|
||||
val = json_parse(DBufValue(buf), DBufLen(buf));
|
||||
if (!val) {
|
||||
fprintf(stderr, "Unable to parse JSON line `%s'\n", DBufValue(buf));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (val->type != json_object) {
|
||||
fprintf(stderr, "Expecting JSON object; found `%s'\n",
|
||||
DBufValue(buf));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
c = NEW(CalEntry);
|
||||
if (!c) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
c->next = NULL;
|
||||
c->special = SPECIAL_NORMAL;
|
||||
|
||||
int got_date = 0, got_body = 0;
|
||||
size_t i;
|
||||
for (i=0; i<val->u.object.length; i++) {
|
||||
char const *nm = val->u.object.values[i].name;
|
||||
json_value *v = val->u.object.values[i].value;
|
||||
char const *s;
|
||||
if (!strcmp(nm, "date")) {
|
||||
if (v->type == json_string) {
|
||||
s = v->u.string.ptr;
|
||||
c->daynum = (s[8] - '0') * 10 + s[9] - '0';
|
||||
got_date = 1;
|
||||
}
|
||||
} else if (!strcmp(nm, "body")) {
|
||||
if (v->type == json_string) {
|
||||
s = v->u.string.ptr;
|
||||
c->entry = malloc(strlen(s)+1);
|
||||
if (!c->entry) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy(c->entry, s);
|
||||
got_body = 1;
|
||||
}
|
||||
} else if (!strcmp(nm, "passthru")) {
|
||||
if (v->type == json_string) {
|
||||
s = v->u.string.ptr;
|
||||
if (!StrCmpi(s, "PostScript")) {
|
||||
c->special = SPECIAL_POSTSCRIPT;
|
||||
} else if (!StrCmpi(s, "SHADE")) {
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!StrCmpi(s, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!StrCmpi(s, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else if (!StrCmpi(s, "PSFile")) {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
} else if (!StrCmpi(s, "COLOUR") ||
|
||||
!StrCmpi(s, "COLOR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
} else {
|
||||
c->special = SPECIAL_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json_value_free(val);
|
||||
|
||||
if (!got_body || !got_date) {
|
||||
fprintf(stderr, "Could not parse line `%s'\n", DBufValue(buf));
|
||||
exit(1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* Parse the old-style REM2PS intermediate format */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static CalEntry *
|
||||
TextToCalEntry(DynamicBuffer *buf)
|
||||
{
|
||||
char const *startOfBody;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
|
||||
CalEntry *c = NEW(CalEntry);
|
||||
if (!c) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
c->next = NULL;
|
||||
c->special = SPECIAL_NORMAL;
|
||||
c->daynum = (DBufValue(buf)[8] - '0') * 10 + DBufValue(buf)[9] - '0';
|
||||
|
||||
/* Skip the tag, duration and time */
|
||||
startOfBody = DBufValue(buf)+10;
|
||||
|
||||
/* Eat the passthru */
|
||||
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
|
||||
|
||||
/* Eat the tag */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
/* Eat the duration */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
/* Eat the time */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
c->entry = malloc(strlen(startOfBody) + 1);
|
||||
if (!c->entry) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy(c->entry, startOfBody);
|
||||
|
||||
/* Save the type of SPECIAL */
|
||||
if (!StrCmpi(passthru, "PostScript")) {
|
||||
c->special = SPECIAL_POSTSCRIPT;
|
||||
} else if (!StrCmpi(passthru, "SHADE")) {
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!StrCmpi(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!StrCmpi(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
} else if (!StrCmpi(passthru, "PSFile")) {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
} else if (!StrCmpi(passthru, "COLOUR") ||
|
||||
!StrCmpi(passthru, "COLOR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
} else if (StrCmpi(passthru, "*")) {
|
||||
c->special = SPECIAL_UNKNOWN;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* MAIN PROGRAM */
|
||||
@@ -154,13 +323,20 @@ int main(int argc, char *argv[])
|
||||
Usage("Input should not come from a terminal");
|
||||
}
|
||||
|
||||
int first_line = 1;
|
||||
/* Search for a valid input file */
|
||||
while (!feof(stdin)) {
|
||||
DBufGets(&buf, stdin);
|
||||
if (!strcmp(DBufValue(&buf), PSBEGIN)) {
|
||||
if (first_line && (!strcmp(DBufValue(&buf), "["))) {
|
||||
fprintf(stderr, "Rem2PS: It appears that you have invoked Remind with the -ppp option.\n Please use either -p or -pp, but not -ppp.\n");
|
||||
exit(1);
|
||||
}
|
||||
first_line = 0;
|
||||
if (!strcmp(DBufValue(&buf), PSBEGIN) ||
|
||||
!strcmp(DBufValue(&buf), PSBEGIN2)) {
|
||||
if (!validfile) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-1998 by Dianne Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-2020 by Dianne Skoll\n\n", VERSION);
|
||||
fprintf(stderr, "Generating PostScript calendar\n");
|
||||
}
|
||||
}
|
||||
@@ -191,10 +367,7 @@ void DoPsCal(void)
|
||||
int days, wkday, prevdays, nextdays;
|
||||
int sfirst;
|
||||
int i;
|
||||
int is_ps;
|
||||
int firstcol;
|
||||
char const *startOfBody;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
DynamicBuffer buf;
|
||||
CalEntry *c, *d, *p;
|
||||
|
||||
@@ -230,6 +403,7 @@ void DoPsCal(void)
|
||||
|
||||
printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2],
|
||||
year[2], year[3], validfile);
|
||||
printf("%%%%PageBoundingBox: 0 0 %d %d\n", CurPage->xsize, CurPage->ysize);
|
||||
|
||||
/* Emit PostScript to do the heading */
|
||||
if (!PortraitMode) printf("90 rotate 0 XSIZE neg translate\n");
|
||||
@@ -272,80 +446,48 @@ void DoPsCal(void)
|
||||
}
|
||||
|
||||
DBufGets(&buf, stdin);
|
||||
if (!strcmp(DBufValue(&buf), PSEND)) {
|
||||
if (!strcmp(DBufValue(&buf), PSEND) ||
|
||||
!strcmp(DBufValue(&buf), PSEND2)) {
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ignore lines beginning with '#' */
|
||||
if (DBufValue(&buf)[0] == '#') {
|
||||
DBufFree(&buf);
|
||||
continue;
|
||||
}
|
||||
/* Read the day number - a bit of a hack! */
|
||||
DayNum = (DBufValue(&buf)[8] - '0') * 10 + DBufValue(&buf)[9] - '0';
|
||||
if (DayNum != CurDay) {
|
||||
for(; CurDay<DayNum; CurDay++) {
|
||||
|
||||
if (DBufValue(&buf)[0] == '{') {
|
||||
/* Starts with '{', so assume new-style JSON format */
|
||||
c = JSONToCalEntry(&buf);
|
||||
} else {
|
||||
/* Assume it's the old-style rem2ps intermediate format */
|
||||
c = TextToCalEntry(&buf);
|
||||
}
|
||||
|
||||
/* If it's an unknown special, ignore */
|
||||
if (c->special == SPECIAL_UNKNOWN) {
|
||||
DBufFree(&buf);
|
||||
free(c);
|
||||
c = NULL;
|
||||
continue;
|
||||
}
|
||||
if (c->daynum != CurDay) {
|
||||
for(; CurDay<c->daynum; CurDay++) {
|
||||
WriteCalEntry();
|
||||
WkDayNum = (WkDayNum + 1) % 7;
|
||||
}
|
||||
}
|
||||
/* Add the text */
|
||||
c = NEW(CalEntry);
|
||||
if (!c) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
c->next = NULL;
|
||||
c->special = SPECIAL_NORMAL;
|
||||
|
||||
/* Skip the tag, duration and time */
|
||||
startOfBody = DBufValue(&buf)+10;
|
||||
|
||||
/* Eat the passthru */
|
||||
startOfBody = EatToken(startOfBody, passthru, PASSTHRU_LEN);
|
||||
|
||||
/* Eat the tag */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
/* Eat the duration */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
/* Eat the time */
|
||||
startOfBody = EatToken(startOfBody, NULL, 0);
|
||||
|
||||
is_ps = 0;
|
||||
if (!strcmp(passthru, "PostScript") ||
|
||||
!strcmp(passthru, "PSFile") ||
|
||||
!strcmp(passthru, "MOON") ||
|
||||
!strcmp(passthru, "WEEK") ||
|
||||
!strcmp(passthru, "SHADE")) {
|
||||
is_ps = 1;
|
||||
}
|
||||
c->entry = malloc(strlen(startOfBody) + 1);
|
||||
if (!c->entry) {
|
||||
fprintf(stderr, "malloc failed - aborting.\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy(c->entry, startOfBody);
|
||||
|
||||
if (is_ps) {
|
||||
/* Save the type of SPECIAL */
|
||||
if (!strcmp(passthru, "PostScript")) {
|
||||
c->special = SPECIAL_POSTSCRIPT;
|
||||
} else if (!strcmp(passthru, "SHADE")) {
|
||||
c->special = SPECIAL_SHADE;
|
||||
} else if (!strcmp(passthru, "MOON")) {
|
||||
c->special = SPECIAL_MOON;
|
||||
} else if (!strcmp(passthru, "WEEK")) {
|
||||
c->special = SPECIAL_WEEK;
|
||||
if (c->special == SPECIAL_POSTSCRIPT ||
|
||||
c->special == SPECIAL_SHADE ||
|
||||
c->special == SPECIAL_MOON ||
|
||||
c->special == SPECIAL_WEEK ||
|
||||
c->special == SPECIAL_PSFILE) {
|
||||
if (!PsEntries[c->daynum]) {
|
||||
PsEntries[c->daynum] = c;
|
||||
} else {
|
||||
c->special = SPECIAL_PSFILE;
|
||||
}
|
||||
|
||||
if (!PsEntries[DayNum]) {
|
||||
PsEntries[DayNum] = c;
|
||||
} else {
|
||||
d = PsEntries[DayNum];
|
||||
d = PsEntries[c->daynum];
|
||||
p = NULL;
|
||||
/* Slot it into the right place */
|
||||
while (d->next && (SpecialSortOrder[c->special] <= SpecialSortOrder[d->special])) {
|
||||
@@ -359,14 +501,12 @@ void DoPsCal(void)
|
||||
if (p) {
|
||||
p->next = c;
|
||||
} else {
|
||||
PsEntries[DayNum] = c;
|
||||
PsEntries[c->daynum] = c;
|
||||
}
|
||||
c->next = d;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(passthru, "*") ||
|
||||
!strcmp(passthru, "COLOUR") ||
|
||||
!strcmp(passthru, "COLOR")) {
|
||||
} else {
|
||||
/* Put on linked list */
|
||||
if (!CurEntries) {
|
||||
CurEntries = c;
|
||||
@@ -375,10 +515,6 @@ void DoPsCal(void)
|
||||
while(d->next) d = d->next;
|
||||
d->next = c;
|
||||
}
|
||||
if (!strcmp(passthru, "COLOR") ||
|
||||
!strcmp(passthru, "COLOUR")) {
|
||||
c->special = SPECIAL_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(; CurDay<=days; CurDay++) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Define the PostScript prologue */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -13,7 +13,7 @@ char *PSProlog1[] =
|
||||
{
|
||||
"% This file was produced by Remind and Rem2PS, written by",
|
||||
"% Dianne Skoll.",
|
||||
"% Remind and Rem2PS are Copyright 1992-1997 Dianne Skoll.",
|
||||
"% Remind and Rem2PS are Copyright 1992-2020 Dianne Skoll.",
|
||||
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
|
||||
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
|
||||
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Routines for sorting reminders by trigger date */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
12
src/token.c
@@ -6,7 +6,7 @@
|
||||
/* classifying the tokens parsed. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -228,11 +228,11 @@ void FindToken(char const *s, Token *tok)
|
||||
/* If language is other than English, search the DayNames[] and MonthNames[]
|
||||
array. */
|
||||
#if LANG != ENGLISH
|
||||
for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
|
||||
if (l >= NonEnglishToks[r].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[r], s)) {
|
||||
tok->type = NonEnglishToks[r].type;
|
||||
tok->val = NonEnglishToks[r].val;
|
||||
for (size_t x=0; x<(sizeof(NonEnglishToks) / sizeof(Token)); x++) {
|
||||
if (l >= NonEnglishToks[x].MinLen &&
|
||||
!TokStrCmp(&NonEnglishToks[x], s)) {
|
||||
tok->type = NonEnglishToks[x].type;
|
||||
tok->val = NonEnglishToks[x].val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
155
src/trigger.c
@@ -5,7 +5,7 @@
|
||||
/* Routines for figuring out the trigger date of a reminder */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -408,6 +408,61 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
return simple;
|
||||
}
|
||||
|
||||
int
|
||||
AdjustTriggerForDuration(int today, int r, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
{
|
||||
int y, m, d;
|
||||
/* If we have an AT, save the original event start */
|
||||
if (tim->ttime != NO_TIME) {
|
||||
trig->eventstart = MINUTES_PER_DAY * r + tim->ttime;
|
||||
if (tim->duration != NO_TIME) {
|
||||
trig->eventduration = tim->duration;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now potentially adjust */
|
||||
if (r < today && r + trig->duration_days >= today) {
|
||||
/* Adjust duration down */
|
||||
tim->duration -= (today - r) * MINUTES_PER_DAY;
|
||||
tim->duration += tim->ttime;
|
||||
|
||||
/* Start at midnight */
|
||||
tim->ttime = 0;
|
||||
|
||||
/* Change trigger date to today */
|
||||
r = today;
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(r, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig(adj) = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[r % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tim->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tim->ttime / 60),
|
||||
(tim->ttime % 60));
|
||||
if (tim->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tim->duration / 60),
|
||||
(tim->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
if (save_in_globals) {
|
||||
LastTriggerTime = tim->ttime;
|
||||
SaveLastTimeTrig(tim);
|
||||
SaveLastTrigger(trig);
|
||||
LastTriggerDate = r;
|
||||
LastTrigValid = 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeTrigger */
|
||||
@@ -416,10 +471,30 @@ static int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart
|
||||
/* today's date. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
int ComputeTrigger(int today, Trigger *trig, TimeTrig *tim,
|
||||
int *err, int save_in_globals)
|
||||
{
|
||||
int r = ComputeTriggerNoAdjustDuration(today, trig, tim, err, save_in_globals);
|
||||
if (*err != OK) {
|
||||
return r;
|
||||
}
|
||||
r = AdjustTriggerForDuration(today, r, trig, tim, save_in_globals);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeTriggerNoAdjustDuration */
|
||||
/* */
|
||||
/* Compute a trigger, but do NOT adjust the time trigger */
|
||||
/* duration. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig *tim,
|
||||
int *err, int save_in_globals)
|
||||
{
|
||||
int nattempts = 0,
|
||||
start = today,
|
||||
start = today - trig->duration_days,
|
||||
nextstart = 0,
|
||||
y, m, d, omit,
|
||||
result;
|
||||
@@ -429,15 +504,25 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
LastTrigValid = 0;
|
||||
}
|
||||
|
||||
/* Assume everything works */
|
||||
/* Assume everything works */
|
||||
*err = OK;
|
||||
|
||||
/* But check for obvious problems... */
|
||||
/* But check for obvious problems... */
|
||||
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
|
||||
*err = E_2MANY_LOCALOMIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
*err = E_DATE_OVER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tim->duration != NO_TIME && tim->ttime == NO_TIME) {
|
||||
*err = E_DURATION_NO_AT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (trig->rep != NO_REP &&
|
||||
(trig->d == NO_DAY ||
|
||||
trig->m == NO_MON ||
|
||||
@@ -448,6 +533,11 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
}
|
||||
|
||||
|
||||
/* Save the trigger */
|
||||
if (save_in_globals) {
|
||||
SaveLastTrigger(trig);
|
||||
}
|
||||
|
||||
while (nattempts++ < TRIG_ATTEMPTS) {
|
||||
result = GetNextTriggerDate(trig, start, err, &nextstart);
|
||||
|
||||
@@ -469,7 +559,9 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
} else {
|
||||
omit = 0;
|
||||
}
|
||||
if (result >= today &&
|
||||
|
||||
/** FIXME: Fix bad interaction with SATISFY... need to rethink!!! */
|
||||
if (result+trig->duration_days >= today &&
|
||||
(trig->skip != SKIP_SKIP || !omit)) {
|
||||
if (save_in_globals) {
|
||||
LastTriggerDate = result; /* Save in global var */
|
||||
@@ -477,12 +569,23 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
}
|
||||
if (DebugFlag & DB_PRTTRIG) {
|
||||
FromJulian(result, &y, &m, &d);
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
|
||||
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d",
|
||||
FileName, LineNo,
|
||||
DayName[result % 7],
|
||||
d,
|
||||
MonthName[m],
|
||||
y);
|
||||
if (tim->ttime != NO_TIME) {
|
||||
fprintf(ErrFp, " AT %02d:%02d",
|
||||
(tim->ttime / 60),
|
||||
(tim->ttime % 60));
|
||||
if (tim->duration != NO_TIME) {
|
||||
fprintf(ErrFp, " DURATION %02d:%02d",
|
||||
(tim->duration / 60),
|
||||
(tim->duration % 60));
|
||||
}
|
||||
}
|
||||
fprintf(ErrFp, "\n");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -535,3 +638,41 @@ int ComputeTrigger(int today, Trigger *trig, int *err, int save_in_globals)
|
||||
*err = E_CANT_TRIG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* ComputeScanStart */
|
||||
/* */
|
||||
/* Figure out where to start scan from by examining SCANFROM */
|
||||
/* and DURATION */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
int
|
||||
ComputeScanStart(int today, Trigger *trig, TimeTrig *tt)
|
||||
{
|
||||
int minutes, days;
|
||||
|
||||
/* If we don't have a time/duration, just use scanfrom */
|
||||
if (tt->ttime == NO_TIME ||
|
||||
tt->duration == NO_TIME) {
|
||||
if (trig->scanfrom == NO_DATE) {
|
||||
return today;
|
||||
}
|
||||
return trig->scanfrom;
|
||||
}
|
||||
|
||||
/* Calculate time-based SCANFROM */
|
||||
minutes = tt->ttime + tt->duration - 1;
|
||||
|
||||
/* Figure out how many days to scan backwards from */
|
||||
days = minutes / MINUTES_PER_DAY;
|
||||
|
||||
if (trig->scanfrom != NO_DATE) {
|
||||
if (trig->scanfrom <= today - days) {
|
||||
return trig->scanfrom;
|
||||
} else {
|
||||
return today - days;
|
||||
}
|
||||
}
|
||||
return today - days;
|
||||
}
|
||||
|
||||
31
src/types.h
@@ -5,7 +5,7 @@
|
||||
/* Type definitions all dumped here. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -68,7 +68,11 @@ typedef struct {
|
||||
int typ;
|
||||
int once;
|
||||
int scanfrom;
|
||||
int from;
|
||||
int priority;
|
||||
int duration_days; /* Duration converted to days to search */
|
||||
int eventstart; /* Original event start (datetime) */
|
||||
int eventduration; /* Original event duration (minutes) */
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
@@ -87,16 +91,16 @@ typedef struct {
|
||||
|
||||
/* The parse pointer */
|
||||
typedef struct {
|
||||
char isnested; /* Is it a nested expression? */
|
||||
char allownested;
|
||||
DynamicBuffer pushedToken; /* Pushed-back token */
|
||||
char const *text; /* Start of text */
|
||||
char const *pos; /* Current position */
|
||||
char const *etext; /* Substituted text */
|
||||
char const *epos; /* Position in substituted text */
|
||||
DynamicBuffer pushedToken; /* Pushed-back token */
|
||||
char const *tokenPushed; /* NULL if no pushed-back token */
|
||||
char expr_happened; /* Did we encounter an [expression] ? */
|
||||
char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
|
||||
unsigned char isnested; /* Is it a nested expression? */
|
||||
unsigned char allownested;
|
||||
unsigned char expr_happened; /* Did we encounter an [expression] ? */
|
||||
unsigned char nonconst_expr; /* Did we encounter a non-constant [expression] ? */
|
||||
} Parser;
|
||||
|
||||
typedef Parser *ParsePtr; /* Pointer to parser structure */
|
||||
@@ -212,3 +216,18 @@ typedef struct {
|
||||
/* Flags for FROM / SCANFROM */
|
||||
#define SCANFROM_TYPE 0
|
||||
#define FROM_TYPE 1
|
||||
|
||||
/* PS Calendar levels */
|
||||
|
||||
/* Original interchange format */
|
||||
#define PSCAL_LEVEL1 1
|
||||
|
||||
/* Line-by-line JSON */
|
||||
#define PSCAL_LEVEL2 2
|
||||
|
||||
/* Pure JSON */
|
||||
#define PSCAL_LEVEL3 3
|
||||
|
||||
#define TERMINAL_BACKGROUND_UNKNOWN 0
|
||||
#define TERMINAL_BACKGROUND_DARK 1
|
||||
#define TERMINAL_BACKGROUND_LIGHT 2
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -64,6 +64,7 @@ int DoFset(ParsePtr p)
|
||||
int c;
|
||||
UserFunc *func;
|
||||
Var *v;
|
||||
int orig_namelen;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
@@ -74,6 +75,7 @@ int DoFset(ParsePtr p)
|
||||
DBufFree(&buf);
|
||||
return E_BAD_ID;
|
||||
}
|
||||
orig_namelen = buf.len;
|
||||
|
||||
/* Should be followed by '(' */
|
||||
c = ParseNonSpaceChar(p, &r, 0);
|
||||
@@ -164,6 +166,10 @@ int DoFset(ParsePtr p)
|
||||
|
||||
/* Add the function definition */
|
||||
FSet(func);
|
||||
if (orig_namelen > VAR_NAME_LEN) {
|
||||
Eprint("Warning: Function name `%s...' truncated to `%s'",
|
||||
func->name, func->name);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/* Useful utility functions. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
46
src/var.c
@@ -6,7 +6,7 @@
|
||||
/* user- and system-defined variables. */
|
||||
/* */
|
||||
/* This file is part of REMIND. */
|
||||
/* Copyright (C) 1992-2018 by Dianne Skoll */
|
||||
/* Copyright (C) 1992-2020 by Dianne Skoll */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
@@ -168,6 +168,45 @@ static int datetime_sep_func(int do_set, Value *val)
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int default_color_func(int do_set, Value *val)
|
||||
{
|
||||
int col_r, col_g, col_b;
|
||||
if (!do_set) {
|
||||
/* 12 = strlen("255 255 255\0") */
|
||||
val->v.str = malloc(12);
|
||||
if (!val->v.str) return E_NO_MEM;
|
||||
snprintf(val->v.str, 12, "%d %d %d",
|
||||
DefaultColorR,
|
||||
DefaultColorG,
|
||||
DefaultColorB
|
||||
);
|
||||
val->type = STR_TYPE;
|
||||
return OK;
|
||||
}
|
||||
if (val->type != STR_TYPE) return E_BAD_TYPE;
|
||||
if (sscanf(val->v.str, "%d %d %d", &col_r, &col_g, &col_b) != 3) {
|
||||
return E_BAD_TYPE;
|
||||
}
|
||||
/* They either all have to be -1, or all between 0 and 255 */
|
||||
if (col_r == -1 && col_g == -1 && col_b == -1) {
|
||||
DefaultColorR = -1;
|
||||
DefaultColorG = -1;
|
||||
DefaultColorB = -1;
|
||||
return OK;
|
||||
}
|
||||
if (col_r < 0) return E_2LOW;
|
||||
if (col_r > 255) return E_2HIGH;
|
||||
if (col_g < 0) return E_2LOW;
|
||||
if (col_g > 255) return E_2HIGH;
|
||||
if (col_b < 0) return E_2LOW;
|
||||
if (col_b > 255) return E_2HIGH;
|
||||
|
||||
DefaultColorR = col_r;
|
||||
DefaultColorG = col_g;
|
||||
DefaultColorB = col_b;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int date_sep_func(int do_set, Value *val)
|
||||
{
|
||||
if (!do_set) {
|
||||
@@ -370,6 +409,10 @@ int DoSet (Parser *p)
|
||||
|
||||
if (*DBufValue(&buf) == '$') r = SetSysVar(DBufValue(&buf)+1, &v);
|
||||
else r = SetVar(DBufValue(&buf), &v);
|
||||
if (buf.len > VAR_NAME_LEN) {
|
||||
Eprint("Warning: Variable name `%.*s...' truncated to `%.*s'",
|
||||
VAR_NAME_LEN, DBufValue(&buf), VAR_NAME_LEN, DBufValue(&buf));
|
||||
}
|
||||
DBufFree(&buf);
|
||||
return r;
|
||||
}
|
||||
@@ -604,6 +647,7 @@ static SysVar SysVarArr[] = {
|
||||
{"Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
|
||||
{"DateSep", 1, SPECIAL_TYPE, date_sep_func, 0, 0 },
|
||||
{"DateTimeSep", 1, SPECIAL_TYPE, datetime_sep_func, 0, 0 },
|
||||
{"DefaultColor", 1, SPECIAL_TYPE, default_color_func, 0, 0 },
|
||||
{"DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999},
|
||||
{"DeltaOffset", 0, INT_TYPE, &DeltaOffset, 0, 0 },
|
||||
{"DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
cd /home/dfs/Software/Remind.git || exit 1
|
||||
|
||||
rm -f .git/COMMIT_EDITMSG
|
||||
rm -f .git/COMMIT_EDITMSG .git/*~
|
||||
|
||||
git update-server-info && cd .git && rsync --archive --verbose --progress --delete ./ dianne.skoll.ca:web/projects/remind/git/Remind.git/
|
||||
exit $?
|
||||
|
||||
@@ -28,3 +28,5 @@ REM Fri SPECIAL SHADE 255 204 204
|
||||
REM Sat SPECIAL SHADE 204 255 204
|
||||
REM Sun SPECIAL SHADE 204 204 255
|
||||
|
||||
# This should be ignored by rem2ps
|
||||
REM SPECIAL HTML <b>FOO</b>
|
||||
|
||||
189
tests/test-rem
@@ -79,6 +79,7 @@ rm -f ../tests/purge_dir/*.rem.purged >> ../tests/test.out 2>&1
|
||||
../src/remind ../tests/runtest.rem >> ../tests/test.out 2>&1
|
||||
|
||||
../src/remind -p ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
|
||||
../src/remind -pp ../tests/shade.rem 1 August 2009 | ../src/rem2ps -e -l -c3 >> ../tests/test.out 2>&1
|
||||
|
||||
# The sun tests can fail due to math roundoff error changing the times
|
||||
# by a minute...
|
||||
@@ -99,6 +100,194 @@ REM 1 Jan 2012 AT 10:00 MSG 10am: Should show up
|
||||
MSG [$DontTrigAts]
|
||||
EOF
|
||||
|
||||
# An OMITFUNC should indicate nonconst_expr
|
||||
../src/remind -pp - 1 jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
|
||||
REM Mon OMITFUNC foo MSG bar
|
||||
EOF
|
||||
|
||||
# Test default color
|
||||
../src/remind -ppp - 1 Jan 2012 9:00 <<'EOF' >> ../tests/test.out 2>&1
|
||||
REM 2 MSG Normal
|
||||
SET $DefaultColor "255 0 0"
|
||||
REM 3 MSG Red
|
||||
SET $DefaultColor "-1 -1 -1"
|
||||
REM 4 MSG Normal
|
||||
# Should give an error
|
||||
SET $DefaultColor "256 0 0"
|
||||
EOF
|
||||
|
||||
# Test -@ option
|
||||
../src/remind -w,0,0 -@0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@0
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@0,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@0,0
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@0,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@0,1
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@1
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@1,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@1,0
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@1,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@1,1
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@2 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@2
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@2,0 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@2,0
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
../src/remind -w,0,0 -@2,1 -c - 1 Jan 2020 <<'EOF' >> ../tests/test.out 2>&1
|
||||
rem 1 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 2 SPECIAL COLOR 0 0 65 BLUE
|
||||
rem 3 SPECIAL COLOR 0 65 0 GREEN
|
||||
rem 4 SPECIAL COLOR 0 65 65 CYAN
|
||||
rem 5 msg -@2,1
|
||||
rem 15 SPECIAL COLOR 65 0 0 RED
|
||||
rem 16 SPECIAL COLOR 65 0 65 MAGENTA
|
||||
rem 17 SPECIAL COLOR 65 65 0 YELLOW
|
||||
rem 18 SPECIAL COLOR 65 65 65 WHITE
|
||||
rem 8 SPECIAL COLOR 0 0 0 BLACK
|
||||
rem 9 SPECIAL COLOR 0 0 200 BRIGHT BLUE
|
||||
rem 10 SPECIAL COLOR 0 200 0 BRIGHT GREEN
|
||||
rem 11 SPECIAL COLOR 0 200 200 BRIGHT CYAN
|
||||
rem 22 SPECIAL COLOR 200 0 0 BRIGHT RED
|
||||
rem 23 SPECIAL COLOR 200 0 200 BRIGHT MAGENTA
|
||||
rem 24 SPECIAL COLOR 200 200 0 BRIGHT YELLOW
|
||||
rem 25 SPECIAL COLOR 200 200 200 BRIGHT WHITE
|
||||
EOF
|
||||
|
||||
cmp -s ../tests/test.out ../tests/test.cmp
|
||||
if [ "$?" = "0" ]; then
|
||||
|
||||
1686
tests/test.cmp
@@ -313,6 +313,69 @@ set a082 slide('1991-03-01', 7, "Sat", "Sun")
|
||||
set a083 slide('1991-04-01', -7, "Sat")
|
||||
set a084 nonomitted('1991-03-01', '1991-03-13', "Sat", "Sun")
|
||||
set a085 nonomitted('1991-03-24', '1991-04-01', "Sat")
|
||||
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 MSG foo
|
||||
set a086 trigback()
|
||||
set a087 trigdelta()
|
||||
set a088 trigrep()
|
||||
set a089 triguntil()
|
||||
set a090 trigscanfrom()
|
||||
set a091 trigfrom()
|
||||
set a092 trigpriority()
|
||||
set a093 trigtimedelta()
|
||||
set a094 trigtimerep()
|
||||
set a095 trigduration()
|
||||
|
||||
REM Mon Wed FROM 2010-09-03 ++3 --4 MSG foo
|
||||
set a096 trigback()
|
||||
set a097 trigdelta()
|
||||
set a098 trigrep()
|
||||
set a099 triguntil()
|
||||
set a100 trigscanfrom()
|
||||
set a101 trigfrom()
|
||||
set a102 trigpriority()
|
||||
set a103 trigtimedelta()
|
||||
set a104 trigtimerep()
|
||||
set a105 trigduration()
|
||||
|
||||
REM 2010-09-03 +3 -4 UNTIL 2012-01-01 PRIORITY 7 *14 AT 14:41 +15 *2 DURATION 3:33 MSG foo
|
||||
set a106 trigback()
|
||||
set a107 trigdelta()
|
||||
set a108 trigrep()
|
||||
set a109 triguntil()
|
||||
set a110 trigscanfrom()
|
||||
set a111 trigfrom()
|
||||
set a112 trigpriority()
|
||||
set a113 trigtimedelta()
|
||||
set a114 trigtimerep()
|
||||
set a115 trigduration()
|
||||
|
||||
REM Mon Wed FROM 2010-09-03 ++3 --4 AT 14:44 MSG foo
|
||||
set a116 trigback()
|
||||
set a117 trigdelta()
|
||||
set a118 trigrep()
|
||||
set a119 triguntil()
|
||||
set a120 trigscanfrom()
|
||||
set a121 trigfrom()
|
||||
set a122 trigpriority()
|
||||
set a123 trigtimedelta()
|
||||
set a124 trigtimerep()
|
||||
set a125 trigduration()
|
||||
|
||||
# Test adding TIME+TIME and DATETIME+TIME
|
||||
set a126 11:00 + 3:00
|
||||
set a127 23:00 + 5:30
|
||||
set a128 '2018-02-03@10:00' + 6:45
|
||||
set a129 23:30 + '2019-02-02@16:44'
|
||||
|
||||
# Multi-day reminder
|
||||
REM 13 AT 16:00 DURATION 72:00 MSG 72-hour event
|
||||
set a130 trigdate()
|
||||
set a131 trigtime()
|
||||
set a132 trigdatetime()
|
||||
set a133 trigduration()
|
||||
set a134 trigeventstart()
|
||||
set a135 trigeventduration()
|
||||
|
||||
dump
|
||||
dump $aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
@@ -322,6 +385,18 @@ OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
OMIT DUMP
|
||||
# Regression test for bugfix in Hebrew calendar Adar jahrzeit
|
||||
[_i(14, "Adar", today(), 5761)] MSG Purim
|
||||
|
||||
# Check combo of SATISFY and long-duration events
|
||||
REM 14 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 8:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 8:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 32:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 32:01 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
REM 14 AT 16:00 DURATION 40:00 SATISFY [$Tw == 4] MSG Thursday, the 14th
|
||||
|
||||
# This is now an error
|
||||
REM DURATION 15:00 MSG Should fail... need AT if you have DURATION.
|
||||
|
||||
__EOF__
|
||||
REM This line should not even be seen
|
||||
And you can put whatever you like here.
|
||||
|
||||
@@ -69,6 +69,7 @@ install:
|
||||
sed $(SEDSCRIPT) < moon.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
||||
sed $(SEDSCRIPT) < sunrise.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunrise.rem
|
||||
sed $(SEDSCRIPT) < sunset.rem-DIST > $(DESTDIR)$(SCRIPTDIR)/sunset.rem
|
||||
cp blank.rem $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||
sed $(SEDSCRIPT) < calendar.html-DIST > $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||
sed $(SEDSCRIPT) < hebhtml > $(DESTDIR)$(SCRIPTDIR)/hebhtml
|
||||
sed $(SEDSCRIPT2) < rem2html > $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
||||
@@ -76,6 +77,7 @@ install:
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/moon.rem
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/hebdate.rem
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/sunset.rem
|
||||
chmod 644 $(DESTDIR)$(SCRIPTDIR)/blank.rem
|
||||
chmod 644 $(DESTDIR)$(HTMLDIR)/calendar.html
|
||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/cal_dispatch$(CGISUFFIX)
|
||||
chmod 755 $(DESTDIR)$(SCRIPTDIR)/rem2html$(CGISUFFIX)
|
||||
|
||||
@@ -9,7 +9,7 @@ only tested it with Linux running NCSA's httpd and Apache's httpd, but
|
||||
it should work on any UNIX web server.
|
||||
|
||||
To install it, you need the Remind package, available via ftp from
|
||||
ftp://ftp.doe.carleton.ca/pub/remind-3.0. You should install Remind,
|
||||
https://dianne.skoll.ca/projects/remind/ You should install Remind,
|
||||
setting the lattitude, longitude, location and time zone as appropriate
|
||||
for your machine.
|
||||
|
||||
@@ -38,12 +38,8 @@ where "what" is one of:
|
||||
hebps -- get a PostScript calendar with Jewish holidays.
|
||||
hebhtml -- get an HTML version of the above (requires Perl.)
|
||||
|
||||
(Visit http://www.doe.carleton.ca/~dfs/ for previews.)
|
||||
|
||||
All of these links will be set up in a sample HTML document
|
||||
called "calendar.html" and installed in the HTMLDIR you specified
|
||||
in the Makefile.
|
||||
|
||||
4) Enjoy!
|
||||
|
||||
|
||||
|
||||
5
www/blank.rem
Normal file
@@ -0,0 +1,5 @@
|
||||
[moondate(0)] SPECIAL MOON 0
|
||||
[moondate(1)] SPECIAL MOON 1
|
||||
[moondate(2)] SPECIAL MOON 2
|
||||
[moondate(3)] SPECIAL MOON 3
|
||||
REM Monday SPECIAL WEEK (W[weekno()])
|
||||
@@ -7,5 +7,5 @@
|
||||
echo "Content-type: application/postscript"
|
||||
echo
|
||||
|
||||
$REMIND -p /dev/null | $REM2PS -e -c3 -l
|
||||
$REMIND -p $DIR/blank.rem | $REM2PS -e -c3 -l
|
||||
exit 0
|
||||
|
||||
|
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 354 B |
BIN
www/fullmoon.png
|
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 360 B |
@@ -29,6 +29,8 @@ ENDIF
|
||||
# #
|
||||
##########################################################################
|
||||
|
||||
SET n $NumTrig
|
||||
|
||||
# --- HERE ARE THE JEWISH HOLIDAYS ---
|
||||
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
|
||||
# you get the Diaspora versions of Jewish holidays
|
||||
@@ -138,6 +140,10 @@ ENDIF
|
||||
|
||||
fset msgprefix(x) ""
|
||||
|
||||
IF $NumTrig > n
|
||||
REM SPECIAL SHADE 224 224 255
|
||||
ENDIF
|
||||
|
||||
# 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."
|
||||
# Nice Remind programming example here!
|
||||
@@ -165,7 +171,7 @@ ELSE
|
||||
[trigger(moondate(2))] SPECIAL MOON 2
|
||||
[trigger(moondate(3))] SPECIAL MOON 3
|
||||
REM PS Border Border moveto /DayFont findfont 10 scalefont setfont ([hebday(today())] [hebmon(today())]) show
|
||||
REM SPECIAL HTML <P><FONT SIZE=-1>[hebday(today())] [hebmon(today())]</FONT></P>
|
||||
REM SPECIAL HTML <P>[hebday(today())] [hebmon(today())]</P>
|
||||
|
||||
ENDIF
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 361 B |
BIN
www/newmoon.png
|
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 317 B |
29
www/rem2html
@@ -4,10 +4,11 @@ use strict;
|
||||
use warnings;
|
||||
|
||||
use Getopt::Long;
|
||||
use JSON::Any;
|
||||
|
||||
my %Options;
|
||||
|
||||
my $rem2html_version = '2.0';
|
||||
my $rem2html_version = '2.1';
|
||||
|
||||
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
|
||||
@Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
|
||||
@@ -191,7 +192,7 @@ sub parse_input
|
||||
my $found_data = 0;
|
||||
while(<STDIN>) {
|
||||
chomp;
|
||||
last if /^\# rem2ps begin$/;
|
||||
last if /^\# rem2ps2? begin$/;
|
||||
}
|
||||
|
||||
my $line;
|
||||
@@ -228,13 +229,29 @@ sub parse_input
|
||||
}
|
||||
while(<STDIN>) {
|
||||
chomp;
|
||||
last if /^\# rem2ps end$/;
|
||||
last if /^\# rem2ps2? end$/;
|
||||
next if /^\#/;
|
||||
next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/;
|
||||
my ($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
my ($y, $m, $d, $special, $tag, $duration, $time, $body);
|
||||
if (m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/) {
|
||||
($y, $m, $d, $special, $tag, $duration, $time, $body) =
|
||||
($1, $2, $3, $4, $5, $6, $7, $8);
|
||||
} elsif (/\{/) {
|
||||
my $obj = JSON::Any->jsonToObj($_);
|
||||
next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
|
||||
$y = $1;
|
||||
$m = $2;
|
||||
$d = $3;
|
||||
$special = $obj->{passthru} || '*';
|
||||
$tag = $obj->{tags} || '*';
|
||||
$duration = $obj->{duration} || '*';
|
||||
$time = $obj->{time} || '*';
|
||||
$body = $obj->{body};
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
my $d1 = $d;
|
||||
$d1 =~ s/^0+//;
|
||||
$special = uc($special);
|
||||
if ($special eq 'HTML') {
|
||||
push(@{$days->[$d]}, $body);
|
||||
} elsif ($special eq 'HTMLCLASS') {
|
||||
|
||||