Prepare new maemo release
[maemo-rb.git] / apps / plugins / calendar.c
blob9f6d97096c237d553192b7f13ef4cae83818caad
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 * (based upon 1.1 by calpefrosch) updated by www.HuwSy.ukhackers.net
11 * Copyright (C) 2002
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include "plugin.h"
24 #include <timefuncs.h>
25 #include "lib/playback_control.h"
26 #include "lib/configfile.h"
30 #if CONFIG_KEYPAD == RECORDER_PAD
31 #define CALENDAR_QUIT BUTTON_OFF
32 #define CALENDAR_SELECT BUTTON_PLAY
33 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
34 #define CALENDAR_PREV_WEEK BUTTON_UP
35 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
36 #define CALENDAR_PREV_DAY BUTTON_LEFT
37 #define CALENDAR_NEXT_MONTH (BUTTON_ON|BUTTON_DOWN)
38 #define CALENDAR_PREV_MONTH (BUTTON_ON|BUTTON_UP)
40 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
41 #define CALENDAR_QUIT BUTTON_OFF
42 #define CALENDAR_SELECT BUTTON_SELECT
43 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
44 #define CALENDAR_PREV_WEEK BUTTON_UP
45 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
46 #define CALENDAR_PREV_DAY BUTTON_LEFT
47 #define CALENDAR_NEXT_MONTH (BUTTON_ON|BUTTON_DOWN)
48 #define CALENDAR_PREV_MONTH (BUTTON_ON|BUTTON_UP)
50 #elif CONFIG_KEYPAD == ONDIO_PAD
51 #define CALENDAR_QUIT BUTTON_OFF
52 #define CALENDAR_SELECT (BUTTON_MENU|BUTTON_REL)
53 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
54 #define CALENDAR_PREV_WEEK BUTTON_UP
55 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
56 #define CALENDAR_PREV_DAY BUTTON_LEFT
57 #define CALENDAR_NEXT_MONTH (BUTTON_MENU|BUTTON_DOWN)
58 #define CALENDAR_PREV_MONTH (BUTTON_MENU|BUTTON_UP)
60 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
61 (CONFIG_KEYPAD == IRIVER_H300_PAD)
62 #define CALENDAR_QUIT BUTTON_OFF
63 #define CALENDAR_SELECT BUTTON_SELECT
64 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
65 #define CALENDAR_PREV_WEEK BUTTON_UP
66 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
67 #define CALENDAR_PREV_DAY BUTTON_LEFT
68 #define CALENDAR_NEXT_MONTH BUTTON_MODE
69 #define CALENDAR_PREV_MONTH BUTTON_REC
71 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
72 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
73 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
74 #define CALENDAR_QUIT (BUTTON_SELECT|BUTTON_MENU)
75 #define CALENDAR_SELECT (BUTTON_SELECT|BUTTON_REL)
76 #define CALENDAR_NEXT_WEEK BUTTON_SCROLL_FWD
77 #define CALENDAR_PREV_WEEK BUTTON_SCROLL_BACK
78 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
79 #define CALENDAR_PREV_DAY BUTTON_LEFT
80 #define CALENDAR_NEXT_MONTH BUTTON_PLAY
81 #define CALENDAR_PREV_MONTH (BUTTON_MENU|BUTTON_REL)
83 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
84 #define CALENDAR_QUIT BUTTON_POWER
85 #define CALENDAR_SELECT BUTTON_SELECT
86 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
87 #define CALENDAR_PREV_WEEK BUTTON_UP
88 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
89 #define CALENDAR_PREV_DAY BUTTON_LEFT
90 #define CALENDAR_NEXT_MONTH BUTTON_PLAY
91 #define CALENDAR_PREV_MONTH BUTTON_REC
93 #elif CONFIG_KEYPAD == GIGABEAT_PAD
94 #define CALENDAR_QUIT BUTTON_POWER
95 #define CALENDAR_SELECT BUTTON_SELECT
96 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
97 #define CALENDAR_PREV_WEEK BUTTON_UP
98 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
99 #define CALENDAR_PREV_DAY BUTTON_LEFT
100 #define CALENDAR_NEXT_MONTH BUTTON_VOL_DOWN
101 #define CALENDAR_PREV_MONTH BUTTON_VOL_UP
103 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
104 #define CALENDAR_QUIT BUTTON_PLAY
105 #define CALENDAR_SELECT BUTTON_SELECT
106 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
107 #define CALENDAR_PREV_WEEK BUTTON_UP
108 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
109 #define CALENDAR_PREV_DAY BUTTON_LEFT
110 #define CALENDAR_NEXT_MONTH BUTTON_MODE
111 #define CALENDAR_PREV_MONTH BUTTON_EQ
113 #elif CONFIG_KEYPAD == SANSA_E200_PAD
114 #define CALENDAR_QUIT BUTTON_POWER
115 #define CALENDAR_SELECT BUTTON_SELECT
116 #define CALENDAR_NEXT_WEEK BUTTON_SCROLL_FWD
117 #define CALENDAR_PREV_WEEK BUTTON_SCROLL_BACK
118 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
119 #define CALENDAR_PREV_DAY BUTTON_LEFT
120 #define CALENDAR_NEXT_MONTH BUTTON_DOWN
121 #define CALENDAR_PREV_MONTH BUTTON_UP
123 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
124 #define CALENDAR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
125 #define CALENDAR_SELECT BUTTON_SELECT
126 #define CALENDAR_NEXT_WEEK BUTTON_SCROLL_FWD
127 #define CALENDAR_PREV_WEEK BUTTON_SCROLL_BACK
128 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
129 #define CALENDAR_PREV_DAY BUTTON_LEFT
130 #define CALENDAR_NEXT_MONTH BUTTON_DOWN
131 #define CALENDAR_PREV_MONTH BUTTON_UP
133 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
134 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
135 (CONFIG_KEYPAD == SANSA_M200_PAD)
136 #define CALENDAR_QUIT BUTTON_POWER
137 #define CALENDAR_SELECT BUTTON_SELECT
138 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
139 #define CALENDAR_PREV_WEEK BUTTON_UP
140 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
141 #define CALENDAR_PREV_DAY BUTTON_LEFT
142 #define CALENDAR_NEXT_MONTH BUTTON_VOL_UP
143 #define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN
145 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
146 #define CALENDAR_QUIT BUTTON_POWER
147 #define CALENDAR_SELECT BUTTON_PLAY
148 #define CALENDAR_NEXT_WEEK BUTTON_SCROLL_DOWN
149 #define CALENDAR_PREV_WEEK BUTTON_SCROLL_UP
150 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
151 #define CALENDAR_PREV_DAY BUTTON_LEFT
152 #define CALENDAR_NEXT_MONTH BUTTON_FF
153 #define CALENDAR_PREV_MONTH BUTTON_REW
155 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
156 #define CALENDAR_QUIT BUTTON_BACK
157 #define CALENDAR_SELECT BUTTON_SELECT
158 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
159 #define CALENDAR_PREV_WEEK BUTTON_UP
160 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
161 #define CALENDAR_PREV_DAY BUTTON_LEFT
162 #define CALENDAR_NEXT_MONTH BUTTON_NEXT
163 #define CALENDAR_PREV_MONTH BUTTON_PREV
165 #elif CONFIG_KEYPAD == MROBE100_PAD
166 #define CALENDAR_QUIT BUTTON_POWER
167 #define CALENDAR_SELECT BUTTON_SELECT
168 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
169 #define CALENDAR_PREV_WEEK BUTTON_UP
170 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
171 #define CALENDAR_PREV_DAY BUTTON_LEFT
172 #define CALENDAR_NEXT_MONTH (BUTTON_MENU|BUTTON_DOWN)
173 #define CALENDAR_PREV_MONTH (BUTTON_MENU|BUTTON_UP)
175 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
176 #define CALENDAR_QUIT BUTTON_RC_REC
177 #define CALENDAR_SELECT BUTTON_RC_PLAY
178 #define CALENDAR_NEXT_WEEK BUTTON_RC_VOL_DOWN
179 #define CALENDAR_PREV_WEEK BUTTON_RC_VOL_UP
180 #define CALENDAR_NEXT_DAY BUTTON_RC_FF
181 #define CALENDAR_PREV_DAY BUTTON_RC_REW
182 #define CALENDAR_NEXT_MONTH BUTTON_RC_MODE
183 #define CALENDAR_PREV_MONTH BUTTON_RC_MENU
185 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
186 #define CALENDAR_QUIT BUTTON_POWER
187 #define CALENDAR_SELECT BUTTON_CENTER
188 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
189 #define CALENDAR_PREV_WEEK BUTTON_UP
190 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
191 #define CALENDAR_PREV_DAY BUTTON_LEFT
192 #define CALENDAR_NEXT_MONTH BUTTON_BOTTOMRIGHT
193 #define CALENDAR_PREV_MONTH BUTTON_BOTTOMLEFT
195 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
196 #define CALENDAR_QUIT BUTTON_BACK
197 #define CALENDAR_SELECT BUTTON_SELECT
198 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
199 #define CALENDAR_PREV_WEEK BUTTON_UP
200 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
201 #define CALENDAR_PREV_DAY BUTTON_LEFT
202 #define CALENDAR_NEXT_MONTH BUTTON_CUSTOM
203 #define CALENDAR_PREV_MONTH BUTTON_PLAY
205 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
206 #define CALENDAR_QUIT BUTTON_POWER
207 #define CALENDAR_SELECT BUTTON_SELECT
208 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
209 #define CALENDAR_PREV_WEEK BUTTON_UP
210 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
211 #define CALENDAR_PREV_DAY BUTTON_LEFT
212 #define CALENDAR_NEXT_MONTH BUTTON_VOL_DOWN
213 #define CALENDAR_PREV_MONTH BUTTON_VOL_UP
215 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
216 #define CALENDAR_QUIT BUTTON_POWER
217 #define CALENDAR_SELECT BUTTON_PLAY
218 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
219 #define CALENDAR_PREV_WEEK BUTTON_UP
220 #define CALENDAR_NEXT_DAY BUTTON_NEXT
221 #define CALENDAR_PREV_DAY BUTTON_PREV
222 #define CALENDAR_NEXT_MONTH BUTTON_VOL_DOWN
223 #define CALENDAR_PREV_MONTH BUTTON_VOL_UP
225 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
226 #define CALENDAR_QUIT BUTTON_POWER
227 #define CALENDAR_SELECT BUTTON_PLAY
228 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
229 #define CALENDAR_PREV_WEEK BUTTON_UP
230 #define CALENDAR_NEXT_DAY BUTTON_NEXT
231 #define CALENDAR_PREV_DAY BUTTON_PREV
232 #define CALENDAR_NEXT_MONTH BUTTON_VOL_DOWN
233 #define CALENDAR_PREV_MONTH BUTTON_VOL_UP
235 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
236 #define CALENDAR_QUIT BUTTON_POWER
237 #define CALENDAR_SELECT BUTTON_MENU
238 #define CALENDAR_NEXT_WEEK BUTTON_VOL_DOWN
239 #define CALENDAR_PREV_WEEK BUTTON_VOL_UP
240 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
241 #define CALENDAR_PREV_DAY BUTTON_LEFT
242 #define CALENDAR_NEXT_MONTH BUTTON_BOTTOMRIGHT
243 #define CALENDAR_PREV_MONTH BUTTON_BOTTOMLEFT
245 #elif (CONFIG_KEYPAD == ONDAVX777_PAD)
246 #define CALENDAR_QUIT BUTTON_POWER
248 #elif CONFIG_KEYPAD == MROBE500_PAD
249 #define CALENDAR_QUIT BUTTON_POWER
251 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
252 #define CALENDAR_QUIT BUTTON_REC
253 #define CALENDAR_SELECT BUTTON_PLAY
254 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
255 #define CALENDAR_PREV_WEEK BUTTON_UP
256 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
257 #define CALENDAR_PREV_DAY BUTTON_LEFT
258 #define CALENDAR_NEXT_MONTH BUTTON_FFWD
259 #define CALENDAR_PREV_MONTH BUTTON_REW
261 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
262 #define CALENDAR_QUIT BUTTON_REC
263 #define CALENDAR_SELECT BUTTON_OK
264 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
265 #define CALENDAR_PREV_WEEK BUTTON_UP
266 #define CALENDAR_NEXT_DAY BUTTON_NEXT
267 #define CALENDAR_PREV_DAY BUTTON_PREV
268 #define CALENDAR_NEXT_MONTH BUTTON_PLAY
269 #define CALENDAR_PREV_MONTH BUTTON_MENU
271 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
272 #define CALENDAR_QUIT (BUTTON_REC|BUTTON_PLAY)
273 #define CALENDAR_SELECT BUTTON_FUNC
274 #define CALENDAR_NEXT_WEEK BUTTON_FF
275 #define CALENDAR_PREV_WEEK BUTTON_REW
276 #define CALENDAR_NEXT_DAY BUTTON_VOL_UP
277 #define CALENDAR_PREV_DAY BUTTON_VOL_DOWN
278 #define CALENDAR_NEXT_MONTH BUTTON_PLAY
279 #define CALENDAR_PREV_MONTH BUTTON_REC
281 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
282 #define CALENDAR_QUIT (BUTTON_MENU|BUTTON_REPEAT)
283 #define CALENDAR_SELECT BUTTON_ENTER
284 #define CALENDAR_NEXT_WEEK BUTTON_FF
285 #define CALENDAR_PREV_WEEK BUTTON_REW
286 #define CALENDAR_NEXT_DAY BUTTON_UP
287 #define CALENDAR_PREV_DAY BUTTON_DOWN
288 #define CALENDAR_NEXT_MONTH BUTTON_PLAY
289 #define CALENDAR_PREV_MONTH BUTTON_REC
291 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
292 #define CALENDAR_QUIT BUTTON_POWER
293 #define CALENDAR_SELECT BUTTON_SELECT
294 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
295 #define CALENDAR_PREV_WEEK BUTTON_UP
296 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
297 #define CALENDAR_PREV_DAY BUTTON_LEFT
298 #define CALENDAR_NEXT_MONTH BUTTON_PLAYPAUSE
299 #define CALENDAR_PREV_MONTH BUTTON_BACK
301 #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
302 #define CALENDAR_QUIT BUTTON_POWER
303 #define CALENDAR_SELECT BUTTON_SELECT
304 #define CALENDAR_NEXT_WEEK BUTTON_RIGHT
305 #define CALENDAR_PREV_WEEK BUTTON_LEFT
306 #define CALENDAR_NEXT_DAY BUTTON_UP
307 #define CALENDAR_PREV_DAY BUTTON_DOWN
308 #define CALENDAR_NEXT_MONTH BUTTON_NEXT
309 #define CALENDAR_PREV_MONTH BUTTON_PREV
311 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
312 #define CALENDAR_QUIT BUTTON_BACK
313 #define CALENDAR_SELECT BUTTON_SELECT
314 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
315 #define CALENDAR_PREV_WEEK BUTTON_UP
316 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
317 #define CALENDAR_PREV_DAY BUTTON_LEFT
318 #define CALENDAR_NEXT_MONTH BUTTON_POWER
319 #define CALENDAR_PREV_MONTH BUTTON_USER
321 #elif CONFIG_KEYPAD == HM60X_PAD
322 #define CALENDAR_QUIT BUTTON_POWER
323 #define CALENDAR_SELECT BUTTON_SELECT
324 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
325 #define CALENDAR_PREV_WEEK BUTTON_UP
326 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
327 #define CALENDAR_PREV_DAY BUTTON_LEFT
328 #define CALENDAR_NEXT_MONTH (BUTTON_RIGHT|BUTTON_POWER)
329 #define CALENDAR_PREV_MONTH (BUTTON_LEFT|BUTTON_POWER)
331 #elif CONFIG_KEYPAD == HM801_PAD
332 #define CALENDAR_QUIT BUTTON_POWER
333 #define CALENDAR_SELECT BUTTON_SELECT
334 #define CALENDAR_NEXT_WEEK BUTTON_DOWN
335 #define CALENDAR_PREV_WEEK BUTTON_UP
336 #define CALENDAR_NEXT_DAY BUTTON_RIGHT
337 #define CALENDAR_PREV_DAY BUTTON_LEFT
338 #define CALENDAR_NEXT_MONTH BUTTON_NEXT
339 #define CALENDAR_PREV_MONTH BUTTON_PREV
341 #else
342 #error "No keypad setting."
343 #endif
345 #ifdef HAVE_TOUCHSCREEN
346 #ifndef CALENDAR_QUIT
347 #define CALENDAR_QUIT BUTTON_MIDLEFT
348 #endif
349 #ifndef CALENDAR_SELECT
350 #define CALENDAR_SELECT BUTTON_CENTER
351 #endif
352 #ifndef CALENDAR_NEXT_DAY
353 #define CALENDAR_NEXT_DAY BUTTON_TOPLEFT
354 #endif
355 #ifndef CALENDAR_PREV_DAY
356 #define CALENDAR_PREV_DAY BUTTON_BOTTOMLEFT
357 #endif
358 #ifndef CALENDAR_NEXT_WEEK
359 #define CALENDAR_NEXT_WEEK BUTTON_TOPMIDDLE
360 #endif
361 #ifndef CALENDAR_PREV_WEEK
362 #define CALENDAR_PREV_WEEK BUTTON_BOTTOMMIDDLE
363 #endif
364 #ifndef CALENDAR_NEXT_MONTH
365 #define CALENDAR_NEXT_MONTH BUTTON_TOPRIGHT
366 #endif
367 #ifndef CALENDAR_PREV_MONTH
368 #define CALENDAR_PREV_MONTH BUTTON_BOTTOMRIGHT
369 #endif
370 #endif
372 #define MEMO_FILE PLUGIN_APPS_DATA_DIR "/.memo"
373 #define TEMP_FILE PLUGIN_APPS_DATA_DIR "/~temp"
375 #define X_OFFSET ((LCD_WIDTH%7)/2)
376 #if LCD_HEIGHT <= 80
377 #define Y_OFFSET 1
378 #else
379 #define Y_OFFSET 4
380 #endif
381 #define CELL_WIDTH (LCD_WIDTH / 7)
382 #define CELL_HEIGHT (LCD_HEIGHT / 7)
384 #define CFG_FILE "calendar.cfg"
385 struct info {
386 int first_wday;
387 #if (CONFIG_RTC == 0)
388 int last_mon;
389 int last_year;
390 #endif
392 static struct info info = { .first_wday = 0 }, old_info;
393 static struct configdata config[] = {
394 { TYPE_INT, 0, 6, { .int_p = &(info.first_wday) }, "first wday", NULL },
395 #if (CONFIG_RTC == 0)
396 { TYPE_INT, 1, 12, { .int_p = &(info.last_mon) }, "last mon", NULL },
397 { TYPE_INT, 1, 3000, { .int_p = &(info.last_year) }, "last year", NULL },
398 #endif
401 static bool leap_year;
402 /* days_in_month[][0] is for December */
403 static const int days_in_month[2][13] = {
404 {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
405 {31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
408 static const char *dayname_long[7] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
409 static const char *dayname_short[7] = {"M","T","W","T","F","S","S"};
411 struct shown {
412 int mday; /* day of the month */
413 int mon; /* month */
414 int year; /* year since 1900 */
415 int wday; /* day of the week */
416 int firstday; /* first (w)day of month */
417 int lastday; /* last (w)day of month */
420 static bool use_system_font = false;
422 static bool been_in_usb_mode = false;
424 /* leap year -- account for gregorian reformation in 1752 */
425 static int is_leap_year(int yr)
427 return ((yr) <= 1752 ? !((yr) % 4) : \
428 (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400)) ? 1:0 ;
431 /* searches the weekday of the first day in month,
432 * relative to the given values */
433 static int calc_weekday( struct shown *shown )
435 return ( shown->wday + 36 - shown->mday ) % 7 ;
438 #if (CONFIG_RTC == 0)
439 /* from timefunc.c */
440 static void my_set_day_of_week(struct shown *shown)
442 int y = shown->year;
443 int d = shown->mday;
444 int m = shown->mon-1;
445 static const char mo[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
447 if(m == 0 || m == 1) y--;
448 shown->wday = (d + mo[m] + y + y/4 - y/100 + y/400) % 7 - 1;
450 #endif
452 static void calendar_init(struct shown *shown)
454 int w, h;
455 #if CONFIG_RTC
456 struct tm *tm;
457 #endif
458 rb->lcd_getstringsize("A", &w, &h);
459 if ( ((w * 14) > LCD_WIDTH) || ((h * 7) > LCD_HEIGHT) )
461 use_system_font = true;
463 #if CONFIG_RTC
464 tm = rb->get_time();
465 shown->mday = tm->tm_mday;
466 shown->mon = tm->tm_mon + 1;
467 shown->year = 2000 + (tm->tm_year%100);
468 shown->wday = tm->tm_wday - 1;
469 #else
470 #define S100(x) 1 ## x
471 #define C2DIG2DEC(x) (S100(x)-100)
472 if(info.last_mon == 0 || info.last_year == 0)
474 shown->mon = C2DIG2DEC(MONTH);
475 shown->year = YEAR;
477 else
479 shown->mon = info.last_mon;
480 shown->year = info.last_year;
482 shown->mday = 1;
483 my_set_day_of_week(shown);
484 #endif
485 shown->firstday = calc_weekday(shown);
486 leap_year = is_leap_year(shown->year);
489 static void draw_headers(void)
491 int i, w, h;
492 int x = X_OFFSET;
493 int wday;
494 const char **dayname = dayname_long;
496 for (i = 0; i < 7; i++)
498 rb->lcd_getstringsize(dayname[i], &w, &h);
499 if (w > CELL_WIDTH)
501 dayname = dayname_short;
502 break;
506 wday = info.first_wday;
507 rb->lcd_getstringsize("A", &w, &h);
508 for (i = 0; i < 7; i++)
510 if (wday >= 7) wday = 0;
511 rb->lcd_putsxy(x, 0, dayname[wday++]);
512 x += CELL_WIDTH;
514 rb->lcd_hline(0, LCD_WIDTH-1, h);
517 static bool day_has_memo[32];
518 static bool wday_has_memo[7];
519 static void draw_calendar(struct shown *shown)
521 int w, h;
522 int x, y, pos, days_per_month, j;
523 int wday;
524 const char *monthname[] = {
525 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
526 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
528 if(use_system_font)
530 rb->lcd_setfont(FONT_SYSFIXED);
532 rb->lcd_getstringsize("A", &w, &h);
533 rb->lcd_clear_display();
534 draw_headers();
535 wday = shown->firstday;
536 pos = wday + 7 - info.first_wday;
537 if (pos >= 7) pos -= 7;
539 days_per_month = days_in_month[leap_year][shown->mon];
540 x = X_OFFSET + (pos * CELL_WIDTH);
541 y = Y_OFFSET + h;
542 for (j = 1; j <= days_per_month; j++)
544 if (shown->mday == j)
546 rb->lcd_set_drawmode(DRMODE_SOLID);
547 rb->lcd_fillrect(x, y - 1, CELL_WIDTH - 1, CELL_HEIGHT);
548 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
549 shown->wday = wday;
551 else
553 rb->lcd_set_drawmode(DRMODE_SOLID);
555 if ( (day_has_memo[j]) || (wday_has_memo[wday]) )
556 rb->lcd_putsxyf(x, y, "%02d.", j);
557 else
558 rb->lcd_putsxyf(x, y, "%02d", j);
559 x += CELL_WIDTH;
560 wday++;
561 if (wday >= 7)
562 wday = 0;
563 pos++;
564 if (pos >= 7)
566 pos = 0;
567 x = X_OFFSET;
568 y += CELL_HEIGHT;
571 shown->lastday = wday;
572 rb->lcd_set_drawmode(DRMODE_SOLID);
573 rb->lcd_vline(LCD_WIDTH-w*8-10, LCD_HEIGHT-h-3, LCD_HEIGHT-1);
574 rb->lcd_hline(LCD_WIDTH-w*8-10, LCD_WIDTH-1, LCD_HEIGHT-h-3);
575 rb->lcd_putsxyf(LCD_WIDTH-w*8-8, LCD_HEIGHT-h-1, "%s %04d",
576 monthname[shown->mon-1], shown->year);
577 rb->lcd_update();
580 #define MAX_CHAR_MEMO_LEN 64
581 #define MAX_MEMOS_IN_A_MONTH 128
582 struct memo {
583 char message[MAX_CHAR_MEMO_LEN];
584 int day;
585 int month;
586 int file_pointer_start;
587 int file_pointer_end;
588 int year;
589 int wday;
590 int type;
591 } memos[MAX_MEMOS_IN_A_MONTH];
592 static int pointer_array[MAX_MEMOS_IN_A_MONTH];
593 static int memos_in_memory = 0;
594 static int memos_in_shown_memory = 0;
596 static void load_memo(struct shown *shown)
598 int k, fp;
599 bool exit = false;
600 char temp_memo1[2];
601 char temp_memo2[3];
602 char temp_memo4[5];
603 temp_memo1[1] = 0;
604 temp_memo2[2] = 0;
605 temp_memo4[4] = 0;
606 for (k = 1; k < 32; k++)
607 day_has_memo[k] = false;
608 for (k = 0; k < 7; k++)
609 wday_has_memo[k] = false;
610 memos_in_memory = 0;
611 fp = rb->open(MEMO_FILE, O_RDONLY);
612 if (fp > -1)
614 rb->lseek(fp, 0, SEEK_SET);
615 while (!exit)
617 bool load_to_memory;
618 struct memo *memo = &memos[memos_in_memory];
619 rb->memset(memo, 0, sizeof(*memo));
620 memo->file_pointer_start = rb->lseek(fp, 0, SEEK_CUR);
621 if (rb->read(fp, temp_memo2, 2) == 2)
622 memo->day = rb->atoi(temp_memo2);
623 if (rb->read(fp, temp_memo2, 2) == 2)
624 memo->month = rb->atoi(temp_memo2);
625 if (rb->read(fp, temp_memo4, 4) == 4)
626 memo->year = rb->atoi(temp_memo4);
627 if (rb->read(fp, temp_memo1, 1) == 1)
628 memo->wday = rb->atoi(temp_memo1);
629 if (rb->read(fp, temp_memo1, 1) == 1)
630 memo->type = rb->atoi(temp_memo1);
631 load_to_memory = ((memo->type < 2) ||
632 ((memo->type == 2) &&
633 (memo->month == shown->mon)) ||
634 ((memo->type > 2) &&
635 (memo->month == shown->mon) &&
636 (memo->year == shown->year)));
637 k = 0;
638 while (1)
640 if (rb->read(fp, temp_memo1, 1) != 1)
642 memo->day = 0;
643 memo->month = 0;
644 memo->file_pointer_start = 0;
645 memo->file_pointer_end = 0;
646 memo->year = 0;
647 memo->type = 0;
648 memo->wday = 0;
649 memo->message[0] = 0;
650 exit = true;
651 break;
653 if (load_to_memory)
655 if (temp_memo1[0] == '\n')
657 if (memo->type > 0)
658 day_has_memo[memo->day] = true;
659 else
660 wday_has_memo[memo->wday] = true;
661 memo->file_pointer_end = rb->lseek(fp, 0, SEEK_CUR);
662 memos_in_memory++;
664 else if ( (temp_memo1[0] != '\r') &&
665 (temp_memo1[0] != '\t') &&
666 k < MAX_CHAR_MEMO_LEN-1 )
667 memo->message[k++] = temp_memo1[0];
669 if (temp_memo1[0] == '\n')
670 break;
673 rb->close(fp);
677 static bool save_memo(int changed, bool new_mod, struct shown *shown)
679 int fp, fq;
680 /* use O_RDWR|O_CREAT so that file is created if it doesn't exist. */
681 fp = rb->open(MEMO_FILE, O_RDWR|O_CREAT, 0666);
682 fq = rb->creat(TEMP_FILE, 0666);
683 if ( (fq > -1) && (fp > -1) )
685 int i;
686 char temp[MAX_CHAR_MEMO_LEN];
687 struct memo *memo = &memos[changed];
688 rb->lseek(fp, 0, SEEK_SET);
689 for (i = 0; i < memo->file_pointer_start; i++)
691 rb->read(fp, temp, 1);
692 rb->write(fq, temp, 1);
694 if (new_mod)
696 rb->fdprintf(fq, "%02d%02d%04d%01d%01d%s\n",
697 memo->day, memo->month, memo->year, memo->wday,
698 memo->type, memo->message);
700 rb->lseek(fp, memo->file_pointer_end, SEEK_SET);
701 while(rb->read(fp, temp, 1) == 1)
703 rb->write(fq, temp, 1);
705 rb->close(fp);
706 rb->close(fq);
707 rb->remove(MEMO_FILE);
708 rb->rename(TEMP_FILE, MEMO_FILE);
709 load_memo(shown);
710 return true;
712 else if (fp > -1)
713 rb->close(fp);
714 else if (fq > -1)
715 rb->close(fq);
716 return false;
719 static void add_memo(struct shown *shown, int type)
721 bool saved = false;
722 struct memo *memo = &memos[memos_in_memory];
723 if (rb->kbd_input(memo->message, MAX_CHAR_MEMO_LEN) == 0)
725 if (memo->message[0])
727 memo->file_pointer_start = 0;
728 memo->file_pointer_end = 0;
729 memo->day = shown->mday;
730 memo->month = shown->mon;
731 memo->wday = shown->wday;
732 memo->year = shown->year;
733 memo->type = type;
734 if (save_memo(memos_in_memory, true, shown))
736 saved = true;
738 else
740 memo->file_pointer_start = 0;
741 memo->file_pointer_end = 0;
742 memo->day = 0;
743 memo->month = 0;
744 memo->year = 0;
745 memo->type = 0;
746 memo->wday = 0;
750 rb->lcd_clear_display();
751 if (saved)
752 rb->splash(HZ/2, "Event added");
753 else
754 rb->splash(HZ/2, "Event not added");
757 static int edit_menu_cb(int action, const struct menu_item_ex *this_item)
759 int i = (intptr_t)this_item;
760 if (action == ACTION_REQUEST_MENUITEM
761 && memos_in_shown_memory <= 0 && (i==0 || i==1))
762 return ACTION_EXIT_MENUITEM;
763 return action;
766 static bool edit_memo(int change, struct shown *shown)
768 bool exit = false;
769 int selected = 0;
771 static const struct opt_items modes[7] = {
772 { "Mon", -1 },
773 { "Tue", -1 },
774 { "Wed", -1 },
775 { "Thu", -1 },
776 { "Fri", -1 },
777 { "Sat", -1 },
778 { "Sun", -1 },
781 MENUITEM_STRINGLIST(edit_menu, "Edit menu", edit_menu_cb,
782 "Remove", "Edit",
783 "New Weekly", "New Monthly",
784 "New Yearly", "New One off",
785 "First Day of Week",
786 "Playback Control");
788 while (!exit)
790 switch (rb->do_menu(&edit_menu, &selected, NULL, false))
792 case 0: /* remove */
793 save_memo(change, false, shown);
794 return false;
796 case 1: /* edit */
797 if(rb->kbd_input(memos[change].message,
798 MAX_CHAR_MEMO_LEN) == 0)
799 save_memo(change, true, shown);
800 return false;
802 case 2: /* weekly */
803 add_memo(shown, 0);
804 return false;
806 case 3: /* monthly */
807 add_memo(shown, 1);
808 return false;
810 case 4: /* yearly */
811 add_memo(shown, 2);
812 return false;
814 case 5: /* one off */
815 add_memo(shown, 3);
816 return false;
818 case 6: /* weekday */
819 rb->set_option("First Day of Week", &info.first_wday,
820 INT, modes, 7, NULL);
821 break;
823 case 7: /* playback control */
824 playback_control(NULL);
825 break;
827 case GO_TO_PREVIOUS:
828 return false;
830 case MENU_ATTACHED_USB:
831 been_in_usb_mode = true;
832 break;
835 return false;
838 static const char* get_event_text(int selected, void *data,
839 char *buffer, size_t buffer_len)
841 struct shown *shown = (struct shown *) data;
842 struct memo *memo;
843 if (selected < 0 || memos_in_shown_memory <= selected)
845 return NULL;
847 memo = &memos[pointer_array[selected]];
848 if (memo->type == 2)
849 rb->snprintf(buffer, buffer_len, "%s (%d yrs)",
850 memo->message, shown->year - memo->year);
851 else
852 rb->snprintf(buffer, buffer_len, "%s", memo->message);
853 return buffer;
856 static bool view_events(int selected, struct shown *shown)
858 struct gui_synclist gui_memos;
859 bool exit=false;
860 int button;
862 rb->gui_synclist_init(&gui_memos, &get_event_text, shown, false, 1, NULL);
863 rb->gui_synclist_set_title(&gui_memos, "Events (play : menu)", NOICON);
864 rb->gui_synclist_set_nb_items(&gui_memos, memos_in_shown_memory);
865 rb->gui_synclist_select_item(&gui_memos, selected);
866 rb->gui_synclist_draw(&gui_memos);
868 while (!exit)
870 button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
871 rb->gui_synclist_do_button(&gui_memos, &button, LIST_WRAP_UNLESS_HELD);
873 switch (button)
875 case ACTION_STD_OK:
876 selected = rb->gui_synclist_get_sel_pos(&gui_memos);
877 return edit_memo(pointer_array[selected], shown);
878 break;
880 case ACTION_STD_CANCEL:
881 return false;
882 break;
884 default:
885 if(rb->default_event_handler(button) == SYS_USB_CONNECTED)
886 been_in_usb_mode = true;
887 break;
891 return false;
894 static void update_memos_shown(struct shown *shown)
896 int i;
897 struct memo *memo;
898 memos_in_shown_memory = 0;
899 for (i = 0; i < memos_in_memory; i++)
901 memo = &memos[i];
902 if (((memo->type >= 1) && (memo->day == shown->mday)) ||
903 ((memo->type < 1) && (memo->wday == shown->wday)))
904 pointer_array[memos_in_shown_memory++] = i;
908 static bool any_events(struct shown *shown, bool force)
910 update_memos_shown(shown);
912 if (memos_in_shown_memory > 0)
913 return view_events(0, shown);
914 else if (force)
915 return edit_memo(0, shown);
916 else
917 return false;
919 return false;
922 static void next_month(struct shown *shown, int step)
924 shown->mon++;
925 if (shown->mon > 12)
927 shown->mon = 1;
928 shown->year++;
929 leap_year = is_leap_year(shown->year);
931 if (step > 0)
932 shown->mday = shown->mday - days_in_month[leap_year][shown->mon-1];
933 else if (shown->mday > days_in_month[leap_year][shown->mon])
934 shown->mday = days_in_month[leap_year][shown->mon];
935 shown->firstday = shown->lastday;
936 load_memo(shown);
937 draw_calendar(shown);
940 static void prev_month(struct shown *shown, int step)
942 shown->mon--;
943 if (shown->mon < 1)
945 shown->mon = 12;
946 shown->year--;
947 leap_year = is_leap_year(shown->year);
949 if (step > 0)
950 shown->mday = shown->mday + days_in_month[leap_year][shown->mon];
951 else if (shown->mday > days_in_month[leap_year][shown->mon])
952 shown->mday = days_in_month[leap_year][shown->mon];
953 shown->firstday += 7 - (days_in_month[leap_year][shown->mon] % 7);
954 if (shown->firstday >= 7)
955 shown->firstday -= 7;
956 load_memo(shown);
957 draw_calendar(shown);
960 static void next_day(struct shown *shown, int step)
962 shown->mday += step;
963 if (shown->mday > days_in_month[leap_year][shown->mon])
964 next_month(shown, step);
965 else
966 draw_calendar(shown);
969 static void prev_day(struct shown *shown, int step)
971 shown->mday -= step;
972 if (shown->mday < 1)
973 prev_month(shown, step);
974 else
975 draw_calendar(shown);
978 enum plugin_status plugin_start(const void* parameter)
980 struct shown shown;
981 bool exit = false;
982 int button;
984 (void)(parameter);
986 configfile_load(CFG_FILE, config, ARRAYLEN(config), 0);
987 rb->memcpy(&old_info, &info, sizeof(struct info));
989 calendar_init(&shown);
990 load_memo(&shown);
991 any_events(&shown, false);
992 draw_calendar(&shown);
994 while (!exit)
996 button = rb->button_get(true);
997 switch (button)
999 case CALENDAR_QUIT:
1000 exit = true;
1001 break;
1003 case CALENDAR_NEXT_MONTH:
1004 case CALENDAR_NEXT_MONTH | BUTTON_REPEAT:
1005 next_month(&shown, 0);
1006 break;
1008 case CALENDAR_PREV_MONTH:
1009 case CALENDAR_PREV_MONTH | BUTTON_REPEAT:
1010 prev_month(&shown, 0);
1011 break;
1013 case CALENDAR_NEXT_WEEK:
1014 case CALENDAR_NEXT_WEEK | BUTTON_REPEAT:
1015 next_day(&shown, 7);
1016 break;
1018 case CALENDAR_PREV_WEEK:
1019 case CALENDAR_PREV_WEEK | BUTTON_REPEAT:
1020 prev_day(&shown, 7);
1021 break;
1023 case CALENDAR_PREV_DAY:
1024 case CALENDAR_PREV_DAY | BUTTON_REPEAT:
1025 prev_day(&shown, 1);
1026 break;
1028 case CALENDAR_NEXT_DAY:
1029 case CALENDAR_NEXT_DAY | BUTTON_REPEAT:
1030 next_day(&shown, 1);
1031 break;
1033 case CALENDAR_SELECT:
1034 any_events(&shown, true);
1035 draw_calendar(&shown);
1036 break;
1038 default:
1039 if(rb->default_event_handler(button) == SYS_USB_CONNECTED)
1040 been_in_usb_mode = true;
1041 draw_calendar(&shown);
1042 break;
1047 #if (CONFIG_RTC == 0)
1048 info.last_mon = shown.mon;
1049 info.last_year = shown.year;
1050 #endif
1051 if (rb->memcmp(&old_info, &info, sizeof(struct info)))
1052 configfile_save(CFG_FILE, config, ARRAYLEN(config), 0);
1053 return been_in_usb_mode?PLUGIN_USB_CONNECTED:PLUGIN_OK;