/***************************************************************************
 *             __________               __   ___.
 *   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"

#ifdef HAVE_LCD_COLOR

PLUGIN_HEADER static struct plugin_api *rb;

#if CONFIG_KEYPAD == IRIVER_H300_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

#elif CONFIG_KEYPAD == IPOD_4G_PAD

#define UP     BUTTON_MENU
#define DOWN   BUTTON_PLAY
#define LEFT   LEFT
#define RIGHT  RIGHT
#define SELECT SELECT
#define CANCEL (BUTTON_PLAY | BUTTON_REPEAT)
#define NEXT_MONTH BUTTON_SCROLL_FWD
#define PREV_MONTH BUTTON_SCROLL_BACK
#define MENU (SELECT | BUTTON_REPEAT)

#endif

/* ################################################################ 
   ##############             Bitmaps                ##############
   ################################################################ */
#define NOTE_WIDTH 12
#define NOTE_HEIGHT 13
extern const fb_data rockcalendar_note[];

#define BALLOONS_WIDTH 10
#define BALLOONS_HEIGHT 15
extern const fb_data rockcalendar_balloons[];

#define HOUSE_WIDTH 15
#define HOUSE_HEIGHT 14
extern const fb_data rockcalendar_house[];

#define KEY_WIDTH 220
#define KEY_HEIGHT 81
#define KEY_YPOS LCD_HEIGHT-KEY_HEIGHT
extern const fb_data rockcalendar_keyboard[];
extern const fb_data rockcalendar_disable_keyboard[];

/* ################################################################ 
   ##############              KeyBoard              ##############
   ################################################################ 
   The keyboard bitmap and code takes from RockWord
 */

#define KEYBOARD_SIZE 57
enum keys
{
    KEY_BACK,
    KEY_CR,
    KEY_CTRL,
    KEY_HOME,
    KEY_END,
    KEY_DEL,
    KEY_UP,
    KEY_LEFT,
    KEY_DOWN,
    KEY_RIGHT,
    KEYS_ACTIONS,
};

static short key_coords[KEYBOARD_SIZE][4] =
    /* 1st line - 0 */
{ {0, 0, 12}, /* ` */ {11, 0, 17}, /* 1 */ {27, 0, 17}, /* 2 */ {43, 0, 17}, /* 3 */ {59, 0, 17}, /* 4 */ {75, 0, 17}, /* 5 */ {91, 0, 17},     /* 6 */
{107, 0, 17}, /* 7 */ {123, 0, 17}, /* 8 */ {139, 0, 17}, /* 9 */ {155, 0, 17}, /* 0 */ {171, 0, 17}, /* - */ {187, 0, 17}, /* = */ {203, 0, 17},       /* <- */
/* 2nd line - 16 */
{20, 16, 17}, /* q */ {36, 16, 17}, /* w */ {52, 16, 17}, /* e */ {68, 16, 17}, /* r */ {84, 16, 17}, /* t */ {100, 16, 17},    /* y */
{116, 16, 17}, /* u */ {132, 16, 17}, /* i */ {148, 16, 17}, /* o */ {164, 16, 17}, /* p */ {180, 16, 17}, /* [ */ {196, 16, 17},       /* ] */
/* 3rd line - 32 */
{25, 32, 17}, /* a */ {41, 32, 17}, /* s */ {57, 32, 17}, /* d */ {73, 32, 17}, /* f */ {89, 32, 17}, /* g */ {105, 32, 17},    /* h */
{121, 32, 17}, /* j */ {137, 32, 17}, /* k */ {153, 32, 17}, /* l */ {169, 32, 17}, /* ; */ {185, 32, 17}, /* ' */ {201, 32, 19},       /* Cr */
/* 4th line - 48 */
{27, 48, 17}, /* z */ {43, 48, 17}, /* x */ {59, 48, 17}, /* c */ {75, 48, 17}, /* v */ {91, 48, 17}, /* b */ {107, 48, 17},    /* n */
{123, 48, 17}, /* m */ {139, 48, 17}, /* , */ {155, 48, 17}, /* . */ {171, 48, 17}, /* / */ {187, 48, 17}, /* ^ */ {203, 48, 17},       /* \ */
/* 5th line - 64 */
{38, 64, 84}, /*   */ {121, 64, 21}, /* Hm */ {141, 64, 17}, /* En */ {157, 64, 15},    /* dl */
{171, 64, 17}, /* < */ {187, 64, 17}, /* V */ {203, 64, 17} /* > */
};

