2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: reutil.c /main/7 1996/11/21 19:47:12 drk $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company
26 * (c) Copyright 1993, 1994 International Business Machines Corp.
27 * (c) Copyright 1993, 1994 Novell, Inc.
28 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
38 #define XOS_USE_NO_LOCKING
39 #define X_INCLUDE_TIME_H
43 #include <X11/Xos_r.h>
45 extern int monthdays[12];
46 extern RepeatEvent *_DtCm_repeat_info;
47 extern char *_DtCm_rule_buf;
48 extern void _DtCm_rule_parser();
49 extern char *ReToString(RepeatEvent *);
53 * Check to make sure the current interval number is not greater than the
58 const unsigned int ninterval,
59 const Duration duration)
61 if (duration == RE_INFINITY || duration == RE_NOTSET) return TRUE;
63 if (ninterval >= duration)
70 * Given two days of the week, compute the forward difference between them.
80 return (7 - (start - end));
84 * Returns true if a day exists in the specified month and year.
92 int valid_day = DayOfMonth(day, month, year);
94 if (valid_day < 29) return TRUE;
96 /* month = 0 = January */
97 if ((month == 1) && leapyr(year + 1900)) {
104 if (valid_day <= monthdays[month])
111 * Given a date (specifically a month and year) determine if any of the
112 * occurences of a weekday (e.g. 4th Sunday) exist in the given month.
116 const WeekDayTime *wdt_list,
117 const unsigned int nwdt_list,
122 for (i = 0; i < nwdt_list; i++) {
123 for (j = 0; j < wdt_list[i].wdt_nweek; j++) {
124 for (k = 0; k < wdt_list[i].wdt_nday; k++) {
125 if (WeekNumberToDay(date,
126 wdt_list[i].wdt_week[j],
127 wdt_list[i].wdt_day[k])) {
141 switch (DayToWeekNumber(date)) {
158 * Calculate the position of a week day (e.g. SU) in the month:
159 * 7/1/94 would return 1 since this is the first Friday of the month.
160 * 7/6/94 would return 1 even though it is in the second week since this
161 * is the first Wed of the month.
162 * 7/15/94 would return 3.
168 _Xltimeparams localtime_buf;
169 struct tm *date_tm = _XLocaltime(&date, localtime_buf);
172 week_number = date_tm->tm_mday / 7;
174 if (date_tm->tm_mday % 7)
181 * Given a week number and a day of the week determine what day of the month
182 * it falls on given a month in ``date''.
187 const WeekNumber week,
188 const WeekDay weekday)
190 _Xltimeparams localtime_buf;
191 struct tm *date_tm = _XLocaltime(&date, localtime_buf);
195 initial_month_number = date_tm->tm_mon;
198 /* From the first day (or last day in the WK_L* cases) of the month
199 * work forward (or backward) to find the weekday requested.
201 if (week <= (const WeekDay)WK_F5) {
203 first_weekday = fdom(date);
204 if (weekday != first_weekday)
205 day_of_month += GetWDayDiff(first_weekday, weekday);
207 day_of_month = monthlength(date);
208 last_weekday = ldom(date);
209 if (weekday != last_weekday)
210 day_of_month -= GetWDayDiff(weekday, last_weekday);
213 /* Now move forward or backward through the month added or subtracting
214 * the appropriate number of weeks to get to the correct location.
216 if (week <= (const WeekDay)WK_F5) {
217 date_tm->tm_mday = day_of_month + (int)week * 7;
219 /* ((int)week - WK_L1) normalizes the WK_L* to the values
220 * of 0 to 4. See the WeekNumber enum.
222 date_tm->tm_mday = day_of_month - ((int)week - WK_L1) * 7;
225 date_tm->tm_isdst = -1;
226 _date = mktime(date_tm);
227 date_tm = _XLocaltime(&_date, localtime_buf);
229 /* It is possible that the requested week number is not in this
232 if (date_tm->tm_mon != initial_month_number)
245 if (day != RE_LASTDAY) return day;
247 /* month = 0 = January */
248 if ((month == 1) && leapyr(year + 1900))
251 return monthdays[month];
259 struct tm tm11 = *tm1;
260 struct tm tm22 = *tm2;
262 _Xltimeparams localtime_buf;
264 tm11.tm_mday -= tm11.tm_wday;
265 tm22.tm_mday -= tm22.tm_wday;
266 time1 = mktime(&tm11);
267 time2 = mktime(&tm22);
268 tm11 = *_XLocaltime(&time1, localtime_buf);
269 tm22 = *_XLocaltime(&time2, localtime_buf);
271 if (tm11.tm_yday == tm22.tm_yday)
279 const Tick start_time,
281 const Tick current_time,
282 const Tick target_time,
288 RepeatEventState *res;
290 /* Count the number of events from the start time to the current time */
291 end_date = old_re->re_end_date;
292 old_re->re_end_date = current_time;
293 /* XXX: Need to deal with excluded events */
294 num_events = CountEvents(start_time, old_re, NULL);
295 old_re->re_end_date = end_date;
297 if (!ClosestTick(current_time, start_time, old_re, &res)) {
298 /* XXX: Are we at the last tick or are there other problems? */
302 an_event = target_time;
304 /* Walk backwards from the new target time to where the new start
307 while (--num_events &&
308 (an_event = PrevTick(an_event, 0, new_re, res))) {
316 * Return True if rule1 is the same as rule2. This function returns True
317 * if the rule portion of the rules are == reguardless of the duration or
319 * re1 should point to the RepeatEvent struct for rule1. If you pass in
320 * NULL for re1 the function *may* parse rule1 for you and return the
321 * RepeatEvent struct through re1. You will need to free it.
322 * The same applies for re2.
329 Duration old_duration;
336 /* If rules are the same then we are done */
337 if (!strcmp(rule1, rule2))
340 _DtCm_rule_buf = rule1;
342 if (!_DtCm_repeat_info) {
343 /* Bad rule - fail */
346 re1 = _DtCm_repeat_info;
348 _DtCm_rule_buf = rule2;
350 if (!_DtCm_repeat_info) {
351 /* Bad rule - fail */
355 re2 = _DtCm_repeat_info;
357 /* If rule1 != rule2 and the duration and end_date are the same
358 * then the rules themselves must be different.
360 if (re1->re_duration == re2->re_duration &&
361 re1->re_end_date == re2->re_end_date) {
368 /* If the duration or end_date are different, the rules themselves
369 * may still be different. So we make the durations and end_dates
370 * the same and reconstruct the rules.
372 old_duration = re2->re_duration;
373 old_end_date = re2->re_end_date;
375 re2->re_duration = re1->re_duration;
376 re2->re_end_date = re1->re_end_date;
378 new_rule1 = ReToString(re1);
379 new_rule2 = ReToString(re2);
381 re2->re_duration = old_duration;
382 re2->re_end_date = old_end_date;
384 if (!strcmp(new_rule1, new_rule2)) {