menu: added new Keywords tag to .desktop files
[barry.git] / src / r_recur_base.cc
blob3f4cd3b8f6035cf08241906c990dcdd6b14b5dac
1 ///
2 /// \file r_recur_base.cc
3 /// Base class for recurring calendar event data.
4 ///
6 /*
7 Copyright (C) 2005-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "i18n.h"
23 #include "r_recur_base.h"
24 #include "protostructs.h"
25 #include "error.h"
26 #include "endian.h"
27 #include "time.h"
28 #include "ios_state.h"
29 #include <string.h>
30 #include <iomanip>
32 #define __DEBUG_MODE__
33 #include "debug.h"
35 using namespace std;
36 using namespace Barry::Protocol;
39 #define FIELDCODE_RECURRENCE_DATA 0x0c
41 namespace Barry {
44 ///////////////////////////////////////////////////////////////////////////////
45 // RecurBase class, static members
47 unsigned char RecurBase::WeekDayProto2Rec(uint8_t raw_field)
49 // Note: this simple copy is only possible since
50 // the CAL_WD_* constants are the same as CRDF_WD_* constants.
51 // If this ever changes, this code will need to change.
52 return raw_field;
55 uint8_t RecurBase::WeekDayRec2Proto(unsigned char weekdays)
57 // Note: this simple copy is only possible since
58 // the CAL_WD_* constants are the same as CRDF_WD_* constants.
59 // If this ever changes, this code will need to change.
60 return weekdays;
64 ///////////////////////////////////////////////////////////////////////////////
65 // RecurBase class
67 RecurBase::RecurBase()
69 Clear();
72 RecurBase::~RecurBase()
76 bool RecurBase::ParseField(uint8_t type,
77 const unsigned char *data,
78 size_t size,
79 const IConverter *ic)
81 // handle special cases
82 switch( type )
84 case FIELDCODE_RECURRENCE_DATA:
85 if( size >= CALENDAR_RECURRENCE_DATA_FIELD_SIZE ) {
86 // good data
87 ParseRecurrenceData(data);
89 else {
90 // not enough data!
91 throw Error(_("RecurBase::ParseField: not enough data in recurrence data field"));
93 return true;
96 // unknown field
97 return false;
100 // this function assumes the size has already been checked
101 void RecurBase::ParseRecurrenceData(const void *data)
103 const CalendarRecurrenceDataField *rec =
104 (const CalendarRecurrenceDataField*) data;
106 Interval = btohs(rec->interval);
107 if( Interval < 1 )
108 Interval = 1; // must always be >= 1
110 if( rec->endTime == 0xffffffff ) {
111 Perpetual = true;
113 else {
114 RecurringEndTime.Time = min2time(rec->endTime);
115 Perpetual = false;
118 switch( rec->type )
120 case CRDF_TYPE_DAY:
121 RecurringType = Day;
122 // no extra data
123 break;
125 case CRDF_TYPE_MONTH_BY_DATE:
126 RecurringType = MonthByDate;
127 DayOfMonth = rec->u.month_by_date.monthDay;
128 break;
130 case CRDF_TYPE_MONTH_BY_DAY:
131 RecurringType = MonthByDay;
132 DayOfWeek = rec->u.month_by_day.weekDay;
133 WeekOfMonth = rec->u.month_by_day.week;
134 break;
136 case CRDF_TYPE_YEAR_BY_DATE:
137 RecurringType = YearByDate;
138 DayOfMonth = rec->u.year_by_date.monthDay;
139 MonthOfYear = rec->u.year_by_date.month;
140 break;
142 case CRDF_TYPE_YEAR_BY_DAY:
143 RecurringType = YearByDay;
144 DayOfWeek = rec->u.year_by_day.weekDay;
145 WeekOfMonth = rec->u.year_by_day.week;
146 MonthOfYear = rec->u.year_by_day.month;
147 break;
149 case CRDF_TYPE_WEEK:
150 RecurringType = Week;
151 WeekDays = WeekDayProto2Rec(rec->u.week.days);
152 break;
154 default:
155 eout("Unknown recurrence data type: 0x"
156 << setbase(16) << (unsigned int) rec->type);
157 throw Error(_("Unknown recurrence data type"));
160 Recurring = true;
163 void RecurBase::Validate() const
167 // this function assumes there is CALENDAR_RECURRENCE_DATA_FIELD_SIZE bytes
168 // available in data
169 void RecurBase::BuildRecurrenceData(time_t StartTime, void *data) const
171 if( !Recurring )
172 throw Error(_("RecurBase::BuildRecurrenceData: Attempting to build recurrence data on non-recurring record."));
174 CalendarRecurrenceDataField *rec = (CalendarRecurrenceDataField*) data;
176 // set all to zero
177 memset(data, 0, CALENDAR_RECURRENCE_DATA_FIELD_SIZE);
179 rec->interval = htobs(Interval);
180 rec->startTime = time2min(StartTime);
181 if( Perpetual )
182 rec->endTime = 0xffffffff;
183 else
184 rec->endTime = time2min(RecurringEndTime.Time);
186 switch( RecurringType )
188 case Day:
189 rec->type = CRDF_TYPE_DAY;
190 // no extra data
191 break;
193 case MonthByDate:
194 rec->type = CRDF_TYPE_MONTH_BY_DATE;
195 rec->u.month_by_date.monthDay = (uint8_t)DayOfMonth;
196 break;
198 case MonthByDay:
199 rec->type = CRDF_TYPE_MONTH_BY_DAY;
200 rec->u.month_by_day.weekDay = (uint8_t)DayOfWeek;
201 rec->u.month_by_day.week = (uint8_t)WeekOfMonth;
202 break;
204 case YearByDate:
205 rec->type = CRDF_TYPE_YEAR_BY_DATE;
206 rec->u.year_by_date.monthDay = (uint8_t)DayOfMonth;
207 rec->u.year_by_date.month = (uint8_t)MonthOfYear;
208 break;
210 case YearByDay:
211 rec->type = CRDF_TYPE_YEAR_BY_DAY;
212 rec->u.year_by_day.weekDay = (uint8_t)DayOfWeek;
213 rec->u.year_by_day.week = (uint8_t)WeekOfMonth;
214 rec->u.year_by_day.month = (uint8_t)MonthOfYear;
215 break;
217 case Week:
218 rec->type = CRDF_TYPE_WEEK;
219 rec->u.week.days = WeekDayRec2Proto(WeekDays);
220 break;
222 default:
223 eout("RecurBase::BuildRecurrenceData: "
224 "Unknown recurrence data type: 0x"
225 << setbase(16) << (unsigned int) rec->type);
226 throw Error(_("RecurBase::BuildRecurrenceData: Unknown recurrence data type"));
230 uint8_t RecurBase::RecurringFieldType() const
232 return FIELDCODE_RECURRENCE_DATA;
235 void RecurBase::Clear()
237 Recurring = false;
238 RecurringType = RecurBase::Week;
239 Interval = 1;
240 RecurringEndTime.clear();
241 Perpetual = false;
242 DayOfWeek = WeekOfMonth = DayOfMonth = MonthOfYear = 0;
243 WeekDays = 0;
246 void RecurBase::Dump(std::ostream &os) const
248 ios_format_state state(os);
250 static const char *DayNames[] = {
251 N_("Sun"),
252 N_("Mon"),
253 N_("Tue"),
254 N_("Wed"),
255 N_("Thu"),
256 N_("Fri"),
257 N_("Sat")
259 static const char *MonthNames[] = {
260 N_("Jan"),
261 N_("Feb"),
262 N_("Mar"),
263 N_("Apr"),
264 N_("May"),
265 N_("Jun"),
266 N_("Jul"),
267 N_("Aug"),
268 N_("Sep"),
269 N_("Oct"),
270 N_("Nov"),
271 N_("Dec")
274 // FIXME - need a "check all data" function that make sure that all
275 // recurrence data is within range. Then call that before using
276 // the data, such as in Build and in Dump.
278 // print recurrence data if available
279 os << _(" Recurring: ") << (Recurring ? _("yes") : _("no")) << "\n";
280 if( Recurring ) {
281 switch( RecurringType )
283 case Day:
284 os << _(" Every day.\n");
285 break;
287 case MonthByDate:
288 // TRANSLATORS: to remove the 'th' ending on numbers,
289 // just replace the %s with %.0s in this string.
290 os << string_vprintf(_(" Every month on the %u%s"),
291 DayOfMonth,
292 (DayOfMonth == 1 ? "st" :
293 (DayOfMonth == 2 ? "nd" :
294 (DayOfMonth == 3 ? "rd" :
295 (DayOfMonth > 3 ? "th" : "")))))
296 << "\n";
297 break;
299 case MonthByDay:
300 os << string_vprintf(_(" Every month on the %s of week %u"),
301 gettext( DayNames[DayOfWeek] ),
302 WeekOfMonth)
303 << "\n";
304 break;
306 case YearByDate:
307 os << string_vprintf(_(" Every year on %s %u"),
308 gettext( MonthNames[MonthOfYear-1] ),
309 DayOfMonth)
310 << "\n";
311 break;
313 case YearByDay:
314 os << string_vprintf(_(" Every year in %s on %s of week %u"),
315 gettext( MonthNames[MonthOfYear-1] ),
316 gettext( DayNames[DayOfWeek] ),
317 WeekOfMonth)
318 << "\n";
319 break;
321 case Week:
322 os << _(" Every week on: ");
323 if( WeekDays & CAL_WD_SUN ) os << gettext("Sun") << " ";
324 if( WeekDays & CAL_WD_MON ) os << gettext("Mon") << " ";
325 if( WeekDays & CAL_WD_TUE ) os << gettext("Tue") << " ";
326 if( WeekDays & CAL_WD_WED ) os << gettext("Wed") << " ";
327 if( WeekDays & CAL_WD_THU ) os << gettext("Thu") << " ";
328 if( WeekDays & CAL_WD_FRI ) os << gettext("Fri") << " ";
329 if( WeekDays & CAL_WD_SAT ) os << gettext("Sat") << " ";
330 os << "\n";
331 break;
333 default:
334 os << _(" Unknown recurrence type\n");
335 break;
338 os << dec << _(" Interval: ") << Interval << "\n";
340 if( Perpetual )
341 os << _(" Ends: never\n");
342 else
343 os << _(" Ends: ") << RecurringEndTime << "\n";
348 } // namespace Barry