/********************************************************************
 *																	*
 *	Custom slider routine											*
 *																	*
 *	Copyright (c) Clever Bits and Bitgate Software 1993 - 1994		*
 *	All Rights Reserved.											*
 *																	*
 *	Portions of this code are copyright (c) Tom Hudson 1986.		*
 *																	*
 *	In order to protect Tom's copyright, all comments must remain	*
 *	intact, unmodified.												*
 *																	*
 *	Here are the slider routines, with a faster redraw, and a much	*
 *	smarter routine.  These work better than his original routines. *
 *																	*
 ********************************************************************
 *																	*
 *	Update log:														*
 *																	*
 *	[3.2.86 - 6.4.86] Tom Hudson									*
 *		not documented												*
 *	[15.6.93 - 23.3.94] Ken Hollis									*
 *		(global)			- optimized, modulized, and fixed bugs	*
 *							- fixed redrawing of slider track		*
 *		DoHorizontalSlide	- optimized redraws (made w/deltas)		*
 *							- added check for 3D objects			*
 *		DoVerticalSlide		- optimized redraws (made w/deltas)		*
 *							- added check for 3D objects			*
 *																	*
 ********************************************************************/

#include <aes.h>
#include <stdio.h>

#include "winlib.h"		/* WinLIB header file */
#include "nkcc.h"		/* Normalized Keycodes header file */

#ifndef __SLIDERS__
#define __SLIDERS__
#endif

static int mousex,mousey,dum,moved;
static int tbasex,tbasey,sbasex,sbasey;

/****************************************************/
/* RESET HORIZONTAL SLIDER                          */
/* -----------------------                          */
/* Parameters:                                      */
/* win     = window structure                       */
/* number  = slider number (0-9)                    */
/* maximum = maximum slider setting (0-maximum)     */
/* initial = initial slider setting (0-maximum)     */
/****************************************************/

void HorizontalSlideReset(WINDOW *win, int number, int maximum, int initial,
					int trackix, int slidix, int strtrack, int redraw)
{
	GRECT work;

	WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);

	win->slidmax[number]=maximum;
	win->slidpos[number]=initial;
	win->slidstep[number]=((long)(win->tree[trackix].ob_width-win->tree[slidix].ob_width)<<16)/(long)maximum;
	win->slidacc[number]=win->slidstep[number]*(long)initial;
	win->tree[slidix].ob_x=(int)(win->slidacc[number]>>16);

	if (strtrack)
		ChangeObjectText(win->tree, strtrack, "  0", 3, TE_CNTR);

	if (redraw)
		WRedrawWindow(win, win->tree[trackix].ob_x + win->size.g_x + work.g_x, win->tree[trackix].ob_y + win->size.g_y + work.g_y, win->tree[trackix].ob_width, win->tree[trackix].ob_height);
}

/****************************************************/
/* PROCESS HORIZONTAL SLIDER                        */
/* -------------------------                        */
/* Parameters:                                      */
/* number  = slider number (0-9)                    */
/* trackix = index of slider track                  */
/* slidix  = index of slider                        */
/* leftix  = index of left-move button              */
/* rightix = index of right-move button             */
/* whichix = index of item from form_do             */
/* trakstep = # of steps for in-track click         */
/****************************************************/