unsigned char key_chars[KEYBOARD_SIZE] = {
    /* English */
    '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', KEY_BACK,
    'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
    '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
};


/* ################################################################ 
   ##############          Global variables          ##############
   ################################################################ */

int first_week_day = 0;         /* default 0=sunday */
int iriver_fw = 0;              /* use it when the date is set in iriver orginal firmware to dd/mm/1999 for the year 2006 */
static struct configdata config[2] = {
    {TYPE_INT, 0, 1, &first_week_day, "first_week_day", NULL, NULL},
    {TYPE_INT, 0, 1, &iriver_fw, "iriver_fw", NULL, NULL}
};


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] = {
    "Sun",
    "Mon",
    "Tue",
    "Wed",
    "Thu",
    "Fri",
    "Sat",
};

#define MESSAGE_LENGTH 30
#define MESSAGE_LINES 8

enum notes_types
{
    NOTE,
    FREE_DAY,
    BIRTHDAY,
    HOLIDAY,
    MAX_NOTESTYPES
};

static char type_name[MAX_NOTESTYPES][10] = {
    "Note",
    "Free Day",
    "Birthday",
    "Holiday",
};

enum addmenuitems
{
    ADD_MENU_DELETE,
    ADD_MENU_EDIT,
    ADD_MENU_YEAR,
    ADD_MENU_TYPE,
    ADD_MENU_DONE,
    ADD_MENU_ITEMS
};

enum daymenuitems
{
    DM_ADD,
    DM_VIEW,
    DM_DELETE,
    DM_CANCEL,
    DM_ITEMS
};

enum _menu
{
    MENU_1F_WIDTH,
    MENU_1F_HEIGHT,
    MENU_1F_XPOS,
    MENU_1F_YPOS,
    MENU_2F_WIDTH,
    MENU_2F_HEIGHT,
    MENU_2F_XPOS,
    MENU_2F_YPOS,
};

enum mainmenuitems
{
    MM_FIRST,
    MM_IRIVER,
    MM_QUITM,
    MM_QUIT,
    MM_ITEMS
};

enum _menus
{
    DAY_MENU_VIEW,
    DAY_MENU_ADD,
    ADD_MENU,
    VIEW_MENU,
    MAIN_MENU,
    MENUS_NUMBER,
};

static int menus[MENUS_NUMBER][8] = {
    {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},
    {145, 13, 37, 53, 145, 44, 37, 65},
};

static char menu_items[MENUS_NUMBER][5][16] = {
    {"Add New", "View", "Delete", "Cancel", ""},
    {"Add New", "View", "Delete", "Cancel", ""},
    {"Delete", "Edit Message", "Year:", "Type:", "Done"},
    {"Delete", "Edit Message", "Year:", "Type:", "Done"},
    {"First Week Day:", "iRiver FW Date:", "Quit Menu", "Quit Calendar", ""},
};

#define ADD_MENU_1F_WIDTH 120
#define ADD_MENU_1F_HEIGHT 13
#define ADD_MENU_1F_XPOS 50
#define ADD_MENU_1F_YPOS 45
#define ADD_MENU_2F_WIDTH 120
#define ADD_MENU_2F_XPOS 50
#define ADD_MENU_2F_YPOS 57

#define MENU_1F_COLOR LCD_RGBPACK(0, 70, 157)
#define MENU_2F_COLOR LCD_RGBPACK(0, 83, 187)

#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 VIEW_NOTE_MODE 0
#define ADD_NOTE_MODE 1

#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;
};

struct calendar
{
    int calen[6][7];
    int first_day, last_day;
    int notes_count;
    int year;                   /* the current year */
    int month;                  /* the current month */
    int row, col;               /* the cursor of the calendar */
    struct _note note[200];
};

#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

#define UNUSED_TEXT_COLOR LCD_RGBPACK(188,188,188)


static struct calendar cl;

/* ################################################################ 
   ##############   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, true, "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);



    configfile_init (rb);
    configfile_load ("cal.cfg", config, 2, 0);

}

/* ################################################################ 
   ##############      Save the notes to file        ##############
   ################################################################ */

