/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 *
 * Copyright (C) 2004 Mike Holden
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "plugin.h"

#define TIMER_Y 1

#define LAP_Y TIMER_Y+1
#define MAX_LAPS 64

#define STOPWATCH_FILE PLUGIN_APPS_DATA_DIR "/stopwatch.dat"

/* variable button definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
      (CONFIG_KEYPAD == IRIVER_H300_PAD)
#define STOPWATCH_QUIT BUTTON_OFF
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_DOWN
#define STOPWATCH_LAP_TIMER BUTTON_ON
#define STOPWATCH_SCROLL_UP BUTTON_RIGHT
#define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
#define STOPWATCH_RC_QUIT BUTTON_RC_STOP

#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
      (CONFIG_KEYPAD == IPOD_3G_PAD) || \
      (CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define STOPWATCH_QUIT BUTTON_MENU
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD
#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK

#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_REC
#define STOPWATCH_LAP_TIMER BUTTON_SELECT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == GIGABEAT_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_A
#define STOPWATCH_LAP_TIMER BUTTON_MENU
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
(CONFIG_KEYPAD == SANSA_C200_PAD) || \
(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
(CONFIG_KEYPAD == SANSA_M200_PAD)
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_RIGHT
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER BUTTON_SELECT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
#define STOPWATCH_QUIT (BUTTON_HOME|BUTTON_REPEAT)
#define STOPWATCH_START_STOP BUTTON_RIGHT
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER BUTTON_SELECT
#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_BACK
#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_FWD

#elif CONFIG_KEYPAD == IRIVER_H10_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_REW
#define STOPWATCH_LAP_TIMER BUTTON_FF
#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_DOWN

#elif CONFIG_KEYPAD == MROBE500_PAD
#define STOPWATCH_QUIT BUTTON_POWER

#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
#define STOPWATCH_QUIT BUTTON_BACK
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_MENU
#define STOPWATCH_LAP_TIMER BUTTON_SELECT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == MROBE100_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_DISPLAY
#define STOPWATCH_LAP_TIMER BUTTON_MENU
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
#define STOPWATCH_QUIT BUTTON_RC_REC
#define STOPWATCH_START_STOP BUTTON_RC_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_RC_REW
#define STOPWATCH_LAP_TIMER BUTTON_RC_FF
#define STOPWATCH_SCROLL_UP BUTTON_RC_VOL_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_RC_VOL_DOWN
#define STOPWATCH_RC_QUIT BUTTON_REC

#elif CONFIG_KEYPAD == COWON_D2_PAD
#define STOPWATCH_QUIT BUTTON_POWER

#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP (BUTTON_PLAY|BUTTON_REL)
#define STOPWATCH_RESET_TIMER (BUTTON_PLAY|BUTTON_REPEAT)
#define STOPWATCH_LAP_TIMER BUTTON_MENU
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_MENU
#define STOPWATCH_LAP_TIMER BUTTON_VIEW
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_MENU
#define STOPWATCH_LAP_TIMER BUTTON_NEXT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_MENU
#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == ONDAVX747_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#elif CONFIG_KEYPAD == ONDAVX777_PAD
#define STOPWATCH_QUIT BUTTON_POWER

#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
      (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
#define STOPWATCH_QUIT        BUTTON_REW
#define STOPWATCH_START_STOP  BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER   BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP   BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
#define STOPWATCH_QUIT        BUTTON_REC
#define STOPWATCH_START_STOP  BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_OK
#define STOPWATCH_LAP_TIMER   BUTTON_MENU
#define STOPWATCH_SCROLL_UP   BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == MPIO_HD200_PAD
#define STOPWATCH_QUIT (BUTTON_REC|BUTTON_PLAY)
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_REW
#define STOPWATCH_LAP_TIMER BUTTON_FF
#define STOPWATCH_SCROLL_UP BUTTON_VOL_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_VOL_DOWN

#elif CONFIG_KEYPAD == MPIO_HD300_PAD
#define STOPWATCH_QUIT (BUTTON_MENU|BUTTON_REPEAT)
#define STOPWATCH_START_STOP BUTTON_PLAY
#define STOPWATCH_RESET_TIMER BUTTON_REW
#define STOPWATCH_LAP_TIMER BUTTON_FF
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_PLAYPAUSE
#define STOPWATCH_RESET_TIMER BUTTON_BACK
#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
#define STOPWATCH_QUIT BUTTON_BACK
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_MENU
#define STOPWATCH_LAP_TIMER BUTTON_USER
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif (CONFIG_KEYPAD == HM60X_PAD) || \
    (CONFIG_KEYPAD == HM801_PAD)
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_SELECT
#define STOPWATCH_RESET_TIMER BUTTON_LEFT
#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP BUTTON_UP
#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN

#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_PLAY
#define STOPWATCH_RESET_TIMER    BUTTON_BACK
#define STOPWATCH_LAP_TIMER      BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP      BUTTON_UP
#define STOPWATCH_SCROLL_DOWN    BUTTON_DOWN

#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)
#define STOPWATCH_QUIT           BUTTON_BACK
#define STOPWATCH_START_STOP     BUTTON_PLAYPAUSE
#define STOPWATCH_RESET_TIMER    BUTTON_SHORTCUT
#define STOPWATCH_LAP_TIMER      BUTTON_SELECT
#define STOPWATCH_SCROLL_UP      BUTTON_UP
#define STOPWATCH_SCROLL_DOWN    BUTTON_DOWN

#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD)
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_SELECT
#define STOPWATCH_RESET_TIMER    BUTTON_LEFT
#define STOPWATCH_LAP_TIMER      BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP      BUTTON_UP
#define STOPWATCH_SCROLL_DOWN    BUTTON_DOWN

#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_NEXT
#define STOPWATCH_RESET_TIMER    BUTTON_PREV
#define STOPWATCH_LAP_TIMER      BUTTON_PLAY
#define STOPWATCH_SCROLL_UP      BUTTON_HOME
#define STOPWATCH_SCROLL_DOWN    BUTTON_OPTION

#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_NEXT
#define STOPWATCH_RESET_TIMER    BUTTON_PREV
#define STOPWATCH_LAP_TIMER      BUTTON_PLAY
#define STOPWATCH_SCROLL_UP      BUTTON_HOME
#define STOPWATCH_SCROLL_DOWN    BUTTON_OPTION

#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_NEXT
#define STOPWATCH_RESET_TIMER    BUTTON_PREV
#define STOPWATCH_LAP_TIMER      BUTTON_PLAY
#define STOPWATCH_SCROLL_UP      BUTTON_VOL_UP
#define STOPWATCH_SCROLL_DOWN    BUTTON_VOL_DOWN

#elif CONFIG_KEYPAD == EROSQ_PAD
#define STOPWATCH_QUIT           BUTTON_POWER
#define STOPWATCH_START_STOP     BUTTON_PLAY
#define STOPWATCH_RESET_TIMER    BUTTON_BACK
#define STOPWATCH_LAP_TIMER      BUTTON_MENU
#define STOPWATCH_SCROLL_UP      BUTTON_SCROLL_FWD
#define STOPWATCH_SCROLL_DOWN    BUTTON_SCROLL_BACK

#elif CONFIG_KEYPAD == FIIO_M3K_PAD
#define STOPWATCH_QUIT          BUTTON_POWER
#define STOPWATCH_START_STOP    BUTTON_PLAY
#define STOPWATCH_RESET_TIMER   BUTTON_BACK
#define STOPWATCH_LAP_TIMER     BUTTON_SELECT
#define STOPWATCH_SCROLL_UP     BUTTON_SCROLL_BACK
#define STOPWATCH_SCROLL_DOWN   BUTTON_SCROLL_FWD

#elif CONFIG_KEYPAD == MA_PAD
#define STOPWATCH_QUIT          BUTTON_BACK
#define STOPWATCH_START_STOP    BUTTON_PLAY
#define STOPWATCH_RESET_TIMER   BUTTON_LEFT
#define STOPWATCH_LAP_TIMER     BUTTON_RIGHT
#define STOPWATCH_SCROLL_UP     BUTTON_UP
#define STOPWATCH_SCROLL_DOWN   BUTTON_DOWN

#elif CONFIG_KEYPAD == RG_NANO_PAD
#define STOPWATCH_QUIT          BUTTON_START
#define STOPWATCH_START_STOP    BUTTON_A
#define STOPWATCH_RESET_TIMER   BUTTON_X
#define STOPWATCH_LAP_TIMER     BUTTON_Y
#define STOPWATCH_SCROLL_UP     BUTTON_UP
#define STOPWATCH_SCROLL_DOWN   BUTTON_DOWN

#elif CONFIG_KEYPAD == CTRU_PAD
#define STOPWATCH_QUIT          BUTTON_BACK
#define STOPWATCH_START_STOP    BUTTON_SELECT
#define STOPWATCH_RESET_TIMER   BUTTON_MENU
#define STOPWATCH_LAP_TIMER     BUTTON_USER
#define STOPWATCH_SCROLL_UP     BUTTON_UP
#define STOPWATCH_SCROLL_DOWN   BUTTON_DOWN

#else
#error No keymap defined!
#endif

#ifdef HAVE_TOUCHSCREEN
#ifndef STOPWATCH_QUIT
#define STOPWATCH_QUIT        BUTTON_TOPLEFT
#endif
#ifndef STOPWATCH_START_STOP
#define STOPWATCH_START_STOP  BUTTON_CENTER
#endif
#ifndef STOPWATCH_RESET_TIMER
#define STOPWATCH_RESET_TIMER BUTTON_MIDRIGHT
#endif
#ifndef STOPWATCH_LAP_TIMER
#define STOPWATCH_LAP_TIMER   BUTTON_MIDLEFT
#endif
#ifndef STOPWATCH_SCROLL_UP
#define STOPWATCH_SCROLL_UP   BUTTON_TOPMIDDLE
#endif
#ifndef STOPWATCH_SCROLL_DOWN
#define STOPWATCH_SCROLL_DOWN BUTTON_BOTTOMMIDDLE
#endif
#endif

static int stopwatch = 0;
static long start_at = 0;
static int prev_total = 0;
static bool counting = false;
static int curr_lap = 0;
static int lap_scroll = 0;
static int lap_start;
static int lap_times[MAX_LAPS];

static void ticks_to_string(int ticks,int lap,int buflen, char * buf)
{
    int hours, minutes, seconds, cs;

    hours = ticks / (HZ * 3600);
    ticks -= (HZ * hours * 3600);
    minutes = ticks / (HZ * 60);
    ticks -= (HZ * minutes * 60);
    seconds = ticks / HZ;
    ticks -= (HZ * seconds);
    cs = ticks;
    if (!lap)
        rb->snprintf(buf, buflen,
                     "%2d:%02d:%02d.%02d  ",       /* add some blank space, in case  */
                     hours, minutes, seconds, cs); /* char width differs, since we   */
                                                   /* don't clear the viewport       */
    else if (lap > 1)
    {
        int last_ticks, last_hours, last_minutes, last_seconds, last_cs;
        last_ticks = lap_times[(lap-1)%MAX_LAPS] - lap_times[(lap-2)%MAX_LAPS];
        last_hours = last_ticks / (HZ * 3600);
        last_ticks -= (HZ * last_hours * 3600);
        last_minutes = last_ticks / (HZ * 60);
        last_ticks -= (HZ * last_minutes * 60);
        last_seconds = last_ticks / HZ;
        last_ticks -= (HZ * last_seconds);
        last_cs = last_ticks;

        rb->snprintf(buf, buflen,
                     "%2d %2d:%02d:%02d.%02d [%2d:%02d:%02d.%02d]",
                     lap, hours, minutes, seconds, cs, last_hours,
                     last_minutes, last_seconds, last_cs);
    }
    else
        rb->snprintf(buf, buflen,
                     "%2d %2d:%02d:%02d.%02d",
                     lap, hours, minutes, seconds, cs);
}