void DoHorizontalSlide(WINDOW *win, int number, int trackix,
				int slidix, int leftix, int rightix, int whichix,
				int trakstep, int strtrack)
{
	register int ix;
	int tempx,temp,xx,yy,deltax,deltaw,origx,origy;
	GRECT work;

	WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);

	moved=0;

	temp=win->slidpos[number];
	graf_mkstate(&mousex,&mousey,&dum,&dum);

	objc_offset(win->tree,trackix,&xx,&yy);
	objc_offset(win->tree,slidix,&origx,&origy);

	if(whichix==trackix) {
		objc_offset(win->tree,slidix,&sbasex,&dum);

		if(mousex>sbasex) {
			for(ix=0; ix<trakstep; ++ix) {
				if(win->slidpos[number]<win->slidmax[number]) {
					win->slidacc[number]+=win->slidstep[number];
					win->slidpos[number]++;
					moved=1;
				} else break;
			}
		} else {
			for(ix=0; ix<trakstep; ++ix) {
				if(win->slidpos[number]>0) {
					win->slidacc[number]-=win->slidstep[number];
					win->slidpos[number]--;
					moved=1;
				} else break;
			}
		}
	} else if(whichix==rightix) {
		if(win->slidpos[number]<win->slidmax[number]) {
			win->slidacc[number]+=win->slidstep[number];
			win->slidpos[number]++;
			moved=1;
		}
	} else if(whichix==leftix) {
		if(win->slidpos[number]>0) {
			win->slidacc[number]-=win->slidstep[number];
			win->slidpos[number]--;
			moved=1;
		}
	} else if(whichix==slidix) {
		objc_offset(win->tree,slidix,&sbasex,&sbasey);
		objc_offset(win->tree,trackix,&tbasex,&tbasey);

		tempx = (mousex-((win->tree[slidix].ob_width)/2)+3);

		if(tempx!=sbasex) {
			win->slidacc[number]=(long)(tempx-tbasex)<<16;
			win->slidpos[number]=(int)(win->slidacc[number]/win->slidstep[number]);
			win->slidacc[number]=(long)win->slidpos[number]*win->slidstep[number];
			moved=1;
		}
	}

	if(moved) {
		if (win->slidacc[number]<0)
			win->slidacc[number]=win->slidpos[number]=0;

		win->tree[slidix].ob_x=(int)(win->slidacc[number]>>16);

		if ((win->tree[slidix].ob_x+win->tree[slidix].ob_width)>win->tree[trackix].ob_width) {
			win->tree[slidix].ob_x=(win->tree[trackix].ob_width-win->tree[slidix].ob_width);
			win->slidpos[number]=(int)win->slidmax[number];
			win->slidacc[number]=(long)(win->tree[trackix].ob_width-win->tree[slidix].ob_width)<<16;
		}

		if (win->slidpos[number]<0)
			win->slidpos[number]=0;

		if (win->slidpos[number]>win->slidmax[number])
			win->slidpos[number]=win->slidmax[number];

		if (temp!=win->slidpos[number]) {
			int newx,newy;
			char *str;

			objc_offset(win->tree,slidix,&newx,&newy);

			deltax = origx - newx;

			if (origx>newx)
				deltaw = (origx + win->tree[slidix].ob_width) - (newx + win->tree[slidix].ob_width);
			else
				deltaw = -((origx + win->tree[slidix].ob_width) - (newx + win->tree[slidix].ob_width));

			if (strtrack) {
				sprintf(str, "%3d", win->slidpos[number]);
				ChangeObjectText(win->tree, strtrack, str, 3, TE_CNTR);
			}

			if ((deltaw != 0) || strtrack)
				if (win->tree[slidix].ob_state & DRAW3D)
					WRedrawWindowLevel(win, (origx>newx) ? newx : origx,
						yy,
						deltaw + win->tree[slidix].ob_width,
						win->tree[trackix].ob_height, trackix, 2);
				else
					WRedrawWindowLevel(win, (origx>newx) ? newx - 1 : origx - 1,
						yy,
						(deltaw + win->tree[slidix].ob_width) + 2,
						win->tree[trackix].ob_height, trackix, 1);
		}
	}
}

/****************************************************/
/* RESET VERTICAL SLIDER                            */
/* ----------------------                           */
/* Parameters:                                      */
/* number  = slider number (0-9)                    */
/* trackix = index of slider track                  */
/* slidix  = index of slider                        */
/* maximum = maximum slider setting (0-maximum)     */
/* initial = initial slider setting (0-maximum)     */
/****************************************************/

void VerticalSlideReset(WINDOW *win, int number, int maximum, int initial,
				int slidix, int trackix, int strtrack, int redraw)
{
	long work1=((long)(win->tree[trackix].ob_height-win->tree[slidix].ob_height)<<16);
	GRECT work;

	WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);

	win->slidmax[number]=maximum;
	win->slidpos[number]=initial;
	win->slidstep[number]=work1/(long)maximum;
	win->slidacc[number]=work1-win->slidstep[number]*(long)initial;
	win->tree[slidix].ob_y=(int)(win->slidacc[number]>>16);

	if (strtrack)
		ChangeObjectText(win->tree, strtrack, (char *) "  0", 3, TE_CNTR);

	if (redraw)
		WRedrawWindow(win, win->tree[trackix].ob_x + win->size.g_x + work.g_x, win->tree[trackix].ob_y + win->size.g_y + work.g_y, win->tree[trackix].ob_width, win->tree[trackix].ob_height);
}

/****************************************************/
/* PROCESS VERTICAL SLIDER                          */
/* -----------------------                          */
/* Parameters:                                      */
/* number  = slider number (0-9)                    */
/* trackix = index of slider track                  */
/* slidix  = index of slider                        */
/* upix    = index of up-move button                */
/* downix  = index of down-move button              */
/* whichix = index of item from form_do             */
/* trakstep = # of steps for in-track click         */
/****************************************************/

