Support multiple TAGs in a single REM.

This commit is contained in:
David F. Skoll
2010-09-23 15:47:22 -04:00
parent da429b9629
commit be86746685
7 changed files with 287 additions and 89 deletions

View File

@@ -42,7 +42,7 @@ typedef struct cal_entry {
int r, g, b;
int time;
int priority;
char tag[TAG_LEN+1];
Tag *tags;
char passthru[PASSTHRU_LEN+1];
int duration;
char const *filename;
@@ -941,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);
@@ -971,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 */
@@ -987,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 */
@@ -1037,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;
}
}
@@ -1059,6 +1101,7 @@ static int DoCalRem(ParsePtr p, int col)
DestroyValue(v);
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
}
@@ -1077,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 &&
@@ -1096,6 +1141,7 @@ static int DoCalRem(ParsePtr p, int col)
DestroyValue(v);
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
}
@@ -1110,6 +1156,7 @@ static int DoCalRem(ParsePtr p, int col)
if (!e) {
DBufFree(&obuf);
DBufFree(&pre_buf);
FreeTrig(&trig);
return E_NO_MEM;
}
#ifdef REM_USE_WCHAR
@@ -1125,17 +1172,18 @@ static int DoCalRem(ParsePtr p, int col)
DBufFree(&pre_buf);
if (!e->text) {
free(e);
FreeTrig(&trig);
return E_NO_MEM;
}
make_wchar_versions(e);
StrnCpy(e->tag, trig.tag, TAG_LEN);
if (!e->tag[0]) {
e->tags = CloneTags(trig.tags);
if (!e->tags) {
if (SynthesizeTags) {
SynthesizeTag(e->tag);
} else {
strcpy(e->tag, "*");
e->tags = SynthesizeTag();
}
}
/* Don't need tags any more */
FreeTrig(&trig);
e->duration = tim.duration;
e->priority = trig.priority;
e->filename = StrDup(FileName);
@@ -1185,7 +1233,13 @@ static void WriteSimpleEntries(int col, int jul)
} else {
printf(" *");
}
printf(" %s ", e->tag);
if (e->tags) {
printf(" ");
PrintTagChain(stdout, e->tags);
printf(" ");
} else {
printf(" * ");
}
if (e->duration != NO_TIME) {
printf("%d ", e->duration);
} else {
@@ -1471,10 +1525,11 @@ static void SortCol(CalEntry **col)
}
}
void SynthesizeTag(char *out)
Tag *SynthesizeTag(void)
{
struct MD5Context ctx;
unsigned char buf[16];
char out[128];
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) CurLine, strlen(CurLine));
MD5Final(buf, &ctx);
@@ -1487,5 +1542,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 MakeTag(out);
}

View File

@@ -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,7 @@ int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim, int save_in_globals)
register int r;
DynamicBuffer buf;
Token tok;
Tag *newtag;
int y, m, d;
DBufInit(&buf);
@@ -181,7 +206,8 @@ 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;
trig->tags = NULL;
trig->last_tag = NULL;
trig->passthru[0] = 0;
tim->ttime = NO_TIME;
tim->delta = NO_DELTA;
@@ -362,7 +388,17 @@ 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);
newtag = MakeTag(DBufValue(&buf));
if (newtag) {
if (trig->last_tag) {
trig->last_tag->next = newtag;
trig->last_tag = newtag;
} else {
trig->tags = newtag;
trig->last_tag = newtag;
}
newtag->next = NULL;
}
break;
case T_Duration:
@@ -751,16 +787,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 (t->tags) {
AppendTagChain(&calRow, t->tags);
DBufPuts(&calRow, " ");
} else {
DBufPuts(&calRow, "* ");
}
if (tim->duration != NO_TIME) {
sprintf(tmpBuf, "%d ", tim->duration);
} else {

View File

@@ -2660,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 {
@@ -2670,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;

View File

@@ -813,6 +813,7 @@ int DoIfTrig(ParsePtr p)
}
}
}
FreeTrig(&trig);
}
NumIfs++;
IfFlags &= ~(IF_MASK << (2*NumIfs - 2));
@@ -1306,3 +1307,99 @@ void SigIntHandler(int d)
GotSigInt();
exit(0);
}
Tag *
CloneTag(Tag const *t)
{
return MakeTag(t->tag);
}
Tag *
MakeTag(char const *s)
{
Tag *u = malloc(sizeof(Tag));
if (!u) return NULL;
StrnCpy(u->tag, s, TAG_LEN);
u->next = NULL;
return u;
}
void
FreeTags (Tag *chain)
{
Tag *next;
if (!chain) return;
while(chain) {
next = chain->next;
free(chain);
chain = next;
}
}
Tag *
CloneTags(Tag const *chain)
{
Tag *head, *tail, *t;
if (!chain) return NULL;
head = NULL;
tail = NULL;
while(chain) {
t = CloneTag(chain);
if (!t) {
FreeTags(head);
return NULL;
}
if (!head) {
head = t;
tail = t;
} else {
tail->next = t;
tail = t;
}
t->next = NULL;
chain = chain->next;
}
return head;
}
void
PrintTagChain(FILE *fp, Tag *chain)
{
if (!chain) return;
int done_one = 0;
while(chain) {
if (done_one) {
fprintf(fp, ",");
}
done_one = 1;
fprintf(fp, "%s", chain->tag);
chain = chain->next;
}
}
void
AppendTagChain(DynamicBuffer *buf, Tag *chain)
{
if (!chain) return;
int done_one = 0;
while(chain) {
if (done_one) {
DBufPuts(buf, ",");
}
done_one = 1;
DBufPuts(buf, chain->tag);
chain = chain->next;
}
}
void
FreeTrig(Trigger *t)
{
FreeTags(t->tags);
t->tags = NULL;
t->last_tag = NULL;
}

View File

@@ -136,5 +136,11 @@ 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 *);
Tag *SynthesizeTag(void);
Tag *CloneTags(Tag const *t);
Tag *MakeTag(char const *s);
void FreeTags(Tag *chain);
void PrintTagChain(FILE *fp, Tag *chain);
void PurgeEchoLine(char const *fmt, ...);
void AppendTagChain(DynamicBuffer *buf, Tag *chain);
void FreeTrig(Trigger *t);

View File

@@ -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];
Tag *tags;
TimeTrig tt;
} QueuedRem;
@@ -96,9 +96,9 @@ 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);
qelem->tags = CloneTags(trig->tags);
if (!qelem->tags && SynthesizeTags) {
qelem->tags = SynthesizeTag();
}
QueueHead = qelem;
return OK;
@@ -235,11 +235,7 @@ void HandleQueuedReminders(void)
printf("NOTE reminder %s",
SimpleTime(q->tt.ttime));
printf("%s", SimpleTime(SystemTime(0)/60));
if (!*q->tag) {
printf("*");
} else {
printf("%s", q->tag);
}
PrintTagChain(stdout, q->tags);
printf("\n");
}

View File

@@ -53,6 +53,12 @@ typedef struct var {
Value v;
} Var;
/* A tag */
typedef struct tag_t {
struct tag_t *next;
char tag[TAG_LEN+1];
} Tag;
/* A trigger */
typedef struct {
int expired;
@@ -73,7 +79,8 @@ 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];
Tag *tags;
Tag *last_tag;
char passthru[PASSTHRU_LEN+1];
} Trigger;