/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Icon.IncDec.c
    Author:  Copyright  1994 Lee Atkinson, David Leftley
    Version: 1.01 (21 Jun 1995)
    Purpose: High-level icon handling routines: Handler for increment and
             decrement icons
    Mods:    David Leftley - call Desk_Icon_SetCaret after each increment/decrement,
                             otherwise the caret is left inbetween digits when
                             99->100 etc.
*/

#include <stdlib.h>

#include "Desk.Core.h"
#include "Desk.Event.h"
#include "Desk.Icon.h"
#include "Desk.Window.h"
#include "Desk.WimpSWIs.h"
#include "Desk.DeskMem.h"




static void Desk_Icon__ResetCaret(const Desk_window_handle window, const Desk_icon_handle icon)
{
  Desk_caret_block caret;
  Desk_Wimp_GetCaretPosition(&caret);
  if (caret.window == window && caret.icon == icon)
  { 
    Desk_Icon_SetCaret(window, icon);
  }
}



static void Increment(const Desk_icon_incdecblock *b)
{
 int i;
 if ((i=Desk_Icon_GetInteger(b->window, b->texticon))<(b->max-b->step))
                               Desk_Icon_SetInteger(b->window, b->texticon, i+b->step);
      /* if value in text icon is less than the max-step increment it by step */
 else if (i<b->max) Desk_Icon_SetInteger(b->window, b->texticon, b->max); /* else if
                                    value less than max, set text icon to max */
 else if (b->loop) Desk_Icon_SetInteger(b->window, b->texticon, b->min); /* else if
                                                   loop, set text icon to min */
Desk_Icon__ResetCaret(b->window, b->texticon);
}



static void Decrement(const Desk_icon_incdecblock *b)
{
 int i;
 if ((i=Desk_Icon_GetInteger(b->window, b->texticon))>(b->min+b->step))
                               Desk_Icon_SetInteger(b->window, b->texticon, i-b->step);
      /* if value in text icon is more than the min+step decrement it by step */
 else if (i>b->min) Desk_Icon_SetInteger(b->window, b->texticon, b->min); /* else if
                                    value more than min, set text icon to min */
 else if (b->loop) Desk_Icon_SetInteger(b->window, b->texticon, b->max);/* else if
                                                   loop, set text icon to max */
Desk_Icon__ResetCaret(b->window, b->texticon);
}


static Desk_bool CheckIncrement(Desk_event_pollblock *event, void *ref)
{
 Desk_icon_incdecblock *b=(Desk_icon_incdecblock *)ref;
 if (event->data.mouse.button.data.select) Increment(b); /* select click */
 else if (event->data.mouse.button.data.adjust) Decrement(b); /* adjust click */

 return(Desk_bool_FALSE);
}


static Desk_bool CheckDecrement(Desk_event_pollblock *event, void *ref)
{
 Desk_icon_incdecblock *b=(Desk_icon_incdecblock *)ref;
 if (event->data.mouse.button.data.select) Decrement(b); /* select click */
 else if (event->data.mouse.button.data.adjust) Increment(b); /* adjust click */

 return(Desk_bool_FALSE);
}

Desk_icon_incdecblock *Desk_Icon_InitIncDecHandler(const Desk_window_handle window,
                                         const Desk_icon_handle   texticon,
                                         const Desk_icon_handle   incrementicon,
                                         const Desk_icon_handle   decrementicon,
                                         const Desk_bool          loop,
                                         const unsigned int  step,
                                         const int           min,
                                         const int           max,
                                         const int           start)
{
 Desk_icon_incdecblock *b;
 b=(Desk_icon_incdecblock *)Desk_DeskMem_Malloc(sizeof(Desk_icon_incdecblock));
                                            /* allocate memory for data block */
 b->window       =window;
 b->texticon     =texticon;
 b->incrementicon=incrementicon;
 b->decrementicon=decrementicon;
 b->loop         =loop;
 b->step         =step;
 b->min          =min;
 b->max          =max;

 Desk_Icon_SetInteger(window, texticon, start);
 if (Desk_Event_Claim(Desk_event_CLICK, window, incrementicon, CheckIncrement, (void *)b)&&
         Desk_Event_Claim(Desk_event_CLICK, window, decrementicon, CheckDecrement, (void *)b))
                                                                       return b;
 else return NULL;
}

Desk_bool Desk_Icon_ReleaseIncDecHandler(Desk_icon_incdecblock *incdecblock)
{
 Desk_bool result;
 result=(Desk_Event_Release(Desk_event_CLICK, incdecblock->window,
                incdecblock->incrementicon, CheckIncrement, (void *)incdecblock)&&
         Desk_Event_Release(Desk_event_CLICK, incdecblock->window,
                incdecblock->decrementicon, CheckDecrement, (void *)incdecblock))
                ? Desk_bool_TRUE : Desk_bool_FALSE;
 Desk_DeskMem_Free((void *)incdecblock);
 return result;
}
