/******************************************************************************
 *
 *  THIS FILE USES 4 COLUMN TAB STOPS. 
 *	
 *
 *	This file contains ruler management routines for Leach Ver 1.3
 *
 ******************************************************************************/

#include	<functions.h>
#include	<exec/ports.h>
#include	<exec/libraries.h>
#include	<graphics/gfx.h>
#include	<graphics/rastport.h>
#include	<graphics/text.h>
#include	<intuition/intuitionbase.h>
#include 	<stdio.h>

/*----------------------------------------------------------------------------*
 * gad.h is a real mixed bag. It defines (allocates storage for) many gadget
 * related variables. It also declares the char array "statustext".
 *----------------------------------------------------------------------------*/

/* #include	"gad.h" */
extern struct Gadget swind_gad[];
extern UBYTE		 statustext[];

#define SHOWGAD swind_gad[0]
#define MOVEGAD swind_gad[1]

#define GLOBAL extern
#include "globals.h"

extern short endpoints[];			/* End point coordinates for ruler	*/

#define x1 0						/* endpoints array indexes.			*/
#define y1 1						/* Note LOWER CASE!					*/
#define x2 2
#define y2 3

extern struct	Border ruler;		/* Border struct for ruler.			*/

/************  VARIABLES USED JUST INSIDE THIS FILE  ********************/

extern short mx, my;			/* Mouse coordinates.	*/
extern short update;			/* TRUE if status display needs refreshing.	*/
extern short ruler_color;
extern short moving;			/* Nonzero if ruler should be tracking mouse*/
extern short sizing;			/* 0 if the ruler is not being sized/moved	*/	
								/* 1 if the first endpoint is being moved.	*/
								/* 2 if the second endpoint is being moved.	*/

/******************************************************************************
 * This function will erase the ruler, deSELECT the show/hide gadget, deSELECT
 * the move/freeze gadget and disable the move/freeze gadget.
 ******************************************************************************/

hide_ruler()
{
	swap_gtext(&SHOWGAD);
	SHOWGAD.Flags &= ~SELECTED;					/* Deselect s/h gadget.	*/
	restore_line(); 							/* Erase line.			*/

	if (MOVEGAD.Flags & SELECTED)				/* If in move mode...	*/
	{
		swap_gtext(&MOVEGAD);
		MOVEGAD.Flags &= ~SELECTED;				/* Deselect m/f gadget.	*/
		HostIDCMPmods &= ~(MOUSEBUTTONS | MOUSEMOVE); 
		ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
		restore_pointer();
	}
	OffGadget(&MOVEGAD, StatWind, NULL);
	RefreshGadgets(swind_gad, StatWind, NULL);	/* Redraw with new text */

} /*  End of hide_ruler()  */


/******************************************************************************
 *  Move the ruler by erasing the old one, altering the endpoint coordinates
 *  and redrawing the border. Looks at variables in the Host's window
 *  structure and prevents the ruler from being run off the screen edges.
 *	Returns TRUE if the ruler was moved, FALSE if it wasn't.
 ******************************************************************************/

move_ruler()
{
short deltax, deltay;	/* Coordinates of first endpoint - mouse coodinates */
short rc;				/* Return code: 1 = frame moved, 0 = not moved.	    */

rc = 0;
deltax = mx - endpoints[x1];	/* Neg deltas mean we're trying to move right */
deltay = my - endpoints[y1];	/* Neg deltas mean we're trying to move up    */

/*----------------------------------------------------------------------*
 * Check the boundry conditions. You never have to check the first	
 * endpoint because the mouse can't be moved off the screen.
 *----------------------------------------------------------------------*/

/* If ruler can move horizontally... Adjust X coordinates.	*/

if (deltax	&& ( endpoints[x2] + deltax < HostWind->LeftEdge + HostWind->Width )
			&& ( endpoints[x2] + deltax > HostWind->LeftEdge) )

{
	endpoints[x1] = mx;
	endpoints[x2] += deltax;
	rc = 1;
}
/* If the ruler can move verically, adjust Y coordinates.		*/

if ( deltay && ( endpoints[y2] + deltay < HostWind->TopEdge + HostWind->Height )
			&& ( endpoints[y2] + deltay > HostWind->TopEdge) )
{
	endpoints[y1] = my;
	endpoints[y2] += deltay;
	rc = 1;
}

/* Restore current line from saved_line buffers. Then redraw line using */
/* the coordinates that we just calculated.								*/

if (rc)
{
	restore_line();
	draw_line(HostRPort, ruler_color, endpoints[x1], endpoints[y1],
									  endpoints[x2], endpoints[y2]);
}
update += rc;

return(rc);

} /*  End of move_ruler()  */