void DoVerticalSlide(WINDOW *win, int number, int trackix,
				int slidix, int upix, int downix, int whichix,
				int trakstep, int strtrack)
{
	register int ix;
	int tempy,temp, xx, yy, origx, origy, deltay, deltah;
	GRECT work;

	WWindGet(win, WF_WORKXYWH, &work.g_x, &work.g_y, &work.g_w, &work.g_h);

	moved=0;

	temp=win->slidpos[number];
	graf_mkstate(&mousex,&mousey,&dum,&dum);

	objc_offset(win->tree,trackix,&xx,&yy);
	objc_offset(win->tree,slidix,&origx,&origy);

	if(whichix==trackix) {
		objc_offset(win->tree,slidix,&dum,&sbasey);
		if(mousey>sbasey) {
			for(ix=0; ix<trakstep; ++ix) {
				if(win->slidpos[number]>0) {
					win->slidacc[number]+=win->slidstep[number];
					win->slidpos[number]--;
				}
			}
			moved=1;
		} else {
			for(ix=0; ix<trakstep; ++ix) {
				if(win->slidpos[number]<win->slidmax[number]) {
					win->slidacc[number]-=win->slidstep[number];
					win->slidpos[number]++;
				}
			}
			moved=1;
		}
	} else if(whichix==downix) {
		if(win->slidpos[number]>0) {
			win->slidacc[number]+=win->slidstep[number];
			win->slidpos[number]--;
			moved=1;
		}
	} else if(whichix==upix) {
		if(win->slidpos[number]<win->slidmax[number]) {
			win->slidacc[number]-=win->slidstep[number];
			win->slidpos[number]++;
			moved=1;
		}
	} else if(whichix==slidix) {
		objc_offset(win->tree,slidix,&sbasex,&sbasey);
		objc_offset(win->tree,trackix,&tbasex,&tbasey);

		tempy = (mousey-((win->tree[slidix].ob_height)/2)+1);

		if(tempy!=sbasey) {
			win->slidacc[number]=(long)(tempy-tbasey)<<16;
			win->slidpos[number]=win->slidmax[number]-(int)(win->slidacc[number]/win->slidstep[number]);
			win->slidacc[number]=((long)(win->tree[trackix].ob_height-win->tree[slidix].ob_height)<<16)
			                -(long)win->slidpos[number]*win->slidstep[number];
			moved=1;
		}
	}

	if(moved) {
		if (win->slidacc[number]<0) {
			win->slidacc[number]=win->tree[slidix].ob_y<<16;
			win->slidpos[number]=win->slidmax[number];
		}

		win->tree[slidix].ob_y=(int)(win->slidacc[number]>>16);

		if ((win->tree[slidix].ob_y+win->tree[slidix].ob_height)>win->tree[trackix].ob_height) {
			win->tree[slidix].ob_y=(win->tree[trackix].ob_height-win->tree[slidix].ob_height);
			win->slidpos[number]=0;
			win->slidacc[number]=(long)(win->tree[trackix].ob_height-win->tree[slidix].ob_height)<<16;
		}

		if (win->slidpos[number]<0)
			win->slidpos[number]=0;

		if (win->slidpos[number]>win->slidmax[number])
			win->slidpos[number]=win->slidmax[number];

		if (temp!=win->slidpos[number]) {
			int newx,newy;
			char *str;

			objc_offset(win->tree,slidix,&newx,&newy);

			deltay = origy - newy;

			if (origy>newy)
				deltah = (origy + win->tree[slidix].ob_height) - (newy + win->tree[slidix].ob_height);
			else
				deltah = -((origy + win->tree[slidix].ob_height) - (newy + win->tree[slidix].ob_height));

			if (strtrack) {
				sprintf(str, "%3d", win->slidpos[number]);
				ChangeObjectText(win->tree, strtrack, str, 3, TE_CNTR);
			}

			if ((deltah != 0) || strtrack)
				if (win->tree[slidix].ob_state & DRAW3D)
					WRedrawWindowLevel(win, xx,
						(origy>newy) ? newy : origy,
						win->tree[slidix].ob_width,
						deltah + win->tree[slidix].ob_height, trackix, 2);
				else
					WRedrawWindowLevel(win, xx,
						(origy>newy) ? newy - 1 : origy - 1,
						win->tree[slidix].ob_width,
						(deltah + win->tree[slidix].ob_height) + 2, trackix, 1);
		}
	}
}