mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
606 lines
17 KiB
C
606 lines
17 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: renexttick.c /main/5 1996/11/21 19:46:22 drk $ */
|
|
/*
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994 Novell, Inc.
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
*/
|
|
|
|
|
|
#define XOS_USE_NO_LOCKING
|
|
#define X_INCLUDE_TIME_H
|
|
#if defined(__linux__)
|
|
#undef SVR4
|
|
#endif
|
|
#include <X11/Xos_r.h>
|
|
|
|
#include "rerule.h"
|
|
#include "repeat.h"
|
|
#include "reutil.h"
|
|
|
|
typedef enum {
|
|
SameInterval = 0,
|
|
NextInterval
|
|
} MoveIndicator;
|
|
|
|
static Tick DoMinute(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoDay(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoWeek(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoMonthDay(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoMonthPos(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoYearByMonth(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick DoYearByDay(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
|
|
static Tick NextDayTick(const Tick, const Tick, const RepeatEvent *,
|
|
RepeatEventState *);
|
|
static Tick NextWeekTick(const struct tm *, const struct tm *,
|
|
const RepeatEvent *, const DayTime *,
|
|
const MoveIndicator, RepeatEventState *);
|
|
static Tick NextMonthTick(const struct tm *, const RepeatEvent *,
|
|
const WeekDayTime *, const MoveIndicator,
|
|
RepeatEventState *);
|
|
extern void FillInRepeatEvent(const Tick, RepeatEvent *);
|
|
|
|
Tick
|
|
NextTick(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
Tick next_time = 0;
|
|
|
|
if (!re) return (Tick)0;
|
|
|
|
FillInRepeatEvent(start_time, re);
|
|
|
|
switch (re->re_type) {
|
|
case RT_MINUTE:
|
|
next_time = DoMinute(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_DAILY:
|
|
next_time = DoDay(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_WEEKLY:
|
|
next_time = DoWeek(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_MONTHLY_POSITION:
|
|
next_time = DoMonthPos(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_MONTHLY_DAY:
|
|
next_time = DoMonthDay(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_YEARLY_MONTH:
|
|
next_time = DoYearByMonth(cur_time, start_time, re, res);
|
|
break;
|
|
case RT_YEARLY_DAY:
|
|
next_time = DoYearByDay(cur_time, start_time, re, res);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* If the duration was not set (thus strictly using the end date)
|
|
* reset the RepeatEventState duration back to not-set. This is
|
|
* cleaner than having conditionals through out the code checking
|
|
* to see if the duration needs to be updated.
|
|
*/
|
|
if (re->re_duration == RE_NOTSET)
|
|
res->res_duration = RE_NOTSET;
|
|
|
|
return next_time;
|
|
}
|
|
|
|
static Tick
|
|
DoMinute(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
return (Tick)0;
|
|
}
|
|
|
|
static Tick
|
|
DoDay(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
Tick next_time;
|
|
Duration res_duration = res->res_duration;
|
|
unsigned int res_time = RES_DSTATE(res).res_time;
|
|
|
|
if (RE_DAILY(re)->dd_ntime) {
|
|
/* Last event was on the last time for this day. Now must
|
|
* move to the next day/interval.
|
|
*/
|
|
if (RES_DSTATE(res).res_time == RE_DAILY(re)->dd_ntime - 1) {
|
|
next_time = NextDayTick(cur_time, start_time, re, res);
|
|
RES_DSTATE(res).res_time = 0;
|
|
} else {
|
|
struct tm *tm;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
/* There is a later valid time on this day, use it */
|
|
tm = _XLocaltime(&cur_time, localtime_buf);
|
|
tm->tm_hour =
|
|
RE_DAILY(re)->
|
|
dd_time[++RES_DSTATE(res).res_time] / 100;
|
|
tm->tm_min =
|
|
RE_DAILY(re)->dd_time[RES_DSTATE(res).res_time]
|
|
% 100;
|
|
tm->tm_isdst = -1;
|
|
next_time = mktime(tm);
|
|
}
|
|
} else {
|
|
/* No alternate times for this day/move to the next interval. */
|
|
next_time = NextDayTick(cur_time, start_time, re, res);
|
|
}
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < next_time) {
|
|
res->res_duration = res_duration;
|
|
RES_DSTATE(res).res_time = res_time;
|
|
return 0;
|
|
}
|
|
|
|
return next_time;
|
|
}
|
|
|
|
static Tick
|
|
DoWeek(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
unsigned int res_daytime = RES_WSTATE(res).res_daytime,
|
|
res_time = RES_WSTATE(res).res_time,
|
|
re_ntime,
|
|
re_ndaytime = RE_WEEKLY(re)->wd_ndaytime;
|
|
Duration res_duration = res->res_duration;
|
|
struct tm cur_tm,
|
|
start_tm;
|
|
DayTime *daytime = RE_WEEKLY(re)->wd_daytime;
|
|
Tick next_time;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
cur_tm = *_XLocaltime((const time_t *)&cur_time, localtime_buf);
|
|
start_tm = *_XLocaltime((const time_t *)&start_time, localtime_buf);
|
|
|
|
re_ntime = daytime[0].dt_ntime;
|
|
|
|
/*
|
|
* We want to stop when the duration == 1 and we have handled all
|
|
* the days in the rule for that week.
|
|
*/
|
|
if ((res->res_duration == 0) || ((res->res_duration == 1) &&
|
|
((re_ndaytime - 1) == RES_WSTATE(res).res_daytime)))
|
|
return (Tick)0;
|
|
|
|
/* If these are equal then we are at the end of the time
|
|
* slots for this day */
|
|
if ((re_ntime - 1) == res_time) {
|
|
/* If these are equal then we used up all the
|
|
* days for this week */
|
|
if ((re_ndaytime - 1) == res_daytime) {
|
|
|
|
/* End of week */
|
|
RES_WSTATE(res).res_daytime = 0;
|
|
RES_WSTATE(res).res_time = 0;
|
|
next_time = NextWeekTick(&cur_tm, &start_tm, re,
|
|
daytime, NextInterval, res);
|
|
} else {
|
|
/* Move to the next day event (same week), use
|
|
* the earliest time.
|
|
*/
|
|
RES_WSTATE(res).res_time = 0;
|
|
RES_WSTATE(res).res_daytime++;
|
|
next_time = NextWeekTick(&cur_tm, &start_tm, re,
|
|
daytime, SameInterval, res);
|
|
}
|
|
} else {
|
|
/* Move to the next time, same day. */
|
|
RES_WSTATE(res).res_time++;
|
|
next_time = NextWeekTick(&cur_tm, &start_tm, re, daytime,
|
|
SameInterval, res);
|
|
}
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < next_time) {
|
|
res->res_duration = res_duration;
|
|
RES_WSTATE(res).res_time = res_time;
|
|
RES_WSTATE(res).res_daytime = res_daytime;
|
|
return 0;
|
|
}
|
|
|
|
return (next_time);
|
|
}
|
|
|
|
static Tick
|
|
DoMonthDay(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
unsigned int *md_days = RE_MONTHLY(re)->md_days,
|
|
md_nitems = RE_MONTHLY(re)->md_nitems,
|
|
res_day = RES_MSTATE(res).res_day;
|
|
Duration res_duration = res->res_duration;
|
|
Tick _cur_time;
|
|
struct tm start_tm,
|
|
cur_tm;
|
|
int next_interval = FALSE;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
start_tm = *_XLocaltime((const time_t *)&start_time, localtime_buf);
|
|
cur_tm = *_XLocaltime((const time_t *)&cur_time, localtime_buf);
|
|
|
|
/*
|
|
* We want to stop when the duration == 1 and we have handled all
|
|
* the days listed in the rule for that month.
|
|
*/
|
|
if ((res->res_duration == 0) || ((res->res_duration == 1) &&
|
|
((md_nitems - 1) == RES_MSTATE(res).res_day)))
|
|
return (Tick)0;
|
|
|
|
/* Check each event day in the month, move to the next interval when
|
|
* we run out of event days for the month. Make sure the event day
|
|
* exists in that month. e.g. the 31st of June does not exist.
|
|
*/
|
|
do {
|
|
if ((md_nitems - 1) == RES_MSTATE(res).res_day) {
|
|
cur_tm.tm_mon += 1 * re->re_interval;
|
|
RES_MSTATE(res).res_day = 0;
|
|
next_interval = TRUE;
|
|
} else
|
|
RES_MSTATE(res).res_day++;
|
|
|
|
cur_tm.tm_isdst = -1;
|
|
cur_tm.tm_mday = 1;
|
|
_cur_time = mktime(&cur_tm);
|
|
cur_tm = *_XLocaltime((const time_t *)&_cur_time, localtime_buf);
|
|
} while (!DayExists(md_days[RES_MSTATE(res).res_day], cur_tm.tm_mon,
|
|
cur_tm.tm_year));
|
|
|
|
cur_tm.tm_mday = DayOfMonth(md_days[RES_MSTATE(res).res_day],
|
|
cur_tm.tm_mon, cur_tm.tm_year);
|
|
cur_tm.tm_isdst = -1;
|
|
_cur_time = mktime(&cur_tm);
|
|
|
|
if (next_interval) res->res_duration--;
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < _cur_time) {
|
|
res->res_duration = res_duration;
|
|
RES_MSTATE(res).res_day = res_day;
|
|
return 0;
|
|
}
|
|
|
|
return (_cur_time);
|
|
}
|
|
|
|
static Tick
|
|
DoMonthPos(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
WeekDayTime *wdt_list = RE_MONTHLY(re)->md_weektime;
|
|
struct tm start_tm,
|
|
cur_tm;
|
|
Tick _cur_time;
|
|
Duration res_duration = res->res_duration;
|
|
unsigned int md_nitems = RE_MONTHLY(re)->md_nitems,
|
|
wdt_nday = wdt_list[md_nitems-1].wdt_nday,
|
|
wdt_nweek = wdt_list[md_nitems-1].wdt_nweek,
|
|
res_weektime = RES_MSTATE(res).res_weektime,
|
|
res_wday = RES_MSTATE(res).res_wday,
|
|
res_wtime = RES_MSTATE(res).res_wtime,
|
|
res_wweek = RES_MSTATE(res).res_wweek;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
if (res->res_duration == 0)
|
|
return (Tick)0;
|
|
|
|
start_tm = *_XLocaltime((const time_t *)&start_time, localtime_buf);
|
|
cur_tm = *_XLocaltime((const time_t *)&cur_time, localtime_buf);
|
|
|
|
/* XXX: This assumes rules of this form only: MP<n> 1+ WE #4 */
|
|
if ((wdt_list[res_weektime].wdt_nday - 1) == res_wday) {
|
|
if ((wdt_list[res_weektime].wdt_nweek - 1) == res_wweek) {
|
|
if ((md_nitems - 1) == res_weektime) {
|
|
RES_MSTATE(res).res_weektime = 0;
|
|
RES_MSTATE(res).res_wday = 0;
|
|
RES_MSTATE(res).res_wtime = 0;
|
|
RES_MSTATE(res).res_wweek = 0;
|
|
_cur_time = NextMonthTick(&cur_tm, re, wdt_list,
|
|
NextInterval, res);
|
|
} else {
|
|
_cur_time = 0;
|
|
}
|
|
} else {
|
|
_cur_time = 0;
|
|
}
|
|
} else {
|
|
_cur_time = 0;
|
|
}
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < _cur_time) {
|
|
res->res_duration = res_duration;
|
|
RES_MSTATE(res).res_weektime = res_weektime;
|
|
RES_MSTATE(res).res_wday = res_wday;
|
|
RES_MSTATE(res).res_wtime = res_wtime;
|
|
RES_MSTATE(res).res_wweek = res_wweek;
|
|
return 0;
|
|
}
|
|
|
|
return (_cur_time);
|
|
}
|
|
|
|
static Tick
|
|
DoYearByMonth(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
struct tm start_tm,
|
|
cur_tm;
|
|
Tick _cur_time;
|
|
Duration res_duration = res->res_duration;
|
|
unsigned int *month_list = RE_YEARLY(re)->yd_items,
|
|
nitems = RE_YEARLY(re)->yd_nitems,
|
|
res_month = RES_YSTATE(res).res_daymonth;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
start_tm = *_XLocaltime((const time_t *)&start_time, localtime_buf);
|
|
cur_tm = *_XLocaltime((const time_t *)&cur_time, localtime_buf);
|
|
|
|
/*
|
|
* We want to stop when the duration == 1 and we have handled all
|
|
* the months listed in the rule for that year.
|
|
*/
|
|
if ((res->res_duration == 0) || ((res->res_duration == 1) &&
|
|
((nitems - 1) == RES_YSTATE(res).res_daymonth)))
|
|
return (Tick)0;
|
|
|
|
cur_tm.tm_mday = start_tm.tm_mday;
|
|
cur_tm.tm_hour = start_tm.tm_hour;
|
|
cur_tm.tm_min = start_tm.tm_min;
|
|
cur_tm.tm_sec = start_tm.tm_sec;
|
|
|
|
/* If these equal then we used up all the months for this year.
|
|
* We must now move to the next interval.
|
|
*/
|
|
if ((nitems - 1) == res_month) {
|
|
cur_tm.tm_year += re->re_interval;
|
|
cur_tm.tm_mon = month_list[0] - 1; /* 0 = January */
|
|
RES_YSTATE(res).res_daymonth = 0;
|
|
res->res_duration--;
|
|
} else {
|
|
/* Take the next month in the month_list, same year */
|
|
cur_tm.tm_mon = month_list[++RES_YSTATE(res).res_daymonth] - 1;
|
|
}
|
|
|
|
cur_tm.tm_isdst = -1;
|
|
_cur_time = mktime(&cur_tm);
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < _cur_time) {
|
|
res->res_duration = res_duration;
|
|
RES_YSTATE(res).res_daymonth = res_month;
|
|
return 0;
|
|
}
|
|
|
|
return (_cur_time);
|
|
}
|
|
|
|
static Tick
|
|
DoYearByDay(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
struct tm start_tm,
|
|
cur_tm;
|
|
Tick _cur_time;
|
|
Duration res_duration = res->res_duration;
|
|
unsigned int *day_list = RE_YEARLY(re)->yd_items,
|
|
nitems = RE_YEARLY(re)->yd_nitems,
|
|
res_month = RES_YSTATE(res).res_daymonth;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
start_tm = *_XLocaltime((const time_t *)&start_time, localtime_buf);
|
|
cur_tm = *_XLocaltime((const time_t *)&cur_time, localtime_buf);
|
|
|
|
/*
|
|
* We want to stop when the duration == 1 and we have handled all
|
|
* the days listed in the rule for that year.
|
|
*/
|
|
if ((res->res_duration == 0) || ((res->res_duration == 1) &&
|
|
((nitems - 1) == RES_YSTATE(res).res_daymonth)))
|
|
return (Tick)0;
|
|
|
|
cur_tm.tm_mday = start_tm.tm_mday;
|
|
cur_tm.tm_hour = start_tm.tm_hour;
|
|
cur_tm.tm_min = start_tm.tm_min;
|
|
cur_tm.tm_sec = start_tm.tm_sec;
|
|
cur_tm.tm_mon = 0;
|
|
cur_tm.tm_isdst = -1;
|
|
|
|
/* If these equal then we used up all the days for this year.
|
|
* We must now move to the next interval.
|
|
*/
|
|
if ((nitems - 1) == res_month) {
|
|
cur_tm.tm_year += re->re_interval;
|
|
cur_tm.tm_mday = day_list[0];
|
|
RES_YSTATE(res).res_daymonth = 0;
|
|
res->res_duration--;
|
|
} else {
|
|
/* Take the next day in the day_list, same year */
|
|
cur_tm.tm_mday = day_list[++RES_YSTATE(res).res_daymonth];
|
|
}
|
|
|
|
_cur_time = mktime(&cur_tm);
|
|
|
|
/* If we went beyond the end date then restore the state info, ret 0 */
|
|
if (re->re_end_date && re->re_end_date < _cur_time) {
|
|
res->res_duration = res_duration;
|
|
RES_YSTATE(res).res_daymonth = res_month;
|
|
return 0;
|
|
}
|
|
|
|
return (_cur_time);
|
|
}
|
|
|
|
static Tick
|
|
NextDayTick(
|
|
const Tick cur_time,
|
|
const Tick start_time,
|
|
const RepeatEvent *re,
|
|
RepeatEventState *res)
|
|
{
|
|
struct tm *tm;
|
|
struct tm start_tm;
|
|
_Xltimeparams localtime_buf;
|
|
|
|
if (res->res_duration == 0) return (Tick)0;
|
|
|
|
res->res_duration--;
|
|
|
|
start_tm = *_XLocaltime(&start_time, localtime_buf);
|
|
tm = _XLocaltime(&cur_time, localtime_buf);
|
|
|
|
tm->tm_mday += re->re_interval;
|
|
tm->tm_hour = start_tm.tm_hour;
|
|
tm->tm_min = start_tm.tm_min;
|
|
tm->tm_isdst = -1;
|
|
|
|
return (mktime(tm));
|
|
}
|
|
|
|
static Tick
|
|
NextWeekTick(
|
|
const struct tm *current_tm,
|
|
const struct tm *start_tm,
|
|
const RepeatEvent *re,
|
|
const DayTime *wd_daytime,
|
|
const MoveIndicator move,
|
|
RepeatEventState *res)
|
|
{
|
|
struct tm *cur_tm = (struct tm *)current_tm;
|
|
unsigned int res_daytime = RES_WSTATE(res).res_daytime;
|
|
unsigned int res_time = RES_WSTATE(res).res_time;
|
|
|
|
/* Move forward to the next interval (at least another week) */
|
|
if (move == (const MoveIndicator) NextInterval) {
|
|
/* Normalize the date to the beginning of the week. */
|
|
cur_tm->tm_mday -= cur_tm->tm_wday;
|
|
cur_tm->tm_sec = cur_tm->tm_min = cur_tm->tm_hour = 0;
|
|
cur_tm->tm_isdst = -1;
|
|
|
|
/* Add an interval */
|
|
cur_tm->tm_mday += re->re_interval * 7;
|
|
|
|
/* Put it on the correct day. */
|
|
cur_tm->tm_mday += wd_daytime[0].dt_day;
|
|
/* Put it on the correct time. */
|
|
cur_tm->tm_hour = wd_daytime[0].dt_time[0] / 100;
|
|
cur_tm->tm_min = wd_daytime[0].dt_time[0] % 100;
|
|
|
|
res->res_duration--;
|
|
|
|
return (mktime(cur_tm));
|
|
}
|
|
|
|
/* SameInterval */
|
|
|
|
/* Move the appropriate number of days forward */
|
|
cur_tm->tm_mday += GetWDayDiff(cur_tm->tm_wday,
|
|
wd_daytime[res_daytime].dt_day);
|
|
|
|
/* Use the indicated time if available */
|
|
if (RE_WEEKLY(re)->wd_daytime[res_daytime].dt_time) {
|
|
cur_tm->tm_hour = wd_daytime[res_daytime].dt_time[res_time]
|
|
/ 100;
|
|
cur_tm->tm_min = wd_daytime[res_daytime].dt_time[res_time]
|
|
% 100;
|
|
} else {
|
|
/* Use the time from the first appt */
|
|
cur_tm->tm_hour = start_tm->tm_hour;
|
|
cur_tm->tm_min = start_tm->tm_min;
|
|
}
|
|
|
|
cur_tm->tm_isdst = -1;
|
|
return (mktime(cur_tm));
|
|
}
|
|
|
|
static Tick
|
|
NextMonthTick(
|
|
const struct tm *current_time,
|
|
const RepeatEvent *re,
|
|
const WeekDayTime *wdt_list,
|
|
const MoveIndicator move,
|
|
RepeatEventState *res)
|
|
{
|
|
struct tm *cur_tm = (struct tm *)current_time;
|
|
unsigned int res_weektime = RES_MSTATE(res).res_weektime,
|
|
res_wweek = RES_MSTATE(res).res_wweek,
|
|
res_wday = RES_MSTATE(res).res_wday;
|
|
Tick next_time;
|
|
|
|
/* Move forward to the next interval (at least another month) */
|
|
if (move == (const MoveIndicator) NextInterval) {
|
|
cur_tm->tm_mday = 1;
|
|
|
|
do {
|
|
/* Add an interval */
|
|
cur_tm->tm_mon += re->re_interval;
|
|
cur_tm->tm_isdst = -1;
|
|
|
|
} while (!(next_time = WeekNumberToDay(mktime(cur_tm),
|
|
wdt_list[res_weektime].wdt_week[res_wweek],
|
|
wdt_list[res_weektime].wdt_day[res_wday])));
|
|
res->res_duration--;
|
|
} else {
|
|
/* SameInterval */
|
|
next_time = 0;
|
|
}
|
|
|
|
return (next_time);
|
|
}
|