/*
 * Load saved stopwatch state, if exists.
 */
static void load_stopwatch(void)
{
    int fd = rb->open(STOPWATCH_FILE, O_RDONLY);
    if (fd < 0)
        return;

    /* variable stopwatch isn't saved/loaded, because it is only used
     * temporarily in main loop
     */

    rb->read(fd, &start_at, sizeof(start_at));
    rb->read(fd, &prev_total, sizeof(prev_total));
    rb->read(fd, &counting, sizeof(counting));
    rb->read(fd, &curr_lap, sizeof(curr_lap));
    rb->read(fd, &lap_scroll, sizeof(lap_scroll));
    rb->read(fd, &lap_start, sizeof(lap_start));
    rb->read(fd, lap_times, sizeof(lap_times));

    if (counting && start_at > *rb->current_tick)
    {
        /* Stopwatch started in the future? Unlikely; probably started on a
         * previous session and powered off in-between.  We'll keep
         * everything intact (user can clear manually) but stop the
         * stopwatch to avoid negative timing.
         */
        start_at = 0;
        counting = false;
    }

    rb->close(fd);
}

/*
 * Save stopwatch state.
 */
static void save_stopwatch(void)
{
    int fd = rb->open(STOPWATCH_FILE, O_CREAT|O_WRONLY|O_TRUNC, 0666);
    if (fd < 0)
        return;

    /* variable stopwatch isn't saved/loaded, because it is only used
     * temporarily in main loop
     */

    rb->write(fd, &start_at, sizeof(start_at));
    rb->write(fd, &prev_total, sizeof(prev_total));
    rb->write(fd, &counting, sizeof(counting));
    rb->write(fd, &curr_lap, sizeof(curr_lap));
    rb->write(fd, &lap_scroll, sizeof(lap_scroll));
    rb->write(fd, &lap_start, sizeof(lap_start));
    rb->write(fd, lap_times, sizeof(lap_times));

    rb->close(fd);
}

