1 /* $XConsortium: recount.c /main/6 1996/11/21 19:45:46 drk $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
9 #define XOS_USE_NO_LOCKING
10 #define X_INCLUDE_TIME_H
11 #include <X11/Xos_r.h>
13 #include <EUSCompat.h>
20 static int InitialEventsToExclude(time_t, RepeatEvent *);
21 static int EventsPerMonth(RepeatEvent *);
22 static int DoBruteForce(const time_t, RepeatEvent *);
25 * Give a start time, a parsed rule and a list of exception dates, determine
26 * the number of events that will be generated.
32 CSA_date_time_entry *dte)
36 int excluded_days = 0;
37 unsigned int nevents1 = (unsigned int)-1,
38 nevents2 = (unsigned int)-1;
40 if (!re || !start_time) return RE_ERROR;
42 if (!re->re_end_date && re->re_duration == RE_INFINITY)
46 * Count the number of times an excluded time hits an event time
47 * generated by the rule.
49 for (; dte; dte = dte->next) {
50 RepeatEventState *res;
52 if (_csa_iso8601_to_tick(dte->date_time, &exclude_time) == -1)
55 if (!(close_time = ClosestTick(exclude_time, start_time, re,
59 last_time = LastTick(start_time, re);
60 if (last_time == exclude_time)
63 if (close_time == exclude_time)
67 _DtCm_free_re_state(res);
71 * If there is an end date, then we must calculate the total number
72 * of events via the brute force method.
74 if (re->re_end_date) {
75 nevents1 = DoBruteForce(start_time, re) - excluded_days;
78 if (re->re_duration == RE_NOTSET)
81 switch (re->re_type) {
85 nevents2 = re->re_duration;
88 if (!RE_WEEKLY(re)->wd_ndaytime)
89 nevents2 = re->re_duration;
91 nevents2 = re->re_duration *
92 RE_WEEKLY(re)->wd_ndaytime;
94 nevents2 -= InitialEventsToExclude(start_time, re);
96 case RT_MONTHLY_POSITION: {
97 int events_per_month = EventsPerMonth(re);
99 if (!events_per_month) {
100 nevents2 = DoBruteForce(start_time, re);
102 nevents2 = re->re_duration * events_per_month -
103 InitialEventsToExclude(start_time, re);
107 case RT_MONTHLY_DAY: {
108 int ndays = RE_MONTHLY(re)->md_nitems;
110 _Xltimeparams localtime_buf;
112 start_tm = _XLocaltime((const time_t *)&start_time, localtime_buf);
114 * Need to do this by brute force if they want days that may
115 * not exist in a given month.
117 if (((!ndays) && start_tm->tm_mday > 28) ||
118 (ndays && RE_MONTHLY(re)->md_days[ndays - 1] > 28)) {
119 nevents2 = DoBruteForce(start_time, re);
122 nevents2 = re->re_duration;
124 nevents2 = re->re_duration * ndays;
126 nevents2 -= InitialEventsToExclude(start_time, re);
130 case RT_YEARLY_MONTH:
131 if (!RE_YEARLY(re)->yd_nitems)
132 nevents2 = re->re_duration;
134 nevents2 = re->re_duration *
135 RE_YEARLY(re)->yd_nitems;
136 nevents2 -= InitialEventsToExclude(start_time, re);
139 if (!RE_YEARLY(re)->yd_nitems)
140 nevents2 = re->re_duration;
142 nevents2 = re->re_duration *
143 RE_YEARLY(re)->yd_nitems;
144 nevents2 -= InitialEventsToExclude(start_time, re);
148 nevents2 -= excluded_days;
151 * If both a duration and and enddate are set the policy is to use
152 * the lesser of the two.
154 if (nevents1 < nevents2)
161 * If the rule is a weekly or monthly style with specific weekdays listed,
162 * such as W1 MO WE FR and the start_time indicates the rule starts on say a
163 * WE, then the first MO would not count as an event day so it must be
164 * excluded from the total count.
167 InitialEventsToExclude(
172 _Xltimeparams localtime_buf;
174 start_tm = _XLocaltime((const time_t *)&start_time, localtime_buf);
176 if (re->re_type == RT_WEEKLY) {
177 DayTime *daytime = (DayTime *)RE_WEEKLY(re)->wd_daytime;
178 int nevent_days = RE_WEEKLY(re)->wd_ndaytime,
181 if (!nevent_days) return 0;
183 for (i = 0; i < nevent_days; i++) {
184 if (daytime[i].dt_day >= start_tm->tm_wday)
187 return (nevent_days);
188 } else if (re->re_type == RT_MONTHLY_POSITION) {
189 WeekDayTime *wdt = (WeekDayTime *)RE_MONTHLY(re)->md_weektime;
193 for (i = 0; i < RE_MONTHLY(re)->md_nitems; i++) {
198 j < RE_MONTHLY(re)->md_weektime[i].wdt_nweek;
202 k < RE_MONTHLY(re)->md_weektime[i].wdt_nday;
205 date = WeekNumberToDay(start_time,
206 RE_MONTHLY(re)->md_weektime[i].
208 RE_MONTHLY(re)->md_weektime[i].
210 if (!date || date < start_time)
216 } else if (re->re_type == RT_MONTHLY_DAY) {
219 if (!RE_MONTHLY(re)->md_nitems) return 0;
221 for (i = 0; i < RE_MONTHLY(re)->md_nitems; i++) {
222 if (RE_MONTHLY(re)->md_days[i] >= start_tm->tm_mday)
225 return (RE_MONTHLY(re)->md_nitems);
226 } else if (re->re_type == RT_YEARLY_MONTH) {
229 if (!RE_YEARLY(re)->yd_nitems) return 0;
231 for (i = 0; i < RE_YEARLY(re)->yd_nitems; i++) {
232 if (RE_YEARLY(re)->yd_items[i] >= (start_tm->tm_mon +1))
235 return (RE_YEARLY(re)->yd_nitems);
236 } else if (re->re_type == RT_YEARLY_DAY) {
239 if (!RE_YEARLY(re)->yd_nitems) return 0;
241 for (i = 0; i < RE_YEARLY(re)->yd_nitems; i++) {
242 if (RE_YEARLY(re)->yd_items[i] >=
243 (start_tm->tm_yday + 1))
246 return (RE_YEARLY(re)->yd_nitems);
253 * Given a parsed MP rule determine the number of events it would generate
254 * in a month. If the rule suggests events should occure on the 5th week
255 * which means the number of events generated in a given month is not
256 * constant, we return 0.
265 for (i = 0, nevents = 0; i < RE_MONTHLY(re)->md_nitems; i++) {
268 /* If 5+ or 5- is used, we must compute count by brute force */
269 for (j = 0; j < RE_MONTHLY(re)->md_weektime[i].wdt_nweek; j++) {
270 if ((RE_MONTHLY(re)->md_weektime[i].wdt_week[j] ==
272 (RE_MONTHLY(re)->md_weektime[i].wdt_week[j] ==
277 nevents += RE_MONTHLY(re)->md_weektime[i].wdt_nday *
278 RE_MONTHLY(re)->md_weektime[i].wdt_nweek;
285 * Given a start time and a parsed rule determine the number events generated
286 * by walking the event stream until we reach the end.
290 const time_t start_time,
293 RepeatEventState *res;
298 if (!(cur_time = ClosestTick(start_time, start_time, re, &res)))
303 while ((cur_time = NextTick(cur_time, start_time, re, res))) {
307 _DtCm_free_re_state(res);