src/recur.c: Support recurrent multi-day appointments
Completely rewrite our inday algorithm in recur_item_inday() and be more fine-grained. This version can deal with recurrent multi-day appointments unless they overlap. In case of overlapping appointments, only the last appointment that starts before the current day is shown. We will need to rewrite the whole recur_item_inday() interface in order to fix this - this relatively trivial patch is only the first step. Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
parent
2d89d33668
commit
0d51e61f3d
95
src/recur.c
95
src/recur.c
@ -635,74 +635,79 @@ recur_item_inday (long item_start, long item_dur, llist_t *item_exc,
|
|||||||
int rpt_type, int rpt_freq, long rpt_until, long day_start)
|
int rpt_type, int rpt_freq, long rpt_until, long day_start)
|
||||||
{
|
{
|
||||||
struct date start_date;
|
struct date start_date;
|
||||||
long day_end, diff;
|
long diff, span;
|
||||||
struct tm lt_item, lt_day;
|
struct tm lt_day, lt_item, lt_item_day;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
day_end = day_start + DAYINSEC;
|
if (day_start < item_start - DAYINSEC + 1)
|
||||||
t = day_start;
|
|
||||||
lt_day = *localtime (&t);
|
|
||||||
|
|
||||||
if (LLIST_FIND_FIRST (item_exc, day_start, exc_inday))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rpt_until == 0) /* we have an endless recurrent item */
|
t = day_start;
|
||||||
rpt_until = day_end;
|
lt_day = *localtime (&t);
|
||||||
|
|
||||||
if (item_start > day_end || rpt_until < day_start)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
t = item_start;
|
t = item_start;
|
||||||
lt_item = *localtime (&t);
|
lt_item = *localtime (&t);
|
||||||
|
|
||||||
|
lt_item_day = lt_item;
|
||||||
|
lt_item_day.tm_sec = lt_item_day.tm_min = lt_item_day.tm_hour = 0;
|
||||||
|
|
||||||
|
span = (item_start - mktime (<_item_day) + item_dur - 1) / DAYINSEC;
|
||||||
|
|
||||||
switch (rpt_type)
|
switch (rpt_type)
|
||||||
{
|
{
|
||||||
case RECUR_DAILY:
|
case RECUR_DAILY:
|
||||||
diff = diff_days (lt_item, lt_day);
|
diff = diff_days (lt_item_day, lt_day) % rpt_freq;
|
||||||
if (diff % rpt_freq != 0)
|
lt_item_day.tm_mday = lt_day.tm_mday - diff;
|
||||||
return (0);
|
lt_item_day.tm_mon = lt_day.tm_mon;
|
||||||
lt_item.tm_mday = lt_day.tm_mday;
|
lt_item_day.tm_year = lt_day.tm_year;
|
||||||
lt_item.tm_mon = lt_day.tm_mon;
|
|
||||||
lt_item.tm_year = lt_day.tm_year;
|
|
||||||
break;
|
break;
|
||||||
case RECUR_WEEKLY:
|
case RECUR_WEEKLY:
|
||||||
if (lt_item.tm_wday != lt_day.tm_wday)
|
diff = diff_days (lt_item_day, lt_day) % (rpt_freq * WEEKINDAYS);
|
||||||
return (0);
|
lt_item_day.tm_mday = lt_day.tm_mday - diff;
|
||||||
else
|
lt_item_day.tm_mon = lt_day.tm_mon;
|
||||||
{
|
lt_item_day.tm_year = lt_day.tm_year;
|
||||||
diff = diff_weeks (lt_item, lt_day);
|
|
||||||
if (diff % rpt_freq != 0)
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
lt_item.tm_mday = lt_day.tm_mday;
|
|
||||||
lt_item.tm_mon = lt_day.tm_mon;
|
|
||||||
lt_item.tm_year = lt_day.tm_year;
|
|
||||||
break;
|
break;
|
||||||
case RECUR_MONTHLY:
|
case RECUR_MONTHLY:
|
||||||
diff = diff_months (lt_item, lt_day);
|
diff = diff_months (lt_item_day, lt_day) % rpt_freq;
|
||||||
if (diff % rpt_freq != 0)
|
if (lt_day.tm_mday < lt_item_day.tm_mday)
|
||||||
return (0);
|
diff++;
|
||||||
lt_item.tm_mon = lt_day.tm_mon;
|
lt_item_day.tm_mon = lt_day.tm_mon - diff;
|
||||||
lt_item.tm_year = lt_day.tm_year;
|
lt_item_day.tm_year = lt_day.tm_year;
|
||||||
break;
|
break;
|
||||||
case RECUR_YEARLY:
|
case RECUR_YEARLY:
|
||||||
diff = diff_years (lt_item, lt_day);
|
diff = diff_years (lt_item_day, lt_day) % rpt_freq;
|
||||||
if (diff % rpt_freq != 0)
|
if (lt_day.tm_mon < lt_item_day.tm_mon ||
|
||||||
return (0);
|
(lt_day.tm_mon == lt_item_day.tm_mon &&
|
||||||
lt_item.tm_year = lt_day.tm_year;
|
lt_day.tm_mday < lt_item_day.tm_mday))
|
||||||
|
diff++;
|
||||||
|
lt_item_day.tm_year = lt_day.tm_year - diff;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
EXIT (_("unknown item type"));
|
EXIT (_("unknown item type"));
|
||||||
}
|
}
|
||||||
start_date.dd = lt_item.tm_mday;
|
|
||||||
start_date.mm = lt_item.tm_mon + 1;
|
|
||||||
start_date.yyyy = lt_item.tm_year + 1900;
|
|
||||||
item_start = date2sec (start_date, lt_item.tm_hour, lt_item.tm_min);
|
|
||||||
|
|
||||||
if (item_start < day_end && item_start >= day_start)
|
lt_item_day.tm_isdst = lt_day.tm_isdst;
|
||||||
return (item_start);
|
t = mktime (<_item_day);
|
||||||
|
|
||||||
|
if (LLIST_FIND_FIRST (item_exc, t, exc_inday))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rpt_until != 0 && t > rpt_until)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lt_item_day = *localtime (&t);
|
||||||
|
diff = diff_days (lt_item_day, lt_day);
|
||||||
|
|
||||||
|
if (diff <= span)
|
||||||
|
{
|
||||||
|
start_date.dd = lt_item_day.tm_mday;
|
||||||
|
start_date.mm = lt_item_day.tm_mon + 1;
|
||||||
|
start_date.yyyy = lt_item_day.tm_year + 1900;
|
||||||
|
|
||||||
|
return date2sec (start_date, lt_item.tm_hour, lt_item.tm_min);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
|
Loading…
x
Reference in New Issue
Block a user