/* Title:   Stopwatch.c */

 

#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "werr.h"
#include "alarm.h"

#include <stdlib.h>

/********************************* CONSTANTS ********************************/

/* Menu items */
#define stopwatch_menu_info     1
#define stopwatch_menu_show     2
#define stopwatch_menu_hide     3
#define stopwatch_menu_quit     4

#define time_field 0
#define start_field 1
#define stop_field 2
#define reset_field 3
#define lap_field 4

/* Info box field for the version string */
#define Example_info_field    4

/******************************** GLOBAL DATA *******************************/

/* Application version */
static char *stopwatch_Version_String = "1.00 (23 December 1989)";

/* The top of the menu tree */
static menu example_menu;

static dbox time_box;

static char *timestring = "00:00 ";

static int start_time, stop_time;

static BOOL clock_running = FALSE;
static BOOL clock_on_screen = FALSE;
static BOOL lap_set = FALSE;
static BOOL clock_reset = TRUE;

/****************************PROGRAM FUNCTIONS*****************************/

static void fadefields(void)
/* fades/ unfades fields in time box according to flags */
{
  if (clock_reset)
    { 
      dbox_unfadefield(time_box,start_field);
      dbox_fadefield(time_box,stop_field);
      dbox_fadefield(time_box,reset_field);
      dbox_fadefield(time_box,lap_field);
      return;
    }

  if (clock_running)
    { if (lap_set)
        { 
          dbox_unfadefield(time_box,start_field);
          dbox_unfadefield(time_box,stop_field);
          dbox_fadefield(time_box,reset_field);
          dbox_fadefield(time_box,lap_field);
          return;
        }
      else
        {
          dbox_fadefield(time_box,start_field);
          dbox_unfadefield(time_box,stop_field);
          dbox_fadefield(time_box,reset_field);
          dbox_unfadefield(time_box,lap_field);
          return;
        }
     }

  if (!clock_reset && !clock_running) /* stop has been clicked */
    {
      dbox_unfadefield(time_box,start_field);
      dbox_fadefield(time_box,stop_field);
      dbox_unfadefield(time_box,reset_field);
      dbox_fadefield(time_box,lap_field);
      return;
    }
}

static char *time_to_string(int time)
/* converts integer time in centiseconds to string display in
   form mm:ss */
{
  int minutes, seconds,c ;

  time = time / 100;  /* time now in seconds */
  minutes = time / 60;
  seconds = time % 60;
  if (lap_set)
    sprintf(timestring,"%2.d:%2.dL",minutes,seconds);
  else 
    sprintf(timestring,"%2.d:%2.d ",minutes,seconds);
  c = -1;
  while (++c < 5)
    if (timestring[c] == 32) timestring[c] = '0';
  return(timestring);
}

static void show_time_box(char* timestring)
{
  if (clock_on_screen) 
    { /*Initialise time text*/
    dbox_setfield(time_box,time_field,timestring);

    /* Show the dialogue box */
    dbox_showstatic(time_box);
    }
 
} 

static void show_time(int time)
{  show_time_box(time_to_string(time));
}


static void update_clock(int called_at,void *handle)
{
  int time_now;

  called_at = called_at; handle = handle;

  if (clock_running && !lap_set)
    { time_now = alarm_timenow();
      show_time(alarm_timedifference(start_time,time_now));
      alarm_set(time_now+100,update_clock,0);
    }
}

static void start_timer(void)
{
  if (!clock_running && clock_reset) /* start clock after reset */
   { 
     clock_reset = FALSE;
     start_time = alarm_timenow();             
     alarm_set(start_time+100,update_clock,0); 
   }
  else
    { if (!clock_running)  /* continued from stopped time */
       { start_time += alarm_timedifference(stop_time,alarm_timenow()); 
         alarm_set(start_time+100,update_clock,0);
       }
      else  /* resume after lap display */
        alarm_set(alarm_timenow()+100,update_clock,0);
    }
  lap_set = FALSE;
  clock_running = TRUE;
  fadefields();
}

static void stop_timer(void)
{
  stop_time = alarm_timenow();
  clock_running = FALSE;
  fadefields();
}