void save_notes (void)
{
    int fd, i, j;
    char str[MESSAGE_LENGTH];

    rb->splash (0, true, "Saving notes...");
    fd = rb->creat (NOTES_FILE, O_WRONLY);
    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);

    configfile_save ("cal.cfg", config, 2, 0);
}

/* ################################################################ 
   ##############  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[cl.year % 4 == 0 ? 1 : 0][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], 17);
    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)
{
    rb->lcd_set_foreground (LCD_BLACK);
    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 disable)
{
    if (disable)
        rb->lcd_bitmap (rockcalendar_disable_keyboard, 0,
                        LCD_HEIGHT - KEY_HEIGHT, KEY_WIDTH, KEY_HEIGHT);
    else
        rb->lcd_bitmap (rockcalendar_keyboard, 0, LCD_HEIGHT - KEY_HEIGHT,
                        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);
    rb->lcd_set_background (LCD_RGBPACK (251, 233, 102));
    rb->lcd_set_foreground (LCD_BLACK);

    kb.selection = 0;
    kb.currow = 0;
    kb.curcol = 0;

    rb->lcd_getstringsize ("A", &kb.font_width, &kb.font_height);

    inv_keysel (kb, true);

    while (!done) {
        button = rb->button_get (true);

        switch (button) {
            case UP:
            case UP | BUTTON_REPEAT:
                inv_keysel (kb, false);
                kb.selection = (kb.selection - 13);
                if (kb.selection < 0)
                    kb.selection += KEYBOARD_SIZE - 1;
                inv_keysel (kb, true);
                break;
            case DOWN:
            case DOWN | BUTTON_REPEAT:
                inv_keysel (kb, false);
                kb.selection = (kb.selection + 13);
                if (kb.selection >= KEYBOARD_SIZE)
                    kb.selection -= KEYBOARD_SIZE - 1;
                inv_keysel (kb, true);
                break;
            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;
            case CANCEL:
                done = true;
                break;
            case SELECT:
            case SELECT | BUTTON_REPEAT:
                if (key_chars[kb.selection] < KEYS_ACTIONS) {   /* then action has been pressed */
                    switch (key_chars[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_set_background (LCD_WHITE);
                            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 - 1)
                                kb.curcol++;
                            inv_cursor (kb, true);
                            break;
                    }
                } else {
                    inv_cursor (kb, false);
                    cl.note[note_num].message[kb.currow][kb.curcol] =
                        key_chars[kb.selection];
                    rb->snprintf (temp, 2, "%c", key_chars[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.currow != MESSAGE_LINES - 1)
                        kb.curcol++;
                    inv_cursor (kb, true);
                }
                break;
        }                       /* end switch */
    }                           /* end while */
}


/* ################################################################ 
   ##############        Delete specific note        ##############
   ################################################################ */
