1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * (based upon 1.1 by calpefrosch) updated by www.HuwSy.ukhackers.net
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
22 #if defined(HAVE_LCD_BITMAP) && (CONFIG_RTC != 0)
24 #include <timefuncs.h>
28 static struct plugin_api
* rb
;
30 static bool leap_year
;
31 static int days_in_month
[2][13] = {
32 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
33 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
37 int mday
; /* day of the month */
39 int year
; /* year since 1900 */
40 int wday
; /* day of the week */
44 int mday
; /* day of the month */
46 int year
; /* year since 1900 */
47 int wday
; /* day of the week */
48 int firstday
; /* first (w)day of month */
49 int lastday
; /* last (w)day of month */
52 static bool use_system_font
= false;
54 static bool been_in_usb_mode
= false;
56 /* leap year -- account for gregorian reformation in 1752 */
57 static int is_leap_year(int yr
)
59 return ((yr
) <= 1752 ? !((yr
) % 4) : \
60 (!((yr
) % 4) && ((yr
) % 100)) || !((yr
) % 400)) ? 1:0 ;
63 /* searches the weekday of the first day in month,
64 * relative to the given values */
65 static int calc_weekday( struct shown
*shown
)
67 return ( shown
->wday
+ 36 - shown
->mday
) % 7 ;
71 static void calendar_init(struct today
*today
, struct shown
*shown
)
79 rb
->lcd_getstringsize("A",&w
,&h
);
80 if ( ((w
* 14) > LCD_WIDTH
) || ((h
* 7) > LCD_HEIGHT
) )
82 rb
->lcd_setfont(FONT_SYSFIXED
);
83 use_system_font
= true;
85 rb
->lcd_clear_display();
88 today
->mon
= tm
->tm_mon
+1;
89 today
->year
= 2000+tm
->tm_year
%100;
90 today
->wday
= tm
->tm_wday
-1;
91 today
->mday
= tm
->tm_mday
;
96 shown
->mday
= today
->mday
;
97 shown
->mon
= today
->mon
;
98 shown
->year
= today
->year
;
99 shown
->wday
= today
->wday
;
101 shown
->firstday
= calc_weekday(shown
);
102 leap_year
= is_leap_year(shown
->year
);
105 static int space
= LCD_WIDTH
/ 7;
106 static void draw_headers(void)
109 char *Dayname
[7] = {"M","T","W","T","F","S","S"};
111 rb
->lcd_getstringsize("A",&w
,&h
);
114 rb
->lcd_putsxy(ws
, 0 , Dayname
[i
++]);
117 rb
->lcd_drawline(0 ,h
,LCD_WIDTH
-1 ,h
);
120 static bool day_has_memo
[31];
121 static bool wday_has_memo
[6];
122 static void draw_calendar(struct shown
*shown
)
125 int ws
,row
,pos
,days_per_month
,j
;
127 char *Monthname
[] = {
141 rb
->lcd_getstringsize("A",&w
,&h
);
142 rb
->lcd_clear_display();
144 if (shown
->firstday
> 6)
145 shown
->firstday
-= 7;
147 pos
= shown
->firstday
;
148 days_per_month
= days_in_month
[leap_year
][shown
->mon
];
149 ws
= 2 + (pos
* space
);
150 for (j
= 0; j
< days_per_month
;)
152 if ( (day_has_memo
[++j
]) || (wday_has_memo
[pos
]) )
153 rb
->snprintf(buffer
,4,"%02d.", j
);
155 rb
->snprintf(buffer
,4,"%02d", j
);
156 rb
->lcd_putsxy(ws
, (row
* h
) + 5 ,buffer
);
157 if (shown
->mday
== j
)
159 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
160 rb
->lcd_fillrect(ws
, row
*h
+5, space
, h
);
161 rb
->lcd_set_drawmode(DRMODE_SOLID
);
173 rb
->lcd_drawline(60,LCD_HEIGHT
-h
-3,60,LCD_HEIGHT
-1);
174 rb
->lcd_drawline(60,LCD_HEIGHT
-h
-3,LCD_WIDTH
-1,LCD_HEIGHT
-h
-3);
175 rb
->snprintf(buffer
,9,"%s %04d",Monthname
[shown
->mon
-1],shown
->year
);
176 rb
->lcd_putsxy(62,(LCD_HEIGHT
-h
-1),buffer
);
177 shown
->lastday
= pos
;
181 #define MAX_CHAR_MEMO_LEN 63
182 #define MAX_MEMOS_IN_A_MONTH 127
184 char message
[MAX_CHAR_MEMO_LEN
];
187 int file_pointer_start
;
188 int file_pointer_end
;
192 } memos
[MAX_MEMOS_IN_A_MONTH
];
193 static int pointer_array
[MAX_MEMOS_IN_A_MONTH
];
194 static int memos_in_memory
= 0;
195 static int memos_in_shown_memory
= 0;
197 static void load_memo(struct shown
*shown
)
204 for (k
= 0; k
< memos_in_memory
; k
++)
208 memos
[k
].file_pointer_start
= 0;
209 memos
[k
].file_pointer_end
= 0;
213 for (i
= 0; i
<= MAX_CHAR_MEMO_LEN
; i
++)
214 rb
->strcpy(&memos
[k
].message
[i
],"");
216 for (k
= 1; k
< 32; k
++)
217 day_has_memo
[k
] = false;
218 for (k
= 0; k
< 7; k
++)
219 wday_has_memo
[k
] = false;
221 fp
= rb
->open(ROCKBOX_DIR
"/.memo",O_RDONLY
);
224 int count
= rb
->filesize(fp
);
225 rb
->lseek(fp
, 0, SEEK_SET
);
228 memos
[memos_in_memory
].file_pointer_start
= rb
->lseek(fp
, 0,
230 if (rb
->read(fp
, temp_memo2
, 2) == 2)
231 memos
[memos_in_memory
].day
= rb
->atoi(&temp_memo2
[0]);
233 memos
[memos_in_memory
].day
= 0;
234 if (rb
->read(fp
, temp_memo2
, 2) == 2)
235 memos
[memos_in_memory
].month
= rb
->atoi(&temp_memo2
[0]);
237 memos
[memos_in_memory
].month
= 0;
238 if (rb
->read(fp
, temp_memo4
, 4) == 4)
239 memos
[memos_in_memory
].year
= rb
->atoi(&temp_memo4
[0]);
241 memos
[memos_in_memory
].year
= 0;
242 /* as the year returned is sometimes yearmonth, ie if yr should =
243 2003, and month = 06, then it returns 200306 */
244 if (memos
[memos_in_memory
].year
> (shown
->year
* 10))
245 memos
[memos_in_memory
].year
= (memos
[memos_in_memory
].year
-
246 memos
[memos_in_memory
].month
) /
248 if (rb
->read(fp
, temp_memo1
, 1) == 1)
249 memos
[memos_in_memory
].wday
= rb
->atoi(&temp_memo1
[0]);
251 memos
[memos_in_memory
].wday
= 0;
252 if (rb
->read(fp
, temp_memo1
, 1) == 1)
253 memos
[memos_in_memory
].type
= rb
->atoi(&temp_memo1
[0]);
255 memos
[memos_in_memory
].type
= 0;
256 for (k
= 0; k
<= count
; k
++)
258 if (rb
->read(fp
, temp_memo1
, 1) == 1)
261 (memos
[memos_in_memory
].type
< 2)
264 (memos
[memos_in_memory
].type
== 2)
266 (memos
[memos_in_memory
].month
== shown
->mon
)
270 (memos
[memos_in_memory
].type
> 2)
272 (memos
[memos_in_memory
].month
== shown
->mon
)
274 (memos
[memos_in_memory
].year
== shown
->year
)
278 if (temp_memo1
[0] == '\n')
280 if (memos
[memos_in_memory
].type
> 0)
281 day_has_memo
[memos
[memos_in_memory
].day
] =
284 wday_has_memo
[memos
[memos_in_memory
].wday
] =
286 memos
[memos_in_memory
++].file_pointer_end
=
287 rb
->lseek(fp
, 0, SEEK_CUR
);
289 else if ( (temp_memo1
[0] != '\r') &&
290 (temp_memo1
[0] != '\t') )
291 memos
[memos_in_memory
].message
[k
] = temp_memo1
[0];
293 if (temp_memo1
[0] == '\n')
298 memos
[memos_in_memory
].day
= 0;
299 memos
[memos_in_memory
].month
= 0;
300 memos
[memos_in_memory
].file_pointer_start
= 0;
301 memos
[memos_in_memory
].file_pointer_end
= 0;
302 memos
[memos_in_memory
].year
= 0;
303 memos
[memos_in_memory
].type
= 0;
304 memos
[memos_in_memory
].wday
= 0;
305 rb
->strcpy(&memos
[memos_in_memory
].message
[0], "");
315 static bool save_memo(int changed
, bool new_mod
, struct shown
*shown
)
318 fp
= rb
->open(ROCKBOX_DIR
"/.memo",O_RDONLY
| O_CREAT
);
319 fq
= rb
->creat(ROCKBOX_DIR
"/~temp");
320 if ( (fq
!= -1) && (fp
!= -1) )
323 char temp
[MAX_CHAR_MEMO_LEN
+ 1];
324 rb
->lseek(fp
, 0, SEEK_SET
);
325 for (i
= 0; i
< memos
[changed
].file_pointer_start
; i
++)
327 rb
->read(fp
, temp
, 1);
328 rb
->write(fq
,temp
,1);
332 rb
->fdprintf(fq
, "%02d%02d%04d%01d%01d%s\n",
334 memos
[changed
].month
,
338 memos
[changed
].message
);
340 rb
->lseek(fp
, memos
[changed
].file_pointer_end
, SEEK_SET
);
341 for (i
= memos
[changed
].file_pointer_end
;
342 i
< rb
->filesize(fp
); i
++)
344 rb
->read(fp
, temp
, 1);
345 rb
->write(fq
,temp
,1);
348 fp
= rb
->creat(ROCKBOX_DIR
"/.memo");
349 rb
->lseek(fp
, 0, SEEK_SET
);
350 rb
->lseek(fq
, 0, SEEK_SET
);
351 for (i
= 0; i
< rb
->filesize(fq
); i
++)
353 rb
->read(fq
, temp
, 1);
354 rb
->write(fp
,temp
,1);
358 rb
->remove(ROCKBOX_DIR
"/~temp");
369 static void add_memo(struct shown
*shown
, int type
)
372 if (rb
->kbd_input(memos
[memos_in_memory
].message
,
373 sizeof memos
[memos_in_memory
].message
) != -1)
375 if (rb
->strlen(memos
[memos_in_memory
].message
))
377 memos
[memos_in_memory
].file_pointer_start
= 0;
378 memos
[memos_in_memory
].file_pointer_end
= 0;
379 memos
[memos_in_memory
].day
= shown
->mday
;
380 memos
[memos_in_memory
].month
= shown
->mon
;
381 memos
[memos_in_memory
].wday
= shown
->wday
;
382 memos
[memos_in_memory
].year
= shown
->year
;
383 memos
[memos_in_memory
].type
= type
;
384 if (save_memo(memos_in_memory
,true,shown
))
391 memos
[memos_in_memory
].file_pointer_start
= 0;
392 memos
[memos_in_memory
].file_pointer_end
= 0;
393 memos
[memos_in_memory
].day
= 0;
394 memos
[memos_in_memory
].month
= 0;
395 memos
[memos_in_memory
].year
= 0;
396 memos
[memos_in_memory
].type
= 0;
397 memos
[memos_in_memory
].wday
= 0;
401 rb
->lcd_clear_display();
403 rb
->lcd_setfont(FONT_SYSFIXED
);
405 rb
->lcd_puts(0,0,"Event added");
407 rb
->lcd_puts(0,0,"Event not added");
412 static bool edit_memo(int change
, struct shown
*shown
)
419 rb
->lcd_clear_display();
420 if (memos_in_shown_memory
> 0)
422 rb
->lcd_puts(0,0,"Remove : Up");
423 rb
->lcd_puts(0,1,"Edit : Down");
424 rb
->lcd_puts(0,2,"New :");
425 rb
->lcd_puts(2,3,"weekly : Left");
426 rb
->lcd_puts(2,4,"monthly : Play");
427 rb
->lcd_puts(2,5,"annually : Right");
428 rb
->lcd_puts(2,6,"one off : On");
432 rb
->lcd_puts(0,0,"New :");
433 rb
->lcd_puts(2,1,"weekly : Left");
434 rb
->lcd_puts(2,2,"monthly : Play");
435 rb
->lcd_puts(2,3,"anualy : Right");
436 rb
->lcd_puts(2,4,"one off : On");
439 button
= rb
->button_get(true);
462 if (memos_in_shown_memory
> 0)
464 if(rb
->kbd_input(memos
[pointer_array
[change
]].message
,
465 sizeof memos
[pointer_array
[change
]].message
) != -1)
466 save_memo(pointer_array
[change
],true,shown
);
468 rb
->lcd_setfont(FONT_SYSFIXED
);
474 if (memos_in_shown_memory
> 0)
476 save_memo(pointer_array
[change
],false,shown
);
482 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
483 been_in_usb_mode
= true;
490 static int start
= 0;
492 static void show_lines(int selected
, struct shown
*shown
)
494 int lines
,j
= 1,w
,h
,i
,k
= 0, pos
= 1,m
= 0;
495 char temp
[MAX_CHAR_MEMO_LEN
+ 12];
496 rb
->lcd_getstringsize("A",&w
,&h
);
497 lines
= (LCD_HEIGHT
/ h
) - 1;
499 rb
->lcd_clear_display();
500 rb
->lcd_puts(0,0,"Events (play : menu)");
502 while (selected
>= (lines
+ start
))
504 while (selected
< start
)
507 while ( (i
< memos_in_shown_memory
) && (k
< lines
) )
509 if (memos
[pointer_array
[i
]].type
== 2)
510 rb
->snprintf(temp
, sizeof temp
, "%s (%d yrs)",
511 memos
[pointer_array
[i
]].message
,
512 shown
->year
- memos
[pointer_array
[i
]].year
);
514 rb
->snprintf(temp
, sizeof temp
, "%s",
515 memos
[pointer_array
[i
]].message
);
520 rb
->lcd_puts_scroll(m
,j
++,temp
);
523 rb
->lcd_puts(m
,j
++,temp
);
527 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
528 rb
->lcd_fillrect(0, (pos
) * h
, LCD_WIDTH
, h
);
529 rb
->lcd_set_drawmode(DRMODE_SOLID
);
532 static void update_memos_shown(struct shown
*shown
)
535 memos_in_shown_memory
= 0;
537 for (i
= 0; i
< memos_in_memory
; i
++)
539 (memos
[i
].day
== shown
->mday
)
544 (memos
[i
].wday
== shown
->wday
)
547 pointer_array
[memos_in_shown_memory
++] = i
;
550 static bool any_events(struct shown
*shown
, bool force
)
552 int lines_displayed
= 0;
556 update_memos_shown(shown
);
557 if (memos_in_shown_memory
> 0)
558 show_lines(lines_displayed
,shown
);
560 return edit_memo(lines_displayed
, shown
);
566 button
= rb
->button_get(true);
570 if (memos_in_shown_memory
> 0)
573 if (lines_displayed
>= memos_in_shown_memory
)
574 lines_displayed
= memos_in_shown_memory
- 1;
575 show_lines(lines_displayed
,shown
);
581 if (memos_in_shown_memory
> 0)
584 if (lines_displayed
< 0)
586 show_lines(lines_displayed
,shown
);
592 return edit_memo(lines_displayed
, shown
);
598 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
599 been_in_usb_mode
= true;
600 show_lines(lines_displayed
,shown
);
608 static void next_month(struct shown
*shown
, int step
)
615 leap_year
= is_leap_year(shown
->year
);
618 shown
->mday
= shown
->mday
- days_in_month
[leap_year
][shown
->mon
-1];
619 else if (shown
->mday
> days_in_month
[leap_year
][shown
->mon
])
620 shown
->mday
= days_in_month
[leap_year
][shown
->mon
];
621 shown
->firstday
= shown
->lastday
;
623 draw_calendar(shown
);
626 static void prev_month(struct shown
*shown
, int step
)
633 leap_year
= is_leap_year(shown
->year
);
636 shown
->mday
= shown
->mday
+ days_in_month
[leap_year
][shown
->mon
];
637 else if (shown
->mday
> days_in_month
[leap_year
][shown
->mon
])
638 shown
->mday
= days_in_month
[leap_year
][shown
->mon
];
639 shown
->firstday
+= 7 - (days_in_month
[leap_year
][shown
->mon
] % 7);
641 draw_calendar(shown
);
644 static void next_day(struct shown
*shown
, int step
)
647 if (shown
->mday
> days_in_month
[leap_year
][shown
->mon
])
648 next_month(shown
, step
);
650 draw_calendar(shown
);
653 static void prev_day(struct shown
*shown
, int step
)
657 prev_month(shown
, step
);
659 draw_calendar(shown
);
662 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
673 calendar_init(&today
, &shown
);
675 any_events(&shown
, false);
676 draw_calendar(&shown
);
679 button
= rb
->button_get(true);
685 case BUTTON_ON
| BUTTON_DOWN
:
686 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REPEAT
:
687 next_month(&shown
, 0);
690 case BUTTON_ON
| BUTTON_UP
:
691 case BUTTON_ON
| BUTTON_UP
| BUTTON_REPEAT
:
692 prev_month(&shown
, 0);
696 case BUTTON_DOWN
| BUTTON_REPEAT
:
701 case BUTTON_UP
| BUTTON_REPEAT
:
706 case BUTTON_LEFT
| BUTTON_REPEAT
:
711 case BUTTON_RIGHT
| BUTTON_REPEAT
:
716 any_events(&shown
, true);
717 draw_calendar(&shown
);
721 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
722 been_in_usb_mode
= true;
723 draw_calendar(&shown
);
727 return been_in_usb_mode
?PLUGIN_USB_CONNECTED
:PLUGIN_OK
;