static void lap_timer(void)
{ 
  if (clock_running)
     { lap_set = TRUE;
       show_time(alarm_timedifference(start_time,alarm_timenow()));
       fadefields();
     }
}

static void reset_timer(void)
{
  if (!clock_running)
    { clock_reset = TRUE;
      lap_set = FALSE;
      show_time(0);
      fadefields();
    }
}   
/***************************** WINDOW FUNCTIONS **************************/


/****************************** EVENT HANDLERS **************************/

/*--- Event handler for time dialogue box. ---*/
static void time_handler(dbox box, void *handle)
{ 
  int field;

  handle = handle; /* We don't need handle: this stops compiler warning */

  field = dbox_get(box);

  switch(field)
  {
    case time_field:   break;
    case start_field:  start_timer(); break;
    case stop_field:   stop_timer(); break;
    case reset_field:  reset_timer(); break;
    case lap_field :   lap_timer(); break;
    default:           dbox_hide(time_box);
  }
}


/*--- Event handler called on a left click on the icon. ---*/
static void stopwatch_iconclick(wimp_i icon)
{

 icon = icon; /* We don't need the handle: this stops compiler warning */

    clock_on_screen = TRUE; 
    show_time_box(timestring);
   
}

/*--- Display the program info box - called from the menu processor. ---*/
static void example_info_about_program(void)
{
  dbox  d;  /* Dialogue box handle */

  /* Create the dialogue box */
  if (d = dbox_new("ProgInfo"), d != NULL)
  {
    /* Fill in the version number */
    dbox_setfield(d, Example_info_field, stopwatch_Version_String);

    /* Show the dialogue box */
    dbox_show(d);

    /* Keep it on the screen as long as needed */
    dbox_fillin(d);

    /* Dispose of the dialogue box */
    dbox_dispose(&d);
  }
}

/*--- Event handler for the menu. ---*/
static void example_menuproc(void *handle, char *hit)
{
  handle = handle; /* We don't need handle: this stops compiler warning */

  /* Find which menu item was hit and take action as appropriate */
  switch (hit[0])
  {
    case stopwatch_menu_info:
      example_info_about_program();
      break;
    
    case stopwatch_menu_show:
      clock_on_screen = TRUE;
      show_time_box(timestring);
      break;

    case stopwatch_menu_hide:
      clock_on_screen = FALSE;
      dbox_hide(time_box);
      break;

    case stopwatch_menu_quit:
      /* Exit from the program. The wimp gets rid of the window and icon */
      exit(0);
  }
}

/****************************** INITIALISATION ******************************/

/*--- Initialise the program, returning TRUE if it was all OK. ---*/
static BOOL stopwatch_initialise(void)
{
  /* RISC_OSlib initialisation */
  wimpt_init("StopWatch Program");/* Main Wimp initialisation */
  res_init("StopWatch");            /* Resources */
  resspr_init();                   /* Application sprites */
  template_init();                 /* Templates */
  dbox_init();                     /* Dialogue boxes */

  /* Create the main window, and declare its event handler */
/*
  if (!example_create_window("MainWindow", &stopwatch_win_handle))
    return FALSE;
  win_register_event_handler(stopwatch_win_handle, stopwatch_event_handler, 0);
  win_claim_idle_events(stopwatch_win_handle);
*/

  /* Create the menu tree */
  if (example_menu = menu_new("Stopwatch", ">Info,Show,Hide,Quit"), example_menu == NULL)
    return FALSE; /* Menu create failed */

  /* Set up the icon on the icon bar, and declare its event handlers */
  baricon("!stopwatch", (int)resspr_area(), stopwatch_iconclick);
  if (!event_attachmenu(win_ICONBAR, example_menu, example_menuproc, 0))
    return FALSE; /* Unable to attach menu */

/* create time_box and assign event handler */
     if(time_box = dbox_new("MainWindow"),time_box == NULL)
        return FALSE;

   dbox_eventhandler(time_box,time_handler,0); 

/* initialise alarm */

alarm_init();
fadefields();

  /* All went ok */
  return TRUE;
}

/******************************* MAIN PROGRAM ********************************/

/*--- Main entry point. ---*/
int main()
{
  if (stopwatch_initialise())
  {

    /* The main event loop */
    while (TRUE)
      event_process();
  }

  return 0;
}
