mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 14:28:40 +02:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4ebb8be6 | ||
|
|
11e2ce5093 | ||
|
|
2c560e6f2b | ||
|
|
643f394e6a | ||
|
|
6d047c2856 | ||
|
|
be86746685 | ||
|
|
da429b9629 | ||
|
|
b21a206c26 | ||
|
|
85bde8ba3a | ||
|
|
f84e658e6b | ||
|
|
8f0eba8bcd | ||
|
|
2faaaf78a8 | ||
|
|
7f659dace2 | ||
|
|
54cdd566c7 | ||
|
|
e212df87f9 | ||
|
|
4fb4db15e8 | ||
|
|
9a15a25a7b | ||
|
|
c02cfb9b17 | ||
|
|
3e726f21f7 | ||
|
|
21d4faa26f | ||
|
|
1d13d0ee07 | ||
|
|
329d13e480 | ||
|
|
2161c09b1d | ||
|
|
3f2e396c3c | ||
|
|
412e242109 | ||
|
|
e827516b72 | ||
|
|
7f953e98d7 | ||
|
|
821d3fe783 |
10
configure
vendored
10
configure
vendored
@@ -4721,7 +4721,9 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
for ac_header in sys/file.h glob.h
|
||||
|
||||
|
||||
for ac_header in sys/file.h glob.h wctype.h locale.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
@@ -5221,7 +5223,9 @@ fi
|
||||
|
||||
|
||||
|
||||
for ac_func in setenv unsetenv glob
|
||||
|
||||
|
||||
for ac_func in setenv unsetenv glob mbstowcs setlocale
|
||||
do
|
||||
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
|
||||
@@ -5314,7 +5318,7 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION=03.01.09
|
||||
VERSION=03.01.10
|
||||
|
||||
ac_config_files="$ac_config_files src/Makefile www/Makefile src/version.h"
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h)
|
||||
AC_CHECK_HEADERS(sys/file.h glob.h wctype.h locale.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_STRUCT_TM
|
||||
@@ -74,7 +74,7 @@ if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob)
|
||||
VERSION=03.01.09
|
||||
AC_CHECK_FUNCS(setenv unsetenv glob mbstowcs setlocale)
|
||||
VERSION=03.01.10
|
||||
AC_SUBST(VERSION)
|
||||
AC_OUTPUT(src/Makefile www/Makefile src/version.h)
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
(sort
|
||||
(list "RUN" "REM" "ONCE" "SATISFY" "BEFORE" "UNSET" "OMIT"
|
||||
"OMIT" "DATE" "SKIP" "ONCE" "AFTER" "WARN" "PRIORITY" "AT" "SCHED" "IF" "ELSE" "ENDIF"
|
||||
"WARN" "UNTIL" "SCANFROM" "DURATION" "TAG" "MSG" "MSF" "CAL" "SPECIAL" "IFTRIG"
|
||||
"WARN" "UNTIL" "THROUGH" "SCANFROM" "DURATION" "TAG" "MSG" "MSF" "CAL" "SPECIAL" "IFTRIG"
|
||||
"PS" "PSFILE" "BANNER" "INCLUDE" "PUSH-OMIT-CONTEXT" "DEBUG" "DUMPVARS"
|
||||
"CLEAR-OMIT-CONTEXT" "POP-OMIT-CONTEXT" "SET" "ERRMSG" "FSET"
|
||||
"EXIT" "FLUSH" "PRESERVE" "MOON" "COLOR")
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
CHANGES TO REMIND
|
||||
|
||||
* Version 3.1 Patch 10 - 2010-11-01
|
||||
|
||||
- NOTE: This is the 20th anniversary of Remind's first public release.
|
||||
|
||||
- ENHANCEMENT: Add the THROUGH keyword. You can omit blocks of dates with:
|
||||
|
||||
OMIT start THROUGH end
|
||||
|
||||
and the syntax REM start THROUGH end is equivalent to REM start *1 UNTIL end
|
||||
|
||||
- ENHANCEMENT: Add support for multibyte characters (eg, UTF-8) in calendar
|
||||
output. Note that UTF-8 strings are still not supported in PostScript
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: Add support for UTF-8 line-drawing characters in calendar
|
||||
output.
|
||||
|
||||
- ENHANCEMENT: You can have multiple TAG clauses in a REM statement.
|
||||
|
||||
- BUG FIX: Avoid spawning long-running background processes in "make test".
|
||||
|
||||
- BUG FIX: Don't declare variables in the middle of statements (old C
|
||||
compilers choke.)
|
||||
|
||||
* Version 3.1 Patch 9 - 2010-06-20
|
||||
|
||||
- MAJOR ENHANCEMENT: New "purge mode" to delete expired reminders. See
|
||||
|
||||
@@ -1,53 +1,79 @@
|
||||
" Vim syntax file
|
||||
" Language: Remind
|
||||
" Maintainer: Davide Alberani <alberanid@bigfoot.com>
|
||||
" Last change: 03 Dec 1999
|
||||
" Version: 0.1
|
||||
" URL: http://members.xoom.com/alberanid/vim/syntax/remind.vim
|
||||
" Maintainer: Davide Alberani <alberanid@libero.it>
|
||||
" Last Change: 18 Sep 2009
|
||||
" Version: 0.5
|
||||
" URL: http://erlug.linux.it/~da/vim/syntax/remind.vim
|
||||
"
|
||||
" remind is a sophisticated reminder service
|
||||
" you can download remind from ftp://ftp.doe.carleton.ca/pub/remind-3.0/
|
||||
" you can download remind from:
|
||||
" http://www.roaringpenguin.com/penguin/open_source_remind.php
|
||||
|
||||
" clear any unwanted syntax defs
|
||||
syn clear
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" shut case off
|
||||
" shut case off.
|
||||
syn case ignore
|
||||
|
||||
syn keyword remindCommands REM OMIT SET FSET UNSET
|
||||
syn keyword remindExpiry UNTIL SCANFROM SCAN WARN SCHED
|
||||
syn keyword remindExpiry UNTIL FROM SCANFROM SCAN WARN SCHED
|
||||
syn keyword remindTag PRIORITY TAG
|
||||
syn keyword remindTimed AT DURATION
|
||||
syn keyword remindMove ONCE SKIP BEFORE AFTER
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP
|
||||
syn keyword remindSpecial INCLUDE INC BANNER PUSH-OMIT-CONTEXT PUSH CLEAR-OMIT-CONTEXT CLEAR POP-OMIT-CONTEXT POP COLOR
|
||||
syn keyword remindRun MSG MSF RUN CAL SATISFY SPECIAL PS PSFILE SHADE MOON
|
||||
syn keyword remindConditional IF ELSE ENDIF IFTRIG
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindComment "#.*$"
|
||||
syn region remindString start=+'+ end=+'+ skip=+\\\\\|\\'+ oneline
|
||||
syn region remindString start=+"+ end=+"+ skip=+\\\\\|\\"+ oneline
|
||||
syn keyword remindDebug DEBUG DUMPVARS DUMP ERRMSG FLUSH PRESERVE
|
||||
syn match remindVar "\$[_a-zA-Z][_a-zA-Z0-9]*"
|
||||
syn match remindSubst "%[^ ]"
|
||||
syn match remindAdvanceNumber "\(\*\|+\|-\|++\|--\)[0-9]\+"
|
||||
" XXX: use different separators for dates and times?
|
||||
syn match remindDateSeparators "[/:@\.-]" contained
|
||||
syn match remindTimes "[0-9]\{1,2}[:\.][0-9]\{1,2}" contains=remindDateSeparators
|
||||
" XXX: why not match only valid dates? Ok, checking for 'Feb the 30' would
|
||||
" be impossible, but at least check for valid months and times.
|
||||
syn match remindDates "'[0-9]\{4}[/-][0-9]\{1,2}[/-][0-9]\{1,2}\(@[0-9]\{1,2}[:\.][0-9]\{1,2}\)\?'" contains=remindDateSeparators
|
||||
" This will match trailing whitespaces that seem to break rem2ps.
|
||||
" Courtesy of Michael Dunn.
|
||||
syn match remindWarning display excludenl "\S\s\+$"ms=s+1
|
||||
|
||||
if !exists("did_remind_syntax_inits")
|
||||
let did_remind_syntax_inits = 1
|
||||
hi link remindCommands Function
|
||||
hi link remindExpiry Repeat
|
||||
hi link remindTag Label
|
||||
hi link remindTimed Statement
|
||||
hi link remindMove Statement
|
||||
hi link remindSpecial Include
|
||||
hi link remindRun Function
|
||||
hi link remindConditional Conditional
|
||||
hi link remindComment Comment
|
||||
hi link remindString String
|
||||
hi link remindDebug Debug
|
||||
hi link remindVar Identifier
|
||||
hi link remindSubst Constant
|
||||
hi link remindAdvanceNumber Number
|
||||
|
||||
if version >= 508 || !exists("did_remind_syn_inits")
|
||||
if version < 508
|
||||
let did_remind_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
|
||||
HiLink remindCommands Function
|
||||
HiLink remindExpiry Repeat
|
||||
HiLink remindTag Label
|
||||
HiLink remindTimed Statement
|
||||
HiLink remindMove Statement
|
||||
HiLink remindSpecial Include
|
||||
HiLink remindRun Function
|
||||
HiLink remindConditional Conditional
|
||||
HiLink remindComment Comment
|
||||
HiLink remindTimes String
|
||||
HiLink remindString String
|
||||
HiLink remindDebug Debug
|
||||
HiLink remindVar Identifier
|
||||
HiLink remindSubst Constant
|
||||
HiLink remindAdvanceNumber Number
|
||||
HiLink remindDateSeparators Comment
|
||||
HiLink remindDates String
|
||||
HiLink remindWarning Error
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
let b:current_syntax = "remind"
|
||||
|
||||
"EOF vim: ts=8 noet tw=100 sw=8 sts=0
|
||||
" vim: ts=8 sw=2
|
||||
|
||||
@@ -362,7 +362,10 @@ Other back-ends may understand other specials. A back end should
|
||||
\fIsilently ignore\fR a reminder with a special it doesn't understand.
|
||||
.PP
|
||||
\fItag\fR is whatever tag the user provided with the \fBTAG\fR clause,
|
||||
or "*" if no tag was provided.
|
||||
or "*" if no tag was provided. If there is more than one \fBTAG\fR clause,
|
||||
the tags appear in a comma-separated list. For example, the command
|
||||
\fBREM TAG foo TAG bar TAG quux\fR would result in \fBfoo,bar,quux\fR
|
||||
in the \fItag\fR field.
|
||||
.PP
|
||||
\fIdur\fR is the \fBDURATION\fR value in minutes, or "*" if no duration
|
||||
was provided.
|
||||
|
||||
68
man/remind.1
68
man/remind.1
@@ -61,6 +61,11 @@ causes \fBRemind\fR to use VT100 line-drawing characters to draw
|
||||
the calendar. The characters are hard-coded and will only work
|
||||
on terminals that emulate the VT00 line-drawing character set.
|
||||
.TP
|
||||
.B 'u'
|
||||
is similar to 'l', but causes \fBRemind\fR to use UNICODE line-drawing
|
||||
characters to draw the calendar. The characters are hard-coded and will
|
||||
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
|
||||
@@ -330,6 +335,16 @@ wish to pass a \fBRemind\fR script through the C pre-processor, which
|
||||
interprets the '#' character as the start of a pre-processing
|
||||
directive.
|
||||
.PP
|
||||
Note that \fBRemind\fR processes line continuations before anything else.
|
||||
For example:
|
||||
.PP
|
||||
.nf
|
||||
# This is a comment \\
|
||||
This line is part of the comment because of line continuation \\
|
||||
and so on.
|
||||
REM MSG This line is not ignored (no \\ above)
|
||||
.fi
|
||||
.PP
|
||||
\fBRemind\fR is not case sensitive; you can generally use any mixture of upper-
|
||||
or lower-case for commands, parameters, invocation options, etc.
|
||||
.SH THE REM COMMAND
|
||||
@@ -350,7 +365,7 @@ Its syntax is:
|
||||
[\fBAT\fR \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]]
|
||||
[\fBSCHED\fR \fIsched_function\fR]
|
||||
[\fBWARN\fR \fIwarn_function\fR]
|
||||
[\fBUNTIL\fR \fIexpiry_date\fR]
|
||||
[\fBUNTIL\fR \fIexpiry_date\fR | \fBTHROUGH\fR \fIlast_date\fR]
|
||||
[\fBSCANFROM\fR \fIscan_date\fR | \fBFROM\fR \fIstart_date\fR]
|
||||
[\fBDURATION\fR \fIduration\fR]
|
||||
[\fBTAG\fR \fItag\fR]
|
||||
@@ -786,6 +801,15 @@ of your jury duty, as well as 2 days ahead of time:
|
||||
Note that the \fIrepeat\fR of *1 is necessary; without it, the reminder
|
||||
would be issued only on 30 November (and the two days preceding.)
|
||||
.PP
|
||||
As a special case, you can use the \fBTHROUGH\fR keyword instead of
|
||||
*1 and \fBUNTIL\fR. The following two \fBREM\fR commands are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
REM 1992-11-30 *1 +2 UNTIL 1992-12-04 MSG Jury duty
|
||||
|
||||
REM 1992-11-30 +2 THROUGH 1992-12-04 MSG Jury duty
|
||||
.fi
|
||||
.PP
|
||||
.B THE ONCE KEYWORD
|
||||
.PP
|
||||
Sometimes, it is necessary to ensure that reminders are run only once
|
||||
@@ -989,11 +1013,11 @@ expressions and user-defined functions are explained. See the subsection
|
||||
The \fBTAG\fR keyword lets you "tag" certain reminders. This facility
|
||||
is used by certain back-ends or systems built around \fBRemind\fR,
|
||||
such as \fBTkRemind\fR. These back-ends have specific rules about
|
||||
tags; you should \fInot\fR use the \fBTAG\fR keyword yourself, or
|
||||
your script will interact badly with back-ends.
|
||||
tags; see their documentation for details.
|
||||
.PP
|
||||
The \fBTAG\fR keyword is followed by a tag consisting of up to
|
||||
48 characters.
|
||||
48 characters. You can have as many TAG clauses as you like in
|
||||
a given REM statement.
|
||||
.PP
|
||||
If you supply the \fB\-y\fR option to \fBRemind\fR, then any
|
||||
reminder that lacks a \fBTAG\fR will have one synthesized. The
|
||||
@@ -1289,6 +1313,10 @@ In addition to being a keyword in the \fBREM\fR command,
|
||||
.PP
|
||||
.RS
|
||||
\fBOMIT\fR \fIday\fR \fImonth\fR [\fIyear\fR]
|
||||
.PP
|
||||
or:
|
||||
.PP
|
||||
\fBOMIT\fR \fIday1\fR \fImonth1\fR \fIyear1\fR \fBTHROUGH\fR \fIday2\fR \fImonth2\fR \fIyear2\fR
|
||||
.RE
|
||||
.PP
|
||||
The \fBOMIT\fR command is used to "globally" omit certain days
|
||||
@@ -1316,7 +1344,7 @@ the following are equivalent:
|
||||
.fi
|
||||
.PP
|
||||
For convenience, you can use a \fIdelta\fR and \fBMSG\fR or \fBRUN\fR
|
||||
keyword in the \fBOMIT\fR command. The following sequences are exactly
|
||||
keyword in the \fBOMIT\fR command. The following sequences are
|
||||
equivalent:
|
||||
.PP
|
||||
.nf
|
||||
@@ -1328,6 +1356,36 @@ equivalent:
|
||||
OMIT 1 Jan +4 MSG New year's day is %b!
|
||||
.fi
|
||||
.PP
|
||||
The \fBTHROUGH\fR keyword lets you conveniently OMIT a range of days.
|
||||
The starting and ending points must be fully-specified (ie, they must
|
||||
include day, month and year.). For example, the following sequences
|
||||
are equivalent:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 3 Jan 2011
|
||||
OMIT 4 Jan 2011
|
||||
OMIT 5 Jan 2011
|
||||
|
||||
and
|
||||
|
||||
OMIT 3 Jan 2011 THROUGH 5 Jan 2011
|
||||
.fi
|
||||
.PP
|
||||
You can make a THROUGH \fBOMIT\fR do double-duty as a \fBREM\fR command:
|
||||
.PP
|
||||
.nf
|
||||
OMIT 6 Sep 2010 THROUGH 10 Sep 2010 MSG Vacation
|
||||
.fi
|
||||
|
||||
.PP
|
||||
You can debug your global OMITs with the following command:
|
||||
.PP
|
||||
.nf
|
||||
OMIT DUMP
|
||||
.fi
|
||||
.PP
|
||||
The OMIT DUMP command prints the current global omits to standard output.
|
||||
.PP
|
||||
.B THE BEFORE, AFTER AND SKIP KEYWORDS
|
||||
.PP
|
||||
Normally, days that are omitted, whether by a global \fBOMIT\fR
|
||||
|
||||
@@ -289,7 +289,9 @@ file to store additional state. You can certainly mix
|
||||
if you are aware of the following rules and limitations:
|
||||
.TP
|
||||
o
|
||||
Do not use the \fBTAG\fR keyword in hand-crafted reminders.
|
||||
\fBTkRemind\fR uses \fBTAG\fRs of the form \fBTKTAG\fR\fInnn\fR
|
||||
where \fInnn\fR is a number. You should not use such \fBTAG\fRs
|
||||
in hand-crafted reminders.
|
||||
.TP
|
||||
o
|
||||
Do not edit lines starting with "# TKTAGnnn", "# TKEND", or any
|
||||
|
||||
@@ -392,11 +392,7 @@ proc ConfigureCalFrame { w firstDay numDays } {
|
||||
set first [expr $offset+1]
|
||||
set last [expr $offset+$numDays]
|
||||
|
||||
if {$tk_version >= 8.5} {
|
||||
set bg "#d9d9d9"
|
||||
} else {
|
||||
set bg [lindex [$w.t0 configure -background] 3]
|
||||
}
|
||||
set bg [lindex [. configure -background] 3]
|
||||
|
||||
for {set i 0} {$i < $first} {incr i} {
|
||||
grid $w.l$i $w.t$i
|
||||
|
||||
500
src/calendar.c
500
src/calendar.c
@@ -18,6 +18,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "protos.h"
|
||||
#include "expr.h"
|
||||
@@ -30,11 +34,15 @@ typedef struct cal_entry {
|
||||
struct cal_entry *next;
|
||||
char const *text;
|
||||
char const *pos;
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *wc_text;
|
||||
wchar_t const *wc_pos;
|
||||
#endif
|
||||
int is_color;
|
||||
int r, g, b;
|
||||
int time;
|
||||
int priority;
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
int duration;
|
||||
char const *filename;
|
||||
@@ -45,17 +53,32 @@ typedef struct cal_entry {
|
||||
struct line_drawing {
|
||||
char const *graphics_on;
|
||||
char const *graphics_off;
|
||||
char tlr, bl, tbl, blr, tblr, tr, tb, br, tbr, tl, lr;
|
||||
char *tlr, *bl, *tbl, *blr, *tblr, *tr, *tb, *br, *tbr, *tl, *lr;
|
||||
};
|
||||
|
||||
static struct line_drawing NormalDrawing = {
|
||||
"", "", '+', '+', '+', '+', '+', '+', '|', '+', '+', '+', '-'
|
||||
"", "", "+", "+", "+", "+", "+", "+", "|", "+", "+", "+", "-"
|
||||
};
|
||||
|
||||
static struct line_drawing VT100Drawing = {
|
||||
"\x1B(0", "\x1B(B",
|
||||
'\x76', '\x6b', '\x75', '\x77', '\x6e', '\x6d', '\x78',
|
||||
'\x6c', '\x74', '\x6a', '\x71'
|
||||
"\x76", "\x6b", "\x75", "\x77", "\x6e", "\x6d", "\x78",
|
||||
"\x6c", "\x74", "\x6a", "\x71"
|
||||
};
|
||||
|
||||
static struct line_drawing UTF8Drawing = {
|
||||
"", "",
|
||||
"\xe2\x94\xb4",
|
||||
"\xe2\x94\x90",
|
||||
"\xe2\x94\xa4",
|
||||
"\xe2\x94\xac",
|
||||
"\xe2\x94\xbc",
|
||||
"\xe2\x94\x94",
|
||||
"\xe2\x94\x82",
|
||||
"\xe2\x94\x8c",
|
||||
"\xe2\x94\x9c",
|
||||
"\xe2\x94\x98",
|
||||
"\xe2\x94\x80"
|
||||
};
|
||||
|
||||
static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
@@ -108,7 +131,7 @@ static char *VT100Colors[2][2][2][2] /* [Br][R][G][B] */ = {
|
||||
};
|
||||
|
||||
static struct line_drawing *linestruct;
|
||||
#define DRAW(x) putchar(linestruct->x)
|
||||
#define DRAW(x) fputs(linestruct->x, stdout)
|
||||
|
||||
/* Global variables */
|
||||
static CalEntry *CalColumn[7];
|
||||
@@ -124,7 +147,7 @@ static int WriteCalendarRow (void);
|
||||
static void WriteWeekHeaderLine (void);
|
||||
static void WritePostHeaderLine (void);
|
||||
static void PrintLeft (char const *s, int width, char pad);
|
||||
static void PrintCentered (char const *s, int width, char pad);
|
||||
static void PrintCentered (char const *s, int width, char *pad);
|
||||
static int WriteOneCalLine (void);
|
||||
static int WriteOneColLine (int col);
|
||||
static void GenerateCalEntries (int col);
|
||||
@@ -137,6 +160,40 @@ static void WriteBottomCalLine (void);
|
||||
static void WriteIntermediateCalLine (void);
|
||||
static void WriteCalDays (void);
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
static void PutWideChar(wchar_t const wc)
|
||||
{
|
||||
char buf[MB_CUR_MAX+1];
|
||||
int len;
|
||||
|
||||
len = wctomb(buf, wc);
|
||||
if (len > 0) {
|
||||
buf[len] = 0;
|
||||
fputs(buf, stdout);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int make_wchar_versions(CalEntry *e)
|
||||
{
|
||||
#ifdef REM_USE_WCHAR
|
||||
size_t len;
|
||||
wchar_t *buf;
|
||||
len = mbstowcs(NULL, e->text, 0);
|
||||
if (len == (size_t) -1) return 0;
|
||||
|
||||
buf = calloc(len+1, sizeof(wchar_t));
|
||||
if (!buf) return 0;
|
||||
|
||||
(void) mbstowcs(buf, e->text, len+1);
|
||||
e->wc_text = buf;
|
||||
e->wc_pos = buf;
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gon(void)
|
||||
{
|
||||
printf("%s", linestruct->graphics_on);
|
||||
@@ -179,7 +236,9 @@ void ProduceCalendar(void)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
if (UseVTChars) {
|
||||
if (UseUTF8Chars) {
|
||||
linestruct = &UTF8Drawing;
|
||||
} else if (UseVTChars) {
|
||||
linestruct = &VT100Drawing;
|
||||
} else {
|
||||
linestruct = &NormalDrawing;
|
||||
@@ -460,20 +519,55 @@ static void PrintLeft(char const *s, int width, char pad)
|
||||
/* */
|
||||
/* PrintCentered */
|
||||
/* */
|
||||
/* Center a piec of text */
|
||||
/* Center a piece of text */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
static void PrintCentered(char const *s, int width, char pad)
|
||||
static void PrintCentered(char const *s, int width, char *pad)
|
||||
{
|
||||
#ifndef REM_USE_WCHAR
|
||||
int len = strlen(s);
|
||||
int d = (width - len) / 2;
|
||||
int i;
|
||||
|
||||
for (i=0; i<d; i++) PutChar(pad);
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
if (*s) PutChar(*s++); else break;
|
||||
}
|
||||
for (i=d+len; i<width; i++) PutChar(pad);
|
||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||
#else
|
||||
size_t len = mbstowcs(NULL, s, 0);
|
||||
int i;
|
||||
wchar_t static_buf[128];
|
||||
wchar_t *buf;
|
||||
wchar_t *ws;
|
||||
int d;
|
||||
|
||||
if (!len) {
|
||||
for (i=0; i<width; i++) {
|
||||
fputs(pad, stdout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (len + 1 <= 128) {
|
||||
buf = static_buf;
|
||||
} else {
|
||||
buf = calloc(len+1, sizeof(wchar_t));
|
||||
if (!buf) {
|
||||
/* Uh-oh... cannot recover */
|
||||
fprintf(stderr, "%s\n", ErrMsg[E_NO_MEM]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
(void) mbstowcs(buf, s, len+1);
|
||||
d = (width - len) / 2;
|
||||
ws = buf;
|
||||
for (i=0; i<d; i++) fputs(pad, stdout);
|
||||
for (i=0; i<width; i++) {
|
||||
if (*ws) PutWideChar(*ws++); else break;
|
||||
}
|
||||
for (i=d+len; i<width; i++) fputs(pad, stdout);
|
||||
if (buf != static_buf) free(buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -494,7 +588,7 @@ static int WriteOneCalLine(void)
|
||||
if (CalColumn[i]) {
|
||||
if (WriteOneColLine(i)) done = 0;
|
||||
} else {
|
||||
PrintCentered("", ColSpaces, ' ');
|
||||
PrintCentered("", ColSpaces, " ");
|
||||
}
|
||||
gon();
|
||||
DRAW(tb);
|
||||
@@ -519,74 +613,158 @@ static int WriteOneColLine(int col)
|
||||
CalEntry *e = CalColumn[col];
|
||||
char const *s;
|
||||
char const *space;
|
||||
|
||||
#ifdef REM_USE_WCHAR
|
||||
wchar_t const *ws;
|
||||
wchar_t const *wspace;
|
||||
#endif
|
||||
|
||||
int numwritten = 0;
|
||||
|
||||
/* Print as many characters as possible within the column */
|
||||
space = NULL;
|
||||
s = e->pos;
|
||||
/* Print as many characters as possible within the column */
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) {
|
||||
wspace = NULL;
|
||||
ws = e->wc_pos;
|
||||
|
||||
/* If we're at the end, and there's another entry, do a blank line and move
|
||||
to next entry. */
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (*s == ' ') space = s;
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!space) {
|
||||
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*ws && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
e->pos = s;
|
||||
} else {
|
||||
|
||||
/* We found a space - print everything before it. */
|
||||
for (s = e->pos; s<space; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
/* Find the last space char within the column. */
|
||||
while (ws - e->wc_pos <= ColSpaces) {
|
||||
if (!*ws) {wspace = ws; break;}
|
||||
if (iswspace(*ws)) wspace = ws;
|
||||
ws++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!wspace) {
|
||||
for (ws = e->wc_pos; ws - e->wc_pos < ColSpaces; ws++) {
|
||||
if (!*ws) break;
|
||||
numwritten++;
|
||||
PutWideChar(*ws);
|
||||
}
|
||||
e->wc_pos = ws;
|
||||
} else {
|
||||
/* We found a space - print everything before it. */
|
||||
for (ws = e->wc_pos; ws<wspace; ws++) {
|
||||
if (!*ws) break;
|
||||
numwritten++;
|
||||
PutWideChar(*ws);
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (*s == ' ') s++;
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free(e);
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (iswspace(*ws)) ws++;
|
||||
|
||||
/* 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);
|
||||
} else {
|
||||
e->wc_pos = ws;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
} else {
|
||||
e->pos = s;
|
||||
#endif
|
||||
space = NULL;
|
||||
s = e->pos;
|
||||
|
||||
/* If we're at the end, and there's another entry, do a blank
|
||||
line and move to next entry. */
|
||||
if (!*s && e->next) {
|
||||
PrintLeft("", ColSpaces, ' ');
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the last space char within the column. */
|
||||
while (s - e->pos <= ColSpaces) {
|
||||
if (!*s) {space = s; break;}
|
||||
if (*s == ' ') space = s;
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Colorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Colorize(e);
|
||||
}
|
||||
|
||||
/* If we couldn't find a space char, print what we have. */
|
||||
if (!space) {
|
||||
for (s = e->pos; s - e->pos < ColSpaces; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
}
|
||||
e->pos = s;
|
||||
} else {
|
||||
/* We found a space - print everything before it. */
|
||||
for (s = e->pos; s<space; s++) {
|
||||
if (!*s) break;
|
||||
numwritten++;
|
||||
PutChar(*s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decolorize reminder if necessary */
|
||||
if (UseVTColors && e->is_color) {
|
||||
Decolorize();
|
||||
}
|
||||
|
||||
/* Flesh out the rest of the column */
|
||||
while(numwritten++ < ColSpaces) PutChar(' ');
|
||||
|
||||
/* Skip any spaces before next word */
|
||||
while (*s == ' ') s++;
|
||||
|
||||
/* If done, free memory if no next entry. */
|
||||
if (!*s && !e->next) {
|
||||
CalColumn[col] = e->next;
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
free(e);
|
||||
} else {
|
||||
e->pos = s;
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
#ifdef REM_USE_WCHAR
|
||||
}
|
||||
if (CalColumn[col]) return 1; else return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -714,7 +892,7 @@ static void WriteCalHeader(void)
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
PrintCentered(buf, CalWidth-2, ' ');
|
||||
PrintCentered(buf, CalWidth-2, " ");
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
@@ -763,29 +941,52 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufInit(&pre_buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Don't include timed reminders in calendar if -a option supplied. */
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) return OK;
|
||||
if (trig.typ == NO_TYPE) return E_EOLN;
|
||||
if (DontIssueAts && tim.ttime != NO_TIME) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (trig.typ == NO_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
return r;
|
||||
}
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) return OK;
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR;
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (tok.val == PASSTHRU_TYPE) {
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (!DBufLen(&buf)) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
StrnCpy(trig.passthru, DBufValue(&buf), PASSTHRU_LEN);
|
||||
@@ -793,11 +994,17 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
}
|
||||
trig.typ = tok.val;
|
||||
jul = LastTriggerDate;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert PS and PSF to PASSTHRU */
|
||||
@@ -809,39 +1016,50 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
trig.typ = PASSTHRU_TYPE;
|
||||
}
|
||||
if (trig.typ == PASSTHRU_TYPE) {
|
||||
if (!PsCal && strcmp(trig.passthru, "COLOR")) return OK;
|
||||
if (!strcmp(trig.passthru, "COLOR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) return r;
|
||||
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
|
||||
&col_r, &col_g, &col_b);
|
||||
if (col_r < 0) col_r = 0;
|
||||
else if (col_r > 255) col_r = 255;
|
||||
if (col_g < 0) col_g = 0;
|
||||
else if (col_g > 255) col_g = 255;
|
||||
if (col_b < 0) col_b = 0;
|
||||
else if (col_b > 255) col_b = 255;
|
||||
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
DBufFree(&pre_buf);
|
||||
}
|
||||
}
|
||||
if (!PsCal && strcmp(trig.passthru, "COLOR")) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (!strcmp(trig.passthru, "COLOR")) {
|
||||
is_color = 1;
|
||||
/* Strip off the three color numbers */
|
||||
DBufFree(&buf);
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
DBufPuts(&pre_buf, DBufValue(&buf));
|
||||
DBufPutc(&pre_buf, ' ');
|
||||
DBufFree(&buf);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
(void) sscanf(DBufValue(&pre_buf), "%d %d %d",
|
||||
&col_r, &col_g, &col_b);
|
||||
if (col_r < 0) col_r = 0;
|
||||
else if (col_r > 255) col_r = 255;
|
||||
if (col_g < 0) col_g = 0;
|
||||
else if (col_g > 255) col_g = 255;
|
||||
if (col_b < 0) col_b = 0;
|
||||
else if (col_b > 255) col_b = 255;
|
||||
if (!PsCal && !DoSimpleCalendar) {
|
||||
DBufFree(&pre_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If trigger date == today, add it to the current entry */
|
||||
@@ -859,12 +1077,14 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (DBufPuts(&obuf, SimpleTime(NO_TIME)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
if (DBufPuts(&obuf, CalendarTime(tim.ttime, tim.duration)) != OK) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -881,6 +1101,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DestroyValue(v);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -899,11 +1120,13 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
if (r) {
|
||||
DBufFree(&pre_buf);
|
||||
DBufFree(&obuf);
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (DBufLen(&obuf) <= oldLen) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (trig.typ != PASSTHRU_TYPE &&
|
||||
@@ -918,6 +1141,7 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DestroyValue(v);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
}
|
||||
@@ -929,30 +1153,37 @@ static int DoCalRem(ParsePtr p, int col)
|
||||
DBufPuts(&pre_buf, s);
|
||||
s = DBufValue(&pre_buf);
|
||||
e = NEW(CalEntry);
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
#ifdef REM_USE_WCHAR
|
||||
e->wc_pos = NULL;
|
||||
e->wc_text = NULL;
|
||||
#endif
|
||||
e->is_color = is_color;
|
||||
e->r = col_r;
|
||||
e->g = col_g;
|
||||
e->b = col_b;
|
||||
if (!e) {
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
e->text = StrDup(s);
|
||||
DBufFree(&obuf);
|
||||
DBufFree(&pre_buf);
|
||||
if (!e->text) {
|
||||
free(e);
|
||||
FreeTrig(&trig);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
StrnCpy(e->tag, trig.tag, TAG_LEN);
|
||||
if (!e->tag[0]) {
|
||||
if (SynthesizeTags) {
|
||||
SynthesizeTag(e->tag);
|
||||
} else {
|
||||
strcpy(e->tag, "*");
|
||||
}
|
||||
make_wchar_versions(e);
|
||||
DBufInit(&(e->tags));
|
||||
DBufPuts(&(e->tags), DBufValue(&(trig.tags)));
|
||||
if (SynthesizeTags) {
|
||||
AppendTag(&(e->tags), SynthesizeTag());
|
||||
}
|
||||
|
||||
/* Don't need tags any more */
|
||||
FreeTrig(&trig);
|
||||
e->duration = tim.duration;
|
||||
e->priority = trig.priority;
|
||||
e->filename = StrDup(FileName);
|
||||
@@ -1002,7 +1233,11 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
} else {
|
||||
printf(" *");
|
||||
}
|
||||
printf(" %s ", e->tag);
|
||||
if (*DBufValue(&(e->tags))) {
|
||||
printf(" %s ", DBufValue(&(e->tags)));
|
||||
} else {
|
||||
printf(" * ");
|
||||
}
|
||||
if (e->duration != NO_TIME) {
|
||||
printf("%d ", e->duration);
|
||||
} else {
|
||||
@@ -1014,8 +1249,11 @@ static void WriteSimpleEntries(int col, int jul)
|
||||
printf("* ");
|
||||
}
|
||||
printf("%s\n", e->text);
|
||||
free((char *) e->text);
|
||||
free((char *) e->filename);
|
||||
free((void *)e->text);
|
||||
free((void *)e->filename);
|
||||
#ifdef REM_USE_WCHAR
|
||||
if (e->wc_text) free((void *)e->wc_text);
|
||||
#endif
|
||||
n = e->next;
|
||||
free(e);
|
||||
e = n;
|
||||
@@ -1115,9 +1353,9 @@ static void WriteCalDays(void)
|
||||
goff();
|
||||
for (i=0; i<7; i++) {
|
||||
if (!MondayFirst)
|
||||
PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
|
||||
PrintCentered(DayName[(i+6)%7], ColSpaces, " ");
|
||||
else
|
||||
PrintCentered(DayName[i%7], ColSpaces, ' ');
|
||||
PrintCentered(DayName[i%7], ColSpaces, " ");
|
||||
gon();
|
||||
DRAW(tb);
|
||||
goff();
|
||||
@@ -1285,10 +1523,11 @@ static void SortCol(CalEntry **col)
|
||||
}
|
||||
}
|
||||
|
||||
void SynthesizeTag(char *out)
|
||||
char const *SynthesizeTag(void)
|
||||
{
|
||||
struct MD5Context ctx;
|
||||
unsigned char buf[16];
|
||||
static char out[128];
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
|
||||
MD5Final(buf, &ctx);
|
||||
@@ -1301,5 +1540,6 @@ void SynthesizeTag(char *out)
|
||||
(unsigned int) buf[10], (unsigned int) buf[11],
|
||||
(unsigned int) buf[12], (unsigned int) buf[13],
|
||||
(unsigned int) buf[14], (unsigned int) buf[15]);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,20 @@
|
||||
/* Define if you have the <glob.h> header file */
|
||||
#undef HAVE_GLOB_H
|
||||
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
#undef HAVE_GLOB
|
||||
|
||||
#undef HAVE_SETENV
|
||||
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
#undef HAVE_MBSTOWCS
|
||||
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* The number of bytes in a unsigned int. */
|
||||
#undef SIZEOF_UNSIGNED_INT
|
||||
|
||||
|
||||
10
src/custom.h
10
src/custom.h
@@ -183,12 +183,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -221,3 +221,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
@@ -183,12 +183,12 @@
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form YYYY MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_FULL_OMITS 250
|
||||
#define MAX_FULL_OMITS 500
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* How many global omits of the form MM DD do we handle? */
|
||||
/*---------------------------------------------------------------------*/
|
||||
#define MAX_PARTIAL_OMITS 250
|
||||
#define MAX_PARTIAL_OMITS 366
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* A newline - some systems need "\n\r" */
|
||||
@@ -221,3 +221,9 @@
|
||||
#define Putc putc
|
||||
#define PutChar putchar
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MBSTOWCS) && defined(HAVE_WCTYPE_H)
|
||||
#define REM_USE_WCHAR 1
|
||||
#else
|
||||
#undef REM_USE_WCHAR
|
||||
#endif
|
||||
|
||||
84
src/dorem.c
84
src/dorem.c
@@ -56,10 +56,14 @@ int DoRem(ParsePtr p)
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the trigger date and time */
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) return r;
|
||||
if ( (r=ParseRem(p, &trig, &tim, 1)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (trig.typ == NO_TYPE) {
|
||||
PurgeEchoLine("%s\n%s\n", "#!P! Cannot parse next line", CurLine);
|
||||
FreeTrig(&trig);
|
||||
return E_EOLN;
|
||||
}
|
||||
if (trig.typ == SAT_TYPE) {
|
||||
@@ -67,26 +71,39 @@ int DoRem(ParsePtr p)
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
r=DoSatRemind(&trig, &tim, p);
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
if (r == E_EXPIRED) return OK;
|
||||
return r;
|
||||
}
|
||||
if (!LastTrigValid) return OK;
|
||||
if (!LastTrigValid) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
DBufFree(&buf);
|
||||
if (tok.type == T_Empty || tok.type == T_Comment) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
if (tok.type != T_RemType || tok.val == SAT_TYPE) {
|
||||
DBufFree(&buf);
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (tok.val == PASSTHRU_TYPE) {
|
||||
r=ParseToken(p, &buf);
|
||||
if (r) return r;
|
||||
if (r) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
if (!DBufLen(&buf)) {
|
||||
FreeTrig(&trig);
|
||||
DBufFree(&buf);
|
||||
return E_EOLN;
|
||||
}
|
||||
@@ -95,8 +112,10 @@ int DoRem(ParsePtr p)
|
||||
}
|
||||
trig.typ = tok.val;
|
||||
jul = LastTriggerDate;
|
||||
if (!LastTrigValid) return OK;
|
||||
if (PurgeMode) return OK;
|
||||
if (!LastTrigValid || PurgeMode) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
} else {
|
||||
/* Calculate the trigger date */
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 1);
|
||||
@@ -105,6 +124,7 @@ int DoRem(ParsePtr p)
|
||||
PurgeEchoLine("%s: %s\n", "#!P! Problem calculating trigger date", ErrMsg[r]);
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -125,6 +145,7 @@ int DoRem(ParsePtr p)
|
||||
} else {
|
||||
PurgeEchoLine("%s\n", CurLine);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
/* Queue the reminder, if necessary */
|
||||
@@ -134,17 +155,21 @@ int DoRem(ParsePtr p)
|
||||
FileAccessDate == JulianToday))
|
||||
QueueReminder(p, &trig, &tim, trig.sched);
|
||||
/* If we're in daemon mode, do nothing over here */
|
||||
if (Daemon) return OK;
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
if (Daemon) {
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (ShouldTriggerReminder(&trig, &tim, jul, &err)) {
|
||||
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
|
||||
FreeTrig(&trig);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
FreeTrig(&trig);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
@@ -159,7 +184,6 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
register int r;
|
||||
DynamicBuffer buf;
|
||||
Token tok;
|
||||
|
||||
int y, m, d;
|
||||
|
||||
DBufInit(&buf);
|
||||
@@ -181,7 +205,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
trig->sched[0] = 0;
|
||||
trig->warn[0] = 0;
|
||||
trig->omitfunc[0] = 0;
|
||||
trig->tag[0] = 0;
|
||||
DBufInit(&(trig->tags));
|
||||
trig->passthru[0] = 0;
|
||||
tim->ttime = NO_TIME;
|
||||
tim->delta = NO_DELTA;
|
||||
@@ -277,6 +301,14 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
}
|
||||
return OK;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (trig->rep != NO_REP) return E_REP_TWICE;
|
||||
trig->rep = 1;
|
||||
r = ParseUntil(s, trig);
|
||||
if (r) return r;
|
||||
break;
|
||||
|
||||
case T_Until:
|
||||
DBufFree(&buf);
|
||||
r=ParseUntil(s, trig);
|
||||
@@ -354,7 +386,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
|
||||
case T_Tag:
|
||||
r = ParseToken(s, &buf);
|
||||
if (r) return r;
|
||||
StrnCpy(trig->tag, DBufValue(&buf), TAG_LEN);
|
||||
AppendTag(&(trig->tags), DBufValue(&buf));
|
||||
break;
|
||||
|
||||
case T_Duration:
|
||||
@@ -743,16 +775,12 @@ int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (t->tag[0]) {
|
||||
sprintf(tmpBuf, "%s ", t->tag);
|
||||
} else {
|
||||
sprintf(tmpBuf, "* ");
|
||||
}
|
||||
if (DBufPuts(&calRow, tmpBuf) != OK) {
|
||||
DBufFree(&calRow);
|
||||
DBufFree(&pre_buf);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
if (*DBufValue(&(t->tags))) {
|
||||
DBufPuts(&calRow, DBufValue(&(t->tags)));
|
||||
DBufPutc(&calRow, ' ');
|
||||
} else {
|
||||
DBufPuts(&calRow, "* ");
|
||||
}
|
||||
if (tim->duration != NO_TIME) {
|
||||
sprintf(tmpBuf, "%d ", tim->duration);
|
||||
} else {
|
||||
@@ -923,9 +951,9 @@ int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul, int *err)
|
||||
if (t->delta < 0)
|
||||
jul = jul + t->delta;
|
||||
else {
|
||||
r = t->delta;
|
||||
int iter = 0;
|
||||
int max = MaxSatIter;
|
||||
r = t->delta;
|
||||
if (max < r*2) max = r*2;
|
||||
while(iter++ < max) {
|
||||
if (!r || (jul <= JulianToday)) {
|
||||
|
||||
@@ -205,7 +205,7 @@ EXTERN char *ErrMsg[]
|
||||
"Back value specified twice",
|
||||
"ONCE keyword used twice. (Hah.)",
|
||||
"Expecting time after AT",
|
||||
"UNTIL keyword used twice",
|
||||
"THROUGH/UNTIL keyword used twice",
|
||||
"Incomplete date specification",
|
||||
"FROM/SCANFROM keyword used twice",
|
||||
"Variable",
|
||||
|
||||
@@ -1335,10 +1335,11 @@ static int FShell(func_info *info)
|
||||
/***************************************************************/
|
||||
static int FIsomitted(func_info *info)
|
||||
{
|
||||
int r;
|
||||
if (!HASDATE(ARG(0))) return E_BAD_TYPE;
|
||||
|
||||
RetVal.type = INT_TYPE;
|
||||
int r = IsOmitted(DATEPART(ARG(0)), 0, NULL, &RETVAL);
|
||||
r = IsOmitted(DATEPART(ARG(0)), 0, NULL, &RETVAL);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2659,7 +2660,10 @@ FEvalTrig(func_info *info)
|
||||
p.allownested = 0;
|
||||
r = ParseRem(&p, &trig, &tim, 0);
|
||||
if (r) return r;
|
||||
if (trig.typ != NO_TYPE) return E_PARSE_ERR;
|
||||
if (trig.typ != NO_TYPE) {
|
||||
FreeTrig(&trig);
|
||||
return E_PARSE_ERR;
|
||||
}
|
||||
if (scanfrom == NO_DATE) {
|
||||
jul = ComputeTrigger(trig.scanfrom, &trig, &r, 0);
|
||||
} else {
|
||||
@@ -2669,6 +2673,7 @@ FEvalTrig(func_info *info)
|
||||
}
|
||||
jul = ComputeTrigger(scanfrom, &trig, &r, 0);
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
if (r) return r;
|
||||
if (jul < 0) {
|
||||
RetVal.type = INT_TYPE;
|
||||
|
||||
@@ -96,6 +96,7 @@ EXTERN char const **ArgV;
|
||||
EXTERN INIT( int CalLines, CAL_LINES);
|
||||
EXTERN INIT( int CalPad, 1);
|
||||
EXTERN INIT( int UseVTChars, 0);
|
||||
EXTERN INIT( int UseUTF8Chars, 0);
|
||||
EXTERN INIT( int UseVTColors, 0);
|
||||
|
||||
/* Latitude and longitude */
|
||||
|
||||
@@ -352,6 +352,11 @@ void InitRemind(int argc, char const *argv[])
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'u' || *arg == 'U') {
|
||||
UseUTF8Chars = 1;
|
||||
arg++;
|
||||
continue;
|
||||
}
|
||||
if (*arg == 'c' || *arg == 'C') {
|
||||
UseVTColors = 1;
|
||||
arg++;
|
||||
@@ -785,6 +790,7 @@ static void InitializeVar(char const *str)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static char const pmsg1[] = {
|
||||
0x4c, 0x62, 0x68, 0x20, 0x6e, 0x63, 0x63, 0x72, 0x6e, 0x65, 0x20,
|
||||
0x67, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x68, 0x61, 0x61, 0x76,
|
||||
@@ -815,7 +821,6 @@ static char const pmsg2[] = {
|
||||
0x67, 0x6e, 0x65, 0x76, 0x79, 0x6c, 0x2e, 0x0a, 0x00
|
||||
};
|
||||
|
||||
#if defined(__APPLE__) || defined(__CYGWIN__)
|
||||
static void
|
||||
rkrphgvba(int x)
|
||||
{
|
||||
|
||||
@@ -280,7 +280,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\xE4ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\xE4st\xE4 puuttuu aika",
|
||||
"UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\xE4ytetty kahdesti",
|
||||
"Ep\xE4t\xE4ydellinen p\xE4iv\xE4ys",
|
||||
"FROM/SCANFROM-sanaa k\xE4ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -384,7 +384,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k\x84ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per\x84st\x84 puuttuu aika",
|
||||
"UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k\x84ytetty kahdesti",
|
||||
"Ep\x84t\x84ydellinen p\x84iv\x84ys",
|
||||
"FROM/SCANFROM-sanaa k\x84ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
@@ -488,7 +488,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Peruutusarvo annettu kahdesti",
|
||||
"ONCE-avainsanaa k{ytetty kahdesti. (Hah.)",
|
||||
"AT-sanan per{st{ puuttuu aika",
|
||||
"UNTIL-sanaa k{ytetty kahdesti",
|
||||
"THROUGH/UNTIL-sanaa k{ytetty kahdesti",
|
||||
"Ep{t{ydellinen p{iv{ys",
|
||||
"FROM/SCANFROM-sanaa k{ytetty kahdesti",
|
||||
"Muuttuja",
|
||||
|
||||
@@ -217,7 +217,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour sp\351cifi\351e deux fois",
|
||||
"Mot-cl\351 ONCE utilis\351 deux fois. (Hah.)",
|
||||
"Heure attendue apr\350s AT",
|
||||
"Mot-cl\351 UNTIL utilis\351 deux fois",
|
||||
"Mot-cl\351 THROUGH/UNTIL utilis\351 deux fois",
|
||||
"Sp\351cification de date incompl\350te",
|
||||
"Mot-cl\351 FROM/SCANFROM utilis\351 deux fois",
|
||||
"Variable",
|
||||
@@ -321,7 +321,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valeur de retour specifiee deux fois",
|
||||
"Mot-cle ONCE utilise deux fois. (Hah.)",
|
||||
"Heure attendue apres AT",
|
||||
"Mot-cle UNTIL utilise deux fois",
|
||||
"Mot-cle THROUGH/UNTIL utilise deux fois",
|
||||
"Specification de date incomplete",
|
||||
"Mot-cle FROM/SCANFROM utilise deux fois",
|
||||
"Variable",
|
||||
|
||||
@@ -252,7 +252,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Warto\266\346 cofni\352cia podana dw\363krotnie",
|
||||
"S\263owo ONCE u\277yte dw\363krotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"S\263owo UNTIL u\277yte dw\363krotnie",
|
||||
"S\263owo THROUGH/UNTIL u\277yte dw\363krotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"S\263owo FROM/SCANFROM u\277yte dw\363krotnie",
|
||||
"Zmienna",
|
||||
@@ -355,7 +355,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Wartosc cofniecia podana dwokrotnie",
|
||||
"Slowo ONCE uzyte dwokrotnie.",
|
||||
"Po AT oczekiwany jest czas",
|
||||
"Slowo UNTIL uzyte dwokrotnie",
|
||||
"Slowo THROUGH/UNTIL uzyte dwokrotnie",
|
||||
"Niekompletna specyfikacja daty",
|
||||
"Slowo FROM/SCANFROM uzyte dwokrotnie",
|
||||
"Zmienna",
|
||||
|
||||
@@ -218,7 +218,7 @@ EXTERN char *ErrMsg[] =
|
||||
"Valor de Back especificado duas vezes",
|
||||
"ONCE usado duas vezes (Eheheh)",
|
||||
"Esperando hora apos AT",
|
||||
"Keyword UNTIL usada duas vezes",
|
||||
"Keyword THROUGH/UNTIL usada duas vezes",
|
||||
"Especificacao de data incompleta",
|
||||
"Keyword FROM/SCANFROM usada duas vezes",
|
||||
"Variavel",
|
||||
|
||||
23
src/main.c
23
src/main.c
@@ -19,6 +19,9 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
@@ -57,6 +60,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int pid;
|
||||
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
/* The very first thing to do is to set up ErrFp to be stderr */
|
||||
ErrFp = stderr;
|
||||
|
||||
@@ -806,6 +813,7 @@ int DoIfTrig(ParsePtr p)
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeTrig(&trig);
|
||||
}
|
||||
NumIfs++;
|
||||
IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
|
||||
@@ -1299,3 +1307,18 @@ void SigIntHandler(int d)
|
||||
GotSigInt();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
AppendTag(DynamicBuffer *buf, char const *s)
|
||||
{
|
||||
if (*(DBufValue(buf))) {
|
||||
DBufPutc(buf, ',');
|
||||
}
|
||||
DBufPuts(buf, s);
|
||||
}
|
||||
|
||||
void
|
||||
FreeTrig(Trigger *t)
|
||||
{
|
||||
DBufFree(&(t->tags));
|
||||
}
|
||||
|
||||
138
src/omit.c
138
src/omit.c
@@ -125,7 +125,7 @@ int PushOmitContext(ParsePtr p)
|
||||
free(context);
|
||||
return E_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
/* Copy the context over */
|
||||
for (i=0; i<NumFullOmits; i++)
|
||||
*(context->fullsave + i) = FullOmitArray[i];
|
||||
@@ -272,6 +272,9 @@ static void InsertIntoSortedArray(int *array, int num, int key)
|
||||
*cur = key;
|
||||
}
|
||||
|
||||
static int DoThroughOmit(ParsePtr p, int y, int m, int d);
|
||||
static void DumpOmits(void);
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* DoOmit */
|
||||
@@ -285,15 +288,25 @@ int DoOmit(ParsePtr p)
|
||||
Token tok;
|
||||
int parsing=1;
|
||||
int syndrome;
|
||||
int not_first_token = -1;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
|
||||
/* Parse the OMIT. We need a month and day; year is optional. */
|
||||
while(parsing) {
|
||||
not_first_token++;
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
switch (tok.type) {
|
||||
case T_Dumpvars:
|
||||
if (not_first_token) return E_PARSE_ERR;
|
||||
DBufFree(&buf);
|
||||
r = VerifyEoln(p);
|
||||
if (r != OK) return r;
|
||||
DumpOmits();
|
||||
return OK;
|
||||
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (y != NO_YR) return E_YR_TWICE;
|
||||
@@ -324,6 +337,11 @@ int DoOmit(ParsePtr p)
|
||||
DBufFree(&buf);
|
||||
break;
|
||||
|
||||
case T_Through:
|
||||
DBufFree(&buf);
|
||||
if (y == NO_YR || m == NO_MON || d == NO_DAY) return E_INCOMPLETE;
|
||||
return DoThroughOmit(p, y, m, d);
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
@@ -362,7 +380,123 @@ int DoOmit(ParsePtr p)
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
DoThroughOmit(ParsePtr p, int ystart, int mstart, int dstart)
|
||||
{
|
||||
int yend = NO_YR, mend = NO_MON, dend = NO_DAY, r;
|
||||
int start, end, tmp;
|
||||
|
||||
Token tok;
|
||||
|
||||
DynamicBuffer buf;
|
||||
DBufInit(&buf);
|
||||
int parsing = 1;
|
||||
|
||||
while(parsing) {
|
||||
if ( (r=ParseToken(p, &buf)) ) return r;
|
||||
FindToken(DBufValue(&buf), &tok);
|
||||
|
||||
switch(tok.type) {
|
||||
case T_Date:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
FromJulian(tok.val, ¥d, &mend, &dend);
|
||||
break;
|
||||
|
||||
case T_Year:
|
||||
DBufFree(&buf);
|
||||
if (yend != NO_YR) return E_YR_TWICE;
|
||||
yend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Month:
|
||||
DBufFree(&buf);
|
||||
if (mend != NO_MON) return E_MON_TWICE;
|
||||
mend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Day:
|
||||
DBufFree(&buf);
|
||||
if (dend != NO_DAY) return E_DAY_TWICE;
|
||||
dend = tok.val;
|
||||
break;
|
||||
|
||||
case T_Empty:
|
||||
case T_Comment:
|
||||
case T_RemType:
|
||||
case T_Priority:
|
||||
case T_Tag:
|
||||
case T_Duration:
|
||||
DBufFree(&buf);
|
||||
parsing = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Eprint("%s: `%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN],
|
||||
DBufValue(&buf));
|
||||
DBufFree(&buf);
|
||||
return E_UNKNOWN_TOKEN;
|
||||
|
||||
}
|
||||
}
|
||||
if (yend == NO_YR || mend == NO_MON || dend == NO_DAY) return E_INCOMPLETE;
|
||||
if (dend > DaysInMonth(mend, yend)) return E_BAD_DATE;
|
||||
if (dstart > DaysInMonth(mstart, ystart)) return E_BAD_DATE;
|
||||
|
||||
start = Julian(ystart, mstart, dstart);
|
||||
end = Julian(yend, mend, dend);
|
||||
|
||||
if (end < start) {
|
||||
tmp = start;
|
||||
start = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
tmp = end - start + 1;
|
||||
|
||||
/* Don't create any OMITs if there would be too many. */
|
||||
if (NumFullOmits + tmp >= MAX_FULL_OMITS) return E_2MANY_FULL;
|
||||
for (tmp = start; tmp <= end; tmp++) {
|
||||
if (!BexistsIntArray(FullOmitArray, NumFullOmits, tmp)) {
|
||||
InsertIntoSortedArray(FullOmitArray, NumFullOmits, tmp);
|
||||
NumFullOmits++;
|
||||
}
|
||||
}
|
||||
if (tok.type == T_Tag || tok.type == T_Duration || tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void
|
||||
DumpOmits(void)
|
||||
{
|
||||
int i;
|
||||
int y, m, d;
|
||||
printf("Global Full OMITs (%d of maximum allowed %d):\n", NumFullOmits, MAX_FULL_OMITS);
|
||||
if (!NumFullOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumFullOmits; i++) {
|
||||
FromJulian(FullOmitArray[i], &y, &m, &d);
|
||||
printf("\t%04d%c%02d%c%02d\n",
|
||||
y, DateSep, m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
printf("Global Partial OMITs (%d of maximum allowed %d):\n", NumPartialOmits, MAX_PARTIAL_OMITS);
|
||||
if (!NumPartialOmits) {
|
||||
printf("\tNone.\n");
|
||||
} else {
|
||||
for (i=0; i<NumPartialOmits; i++) {
|
||||
m = PartialOmitArray[i] >> 5 & 0xf;
|
||||
d = PartialOmitArray[i] & 0x1f;
|
||||
printf("\t%02d%c%02d\n", m+1, DateSep, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,5 +136,7 @@ void HuntPhase (int startdate, int starttim, int phas, int *date, int *time);
|
||||
int CompareRems (int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio, int untimed_first);
|
||||
void SigIntHandler (int d);
|
||||
void GotSigInt (void);
|
||||
void SynthesizeTag(char *);
|
||||
void PurgeEchoLine(char const *fmt, ...);
|
||||
void FreeTrig(Trigger *t);
|
||||
void AppendTag(DynamicBuffer *buf, char const *s);
|
||||
char const *SynthesizeTag(void);
|
||||
|
||||
16
src/queue.c
16
src/queue.c
@@ -43,7 +43,7 @@ typedef struct queuedrem {
|
||||
char const *text;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
char sched[VAR_NAME_LEN+1];
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
TimeTrig tt;
|
||||
} QueuedRem;
|
||||
|
||||
@@ -96,9 +96,10 @@ int QueueReminder(ParsePtr p, Trigger *trig,
|
||||
qelem->RunDisabled = RunDisabled;
|
||||
qelem->ntrig = 0;
|
||||
strcpy(qelem->sched, sched);
|
||||
strcpy(qelem->tag, trig->tag);
|
||||
if (! *qelem->tag && SynthesizeTags) {
|
||||
SynthesizeTag(qelem->tag);
|
||||
DBufInit(&(qelem->tags));
|
||||
DBufPuts(&(qelem->tags), DBufValue(&(trig->tags)));
|
||||
if (SynthesizeTags) {
|
||||
AppendTag(&(qelem->tags), SynthesizeTag());
|
||||
}
|
||||
QueueHead = qelem;
|
||||
return OK;
|
||||
@@ -235,12 +236,11 @@ void HandleQueuedReminders(void)
|
||||
printf("NOTE reminder %s",
|
||||
SimpleTime(q->tt.ttime));
|
||||
printf("%s", SimpleTime(SystemTime(0)/60));
|
||||
if (!*q->tag) {
|
||||
printf("*");
|
||||
if (!*DBufValue(&q->tags)) {
|
||||
printf("*\n");
|
||||
} else {
|
||||
printf("%s", q->tag);
|
||||
printf("%s\n", DBufValue(&(q->tags)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Set up global variables so some functions like trigdate()
|
||||
|
||||
@@ -94,6 +94,7 @@ Token TokArray[] = {
|
||||
{ "special", 7, T_RemType, PASSTHRU_TYPE },
|
||||
{ "sunday", 3, T_WkDay, 6 },
|
||||
{ "tag", 3, T_Tag, 0 },
|
||||
{ "through", 7, T_Through, 0 },
|
||||
{ "thursday", 3, T_WkDay, 3 },
|
||||
{ "tuesday", 3, T_WkDay, 1 },
|
||||
{ "unset", 5, T_UnSet, 0 },
|
||||
@@ -359,7 +360,7 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
register int r;
|
||||
char const *tk = t->name;
|
||||
while(*tk && *s && !(*s == ',' && *(s+1) == 0)) {
|
||||
r = *tk - tolower(*s);
|
||||
r = tolower(*tk) - tolower(*s);
|
||||
tk++;
|
||||
s++;
|
||||
if (r) return r;
|
||||
@@ -367,5 +368,5 @@ static int TokStrCmp(Token const *t, char const *s)
|
||||
/* Ignore trailing commas on s */
|
||||
|
||||
if (!*s || (*s == ',' && !*(s+1))) return 0;
|
||||
return (*tk - *s);
|
||||
return (tolower(*tk) - tolower(*s));
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ typedef struct {
|
||||
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
|
||||
char warn[VAR_NAME_LEN+1]; /* Warning function */
|
||||
char omitfunc[VAR_NAME_LEN+1]; /* OMITFUNC function */
|
||||
char tag[TAG_LEN+1];
|
||||
DynamicBuffer tags;
|
||||
char passthru[PASSTHRU_LEN+1];
|
||||
} Trigger;
|
||||
|
||||
@@ -167,7 +167,8 @@ enum TokTypes
|
||||
T_Tag,
|
||||
T_Duration,
|
||||
T_LongTime,
|
||||
T_OmitFunc
|
||||
T_OmitFunc,
|
||||
T_Through
|
||||
};
|
||||
|
||||
/* The structure of a token */
|
||||
|
||||
@@ -22,28 +22,28 @@ chmod 000 include_dir/04cantread.rem
|
||||
TEST_GETENV="foo bar baz" ; export TEST_GETENV
|
||||
echo "Test 1" > ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out
|
||||
../src/remind -e -dxte ../tests/test.rem 16 feb 1991 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 2" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 3" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -s ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "" >> ../tests/test.out
|
||||
echo "Test 4" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -sa ../tests/test2.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 5" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b0 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 6" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b1 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
echo "Test 7" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -p -l -b2 ../tests/test3.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Test 8" >> ../tests/test.out
|
||||
echo "" >> ../tests/test.out
|
||||
@@ -58,14 +58,14 @@ echo "" >> ../tests/test.out
|
||||
chmod 644 include_dir/04cantread.rem
|
||||
|
||||
echo "Color Test" >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out
|
||||
../src/remind -ccl ../tests/colors.rem 1 aug 2007 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "MON WKDAY DAY across year test" >> ../tests/test.out
|
||||
echo 'REM Mon 29 Dec MSG x' | ../src/remind -dt - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Sort Test" >> ../tests/test.out
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaa - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
(echo "REM AT 12:00 MSG Untimed"; echo "REM MSG Timed") | ../src/remind -q -gaaad - 1 Jan 2000 >> ../tests/test.out 2>&1
|
||||
|
||||
echo "Purge Test" >> ../tests/test.out
|
||||
../src/remind -j999 ../tests/purge_dir/f1.rem >> ../tests/test.out 2>&1
|
||||
|
||||
@@ -836,7 +836,7 @@ set a057 value("a05"+"6")
|
||||
"a05" + "6" => "a056"
|
||||
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
|
||||
set a058 version()
|
||||
version() => "03.01.09"
|
||||
version() => "03.01.10"
|
||||
set a059 wkday(today())
|
||||
today() => 1991-02-16
|
||||
wkday(1991-02-16) => "Saturday"
|
||||
@@ -989,7 +989,7 @@ dump
|
||||
a048 "foo"
|
||||
a067 "INT"
|
||||
a039 "February"
|
||||
a058 "03.01.09"
|
||||
a058 "03.01.10"
|
||||
a077 "1992 92
|
||||
"
|
||||
a049 21
|
||||
@@ -1046,6 +1046,32 @@ dump
|
||||
a045 "iess"
|
||||
a064 1
|
||||
a083 1991-03-24
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
OMIT December 25 MSG X
|
||||
../tests/test.rem(286): Trig = Wednesday, 25 December, 1991
|
||||
# Next should give a parse error
|
||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
../tests/test.rem(288): Trig = Sunday, 26 December, 2010
|
||||
OMIT DUMP
|
||||
Global Full OMITs (16 of maximum allowed 500):
|
||||
1991-03-11
|
||||
2010-09-03
|
||||
2010-09-04
|
||||
2010-09-05
|
||||
2010-09-06
|
||||
2010-09-07
|
||||
2010-09-08
|
||||
2010-09-09
|
||||
2010-09-10
|
||||
2010-09-11
|
||||
2010-09-12
|
||||
2010-09-13
|
||||
2010-09-14
|
||||
2010-09-15
|
||||
2010-12-26
|
||||
2010-12-27
|
||||
Global Partial OMITs (1 of maximum allowed 366):
|
||||
12-25
|
||||
|
||||
|
||||
Test 2
|
||||
|
||||
@@ -282,3 +282,8 @@ 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")
|
||||
dump
|
||||
OMIT 2010-09-03 THROUGH 2010-09-15
|
||||
OMIT December 25 MSG X
|
||||
# Next should give a parse error
|
||||
OMIT 26 Dec 2010 THROUGH 27 Dec 2010 MSG This is not legal
|
||||
OMIT DUMP
|
||||
|
||||
Reference in New Issue
Block a user