enum plugin_status plugin_start(const void* parameter)
{
    struct viewport vp, *last_vp;
    struct screen *display;
    char buf[32];
    int button;
    int lap;
    int done = false;
    bool update_lap = true;
    int lines;
    int ret = PLUGIN_OK;
    (void)parameter;
    int h;

    FOR_NB_SCREENS(i)
    {
        rb->sb_set_persistent_title("Stopwatch", Icon_NOICON, i);
        rb->viewportmanager_theme_enable(i, true, NULL);
    }

    rb->viewport_set_defaults(&vp, SCREEN_MAIN);
    display = rb->screens[SCREEN_MAIN];

    display->setfont(FONT_UI);
    display->getstringsize("M", NULL, &h);
    lines = (vp.height / h) - (LAP_Y);

    load_stopwatch();

    while (!done)
    {
        rb->send_event(GUI_EVENT_ACTIONUPDATE, NULL); /* update status bar */
        if (counting)
            stopwatch = prev_total + *rb->current_tick - start_at;
        else
            stopwatch = prev_total;

        ticks_to_string(stopwatch,0,32,buf);
        last_vp = display->set_viewport(&vp);

        if(update_lap)
        {
            display->clear_viewport();
            display->puts(0, TIMER_Y, buf);
            lap_start = curr_lap - lap_scroll;
            for (lap = lap_start; lap > lap_start - lines; lap--)
            {
                if (lap > 0)
                {
                    ticks_to_string(lap_times[(lap-1)%MAX_LAPS],lap,32,buf);
                    display->puts_scroll(0, LAP_Y + lap_start - lap, buf);
                }
                else
                    display->puts(0, LAP_Y + lap_start - lap,
                                  "                  ");
            }
            update_lap = false;
        }
        else
            display->puts(0, TIMER_Y, buf);
        display->update_viewport();
        display->set_viewport(last_vp);
        if (!counting)
            button = rb->button_get_w_tmo(HZ/2);
        else
        {
            button = rb->button_get_w_tmo(HZ/10);
            rb->reset_poweroff_timer();
        }
        switch (button)
        {
#ifdef STOPWATCH_RC_QUIT
            case STOPWATCH_RC_QUIT:
#endif
            case STOPWATCH_QUIT:
                  save_stopwatch();
                  done = true;
                  break;

            /* Stop/Start toggle */
            case STOPWATCH_START_STOP:
                 counting = ! counting;
                 if (counting)
                 {
                     start_at = *rb->current_tick;
                     stopwatch = prev_total + *rb->current_tick - start_at;
                 }
                 else
                 {
                     prev_total += *rb->current_tick - start_at;
                     stopwatch = prev_total;
                 }
                 break;

            /* Reset timer */
            case STOPWATCH_RESET_TIMER:
                 if (!counting)
                 {
                     prev_total = 0;
                     curr_lap = 0;
                     lap_scroll = 0;
                     update_lap = true;
                 }
                 break;

            /* Lap timer */
            case STOPWATCH_LAP_TIMER:
                 /*check if we're timing, and start if not*/
                 if (counting)
                 {
                     lap_times[curr_lap%MAX_LAPS] = stopwatch;
                     curr_lap++;
                     update_lap = true;
                 }
                 else
                 {
                     counting = ! counting;
                     start_at = *rb->current_tick;
                     stopwatch = prev_total + *rb->current_tick - start_at;
                 }
                 break;

            /* Scroll Lap timer up */
            case STOPWATCH_SCROLL_UP:
                 if (lap_scroll > 0)
                 {
                     lap_scroll--;
                     update_lap = true;
                 }
                 break;

            /* Scroll Lap timer down */
            case STOPWATCH_SCROLL_DOWN:
                 if ((lap_scroll < curr_lap - lines) &&
                     (lap_scroll < (MAX_LAPS - lines)) )
                 {
                     lap_scroll++;
                     update_lap = true;
                 }
                 break;

            default:
                if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
                    ret = PLUGIN_USB_CONNECTED;
                break;
        }
    }
    FOR_NB_SCREENS(i)
        rb->viewportmanager_theme_undo(i, false);
    return ret;
}
