Index: apps/plugins/rockcalendar.c =================================================================== --- apps/plugins/rockcalendar.c (revision 0) +++ apps/plugins/rockcalendar.c (revision 0) @@ -0,0 +1,2418 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * by Ben Basha (Paprica) + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "configfile.h" +#include "xlcd.h" + +PLUGIN_HEADER + +static struct plugin_api *rb; +MEM_FUNCTION_WRAPPERS(rb); + +#if (CONFIG_KEYPAD == IRIVER_H300_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H100_PAD) + +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT BUTTON_SELECT +#define CANCEL BUTTON_OFF +#define NEXT_MONTH BUTTON_REC +#define PREV_MONTH BUTTON_ON +#define MENU BUTTON_MODE +#define CHANGE_LANG BUTTON_MODE + +#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_4G_PAD) + +#define LEFT BUTTON_SCROLL_BACK +#define RIGHT BUTTON_SCROLL_FWD +#define NEXT_MONTH BUTTON_RIGHT +#define PREV_MONTH BUTTON_LEFT +#define MENU BUTTON_MENU + +#define SELECT (BUTTON_SELECT | BUTTON_REL) +#define CANCEL (BUTTON_SELECT | BUTTON_MENU) + +#define MENU_SELECT BUTTON_RIGHT +#define MENU_CANCEL BUTTON_LEFT +#define MENU_CANCEL2 BUTTON_MENU +#define MENU_UP BUTTON_SCROLL_BACK +#define MENU_DOWN BUTTON_SCROLL_FWD + +#define CHANGE_LANG BUTTON_PLAY +#define KEYBOARD_MENU BUTTON_MENU + +#elif CONFIG_KEYPAD == RECORDER_PAD + +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT BUTTON_PLAY +#define CANCEL BUTTON_OFF +#define NEXT_MONTH BUTTON_F3 +#define PREV_MONTH BUTTON_F1 +#define MENU BUTTON_ON +#define CHANGE_LANG BUTTON_F1 + +#elif CONFIG_KEYPAD == ONDIO_PAD + +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT (BUTTON_MENU | BUTTON_REL) +#define CANCEL BUTTON_OFF +#define MENU (BUTTON_MENU | BUTTON_REPEAT) +#define CHANGE_LANG (BUTTON_MENU | BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IAUDIO_X5_PAD + +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT (BUTTON_SELECT | BUTTON_REL) +#define CANCEL BUTTON_POWER +#define NEXT_MONTH BUTTON_PLAY +#define PREV_MONTH BUTTON_REC +#define MENU (BUTTON_SELECT | BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD + +#define UP BUTTON_SCROLL_UP +#define DOWN BUTTON_SCROLL_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT (BUTTON_PLAY | BUTTON_REL) +#define CANCEL BUTTON_POWER +#define NEXT_MONTH BUTTON_FF +#define PREV_MONTH BUTTON_REW +#define MENU (BUTTON_PLAY | BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_E200_PAD + +#define UP BUTTON_SCROLL_UP +#define DOWN BUTTON_SCROLL_DOWN +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define SELECT (BUTTON_SELECT | BUTTON_REL) +#define CANCEL BUTTON_POWER +#define NEXT_MONTH BUTTON_UP +#define PREV_MONTH BUTTON_DOWN +#define MENU (BUTTON_SELECT | BUTTON_REPEAT) + +#endif + +/* ################################################################ + ############## Bitmaps ############## + ################################################################ */ +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) +#define NOTE_WIDTH 12 +#define NOTE_HEIGHT 13 + +#define BALLOONS_WIDTH 10 +#define BALLOONS_HEIGHT 15 + +#define HOUSE_WIDTH 15 +#define HOUSE_HEIGHT 14 + +#define KEY_WIDTH 220 +#define KEY_HEIGHT 81 +#define KEY_YPOS LCD_HEIGHT-KEY_HEIGHT + +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) +#define NOTE_WIDTH 7 +#define NOTE_HEIGHT 10 + +#define BALLOONS_WIDTH 6 +#define BALLOONS_HEIGHT 12 + +#define HOUSE_WIDTH 7 +#define HOUSE_HEIGHT 9 + +#define KEY_WIDTH 160 +#define KEY_HEIGHT 51 +#define KEY_YPOS LCD_HEIGHT-KEY_HEIGHT + +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + +#define NOTE_WIDTH 2 +#define NOTE_HEIGHT 2 + +#define BALLOONS_WIDTH 5 +#define BALLOONS_HEIGHT 2 + +#define HOUSE_WIDTH 8 +#define HOUSE_HEIGHT 2 + +#define KEY_WIDTH 112 +#define KEY_HEIGHT 34 +#define KEY_YPOS LCD_HEIGHT-KEY_HEIGHT + +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + +#define NOTE_WIDTH 7 +#define NOTE_HEIGHT 10 + +#define BALLOONS_WIDTH 6 +#define BALLOONS_HEIGHT 12 + +#define HOUSE_WIDTH 7 +#define HOUSE_HEIGHT 9 + +#define KEY_WIDTH 160 +#define KEY_HEIGHT 51 +#define KEY_YPOS LCD_HEIGHT-KEY_HEIGHT +#endif + + +extern const fb_data rockcalendar_note[]; +extern const fb_data rockcalendar_balloons[]; +extern const fb_data rockcalendar_house[]; +extern const fb_data rockcalendar_keyboard[]; +extern const fb_data rockcalendar_caps_keyboard[]; + +/* ################################################################ + ############## KeyBoard ############## + ################################################################ + The keyboard bitmap and code takes from RockWord + */ +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) +#define KEYBOARD_SIZE 58 +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +#define KEYBOARD_SIZE 56 +#endif +enum +{ + KEY_BACK, + KEY_CR, + KEY_CTRL, + KEY_HOME, + KEY_END, + KEY_DEL, + KEY_CAPS, + KEY_UP, + KEY_LEFT, + KEY_DOWN, + KEY_RIGHT, + KEYS_ACTIONS, +}; + +static short key_coords[KEYBOARD_SIZE][4] = { +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + /* 1st line - 0 */ + /* ` */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ + {0, 0, 12}, {11, 0, 17}, {27, 0, 17}, {43, 0, 17}, {59, 0, 17}, {75, 0, + 17}, + /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* 0 */ + {91, 0, 17}, {107, 0, 17}, {123, 0, 17}, {139, 0, 17}, {155, 0, 17}, + /* = */ /* - */ /* <- */ + {171, 0, 17}, {187, 0, 17}, {203, 0, 17}, + /* 2nd line - 16 */ + /* q */ /* w */ /* e */ /* r */ /* t */ + {20, 16, 17}, {36, 16, 17}, {52, 16, 17}, {68, 16, 17}, {84, 16, 17}, + /* y */ /* u */ /* i */ /* o */ /* p */ + {100, 16, 17}, {116, 16, 17}, {132, 16, 17}, {148, 16, 17}, {164, 16, 17}, + /* [ */ /* ] */ + {180, 16, 17}, {196, 16, 17}, + /* 3rd line - 32 */ + /* CAPS */ /* a */ /* s */ /* d */ /* f */ + {0, 32, 26}, {25, 32, 17}, {41, 32, 17}, {57, 32, 17}, {73, 32, 17}, + /* g */ /* h */ /* j */ /* k */ /* l */ + {89, 32, 17}, {105, 32, 17}, {121, 32, 17}, {137, 32, 17}, {153, 32, 17}, + /* ; */ /* ' */ /* Cr */ + {169, 32, 17}, {185, 32, 17}, {201, 32, 19}, + /* 4th line - 48 */ + /* z */ /* x */ /* c */ /* v */ /* b */ + {27, 48, 17}, {43, 48, 17}, {59, 48, 17}, {75, 48, 17}, {91, 48, 17}, + /* n */ /* m */ /* , */ /* . */ /* / */ + {107, 48, 17}, {123, 48, 17}, {139, 48, 17}, {155, 48, 17}, {171, 48, 17}, + /* ^ */ /* \ */ + {187, 48, 17}, {203, 48, 17}, + /* 5th line - 64 */ + /* */ /* Hm */ /* En */ /* dl */ + {38, 64, 84}, {121, 64, 21}, {141, 64, 17}, {157, 64, 15}, + /* < */ /* V */ /* > */ + {171, 64, 17}, {187, 64, 17}, {203, 64, 17} +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) + /* 1st line - 0 */ + /* ` */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ + {0, 0, 12}, {11, 0, 12}, {22, 0, 12}, {33, 0, 12}, {44, 0, 12}, {55, 0, + 12}, + /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* 0 */ + {66, 0, 12}, {77, 0, 12}, {88, 0, 12}, {99, 0, 12}, {110, 0, 12}, + /* = */ /* - */ /* <- */ + {121, 0, 12}, {132, 0, 12}, {143, 0, 17}, + /* 2nd line - 16 */ + /* q */ /* w */ /* e */ /* r */ /* t */ + {20, 10, 12}, {31, 10, 12}, {42, 10, 12}, {53, 10, 12}, {64, 10, 12}, + /* y */ /* u */ /* i */ /* o */ /* p */ + {75, 10, 12}, {86, 10, 12}, {97, 10, 12}, {108, 10, 12}, {119, 10, 12}, + /* [ */ /* ] */ + {130, 10, 12}, {141, 10, 12}, + /* 3rd line - 32 */ + /* CAPS */ /* a */ /* s */ /* d */ /* f */ + {0, 20, 27}, {26, 20, 12}, {37, 20, 12}, {48, 20, 12}, {59, 20, 12}, + /* g */ /* h */ /* j */ /* k */ /* l */ + {70, 20, 12},{81, 20, 12}, {92, 20, 12}, {103, 20, 12}, {114, 20, 12}, + /* ; */ /* ' */ /* Cr */ + {125, 20, 12},{136, 20, 12}, {147, 20, 13}, + /* 4th line - 48 */ + /* z */ /* x */ /* c */ /* v */ /* b */ + {32, 30, 12}, {43, 30, 12}, {54, 30, 12}, {65, 30, 12}, {76, 30, 12}, + /* n */ /* m */ /* , */ /* . */ /* / */ + {87, 30, 12}, {98, 30, 12}, {109, 30, 12}, {120, 30, 12}, {131, 30, 10}, + /* ^ */ /* \ */ + {140, 30, 12}, {151, 30, 9}, + /* 5th line - 64 */ + /* */ /* Hm */ /* En */ /* dl */ + {39, 40, 38}, {76, 40, 16}, {91, 40, 22}, {112, 40, 20}, + /* < */ /* V */ /* > */ + {131, 40, 10}, {140, 40, 12}, {151, 40, 9} +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + /* 1st line - 0 */ + /* ` */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ + {1, 2, 6}, {7, 2, 6}, {13, 2, 6}, {19, 2, 6}, {25, 2, 6}, {31, 2, 6}, + /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* 0 */ /* = */ + {37, 2, 6}, {43, 2, 6}, {49, 2, 6}, {55, 2, 6}, {61, 2, 6}, {67, 2, 6}, + /* - */ /* <- */ /* En */ + {73, 2, 6}, {79, 2, 9}, {93, 2, 19}, + /* 2nd line - 16 */ + /* q */ /* w */ /* e */ /* r */ /* t */ + {1, 10, 6}, {7, 10, 6}, {13, 10, 6}, {19, 10, 6}, {25, 10, 6}, + /* y */ /* u */ /* i */ /* o */ /* p */ + {31, 10, 6}, {37, 10, 6}, {43, 10, 6}, {49, 10, 6}, {55, 10, 6}, + /* [ */ /* ] */ /* ^ */ /* Hm */ + {61, 10, 6}, {67, 10, 6}, {73, 10, 6}, {87, 10, 25}, + /* 3rd line - 32 */ + /* a */ /* s */ /* d */ /* f */ /* g */ + {1, 18, 6}, {7, 18, 6}, {13, 18, 6}, {19, 18, 6}, {25, 18, 6}, + /* h */ /* j */ /* k */ /* l */ /* ; */ + {31, 18, 6}, {37, 18, 6}, {43, 18, 6}, {49, 18, 6}, {55, 18, 6}, + /* ' */ /* < */ /* V */ /* > */ /* dl */ + {61, 18, 6}, {67, 18, 6}, {73, 18, 6}, {79, 18, 6}, {93, 18, 19}, + /* 4th line - 48 */ + /* z */ /* x */ /* c */ /* v */ /* b */ + {1, 26, 6}, {7, 26, 6}, {13, 26, 6}, {19, 26, 6}, {25, 26, 6}, + /* n */ /* m */ /* , */ /* . */ /* / */ + {31, 26, 6}, {37, 26, 6}, {43, 26, 6}, {49, 26, 6}, {55, 26, 6}, + /* \ */ /* */ + {61, 26, 6}, {81, 26, 31}, +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + /* 1st line - 0 */ + /* ` */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ + {0, 0, 12}, {11, 0, 12}, {22, 0, 12}, {33, 0, 12}, {44, 0, 12}, {55, 0, + 12}, + /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* 0 */ + {66, 0, 12}, {77, 0, 12}, {88, 0, 12}, {99, 0, 12}, {110, 0, 12}, + /* = */ /* - */ /* <- */ + {121, 0, 12}, {132, 0, 12}, {143, 0, 17}, + /* 2nd line - 16 */ + /* q */ /* w */ /* e */ /* r */ /* t */ + {20, 10, 12}, {31, 10, 12}, {42, 10, 12}, {53, 10, 12}, {64, 10, 12}, + /* y */ /* u */ /* i */ /* o */ /* p */ + {75, 10, 12}, {86, 10, 12}, {97, 10, 12}, {108, 10, 12}, {119, 10, 12}, + /* [ */ /* ] */ + {130, 10, 12}, {141, 10, 12}, + /* 3rd line - 32 */ + /* CAPS */ /* a */ /* s */ /* d */ /* f */ + {0, 20, 27}, {26, 20, 12}, {37, 20, 12}, {48, 20, 12}, {59, 20, 12}, + /* g */ /* h */ /* j */ /* k */ /* l */ + {70, 20, 12},{81, 20, 12}, {92, 20, 12}, {103, 20, 12}, {114, 20, 12}, + /* ; */ /* ' */ /* Cr */ + {125, 20, 12},{136, 20, 12}, {147, 20, 13}, + /* 4th line - 48 */ + /* z */ /* x */ /* c */ /* v */ /* b */ + {32, 30, 12}, {43, 30, 12}, {54, 30, 12}, {65, 30, 12}, {76, 30, 12}, + /* n */ /* m */ /* , */ /* . */ /* / */ + {87, 30, 12}, {98, 30, 12}, {109, 30, 12}, {120, 30, 12}, {131, 30, 10}, + /* ^ */ /* \ */ + {140, 30, 12}, {151, 30, 9}, + /* 5th line - 64 */ + /* */ /* Hm */ /* En */ /* dl */ + {39, 40, 38}, {76, 40, 16}, {91, 40, 22}, {112, 40, 20}, + /* < */ /* V */ /* > */ + {131, 40, 10}, {140, 40, 12}, {151, 40, 9} +#endif +}; + +enum +{ + KEYBOARD_STANDART, + KEYBOARD_CAPS, + KEYBOARD_MODES, +}; + +unsigned char key_chars[KEYBOARD_MODES][KEYBOARD_SIZE] = { + /* English */ + { +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) + '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', KEY_BACK, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + KEY_CAPS, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', KEY_CR, + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', KEY_UP, '\\', + ' ', KEY_HOME, KEY_END, KEY_DEL, KEY_LEFT, KEY_DOWN, KEY_RIGHT +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', KEY_BACK, + KEY_END, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + KEY_UP, + KEY_HOME, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', + KEY_LEFT, + KEY_DOWN, KEY_RIGHT, KEY_DEL, 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', + '/', '\\', ' ', +#endif + }, + /* English Caps Lock */ + { +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) + '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', KEY_BACK, + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', + KEY_CAPS, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', KEY_CR, + 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', KEY_UP, '|', + ' ', KEY_HOME, KEY_END, KEY_DEL, KEY_LEFT, KEY_DOWN, KEY_RIGHT +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', KEY_BACK, + KEY_END, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', + KEY_UP, + KEY_HOME, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', + KEY_LEFT, + KEY_DOWN, KEY_RIGHT, KEY_DEL, 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', + '?', '|', ' ', +#endif + }, +}; + +#if defined(UP) && defined(DOWN) +static short keyboard_navigation[KEYBOARD_SIZE][2] = { + /* up, down */ +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) + /* 1st line */ + {26, 26}, {51, 14}, {51, 15}, {51, 16}, {51, 17}, {51, 18}, {51, 19}, + {51, 20}, {52, 21}, {53, 22}, {54, 23}, {55, 24}, {56, 25}, {57, 25}, + /* 2nd line */ + {1, 27}, {2, 28}, {3, 29}, {4, 30}, {5, 31}, {6, 32}, {7, 33}, + {8, 34}, {9, 35}, {10, 36}, {11, 37}, {12, 38}, + /* 3rd line */ + {0, 0}, {14, 39}, {15, 40}, {16, 41}, {17, 42}, {18, 43}, {19, 44}, {20, 445}, + {21, 46}, {22, 47}, {23, 48}, {24, 49}, {25, 50}, + /* 4th line */ + {27, 51}, {28, 51}, {29, 51}, {30, 51}, {31, 51}, {32, 51}, {33, 52}, + {34, 53}, {35, 54}, {36, 55}, {37, 56}, {38, 57}, + /* 5th line */ + {39, 1}, {45, 8}, {46, 9}, {47, 10}, {48, 11}, {49, 12}, {50, 13}, +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + /* 1st line */ + {44, 15}, {45, 16}, {46, 17}, {47, 18}, {48, 19}, {49, 20}, {50, 21}, + {51, 22}, {52, 23}, {53, 24}, {54, 25}, {40, 26}, {41, 27}, {42, 42}, + {55, 28}, + /* 2nd line */ + {0, 29}, {1, 30}, {2, 31}, {3, 32}, {4, 33}, {5, 34}, {6, 35}, + {7, 36}, {8, 37}, {9, 38}, {10, 39}, {11, 40}, {12, 41}, {14, 43}, + /* 3rd line */ + {15, 44}, {16, 45}, {17, 46}, {18, 47}, {19, 48}, {20, 49}, {21, 50}, + {22, 51}, {23, 52}, {24, 53}, {25, 54}, {26, 11}, {27, 12}, {13, 13}, + {28, 55}, + /* 4th line */ + {29, 0}, {30, 1}, {31, 2}, {32, 3}, {33, 4}, {34, 5}, {35, 6}, {36, 7}, + {37, 8}, {38, 9}, {39, 10}, {43, 14}, +#endif +}; +#endif + +/* ################################################################ + ############## Global variables ############## + ################################################################ */ + +static int days_in_month[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +}; + +static char month_name[12][10] = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +}; + +static char calen_days[7][4] = { +#if (LCD_WIDTH > 112) && (LCD_HEIGHT > 64) + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", +#else + "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", +#endif +}; + +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) +#define MESSAGE_LENGTH 30 +#define MESSAGE_LINES 8 +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) +#define MESSAGE_LENGTH 25 +#define MESSAGE_LINES 8 +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +#define MESSAGE_LENGTH 17 +#define MESSAGE_LINES 2 +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) +#define MESSAGE_LENGTH 25 +#define MESSAGE_LINES 8 +#endif + +enum +{ + NOTE, + FREE_DAY, + BIRTHDAY, + HOLIDAY, + MAX_NOTESTYPES +}; + +static char type_name[MAX_NOTESTYPES][10] = { + "Note", + "Free Day", + "Birthday", + "Holiday", +}; + +enum +{ + ADD_MENU_DELETE, + ADD_MENU_EDIT, + ADD_MENU_YEAR, + ADD_MENU_TYPE, + ADD_MENU_DONE, + ADD_MENU_ITEMS +}; + +enum +{ + DM_ADD, + DM_VIEW, + DM_DELETE, + DM_CANCEL, + DM_ITEMS +}; + + + +enum +{ + MM_FIRST, +#ifndef CONFIG_RTC + MM_DATE, +#endif + MM_QUITM, + MM_QUIT, + MM_ITEMS +}; + +enum +{ + DAY_MENU_VIEW, + DAY_MENU_ADD, + ADD_MENU, + VIEW_MENU, + MAIN_MENU, + MENUS_NUMBER, +}; + +enum +{ + MENU_1F_WIDTH, + MENU_1F_HEIGHT, + MENU_1F_XPOS, + MENU_1F_YPOS, + MENU_2F_WIDTH, + MENU_2F_HEIGHT, + MENU_2F_XPOS, + MENU_2F_YPOS, +}; + + +static int menus[MENUS_NUMBER][8] = { +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + {84, 13, 68, 63, 84, 44, 68, 75}, + {84, 13, 68, 63, 84, 44, 68, 75}, + {120, 13, 50, 45, 120, 54, 50, 57}, + {120, 13, 50, 95, 120, 54, 50, 107}, +#ifdef CONFIG_RTC + {145, 13, 37, 53, 145, 34, 37, 65}, +#else + {145, 13, 37, 53, 145, 44, 37, 65}, +#endif +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) + {84, 13, 38, 41, 84, 44, 38, 53}, + {84, 13, 38, 41, 84, 44, 38, 53}, + {120, 13, 20, 62, 120, 54, 20, 74}, + {120, 13, 20, 62, 120, 54, 20, 74}, +#ifdef CONFIG_RTC + {145, 13, 8, 23, 145, 34, 8, 35}, +#else + {145, 13, 8, 23, 145, 44, 8, 35}, +#endif +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + {84, 13, 14, 4, 84, 44, 14, 16}, + {84, 13, 14, 4, 84, 44, 14, 16}, + {112, 13, 0, 0, 112, 52, 0, 12}, + {112, 13, 0, 0, 112, 52, 0, 12}, +#ifdef CONFIG_RTC + {112, 13, 0, 10, 112, 34, 0, 22}, +#else + {112, 13, 0, 4, 112, 44, 0, 16}, +#endif +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + {84, 13, 38, 41, 84, 44, 38, 53}, + {84, 13, 38, 41, 84, 44, 38, 53}, + {120, 13, 20, 62, 120, 54, 20, 74}, + {120, 13, 20, 62, 120, 54, 20, 74}, +#ifdef CONFIG_RTC + {145, 13, 8, 23, 145, 34, 8, 35}, +#else + {145, 13, 8, 23, 145, 44, 8, 35}, +#endif +#endif +}; + +static char menu_items[MENUS_NUMBER][5][21] = { + {"Add New", "View", "Delete", "Cancel"}, + {"Add New", "View", "Delete", "Cancel"}, + {"Delete", "Edit Message", "Year:", "Type:", "Done"}, + {"Delete", "Edit Message", "Year:", "Type:", "Done"}, +#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) +#ifdef CONFIG_RTC + {"First Week Day:", "Quit Menu", "Quit Calendar"}, +#else + {"First Week Day:", "Date: %02d/%02d/%04d", "Quit Menu", "Quit Calendar"}, +#endif +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +#ifdef CONFIG_RTC + {"1st Week Day:", "Quit Menu", "Quit Calendar"}, +#else + {"1st Week Day:", "Date: %02d/%02d/%04d", "Quit Menu", "Quit Calendar"}, +#endif +#endif +}; + + + +#if LCD_DEPTH >= 16 +#define MENU_1F_COLOR LCD_RGBPACK(0, 70, 157) +#define MENU_2F_COLOR LCD_RGBPACK(0, 83, 187) +#define UNUSED_TEXT_COLOR LCD_RGBPACK(188,188,188) +#elif LCD_DEPTH == 2 +#define MENU_1F_COLOR LCD_DARKGRAY +#define MENU_2F_COLOR LCD_LIGHTGRAY +#define UNUSED_TEXT_COLOR LCD_DARKGRAY +#endif + +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) +#define MONTH_NAME_YPOS 9 +#define LEFTMARGIN 8 +#define RIGHTMARGIN 8 +#define TOPMARGIN 35 +#define BOTTOMMARGIN 2 +#define SQU_WIDTH 28 +#define SQU_HEIGHT 22 + +#define TEXT_YPOS 25 +#define TEXT_XPOS 4 +#define TEXT_FRAME_XPOS 1 +#define TEXT_FRAME_YPOS 14 +#define TEXT_FRAME_WIDTH 218 +#define TEXT_FRAME_HEIGHT 78 + +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) +#define MONTH_NAME_YPOS 9 +#define LEFTMARGIN 3 +#define RIGHTMARGIN 3 +#define TOPMARGIN 35 +#define BOTTOMMARGIN 2 +#define SQU_WIDTH 21 +#define SQU_HEIGHT 14 + +#define TEXT_YPOS 11 +#define TEXT_XPOS 1 +/* the small lcd's dont have a frame for the text */ +#define TEXT_FRAME_XPOS 1 +#define TEXT_FRAME_YPOS 1 +#define TEXT_FRAME_WIDTH 0 +#define TEXT_FRAME_HEIGHT 0 + +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +#define MONTH_NAME_YPOS 4 +#define LEFTMARGIN 0 +#define RIGHTMARGIN 0 +#define TOPMARGIN 24 +#define BOTTOMMARGIN 0 +#define SQU_WIDTH 15 +#define SQU_HEIGHT 12 + +#define TEXT_YPOS 11 +#define TEXT_XPOS 1 +/* the small lcd's dont have a frame for the text */ +#define TEXT_FRAME_XPOS 0 +#define TEXT_FRAME_YPOS 0 +#define TEXT_FRAME_WIDTH 0 +#define TEXT_FRAME_HEIGHT 0 + +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) +#define MONTH_NAME_YPOS 9 +#define LEFTMARGIN 3 +#define RIGHTMARGIN 3 +#define TOPMARGIN 35 +#define BOTTOMMARGIN 2 +#define SQU_WIDTH 21 +#define SQU_HEIGHT 14 + +#define TEXT_YPOS 11 +#define TEXT_XPOS 1 +/* the small lcd's dont have a frame for the text */ +#define TEXT_FRAME_XPOS 1 +#define TEXT_FRAME_YPOS 1 +#define TEXT_FRAME_WIDTH 0 +#define TEXT_FRAME_HEIGHT 0 + +#endif + +static int yoffset[6] = { +#if (LCD_WIDTH <= 112) && (LCD_HEIGHT <= 64) + 0, 0, -(SQU_HEIGHT + 1), -(SQU_HEIGHT * 2 + 2), -(SQU_HEIGHT * 3 + 3), + -(SQU_HEIGHT * 3 + 3), +#else + 0, 0, 0, 0, 0, 0, +#endif +}; + +#define NOTES_FILE PLUGIN_DIR "/cal.da" + + +struct _note +{ + int day; + int month; + int year; + int type; + unsigned char message[MESSAGE_LINES][MESSAGE_LENGTH]; +}; + +struct _keyboard +{ + int selection; + int font_width, font_height; + int currow, curcol; + int keyboard_mode; +}; + +struct calendar +{ + int calen[6][7]; + int first_day, last_day; + int notes_count; + int year; /* current year */ + int month; /* current month */ + int row, col; /* cursor of the calendar */ + int offset; +#ifndef CONFIG_RTC + int sday; + int smonth; + int syear; +#endif + int first_week_day; + struct _note note[200]; +}; + +static struct calendar cl; + +static struct configdata config[] = { + {TYPE_INT, 0, 6, &cl.first_week_day, "first_week_day", NULL, NULL}, +#ifndef CONFIG_RTC + {TYPE_INT, -148, 299, &cl.syear, "year", NULL, NULL}, + {TYPE_INT, 0, 11, &cl.smonth, "month", NULL, NULL}, + {TYPE_INT, 1, 31, &cl.sday, "day", NULL, NULL}, +#endif +}; + +#ifndef CONFIG_RTC +static int month_table[2][12] = { + {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}, + {6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}, +}; +#endif + +bool leap_year (int year) +{ + if ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) + return true; + return false; +} + +/* ################################################################ + ############## Read the notes from the file ############## + ################################################################ */ + +void read_notes (void) +{ + + char buf[MAX_PATH]; + char t[2]; + char dm[3]; + char y[4]; + int fd, i; + char *pos; + char *ptr; + + rb->splash (0, "Loading data..."); + + fd = rb->open (NOTES_FILE, O_RDONLY); + cl.notes_count = 0; + if (fd > -1) { + rb->lseek (fd, 0, SEEK_SET); + while (true) { + if (rb->read (fd, t, 1) == 1) + cl.note[cl.notes_count].type = rb->atoi (&t[0]); + else + cl.note[cl.notes_count].type = 0; + + if (rb->read (fd, dm, 2) == 2) + cl.note[cl.notes_count].day = rb->atoi (&dm[0]); + else + cl.note[cl.notes_count].day = 0; + + if (rb->read (fd, dm, 2) == 2) + cl.note[cl.notes_count].month = rb->atoi (&dm[0]); + else + cl.note[cl.notes_count].month = 0; + + if (rb->read (fd, y, 3) == 3) + cl.note[cl.notes_count].year = rb->atoi (&y[0]); + else + cl.note[cl.notes_count].year = 0; + + rb->read (fd, buf, 1); + + if (cl.note[cl.notes_count].day == 0 && + cl.note[cl.notes_count].month == 0 && + cl.note[cl.notes_count].year == 0) + break; + + rb->read_line (fd, buf, MAX_PATH); + ptr = buf; + pos = rb->strchr (ptr, '|'); + i = 0; + while (pos != NULL) { + if (pos - ptr + 1 < MESSAGE_LENGTH) + rb->memcpy (cl.note[cl.notes_count].message[i], ptr, + pos - ptr); + else + rb->memcpy (cl.note[cl.notes_count].message[i], ptr, + MESSAGE_LENGTH); + ptr = pos + 1; + pos = rb->strchr (ptr, '|'); + i++; + } + + cl.notes_count++; + } + } + rb->close (fd); + + +#ifdef CONFIG_RTC + configfile_load ("cal.cfg", config, 1, 0); +#else + if (configfile_load ("cal.cfg", config, 4, 0) <= 0) { + cl.sday = 1; + cl.smonth = 0; + cl.syear = 100; + } +#endif + +} + +/* ################################################################ + ############## Save the notes to file ############## + ################################################################ */ + +void save_notes (void) +{ + int fd, i, j; + char str[MESSAGE_LENGTH]; + + rb->splash (0, "Saving data..."); + fd = rb->creat (NOTES_FILE); + for (i = 0; i < cl.notes_count; i++) { + if (cl.note[i].day > 0) { + rb->fdprintf (fd, "%1d%02d%02d%03d:", cl.note[i].type, + cl.note[i].day, cl.note[i].month, cl.note[i].year); + for (j = 0; j < MESSAGE_LINES; j++) + if (cl.note[i].message[j][0] != '\0') { + rb->snprintf (str, MESSAGE_LENGTH, "%s", + cl.note[i].message[j]); + rb->fdprintf (fd, "%s|", str); + } + } + rb->fdprintf (fd, "\n"); + } + rb->close (fd); + + +#ifdef CONFIG_RTC + configfile_save ("cal.cfg", config, 1, 0); +#else + configfile_save ("cal.cfg", config, 4, 0); +#endif +} + +/* ################################################################ + ############## initialization of the calendar ############## + ################################################################ */ + +void calen_init (void) +{ + int x, i, month_day; + + month_day = 0; + for (i = 0; i < 6; i++) { + for (x = 0; x < 7; x++) { + if ((i == 0 && x < cl.first_day) + || (month_day >= + days_in_month[leap_year (cl.year)][cl.month])) + cl.calen[i][x] = 0; + else { + cl.calen[i][x] = ++month_day; + cl.last_day = x; + } + } + } +} + +/* ################################################################ + ############## Keyboard Functions ############## + ################################################################ */ + +static void inv_keysel (struct _keyboard kb, bool update) +{ + rb->lcd_set_drawmode (DRMODE_COMPLEMENT); + rb->lcd_fillrect (key_coords[kb.selection][0], + KEY_YPOS + key_coords[kb.selection][1], + key_coords[kb.selection][2], +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + 17); +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) + 11); +#elif (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + 8); +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + 11); +#endif + rb->lcd_set_drawmode (DRMODE_SOLID); + if (update) + rb->lcd_update_rect (0, KEY_YPOS, KEY_WIDTH, KEY_HEIGHT); +} + +static void inv_cursor (struct _keyboard kb, bool update) +{ +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + rb->lcd_set_drawmode (DRMODE_COMPLEMENT); + /* cross painting */ + rb->lcd_fillrect (TEXT_XPOS + kb.curcol * kb.font_width, + TEXT_YPOS + 2 + kb.currow * kb.font_height, + kb.font_width, kb.font_height); + rb->lcd_set_drawmode (DRMODE_SOLID); + if (update) + rb->lcd_update (); +} + +void keyboard_bitmap (bool mode) +{ + if (mode == KEYBOARD_STANDART) { + rb->lcd_bitmap (rockcalendar_keyboard, 0, + KEY_YPOS, KEY_WIDTH, KEY_HEIGHT); + } else if (mode == KEYBOARD_CAPS) { + rb->lcd_bitmap (rockcalendar_caps_keyboard, 0, KEY_YPOS, + KEY_WIDTH, KEY_HEIGHT); + } +} + +static void keyboard_loop (int note_num) +{ + int button; + bool done = false; + char temp[2]; + struct _keyboard kb; + + rb->lcd_set_drawmode (DRMODE_SOLID); +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background (LCD_RGBPACK (251, 233, 102)); +#endif +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + + kb.selection = 0; + kb.currow = 0; + kb.curcol = 0; + kb.keyboard_mode = 0; + + rb->lcd_getstringsize ("A", &kb.font_width, &kb.font_height); + + inv_cursor (kb, false); + inv_keysel (kb, true); + + while (!done) { + button = rb->button_get (true); + + switch (button) { +#ifdef UP + case UP: + case UP | BUTTON_REPEAT: + inv_keysel (kb, false); + kb.selection = keyboard_navigation[kb.selection][0]; + inv_keysel (kb, true); + break; +#endif +#ifdef DOWN + case DOWN: + case DOWN | BUTTON_REPEAT: + inv_keysel (kb, false); + kb.selection = keyboard_navigation[kb.selection][1]; + inv_keysel (kb, true); + break; +#endif + case LEFT: + case LEFT | BUTTON_REPEAT: + inv_keysel (kb, false); + kb.selection = (kb.selection - 1); + if (kb.selection < 0) + kb.selection = KEYBOARD_SIZE - 1; + inv_keysel (kb, true); + break; + case RIGHT: + case RIGHT | BUTTON_REPEAT: + inv_keysel (kb, false); + kb.selection = (kb.selection + 1); + if (kb.selection >= KEYBOARD_SIZE) + kb.selection = 0; + inv_keysel (kb, true); + break; +#ifdef CHANGE_LANG + case CHANGE_LANG: + inv_keysel (kb, false); + if (kb.keyboard_mode == KEYBOARD_STANDART) + kb.keyboard_mode = KEYBOARD_CAPS; + else + kb.keyboard_mode = KEYBOARD_STANDART; + keyboard_bitmap (kb.keyboard_mode); + inv_keysel (kb, true); + break; +#endif +#ifdef KEYBOARD_MENU + case KEYBOARD_MENU: +#endif + case CANCEL: + done = true; + break; + case SELECT: +#if (CONFIG_KEYPAD != IPOD_3G_PAD) && \ + (CONFIG_KEYPAD != IPOD_4G_PAD) && \ + (CONFIG_KEYPAD != ONDIO_PAD) + case SELECT | BUTTON_REPEAT: +#endif + if (key_chars[kb.keyboard_mode][kb.selection] < KEYS_ACTIONS) { + + switch (key_chars[kb.keyboard_mode][kb.selection]) { + case KEY_BACK: + inv_cursor (kb, false); + if (kb.currow != 0 || kb.curcol != 0) + kb.curcol--; + if (kb.curcol < 0) { + kb.curcol = MESSAGE_LENGTH; + kb.currow--; + } + rb->lcd_putsxy (TEXT_XPOS + + kb.curcol * kb.font_width, + TEXT_YPOS + 2 + + kb.currow * kb.font_height, " "); + cl.note[note_num].message[kb.currow][kb.curcol] = + NULL; + inv_cursor (kb, true); + break; + case KEY_HOME: + inv_cursor (kb, false); + kb.curcol = 0; + inv_cursor (kb, true); + break; + case KEY_END: + inv_cursor (kb, false); + kb.curcol = MESSAGE_LENGTH; + inv_cursor (kb, true); + break; + case KEY_DEL: + inv_cursor (kb, false); + cl.note[note_num].message[kb.currow][kb.curcol] = + NULL; + + rb->lcd_putsxy (TEXT_XPOS + + kb.curcol * kb.font_width, + TEXT_YPOS + 2 + + kb.currow * kb.font_height, " "); + inv_cursor (kb, true); + break; + case KEY_UP: + inv_cursor (kb, false); + if (kb.currow != 0) { + kb.currow--; + } + inv_cursor (kb, true); + break; + case KEY_LEFT: + inv_cursor (kb, false); + if (kb.currow != 0 || kb.curcol != 0) + kb.curcol--; + if (kb.curcol < 0) { + kb.curcol = MESSAGE_LENGTH; + kb.currow--; + } + inv_cursor (kb, true); + break; + case KEY_DOWN: + inv_cursor (kb, false); + if (kb.currow != MESSAGE_LINES - 1) + kb.currow++; + inv_cursor (kb, true); + break; + case KEY_RIGHT: + inv_cursor (kb, false); + if (kb.curcol == MESSAGE_LENGTH + && kb.currow != MESSAGE_LINES - 1) { + kb.curcol = 0; + kb.currow++; + } else if (kb.currow != MESSAGE_LINES) + kb.curcol++; + inv_cursor (kb, true); + break; + case KEY_CAPS: + inv_keysel (kb, false); + if (kb.keyboard_mode == KEYBOARD_STANDART) + kb.keyboard_mode = KEYBOARD_CAPS; + else + kb.keyboard_mode = KEYBOARD_STANDART; + keyboard_bitmap (kb.keyboard_mode); + inv_keysel (kb, true); + break; + } + } else { + inv_cursor (kb, false); + cl.note[note_num].message[kb.currow][kb.curcol] = + key_chars[kb.keyboard_mode][kb.selection]; + rb->snprintf (temp, 2, "%c", + key_chars[kb.keyboard_mode][kb.selection]); + rb->lcd_putsxy (TEXT_XPOS + kb.curcol * kb.font_width, + TEXT_YPOS + 2 + + kb.currow * kb.font_height, temp); + if (kb.curcol == MESSAGE_LENGTH + && kb.currow != MESSAGE_LINES - 1) { + kb.curcol = 0; + kb.currow++; + } else if (kb.curcol != MESSAGE_LENGTH + && kb.currow != MESSAGE_LINES) + kb.curcol++; + inv_cursor (kb, true); + } + break; + } /* end switch */ + } /* end while */ +} + + +/* ################################################################ + ############## Delete specific note ############## + ################################################################ */ +void delete_note (int y) +{ + int i; + cl.notes_count--; + cl.note[y].year = cl.note[cl.notes_count].year; + cl.note[y].day = cl.note[cl.notes_count].day; + cl.note[y].month = cl.note[cl.notes_count].month; + cl.note[y].type = cl.note[cl.notes_count].type; + cl.note[y].year = cl.note[cl.notes_count].year; + for (i = 0; i < MESSAGE_LINES; i++) { + rb->snprintf (cl.note[y].message[0], MESSAGE_LENGTH, "%s", + cl.note[cl.notes_count].message[0]); + rb->strcpy (cl.note[cl.notes_count].message[0], ""); + } + + cl.note[cl.notes_count].year = -1; + cl.note[cl.notes_count].day = -1; + cl.note[cl.notes_count].month = -1; + cl.note[cl.notes_count].type = -1; + cl.note[cl.notes_count].year = -1; + +} + +/* ################################################################ + ############## View specific note message ############## + ################################################################ */ +void view_message (int y) +{ + int i, h; + char str[MESSAGE_LENGTH]; + + rb->lcd_set_drawmode (DRMODE_SOLID); +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background (LCD_RGBPACK (251, 233, 102)); +#endif + rb->lcd_getstringsize ("A", NULL, &h); + + for (i = 0; i < MESSAGE_LINES; i++) { + rb->snprintf (str, MESSAGE_LENGTH, "%s", cl.note[y].message[i]); + rb->lcd_putsxy (TEXT_XPOS, TEXT_YPOS + 2 + i * h, str); + } +} + +/* ################################################################ + ########## Draw the frame on the view/add note screen ########## + ################################################################ */ +void draw_frame (int y) +{ + char str[15]; +#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) + int h, w; + rb->lcd_set_foreground (LCD_BLACK); + + rb->lcd_getstringsize ("Note", &w, &h); + rb->lcd_putsxy (LCD_WIDTH / 2 - w / 2, 4, "Note"); + + rb->lcd_set_foreground (LCD_RGBPACK (251, 233, 102)); + + rb->lcd_fillrect (TEXT_FRAME_XPOS, TEXT_FRAME_YPOS, TEXT_FRAME_WIDTH, + TEXT_FRAME_HEIGHT); + + rb->lcd_set_foreground (LCD_BLACK); + + rb->lcd_drawrect (TEXT_FRAME_XPOS, TEXT_FRAME_YPOS, TEXT_FRAME_WIDTH, + TEXT_FRAME_HEIGHT); +#endif + + if (cl.note[y].year == 555) + rb->snprintf (str, 11, "%02d/%02d/****", cl.calen[cl.row][cl.col], + cl.month + 1); + else + rb->snprintf (str, 11, "%02d/%02d/%04d", cl.calen[cl.row][cl.col], + cl.month + 1, cl.year + 1900); + + rb->lcd_set_drawmode (DRMODE_FG); + rb->lcd_putsxy (TEXT_XPOS, TEXT_FRAME_YPOS + 3, str); + rb->lcd_set_drawmode (DRMODE_SOLID); +} + +/* ################################################################ + ############## Draw the menus ############## + ################################################################ */ +void draw_menu (int menu) +{ + int i, h, w; + char str[15]; + + rb->lcd_getstringsize ("A", NULL, &h); + + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (MENU_1F_COLOR); + + rb->lcd_fillrect (menus[menu][MENU_1F_XPOS], menus[menu][MENU_1F_YPOS], + menus[menu][MENU_1F_WIDTH], + menus[menu][MENU_1F_HEIGHT]); + + rb->lcd_set_foreground (MENU_2F_COLOR); + + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS], menus[menu][MENU_2F_YPOS], + menus[menu][MENU_2F_WIDTH], + menus[menu][MENU_2F_HEIGHT]); + + rb->lcd_set_foreground (LCD_BLACK); +#elif LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID); + rb->lcd_fillrect (menus[menu][MENU_1F_XPOS], menus[menu][MENU_1F_YPOS], + menus[menu][MENU_1F_WIDTH], + menus[menu][MENU_1F_HEIGHT]); + + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS], menus[menu][MENU_2F_YPOS], + menus[menu][MENU_2F_WIDTH], + menus[menu][MENU_2F_HEIGHT]); + rb->lcd_set_drawmode (DRMODE_SOLID); +#endif + + + rb->lcd_drawrect (menus[menu][MENU_1F_XPOS], menus[menu][MENU_1F_YPOS], + menus[menu][MENU_1F_WIDTH], + menus[menu][MENU_1F_HEIGHT]); + rb->lcd_drawrect (menus[menu][MENU_2F_XPOS], menus[menu][MENU_2F_YPOS], + menus[menu][MENU_2F_WIDTH], + menus[menu][MENU_2F_HEIGHT]); + + rb->lcd_set_drawmode (DRMODE_FG); + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_WHITE); +#endif + + + if (menu == DAY_MENU_ADD || menu == DAY_MENU_VIEW) { + rb->snprintf (str, 11, "%02d/%02d/%04d", cl.calen[cl.row][cl.col], + cl.month + 1, cl.year + 1900); + rb->lcd_getstringsize (str, &w, NULL); + } else if (menu == MAIN_MENU) { + rb->snprintf (str, 11, "Main Menu"); + rb->lcd_getstringsize (str, &w, NULL); + } else { + rb->snprintf (str, 11, "Menu"); + rb->lcd_getstringsize (str, &w, NULL); + } + + rb->lcd_putsxy (menus[menu][MENU_1F_XPOS] + + (menus[menu][MENU_1F_WIDTH] / 2 - w / 2), + menus[menu][MENU_1F_YPOS] + 3, str); + + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + + for (i = 0; i < ADD_MENU_ITEMS; i++) { + if (menu_items[menu][i]) { + if (menu == DAY_MENU_VIEW) { + if (i == DM_ADD) { + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (UNUSED_TEXT_COLOR); +#endif + + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + i * h + + i * 2 + 2, menu_items[menu][i]); + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + + } else { + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + i * h + + i * 2 + 2, menu_items[menu][i]); + } + } else if (menu == DAY_MENU_ADD) { + if (i == DM_VIEW || i == DM_DELETE) { + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (UNUSED_TEXT_COLOR); +#endif + + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + i * h + + i * 2 + 2, menu_items[menu][i]); + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + + } else { + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + i * h + + i * 2 + 2, menu_items[menu][i]); + } + } else + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + i * h + i * 2 + 2, + menu_items[menu][i]); + } + } + rb->lcd_set_drawmode (DRMODE_SOLID); + + rb->lcd_update_rect (menus[menu][MENU_1F_XPOS], menus[menu][MENU_1F_YPOS], + menus[menu][MENU_1F_WIDTH], + menus[menu][MENU_1F_HEIGHT] + + menus[menu][MENU_2F_HEIGHT]); + +} + +/* ################################################################ + ############## Menu navigation function ############## + ################################################################ */ +#if (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) +void msg_without_keyboard (void) +{ + int button; + bool exit = false; + + while (!exit) { + button = rb->button_get (true); + switch (button) { + case CANCEL: + exit = true; + break; + } + } +} +#endif + +#ifndef CONFIG_RTC +#define MAX_YEAR 299 +#define MIN_YEAR -148 + +void change_date (void) { + int h, w, cur = 0, button, day, month, year; + bool exit = false; + char str[20]; + + day = cl.sday; + month = cl.smonth; + year = cl.syear; + + int cur_pos[3][2] = { + {menus[MAIN_MENU][MENU_2F_XPOS] + 48, 12}, + {menus[MAIN_MENU][MENU_2F_XPOS] + 66, 12}, + {menus[MAIN_MENU][MENU_2F_XPOS] + 84, 24}, + }; + + rb->lcd_getstringsize ("A", NULL, &h); + + while (!exit) { + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (MENU_2F_COLOR); +#elif LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID); +#endif + + rb->lcd_fillrect (menus[MAIN_MENU][MENU_2F_XPOS] + 11, + menus[MAIN_MENU][MENU_2F_YPOS] + MM_DATE * h + + MM_DATE * 2 + 2, +#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + 100, 8); +#else + 130, 8); +#endif + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + rb->lcd_set_drawmode (DRMODE_FG); + + rb->snprintf (str, sizeof (str), menu_items[MAIN_MENU][MM_DATE], + day, month+1, year + 1900); + rb->lcd_putsxy (menus[MAIN_MENU][MENU_2F_XPOS] + 11, + menus[MAIN_MENU][MENU_2F_YPOS] + MM_DATE * h + + MM_DATE * 2 + 2, str); + + rb->lcd_getstringsize (str, &w, NULL); + + rb->lcd_set_drawmode (DRMODE_COMPLEMENT); + rb->lcd_fillrect (cur_pos[cur][0], + menus[MAIN_MENU][MENU_2F_YPOS] + MM_DATE * h + + MM_DATE * 2 + 2, + cur_pos[cur][1], h); + rb->lcd_set_drawmode (DRMODE_SOLID); + + rb->lcd_update_rect (menus[MAIN_MENU][MENU_2F_XPOS] + 11, + menus[MAIN_MENU][MENU_2F_YPOS] + MM_DATE * h + + MM_DATE * 2 + 2, +#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) + 100, 8); +#else + 130, 8); +#endif + + button = rb->button_get (true); + switch (button) { + case LEFT: + if (--cur < 0) + cur = 2; + break; + case RIGHT: + if (++cur > 2) + cur = 0; + break; + case UP: + case UP | BUTTON_REPEAT: + switch (cur) { + case 0: + if (++day > days_in_month[leap_year (year)][month]) + day = 1; + break; + case 1: + if (++month > 11) + month = 0; + break; + case 2: + if (++year > MAX_YEAR) + year = MIN_YEAR; + break; + } + break; + case DOWN: + case DOWN | BUTTON_REPEAT: + switch (cur) { + case 0: + if (--day < 1) + day = days_in_month[leap_year (year)][month]; + break; + case 1: + if (--month < 0) + month = 11; + break; + case 2: + if (--year < MIN_YEAR) + year = MAX_YEAR; + break; + } + break; + case SELECT: + cl.sday = day; + cl.smonth = month; + cl.syear = year; + + exit=true; + break; + } + + } +} +#endif + +bool menu_navigate (int menu, int note_num) +{ + int h, cur, button; + bool exit = false; + char str[20]; + + + rb->lcd_getstringsize ("A", NULL, &h); + + if (menu == DAY_MENU_VIEW) + cur = 1; + else + cur = 0; + + while (!exit) { + + if (menu == ADD_MENU || menu == VIEW_MENU) { +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (MENU_2F_COLOR); +#elif LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID); +#endif + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1, + menus[menu][MENU_2F_YPOS] + 1, 10, + menus[menu][MENU_2F_HEIGHT] - 3); + + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + 22, 98, 19); + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + rb->lcd_set_drawmode (DRMODE_FG); + rb->snprintf (str, sizeof (str), "%s %s", + menu_items[menu][ADD_MENU_YEAR], + cl.note[note_num].year == + 555 ? "All Year" : "This Year"); + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + ADD_MENU_YEAR * h + + ADD_MENU_YEAR * 2 + 2, str); + rb->snprintf (str, sizeof (str), "%s %s", + menu_items[menu][ADD_MENU_TYPE], + type_name[cl.note[note_num].type]); + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + ADD_MENU_TYPE * h + + ADD_MENU_TYPE * 2 + 2, str); + rb->lcd_set_drawmode (DRMODE_SOLID); + + } else if (menu == MAIN_MENU) { + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (MENU_2F_COLOR); +#elif LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID); +#endif + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1, + menus[menu][MENU_2F_YPOS] + 1, 10, + menus[menu][MENU_2F_HEIGHT] - 3); + +#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +#ifndef CONFIG_RTC + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + 1, 100, 19); +#else + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + 1, 100, 9); +#endif +#else +#ifndef CONFIG_RTC + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + 1, 130, 19); +#else + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + 1, 130, 9); +#endif +#endif + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + rb->lcd_set_drawmode (DRMODE_FG); + rb->snprintf (str, sizeof (str), "%s %s", + menu_items[menu][MM_FIRST], + calen_days[cl.first_week_day]); + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + MM_FIRST * h + + MM_FIRST * 2 + 2, str); +#ifndef CONFIG_RTC + rb->snprintf (str, sizeof (str), menu_items[menu][MM_DATE], + cl.sday, cl.smonth+1, cl.syear + 1900); + rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11, + menus[menu][MENU_2F_YPOS] + MM_DATE * h + + MM_DATE * 2 + 2, str); +#endif + + rb->lcd_set_drawmode (DRMODE_SOLID); + } else { + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (MENU_2F_COLOR); +#elif LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID | DRMODE_INVERSEVID); +#endif + rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1, + menus[menu][MENU_2F_YPOS] + 1, 10, + menus[menu][MENU_2F_HEIGHT] - 3); +#if LCD_DEPTH == 1 + rb->lcd_set_drawmode (DRMODE_SOLID); +#endif + } + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + xlcd_filltriangle (menus[menu][MENU_2F_XPOS] + 4, + menus[menu][MENU_2F_YPOS] + cur * h + cur * 2 + 2, + menus[menu][MENU_2F_XPOS] + 4, + menus[menu][MENU_2F_YPOS] + cur * h + cur * 2 + 2 + + h, menus[menu][MENU_2F_XPOS] + 4 + 5, + menus[menu][MENU_2F_YPOS] + cur * h + cur * 2 + 2 + + (h - 1) / 2 + 1); + + rb->lcd_update_rect (menus[menu][MENU_1F_XPOS], + menus[menu][MENU_1F_YPOS], + menus[menu][MENU_1F_WIDTH], + menus[menu][MENU_1F_HEIGHT] + + menus[menu][MENU_2F_HEIGHT]); + + button = rb->button_get (true); + switch (button) { +#ifdef MENU_CANCEL + case MENU_CANCEL: +#else + case LEFT: + case CANCEL: +#endif +#ifdef MENU_CANCEL2 + case MENU_CANCEL2: +#endif + exit = true; + break; +#ifdef MENU_DOWN + case MENU_DOWN: +#else + case DOWN: + case DOWN | BUTTON_REPEAT: +#endif + if (menu == DAY_MENU_VIEW) { + if (++cur == DM_ITEMS) + cur = DM_VIEW; + } else if (menu == DAY_MENU_ADD) { + if (++cur == DM_ITEMS) + cur = 0; + else if (cur == DM_VIEW) + cur = DM_CANCEL; + + } else if (menu == MAIN_MENU) { + if (++cur == MM_ITEMS) + cur = MM_FIRST; + } else { + if (++cur == ADD_MENU_ITEMS) + cur = ADD_MENU_DELETE; + } + break; +#ifdef MENU_UP + case MENU_UP: +#else + case UP: + case UP | BUTTON_REPEAT: +#endif + if (menu == DAY_MENU_VIEW) { + if (--cur < DM_VIEW) + cur = DM_CANCEL; + } else if (menu == DAY_MENU_ADD) { + if (--cur < 0) + cur = DM_CANCEL; + else if (cur == DM_DELETE) + cur = DM_ADD; + } else if (menu == MAIN_MENU) { + if (--cur < MM_FIRST) + cur = MM_QUIT; + } else { + if (--cur < ADD_MENU_DELETE) + cur = ADD_MENU_DONE; + } + break; +#ifdef MENU_SELECT + case MENU_SELECT: +#else + case RIGHT: +#endif + case SELECT: + + if (menu == DAY_MENU_ADD || menu == DAY_MENU_VIEW) { + switch (cur) { + case DM_ADD: +#if LCD_DEPTH >= 2 + rb->lcd_set_background (LCD_WHITE); +#endif + rb->lcd_clear_display (); + draw_frame (note_num); + keyboard_bitmap (KEYBOARD_STANDART); + rb->lcd_update (); + cl.note[note_num].year = cl.year; + keyboard_loop (note_num); + draw_menu (ADD_MENU); + menu_navigate (ADD_MENU, note_num); + break; + case DM_VIEW: +#if LCD_DEPTH >= 2 + rb->lcd_set_background (LCD_WHITE); + rb->lcd_clear_display (); + draw_frame (note_num); + view_message (note_num); + keyboard_bitmap (KEYBOARD_STANDART); + draw_menu (VIEW_MENU); + rb->lcd_update (); + menu_navigate (VIEW_MENU, note_num); +#else + rb->lcd_clear_display (); + draw_frame (note_num); + view_message (note_num); + rb->lcd_update (); + msg_without_keyboard (); + draw_menu (VIEW_MENU); + menu_navigate (VIEW_MENU, note_num); +#endif + break; + case DM_DELETE: + delete_note (note_num); + rb->splash (HZ, "Deleted!"); + break; + } + exit = true; + } else if (menu == MAIN_MENU) { + switch (cur) { + case MM_FIRST: + if (++cl.first_week_day == 7) + cl.first_week_day = 0; + break; +#ifndef CONFIG_RTC + case MM_DATE: + change_date (); + break; +#endif + case MM_QUITM: + exit = true; + break; + case MM_QUIT: + return true; + break; + } + } else { + switch (cur) { + case ADD_MENU_DELETE: + delete_note (note_num); + rb->splash (HZ, "Deleted!"); + exit = true; + break; + case ADD_MENU_YEAR: + cl.note[note_num].year = + cl.note[note_num].year != + cl.year ? cl.year : 555; + break; + case ADD_MENU_EDIT: +#if LCD_DEPTH >= 2 + rb->lcd_set_background (LCD_WHITE); +#endif + rb->lcd_clear_display (); + draw_frame (note_num); + view_message (note_num); + keyboard_bitmap (KEYBOARD_STANDART); + rb->lcd_update (); + keyboard_loop (note_num); + draw_menu (menu); + break; + case ADD_MENU_TYPE: + if (++cl.note[note_num].type == MAX_NOTESTYPES) + cl.note[note_num].type = 0; + break; + case ADD_MENU_DONE: + if (menu == ADD_MENU) { + cl.note[cl.notes_count].day = + cl.calen[cl.row][cl.col]; + cl.note[cl.notes_count].month = cl.month + 1; + cl.notes_count++; + } + rb->splash (HZ, "Done!"); + exit = true; + break; + } + } + break; + } + + } + return false; +} + + +/* ################################################################ + ############## Draw the main RockCalendar Screen ############## + ################################################################ */ +void calen_draw (void) +{ + + int i, w, h, x, y = 0; + char str[MESSAGE_LENGTH]; + + calen_init (); +#if LCD_DEPTH >= 16 + rb->lcd_set_foreground (LCD_RGBPACK (0, 0, 162)); + rb->lcd_set_background (LCD_WHITE); +#elif LCD_DEPTH == 2 + rb->lcd_set_foreground (LCD_DARKGRAY); + rb->lcd_set_background (LCD_WHITE); +#endif + rb->lcd_clear_display (); + rb->snprintf (str, 20, "%s %d", month_name[cl.month], (1900 + cl.year)); + rb->lcd_getstringsize (str, &w, &h); + rb->lcd_putsxy (LCD_WIDTH / 2 - w / 2, cl.offset + MONTH_NAME_YPOS, str); + +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + + for (i = 0; i < 6; i++) { + for (x = 0; x < 7; x++) { + rb->snprintf (str, 3, "%d", cl.calen[i][x]); + + if (x == 6) { +#if LCD_DEPTH >= 16 + rb->lcd_set_foreground (LCD_RGBPACK (192, 192, 192)); +#elif LCD_DEPTH == 2 + rb->lcd_set_foreground (LCD_LIGHTGRAY); +#endif + +#if LCD_DEPTH >= 2 + rb->lcd_fillrect (LEFTMARGIN + 6 * SQU_WIDTH + 6 + 1, + TOPMARGIN + i * SQU_HEIGHT + i + 1, + SQU_WIDTH, SQU_HEIGHT); + + rb->lcd_set_foreground (LCD_BLACK); +#endif + + rb->lcd_set_drawmode (DRMODE_FG); + if (cl.calen[i][x] != 0) + rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + 1, + cl.offset + TOPMARGIN + i * SQU_HEIGHT + + i + 2, str); + rb->lcd_set_drawmode (DRMODE_SOLID); + } else if (cl.calen[i][x] != 0 && x != 6) { + rb->lcd_set_drawmode (DRMODE_FG); + rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + 1, + cl.offset + TOPMARGIN + i * SQU_HEIGHT + i + + 2, str); + rb->lcd_set_drawmode (DRMODE_SOLID); + } + + + for (y = 0; y <= cl.notes_count; y++) { + + if (cl.note[y].month == cl.month + 1 + && (cl.note[y].year == cl.year || cl.note[y].year == 555) + && cl.note[y].day == cl.calen[i][x]) { + if (cl.note[y].type == NOTE) { +#ifdef HAVE_LCD_COLOR + rb->lcd_bitmap_transparent (rockcalendar_note, +#else + rb->lcd_bitmap (rockcalendar_note, +#endif + LEFTMARGIN + x * SQU_WIDTH + x + +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + (SQU_WIDTH - NOTE_WIDTH - 1), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + (SQU_WIDTH - NOTE_WIDTH), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + (SQU_WIDTH - NOTE_WIDTH), +#endif + cl.offset + TOPMARGIN + + i * SQU_HEIGHT + i + (SQU_HEIGHT - +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + NOTE_HEIGHT - + 1), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + NOTE_HEIGHT), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + NOTE_HEIGHT), +#endif + NOTE_WIDTH, NOTE_HEIGHT); + } else if (cl.note[y].type == FREE_DAY) { +#ifdef HAVE_LCD_COLOR + rb->lcd_bitmap_transparent (rockcalendar_house, +#else + rb->lcd_bitmap (rockcalendar_house, +#endif + LEFTMARGIN + x * SQU_WIDTH + x + +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + (SQU_WIDTH - HOUSE_WIDTH - 1), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + (SQU_WIDTH - HOUSE_WIDTH), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + (SQU_WIDTH - HOUSE_WIDTH), +#endif + cl.offset + TOPMARGIN + + i * SQU_HEIGHT + i + (SQU_HEIGHT - +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + HOUSE_HEIGHT - + 1), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + HOUSE_HEIGHT), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + HOUSE_HEIGHT), +#endif + HOUSE_WIDTH, HOUSE_HEIGHT); + } else if (cl.note[y].type == BIRTHDAY) { +#ifdef HAVE_LCD_COLOR + rb->lcd_bitmap_transparent (rockcalendar_balloons, +#else + rb->lcd_bitmap (rockcalendar_balloons, +#endif + LEFTMARGIN + + x * SQU_WIDTH + x + (SQU_WIDTH - +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + BALLOONS_WIDTH - + 2), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + BALLOONS_WIDTH), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + BALLOONS_WIDTH), +#endif + cl.offset + TOPMARGIN + + i * SQU_HEIGHT + i + (SQU_HEIGHT - +#if (LCD_WIDTH == 220) && (LCD_HEIGHT == 176) + BALLOONS_HEIGHT + - 1), +#elif (LCD_WIDTH <= 160) && (LCD_HEIGHT <= 128) + BALLOONS_HEIGHT), +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) + BALLOONS_HEIGHT), +#endif + BALLOONS_WIDTH, BALLOONS_HEIGHT); + } else if (cl.note[y].type == HOLIDAY) { +#if LCD_DEPTH >= 16 + rb->lcd_set_foreground (LCD_RGBPACK (255, 128, 0)); +#elif LCD_DEPTH == 2 + rb->lcd_set_foreground (LCD_DARKGRAY); +#endif + rb->lcd_fillrect (LEFTMARGIN + x * SQU_WIDTH + x + 1, + cl.offset + TOPMARGIN + + i * SQU_HEIGHT + i + 1, SQU_WIDTH, + SQU_HEIGHT); +#if LCD_DEPTH >= 2 + rb->lcd_set_foreground (LCD_BLACK); +#endif + +#if LCD_DEPTH >= 16 + rb->lcd_set_drawmode (DRMODE_FG); +#endif + rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + 1, + cl.offset + TOPMARGIN + + i * SQU_HEIGHT + i + 2, str); + rb->lcd_set_drawmode (DRMODE_SOLID); + } + } + + } + + } + } + + + i = cl.first_week_day; + for (x = 0; x < 7; x++) { + rb->snprintf (str, 4, "%s", calen_days[i]); + rb->lcd_getstringsize (str, &w, &h); + rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + + (SQU_WIDTH / 2 - w / 2), cl.offset + TOPMARGIN - h, + str); + rb->lcd_vline (LEFTMARGIN + x * SQU_WIDTH + x, cl.offset + TOPMARGIN, + LCD_HEIGHT - BOTTOMMARGIN - 1); + if (i == 6) + i = 0; + else + i++; + } + + rb->lcd_drawrect (LEFTMARGIN, cl.offset + TOPMARGIN, + LCD_WIDTH - LEFTMARGIN - RIGHTMARGIN, + LCD_HEIGHT - TOPMARGIN - BOTTOMMARGIN - cl.offset); + + for (i = 1; i < 6; i++) { + rb->lcd_hline (LEFTMARGIN, LCD_WIDTH - RIGHTMARGIN - 1, + cl.offset + TOPMARGIN + i * SQU_HEIGHT + i); + + } + + + rb->lcd_update (); +} + +/* ################################################################ + ############## mark day from the calendar ############## + ################################################################ */ +void calen_cur (bool update) +{ + rb->lcd_set_drawmode (DRMODE_COMPLEMENT); + rb->lcd_fillrect (LEFTMARGIN + cl.col * SQU_WIDTH + cl.col + 1, + cl.offset + TOPMARGIN + cl.row * SQU_HEIGHT + cl.row + + 1, SQU_WIDTH, SQU_HEIGHT); + rb->lcd_set_drawmode (DRMODE_SOLID); + + if (update) + rb->lcd_update (); +} + +/* ################################################################ + ############## Main RockCalendar loop ############## + ################################################################ */ +bool calen_start (void) +{ + int button; + int y, i = 0; + +#ifdef CONFIG_RTC + int temp_firstday; + struct tm *tm = rb->get_time (); +#else + int temp_firstday, temp_day, temp_month, temp_year; + int week_day; +#endif + int tweek_day, tmonth_day; + bool edit_note = false; + + rb->lcd_set_drawmode (DRMODE_SOLID); + +#ifndef CONFIG_RTC + cl.year = cl.syear; + cl.month = cl.smonth; + + if (cl.year >= -148 && cl.year <= -101) + i = 4; + else if (cl.year >= -100 && cl.year <= -1) + i = 2; + else if (cl.year >= 0 && cl.year <= 99) + i = 0; + else if (cl.year >= 100 && cl.year <= 199) + i = 6; + else if (cl.year >= 200 && cl.year <= 299) + i = 4; + + week_day = (i + (cl.year % 100) + (cl.year % 100 / 4) + + month_table[cl.year % 4 == 0 ? 1 : 0][cl.month] + cl.sday) + % 7; + cl.first_day = (week_day + 36 - cl.sday) % 7 - cl.first_week_day; +#else + cl.first_day = (tm->tm_wday + 36 - tm->tm_mday) % 7 - cl.first_week_day; +#endif + + if (cl.first_day < 0) + cl.first_day += 7; + +#ifdef CONFIG_RTC + cl.year = tm->tm_year; + cl.month = tm->tm_mon; +#endif + + calen_init (); + for (i = 0; i <= 5; i++) { + for (y = 0; y < 7; y++) { +#ifdef CONFIG_RTC + if (cl.calen[i][y] == tm->tm_mday) { +#else + if (cl.calen[i][y] == cl.sday) { +#endif + cl.row = i; + cl.col = y; + break; + break; + } + } + } + cl.offset = yoffset[cl.row]; + + calen_draw (); + + calen_cur (true); + + while (true) { + + button = rb->button_get (true); + switch (button) { + case SELECT: + edit_note = false; + for (y = 0; y < cl.notes_count; y++) { + if (cl.note[y].month == cl.month + 1 + && (cl.note[y].year == cl.year + || cl.note[y].year == 555) + && cl.note[y].day == cl.calen[cl.row][cl.col]) { + draw_menu (DAY_MENU_VIEW); + menu_navigate (DAY_MENU_VIEW, y); + edit_note = true; + break; + } + + } + if (!edit_note) { + draw_menu (DAY_MENU_ADD); + menu_navigate (DAY_MENU_ADD, cl.notes_count); + } + calen_draw (); + calen_cur (true); + break; + case RIGHT: + case RIGHT | BUTTON_REPEAT: + calen_cur (false); + if (cl.col == 6 && cl.calen[cl.row + 1][0] != 0) { + cl.row++; + cl.col = 0; + cl.offset = yoffset[cl.row]; +#if (LCD_WIDTH <= 112) && (LCD_HEIGHT <= 64) + calen_draw (); +#endif + } else if (cl.calen[cl.row][cl.col + 1] == 0) { + if (cl.month == 11) { + cl.month = 0; + cl.year++; + } else + cl.month++; + + if (cl.last_day == 6) + cl.first_day = 0; + else + cl.first_day = cl.last_day + 1; + + cl.col = cl.first_day; + cl.row = 0; + + cl.offset = yoffset[cl.row]; + calen_draw (); + } else + cl.col++; + + calen_cur (true); + break; + case LEFT: + case LEFT | BUTTON_REPEAT: + calen_cur (false); + if (cl.col == 0 && cl.row != 0) { + cl.row--; + cl.col = 6; + cl.offset = yoffset[cl.row]; +#if (LCD_WIDTH <= 112) && (LCD_HEIGHT <= 64) + calen_draw (); +#endif + } else if (cl.row == 0 && cl.col == cl.first_day) { + if (cl.month == 0) { + cl.month = 11; + cl.year--; + } else + cl.month--; + + + tmonth_day = days_in_month[leap_year (cl.year)][cl.month]; + tweek_day = cl.first_day; + + + while (tmonth_day > 0) { + tweek_day--; + if (tweek_day < 0) + tweek_day = 6; + + tmonth_day--; + + } + cl.col = cl.first_day == 0 ? 6 : cl.first_day - 1; + cl.first_day = tweek_day; + + calen_init (); + + if (cl.calen[5][0] == 0) + cl.row = 4; + else + cl.row = 5; + + cl.offset = yoffset[cl.row]; + calen_draw (); + } else + cl.col--; + + calen_cur (true); + break; +#ifdef UP + case UP: + case UP | BUTTON_REPEAT: + calen_cur (false); + if (cl.row == 0 || cl.calen[cl.row - 1][cl.col] == 0) { + cl.row = 5; + while (cl.calen[cl.row][cl.col] == 0) + cl.row--; + } else + cl.row--; + + cl.offset = yoffset[cl.row]; +#if (LCD_WIDTH <= 112) && (LCD_HEIGHT <= 64) + calen_draw (); +#endif + calen_cur (true); + break; +#endif +#ifdef DOWN + case DOWN: + case DOWN | BUTTON_REPEAT: + calen_cur (false); + if (cl.row == 5 || cl.calen[cl.row + 1][cl.col] == 0) { + cl.row = 0; + while (cl.calen[cl.row][cl.col] == 0) + cl.row++; + } else + cl.row++; + + cl.offset = yoffset[cl.row]; +#if (LCD_WIDTH <= 112) && (LCD_HEIGHT <= 64) + calen_draw (); +#endif + calen_cur (true); + break; +#endif +#ifdef NEXT_MONTH + case NEXT_MONTH: + case NEXT_MONTH | BUTTON_REPEAT: +#endif + calen_cur (false); + + if (cl.month == 11) { + cl.month = 0; + cl.year++; + } else + cl.month++; + + if (cl.last_day == 6) + cl.first_day = 0; + else + cl.first_day = cl.last_day + 1; + + cl.col = cl.first_day; + cl.row = 0; + + cl.offset = yoffset[cl.row]; + + calen_draw (); + calen_cur (true); + break; +#ifdef PREV_MONTH + case PREV_MONTH: + case PREV_MONTH | BUTTON_REPEAT: +#endif + calen_cur (false); + + if (cl.month == 0) { + cl.month = 11; + cl.year--; + } else + cl.month--; + + tmonth_day = days_in_month[leap_year (cl.year)][cl.month]; + tweek_day = cl.first_day; + + + while (tmonth_day > 0) { + tweek_day--; + if (tweek_day < 0) + tweek_day = 6; + + tmonth_day--; + + } + + cl.first_day = tweek_day; + cl.col = cl.first_day; + cl.row = 0; + + cl.offset = yoffset[cl.row]; + + calen_draw (); + calen_cur (true); + break; + case MENU: + temp_firstday = cl.first_week_day; +#ifndef CONFIG_RTC + temp_day = cl.sday; + temp_month = cl.smonth; + temp_year = cl.syear; +#endif + + draw_menu (MAIN_MENU); + if (menu_navigate (MAIN_MENU, -1)) + return true; + + if (temp_firstday != cl.first_week_day +#ifndef CONFIG_RTC + || temp_day != cl.sday || + temp_month != cl.smonth || + temp_year != cl.syear +#endif + ) { + rb->splash (HZ, "Restarting Calendar"); +#ifndef CONFIG_RTC + cl.year = cl.syear; + cl.month = cl.smonth; + + if (cl.year >= -148 && cl.year <= -101) + i = 4; + else if (cl.year >= -100 && cl.year <= -1) + i = 2; + else if (cl.year >= 0 && cl.year <= 99) + i = 0; + else if (cl.year >= 100 && cl.year <= 199) + i = 6; + else if (cl.year >= 200 && cl.year <= 299) + i = 4; + + week_day = (i + (cl.syear % 100) + (cl.syear % 100 / 4) + + month_table[cl.syear % 4 == 0 ? 1 : 0][ + cl.smonth] + cl.sday) % 7; + cl.first_day = (week_day + 36 - cl.sday) % 7 - + cl.first_week_day; +#else + cl.first_day = (tm->tm_wday + 36 - tm->tm_mday) % 7 - + cl.first_week_day; +#endif + + if (cl.first_day < 0) + cl.first_day += 7; + +#ifdef CONFIG_RTC + cl.year = tm->tm_year; + cl.month = tm->tm_mon; +#endif + } + + calen_init (); + + if (temp_firstday != cl.first_week_day +#ifndef CONFIG_RTC + || temp_day != cl.sday || + temp_month != cl.smonth || + temp_year != cl.syear +#endif + ) { + for (i = 0; i <= 5; i++) { + for (y = 0; y < 7; y++) { +#ifdef CONFIG_RTC + if (cl.calen[i][y] == tm->tm_mday) { +#else + if (cl.calen[i][y] == cl.sday) { +#endif + cl.row = i; + cl.col = y; + break; + break; + } + } + } + } + + cl.offset = yoffset[cl.row]; + + calen_draw (); + + + + calen_cur (true); + break; + case CANCEL: + return true; + break; + } + + + + + + } +} + +/* this is the plugin entry point */ +enum plugin_status plugin_start (struct plugin_api *api, void *parameter) +{ + (void) parameter; + rb = api; + + /* now go ahead and have fun! */ + rb->lcd_setfont (FONT_SYSFIXED); + + xlcd_init (rb); + configfile_init (rb); + + read_notes (); + + if (calen_start ()) + save_notes (); + + rb->lcd_setfont (FONT_UI); + return PLUGIN_OK; +} Index: apps/plugins/bitmaps/native/SOURCES =================================================================== --- apps/plugins/bitmaps/native/SOURCES (revision 13772) +++ apps/plugins/bitmaps/native/SOURCES (working copy) @@ -257,6 +257,29 @@ minesweeper_tiles.8x8x1.bmp #endif +/* Rockcalendar */ +#if (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) && (LCD_DEPTH == 16) +rockcalendar_note.220x176x16.bmp +rockcalendar_balloons.220x176x16.bmp +rockcalendar_house.220x176x16.bmp +rockcalendar_keyboard.220x176x16.bmp +rockcalendar_caps_keyboard.220x176x16.bmp + +#elif (LCD_WIDTH == 160) && (LCD_HEIGHT == 128) +rockcalendar_note.160x128x2.bmp +rockcalendar_balloons.160x128x2.bmp +rockcalendar_house.160x128x2.bmp +rockcalendar_keyboard.160x128x2.bmp +rockcalendar_caps_keyboard.160x128x2.bmp + +#elif (LCD_WIDTH == 176) && (LCD_HEIGHT == 220) +rockcalendar_note.160x128x2.bmp +rockcalendar_balloons.160x128x2.bmp +rockcalendar_house.160x128x2.bmp +rockcalendar_keyboard.160x128x2.bmp +rockcalendar_caps_keyboard.160x128x2.bmp +#endif + /* Rockblox */ #if (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) && (LCD_DEPTH == 16) rockblox_background.320x240x16.bmp Index: apps/plugins/bitmaps/mono/SOURCES =================================================================== --- apps/plugins/bitmaps/mono/SOURCES (revision 13772) +++ apps/plugins/bitmaps/mono/SOURCES (working copy) @@ -28,6 +28,15 @@ #endif +/* RockCalendar */ +#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) +rockcalendar_keyboard.112x64x1.bmp +rockcalendar_caps_keyboard.112x64x1.bmp +rockcalendar_note.112x64x1.bmp +rockcalendar_balloons.112x64x1.bmp +rockcalendar_house.112x64x1.bmp +#endif + /* Rockblox */ #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) rockblox_background.112x64x1.bmp Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 13772) +++ apps/plugins/SOURCES (working copy) @@ -10,6 +10,12 @@ properties.c random_folder_advance_config.c rockblox.c +#if (LCD_WIDTH != 138) && (LCD_WIDTH != 128) && (LCD_WIDTH != 240) && \ + (LCD_WIDTH != 320) +/* These need adjusting for the iPod Nano, Mini, Video, Toshiba Gigabeat and + iRiver ifp screen's */ +rockcalendar.c +#endif rockbox_flash.c search.c snow.c