/******************************************************************************
 *  Resize the ruler by adjusting one of the endpoints.
 *  Boundry checking is unnecessary because the mouse won't leave the screen.
 *	Always returns TRUE.
 ******************************************************************************/

size_ruler()
{

if ( sizing == 1)
{
	endpoints[x1] = mx;
	endpoints[y1] = my;
}
else if (sizing == 2)
{
	endpoints[x2] = mx;
	endpoints[y2] = my;
}

/* Erase the current ruler and redraw it.	*/
restore_line();				
draw_line(HostRPort, ruler_color, endpoints[x1], endpoints[y1],
						          endpoints[x2], endpoints[y2]);
update = 1;

return(1);

} /*  End of size_ruler()  */


/******************************************************************************
 *  Calculate ruler length and slope in degrees. Display all that plus the
 *  coordinates of the ruler's endpoints.
 *
 *  This routine requires linking with a floating point math library.
 ******************************************************************************/


update_status()
{
short			i;
double			len, sin;
float			degrees;
long			deltax, deltay;

extern double	sqrt(), asin();

extern UBYTE			stext[];


/* Indexes of char data fields in the text string. These indexes must be	*/
/* kept in sync with the text"xxx" string initialization in main.c			*/

#define X1		 4
#define Y1		13
#define X2		22
#define Y2		31
#define LEN		41
#define SLOPE	54

deltax  = endpoints[x2] - endpoints[x1];
deltay  = endpoints[y2] - endpoints[y1];

/* I handle horizontal and vertical lines as a special case because they	*/
/* are used often and are easy.												*/

if (deltay == 0)						/* Horizontal	*/
{
	if (deltax > 0)
	{
		len = deltax + 1;
		degrees = 0.0;
	}
	else
	{
		degrees = 180.0;
		len = -(deltax - 1);
	}
}
else if (deltax == 0)					/* Vertical		*/
{
	if (deltay > 0)
	{
		len = deltay + 1;
		degrees = 270.0;
	}
	else
	{
		degrees = 90.0;
		len = -(deltay - 1);
	}
}
else									/* Other		*/
{
	/*------------------------------------------------------------------*
	 * The signs of the deltas don't matter for length but, the sign of
	 * deltay does make a difference in the slope calculation. The sign
	 * of deltay is wrong to begin with because it is from the screen
	 * coordinate system.
	 *------------------------------------------------------------------*/

	len = deltax * deltax + deltay * deltay;
	len = sqrt(len);

	/* sine = opposite / hypotonuse or someting like that	*/

	sin =  deltay / len;
	if (deltax > 0)		/* If in 1st or 4th quadrant...		*/
	{
		sin = -sin;		/* Fix sign of sine.				*/
	}
	degrees = 57.296 * asin(sin);

	if (deltax > 0)
	{
		if ( deltay > 0)				/* 1st quadrant is ok as is	*/
			degrees += 360.0;			/* 4th quadrant				*/
	}
	else
		degrees += 180.0;				/* 2nd and 3rd quadrants	*/

} /*  end of else "other"  */

/* Now that we have all this great data, we need to display it.	*/

sprintf(&stext[X1], "%03d", endpoints[x1] );
stext[X1 + 3] = ' ';

sprintf(&stext[Y1], "%03d", endpoints[y1] );
stext[Y1 + 3] = ' ';

sprintf(&stext[X2], "%03d", endpoints[x2] );
stext[X2 + 3] = ' ';

sprintf(&stext[Y2], "%03d", endpoints[y2] );
stext[Y2 + 3] = ' ';

sprintf(&stext[LEN], "%04d", (short) (len + 0.5) );
stext[LEN + 4] = ' ';

sprintf(&stext[SLOPE], "%05.1f", degrees);

PrintIText(StatRPort, &statustext, 0L, 0L);

return;

} /*  End of update_title()  */

/****************************  END OF RULER.C  ******************************/