void delete_note (int y)
{
    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;
    rb->snprintf (cl.note[y].message[0], MESSAGE_LENGTH, "%s",
                  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;
    rb->strcpy (cl.note[cl.notes_count].message[0], "");
}

/* ################################################################ 
   ##############      View specific note message    ##############
   ################################################################ */
void view_message (int y)
{
    int i, h;
    char str[MESSAGE_LENGTH];

    rb->lcd_set_drawmode (DRMODE_SOLID);
    rb->lcd_set_background (LCD_RGBPACK (251, 233, 102));

    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)
{
    int h, w;
    char str[15];
    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);

    if (cl.note[y].year == 555)
        rb->snprintf (str, 11, "%02d/%02d/****", cl.calen[cl.col][cl.row],
                      cl.month + 1);
    else
        rb->snprintf (str, 11, "%02d/%02d/%04d", cl.calen[cl.col][cl.row],
                      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);

    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],
                      h * ADD_MENU_ITEMS + 2 * ADD_MENU_ITEMS + 4);

    rb->lcd_set_foreground (LCD_BLACK);
    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],
                      h * ADD_MENU_ITEMS + 2 * ADD_MENU_ITEMS + 4);

    rb->lcd_set_drawmode (DRMODE_FG);
    rb->lcd_set_foreground (LCD_WHITE);

    if (menu == DAY_MENU_ADD || menu == DAY_MENU_VIEW) {
        rb->snprintf (str, 11, "%02d/%02d/%04d", cl.calen[cl.col][cl.row],
                      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);

    rb->lcd_set_foreground (LCD_BLACK);
    for (i = 0; i < ADD_MENU_ITEMS; i++) {
        if (menu_items[menu][i]) {
            if (menu == DAY_MENU_VIEW) {
                if (i == DM_ADD) {
                    rb->lcd_set_foreground (UNUSED_TEXT_COLOR);
                    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_foreground (LCD_BLACK);
                } 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) {
                    rb->lcd_set_foreground (UNUSED_TEXT_COLOR);
                    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_foreground (LCD_BLACK);
                } 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      ##############
   ################################################################ */
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) {
            rb->lcd_set_foreground (MENU_2F_COLOR);
            rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1,
                              menus[menu][MENU_2F_YPOS] + 1, 10,
                              h * ADD_MENU_ITEMS + 2 * ADD_MENU_ITEMS + 4 -
                              2);
            rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11,
                              menus[menu][MENU_2F_YPOS] + 22, 106, 19);

            rb->lcd_set_foreground (LCD_BLACK);
            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) {

            rb->lcd_set_foreground (MENU_2F_COLOR);
            rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1,
                              menus[menu][MENU_2F_YPOS] + 1, 10,
                              h * DM_ITEMS + 2 * DM_ITEMS + 4 - 2);
            rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 11,
                              menus[menu][MENU_2F_YPOS] + 1, 131, 19);

            rb->lcd_set_foreground (LCD_BLACK);
            rb->lcd_set_drawmode (DRMODE_FG);
            rb->snprintf (str, sizeof (str), "%s %s",
                          menu_items[menu][MM_FIRST],
                          calen_days[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);
            rb->snprintf (str, sizeof (str), "%s %s",
                          menu_items[menu][MM_IRIVER],
                          iriver_fw == 1 ? "Yes" : "No");
            rb->lcd_putsxy (menus[menu][MENU_2F_XPOS] + 11,
                            menus[menu][MENU_2F_YPOS] + MM_IRIVER * h +
                            MM_IRIVER * 2 + 2, str);
            rb->lcd_set_drawmode (DRMODE_SOLID);
        } else {

            rb->lcd_set_foreground (MENU_2F_COLOR);
            rb->lcd_fillrect (menus[menu][MENU_2F_XPOS] + 1,
                              menus[menu][MENU_2F_YPOS] + 1, 10,
                              h * DM_ITEMS + 2 * DM_ITEMS + 4 - 2);
        }

        rb->lcd_set_foreground (LCD_BLACK);
        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) {
            case CANCEL:
                exit = true;
                break;
            case DOWN:
            case DOWN | BUTTON_REPEAT:
                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;
            case UP:
            case UP | BUTTON_REPEAT:
                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;
            case SELECT:
                if (menu == DAY_MENU_ADD || menu == DAY_MENU_VIEW) {
                    switch (cur) {
                        case DM_ADD:
                            rb->lcd_set_background (LCD_WHITE);
                            rb->lcd_clear_display ();
                            draw_frame (note_num);
                            keyboard_bitmap (false);
                            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:
                            rb->lcd_set_background (LCD_WHITE);
                            rb->lcd_clear_display ();
                            draw_frame (note_num);
                            view_message (note_num);
                            keyboard_bitmap (true);
                            draw_menu (VIEW_MENU);
                            rb->lcd_update ();
                            menu_navigate (VIEW_MENU, note_num);
                            break;
                        case DM_DELETE:
                            delete_note (note_num);
                            rb->splash (HZ, true, "Deleted!");
                            break;
                    }
                    exit = true;
                } else if (menu == MAIN_MENU) {
                    switch (cur) {
                        case MM_FIRST:
                            if (++first_week_day == 7)
                                first_week_day = 0;
                            break;
                        case MM_IRIVER:
                            iriver_fw = iriver_fw == 0 ? 1 : 0;
                            break;
                        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, true, "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:
                            rb->lcd_set_background (LCD_WHITE);
                            rb->lcd_clear_display ();
                            draw_frame (note_num);
                            view_message (note_num);
                            keyboard_bitmap (false);
                            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.col][cl.row];
                                cl.note[cl.notes_count].month = cl.month + 1;
                                cl.notes_count++;
                            }
                            rb->splash (HZ, true, "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 ();
    rb->lcd_set_background (LCD_WHITE);
    rb->lcd_clear_display ();
    rb->lcd_set_foreground (LCD_RGBPACK (0, 0, 162));
    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, MONTH_NAME_YPOS, str);
    rb->lcd_set_foreground (LCD_BLACK);

    for (i = 0; i < 6; i++) {
        for (x = 0; x < 7; x++) {
            rb->snprintf (str, 3, "%d", cl.calen[i][x]);

            if (x == 6) {
                rb->lcd_set_foreground (LCD_RGBPACK (192, 192, 192));
                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);
                rb->lcd_set_drawmode (DRMODE_FG);
                if (cl.calen[i][x] != 0)
                    rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + 1,
                                    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,
                                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) {
                        rb->lcd_bitmap_transparent (rockcalendar_note,
                                                    LEFTMARGIN +
                                                    x * SQU_WIDTH + x +
                                                    (SQU_WIDTH - NOTE_WIDTH -
                                                     1),
                                                    TOPMARGIN +
                                                    i * SQU_HEIGHT + i +
                                                    (SQU_HEIGHT -
                                                     NOTE_HEIGHT - 1),
                                                    NOTE_WIDTH, NOTE_HEIGHT);
                    } else if (cl.note[y].type == FREE_DAY) {
                        rb->lcd_bitmap_transparent (rockcalendar_house,
                                                    LEFTMARGIN +
                                                    x * SQU_WIDTH + x +
                                                    (SQU_WIDTH - HOUSE_WIDTH -
                                                     1),
                                                    TOPMARGIN +
                                                    i * SQU_HEIGHT + i +
                                                    (SQU_HEIGHT -
                                                     HOUSE_HEIGHT - 1),
                                                    HOUSE_WIDTH,
                                                    HOUSE_HEIGHT);
                    } else if (cl.note[y].type == BIRTHDAY) {
                        rb->lcd_bitmap_transparent (rockcalendar_balloons,
                                                    LEFTMARGIN +
                                                    x * SQU_WIDTH + x +
                                                    (SQU_WIDTH -
                                                     BALLOONS_WIDTH - 2),
                                                    TOPMARGIN +
                                                    i * SQU_HEIGHT + i +
                                                    (SQU_HEIGHT -
                                                     BALLOONS_HEIGHT - 2),
                                                    BALLOONS_WIDTH,
                                                    BALLOONS_HEIGHT);
                    } else if (cl.note[y].type == HOLIDAY) {
                        rb->lcd_set_foreground (LCD_RGBPACK (255, 128, 0));
                        rb->lcd_fillrect (LEFTMARGIN + x * SQU_WIDTH + x + 1,
                                          TOPMARGIN + i * SQU_HEIGHT + i + 1,
                                          SQU_WIDTH, SQU_HEIGHT);
                        rb->lcd_set_foreground (LCD_BLACK);
                        rb->lcd_set_drawmode (DRMODE_FG);
                        rb->lcd_putsxy (LEFTMARGIN + x * SQU_WIDTH + x + 1,
                                        TOPMARGIN + i * SQU_HEIGHT + i + 2,
                                        str);
                        rb->lcd_set_drawmode (DRMODE_SOLID);
                    }
                }

            }

        }
    }

    i = 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), TOPMARGIN - h, str);
        rb->lcd_vline (LEFTMARGIN + x * SQU_WIDTH + x, TOPMARGIN,
                       LCD_HEIGHT - BOTTOMMARGIN - 1);
        if (i == 6)
            i = 0;
        else
            i++;
    }

    rb->lcd_drawrect (LEFTMARGIN, TOPMARGIN,
                      LCD_WIDTH - LEFTMARGIN - RIGHTMARGIN,
                      LCD_HEIGHT - TOPMARGIN - BOTTOMMARGIN);

    for (i = 1; i < 6; i++) {
        rb->lcd_hline (LEFTMARGIN, LCD_WIDTH - RIGHTMARGIN - 1,
                       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.row * SQU_WIDTH + cl.row + 1,
                      TOPMARGIN + cl.col * SQU_HEIGHT + cl.col + 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;
    struct tm *tm = rb->get_time ();
    int tweek_day, tmonth_day;
    bool edit_note = false;

    rb->lcd_set_drawmode (DRMODE_SOLID);

    cl.first_day = (tm->tm_wday + 36 - tm->tm_mday) % 7 - first_week_day;       /* takes from calendar.c, thank u ;] */
    if (cl.first_day < 0)
        cl.first_day += 7;

    cl.year = iriver_fw == 0 ? tm->tm_year : tm->tm_year - 29;
    cl.month = tm->tm_mon;

    calen_draw ();

    for (i = 0; i <= 5; i++) {
        for (y = 0; y < 7; y++) {
            if (cl.calen[i][y] == tm->tm_mday) {
                cl.col = i;
                cl.row = y;
                break;
                break;
            }
        }
    }

    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.col][cl.row]) {
                        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.row == 6 && cl.calen[cl.col + 1][0] != 0) {
                    cl.col++;
                    cl.row = 0;
                } else if (cl.calen[cl.col][cl.row + 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.row = cl.first_day;
                    cl.col = 0;

                    calen_draw ();
                } else
                    cl.row++;

                calen_cur (true);
                break;
            case LEFT:
            case LEFT | BUTTON_REPEAT:
                calen_cur (false);
                if (cl.row == 0 && cl.col != 0) {
                    cl.col--;
                    cl.row = 6;
                } else if (cl.col == 0 && cl.row == cl.first_day) {
                    if (cl.month == 0) {
                        cl.month = 11;
                        cl.year--;
                    } else
                        cl.month--;


                    tmonth_day =
                        days_in_month[cl.year % 4 == 0 ? 1 : 0][cl.month];
                    tweek_day = cl.first_day;


                    while (tmonth_day > 0) {
                        tweek_day--;
                        if (tweek_day < 0)
                            tweek_day = 6;

                        tmonth_day--;

                    }
                    cl.row = cl.first_day == 0 ? 6 : cl.first_day - 1;
                    cl.first_day = tweek_day;

                    calen_draw ();
                    if (cl.calen[5][0] == 0)
                        cl.col = 4;
                    else
                        cl.col = 5;

                } else
                    cl.row--;

                calen_cur (true);
                break;
            case UP:
            case UP | BUTTON_REPEAT:
                calen_cur (false);
                if (cl.col == 0 || cl.calen[cl.col - 1][cl.row] == 0) {
                    cl.col = 5;
                    while (cl.calen[cl.col][cl.row] == 0)
                        cl.col--;
                } else
                    cl.col--;

                calen_cur (true);
                break;
            case DOWN:
            case DOWN | BUTTON_REPEAT:
                calen_cur (false);
                if (cl.col == 5 || cl.calen[cl.col + 1][cl.row] == 0) {
                    cl.col = 0;
                    while (cl.calen[cl.col][cl.row] == 0)
                        cl.col++;
                } else
                    cl.col++;

                calen_cur (true);
                break;
            case NEXT_MONTH:
            case NEXT_MONTH | BUTTON_REPEAT:
                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.row = cl.first_day;
                cl.col = 0;

                calen_draw ();
                calen_cur (true);
                break;
            case PREV_MONTH:
            case PREV_MONTH | BUTTON_REPEAT:
                calen_cur (false);

                if (cl.month == 0) {
                    cl.month = 11;
                    cl.year--;
                } else
                    cl.month--;

                tmonth_day =
                    days_in_month[cl.year % 4 == 0 ? 1 : 0][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.row = cl.first_day;
                cl.col = 0;

                calen_draw ();
                calen_cur (true);
                break;
            case MENU:
                draw_menu (MAIN_MENU);
                if (menu_navigate (MAIN_MENU, -1))
                    return true;

                cl.first_day = (tm->tm_wday + 36 - tm->tm_mday) % 7 - first_week_day;   /* takes from calendar.c, thank u ;] */
                if (cl.first_day < 0)
                    cl.first_day += 7;

                cl.year = iriver_fw == 0 ? tm->tm_year : tm->tm_year - 29;


                calen_draw ();

                for (i = 0; i <= 5; i++) {
                    for (y = 0; y < 7; y++) {
                        if (cl.calen[i][y] == tm->tm_mday) {
                            cl.col = i;
                            cl.row = y;
                            break;
                            break;
                        }
                    }
                }

                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;
}

#endif /* HAVE_LCD_COLOR */
