2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2020 The DragonFly Project. All rights reserved.
5 * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>.
8 * This code is derived from software contributed to The DragonFly Project
9 * by Aaron LI <aly@aaronly.me>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: head/usr.bin/calendar/dates.c 326276 2017-11-27 15:37:16Z pfg $
44 #include "gregorian.h"
50 bool variable; /* Whether a variable event ? */
51 char date[32]; /* Date in Gregorian calendar */
52 char date_user[64]; /* Date in user-chosen calendar */
53 struct cal_desc *description; /* Event description */
54 char *extra; /* Extra data of the event */
58 static struct cal_day *cal_days = NULL;
66 int daycount, dow, year, month, day;
67 int rd_month1, rd_nextmonth, rd_nextyear;
69 daycount = Options.day_end - Options.day_begin + 1;
70 cal_days = xcalloc((size_t)daycount, sizeof(struct cal_day));
72 dow = dayofweek_from_fixed(Options.day_begin);
73 gregorian_from_fixed(Options.day_begin, &date);
79 rd_month1 = fixed_from_gregorian(&date);
80 if (date.month == 12) {
81 date_set(&date, date.year+1, 1, 1);
82 rd_nextmonth = fixed_from_gregorian(&date);
83 rd_nextyear = rd_nextmonth;
86 rd_nextmonth = fixed_from_gregorian(&date);
87 date_set(&date, date.year+1, 1, 1);
88 rd_nextyear = fixed_from_gregorian(&date);
91 for (int i = 0; i < daycount; i++) {
93 dp->rd = Options.day_begin + i;
95 if (dp->rd == rd_nextmonth) {
98 rd_month1 = rd_nextmonth;
99 if (dp->rd == rd_nextyear) {
104 date_set(&date, year, month, day);
105 if (date.month == 12) {
106 date_set(&date, date.year+1, 1, 1);
107 rd_nextmonth = fixed_from_gregorian(&date);
108 rd_nextyear = rd_nextmonth;
111 rd_nextmonth = fixed_from_gregorian(&date);
112 date_set(&date, date.year+1, 1, 1);
113 rd_nextyear = fixed_from_gregorian(&date);
119 dp->day = dp->rd - rd_month1 + 1;
120 dp->dow[0] = (dow + i) % 7;
121 dp->dow[1] = (dp->rd - rd_month1) / 7 + 1;
122 dp->dow[2] = -((rd_nextmonth - dp->rd - 1) / 7 + 1);
123 dp->last_dom = (dp->rd == rd_nextmonth - 1);
125 DPRINTF("%s: [%d] rd:%d, date:%d-%02d-%02d, dow:[%d,%d,%d]\n",
126 __func__, i, dp->rd, dp->year, dp->month,
127 dp->day, dp->dow[0], dp->dow[1], dp->dow[2]);
135 struct cal_day *dp = NULL;
137 while ((dp = loop_dates(dp)) != NULL) {
138 while ((e = dp->events) != NULL) {
139 dp->events = e->next;
148 loop_dates(struct cal_day *dp)
150 int daycount = Options.day_end - Options.day_begin + 1;
157 if (dp < &cal_days[0] || dp > &cal_days[daycount-1])
165 find_rd(int rd, int offset)
168 if (rd < Options.day_begin || rd > Options.day_end)
171 return &cal_days[rd - Options.day_begin];
176 event_add(struct cal_day *dp, bool day_first, bool variable,
177 struct cal_desc *desc, char *extra)
181 struct tm tm = { 0 };
183 e = xcalloc(1, sizeof(*e));
185 gregorian_from_fixed(dp->rd, &gdate);
186 tm.tm_year = gdate.year - 1900;
187 tm.tm_mon = gdate.month - 1;
188 tm.tm_mday = gdate.day;
189 strftime(e->date, sizeof(e->date),
190 (day_first ? "%e %b" : "%b %e"), &tm);
191 if (Calendar->format_date != NULL) {
192 (Calendar->format_date)(e->date_user, sizeof(e->date_user),
196 e->variable = variable;
197 e->description = desc;
198 if (extra != NULL && extra[0] != '\0')
201 e->next = dp->events;
208 event_print_all(FILE *fp)
211 struct cal_day *dp = NULL;
212 struct cal_desc *desc;
213 struct cal_line *line;
215 while ((dp = loop_dates(dp)) != NULL) {
216 for (e = dp->events; e != NULL; e = e->next) {
217 fprintf(fp, "%s%c\t", e->date, e->variable ? '*' : ' ');
218 if (e->date_user[0] != '\0')
219 fprintf(fp, "[%s] ", e->date_user);
221 desc = e->description;
222 for (line = desc->firstline; line; line = line->next) {
223 fprintf(fp, "%s%s%s",
224 (line == desc->firstline) ? "" : "\t\t",
226 (line == desc->lastline) ? "" : "\n");
229 fprintf(fp, " (%s)", e->extra);