/*
 * National Center for SuperComputing Applications, University of Illinois
 *
 * This NCSA software product is public domain software.  Permission
 * is hereby granted to do whatever you like with it. Should you wish
 * to make a contribution towards the production of this software, please
 * send us your comments about your experience with the software,  why
 * you liked or disliked it, how you use it, and most importantly, how it
 * helps your work. We will receive your comments at softdev@ncsa.uiuc.edu.
 *
 * Please send bug reports to bugs@ncsa.uiuc.edu
 *
 * Author: Eng-Whatt Toh, National Center for Supercomputing Applications
 *         ewtoh@ncsa.uiuc.edu
 */
#if ! defined(lint) && ! defined(LINT)
static char rcs_id[] = "$Id: gr_dspl.c,v 1.2 1993/10/28 20:46:33 gbourhis Exp $";
#endif

/*
 *	File:		gr_dspl.c
 *	Contents:	routines for dspl window
 *	$Log: gr_dspl.c,v $
 * Revision 1.2  1993/10/28  20:46:33  gbourhis
 * Little fix in gr_DsplImageSetPixel().
 *
 */

#include "gr_com.h"
#include <math.h>


/*
 * Sets a 'pixel' box of size scale and color pix at the (x,y) coordinates.
 */
void
gr_ImageSetPixel(w,x,y,scale,pix)
Widget w;
int    x,y,scale;
Pixel  pix;
{
	Display		*dpy=XtDisplay(w);
	Drawable	win=XtWindow(w);
	XGCValues	values;
	GC          drawGC;

	values.foreground = pix;
	drawGC = XtGetGC(w,GCForeground,&values);
	if (scale == 1)
		scale = 2;
	XDrawRectangle(dpy,win,drawGC,x,y,scale-1,scale-1);
}

/* ------------------------------------------------------------------ */

/*
 * Called by gr_DsplImageSelect to highlight the selected pixel position
 * (when mouse is clicked on image) and highlight the corresponding
 * entry in the data window.
 */
void
gr_DsplImageSetPixel(dsplWin, call_data)
A_DsplWind_t *dsplWin;
caddr_t		 call_data;
{
	A_Axes_t	 orient;
	Display 	 *dpy=XtDisplay(dsplWin->imageWin);
	XButtonPressedEvent *buttonEvent=(XButtonPressedEvent *)call_data;
	int					x,y,nx,ny;
	int				  	xdim,ydim,scale,index;
	int	tx,ty; /* jng dec 90 */

	orient = dsplWin->axesOrient;
	x = buttonEvent->x;
	y = buttonEvent->y;

	scale = dsplWin->scale;
	if (dsplWin->cull == TRUE)
		scale = 1;
	xdim = dsplWin->xdim;
	ydim = dsplWin->ydim;

	if (x >= xdim * scale) x = xdim * scale - 1;
	if (y >= ydim * scale) y = ydim * scale - 1;
	nx = x/scale;
	ny = y/scale;
	x = nx*scale;
	y = ny*scale;
	index = ny*xdim+nx;

	gr_ListHighlight(dsplWin->listWin,index);
	gr_ListHighlight(dsplWin->hScaleWin,nx);
	gr_ListHighlight(dsplWin->vScaleWin,ny);


	if (dsplWin->traceon == 0) { /* regular "point" mode */

		/* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& */
		if (orient.col < 0) dsplWin->selX = dsplWin->xdim-nx-1;
		else	dsplWin->selX = nx;
		if (orient.row > 0) dsplWin->selY = dsplWin->ydim-ny-1;
		else	dsplWin->selY = ny;

		if (dsplWin->cull)
		{
			dsplWin->selX = dsplWin->selX*dsplWin->scale;
			dsplWin->selY = dsplWin->selY*dsplWin->scale;
		}
		/* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& */

		/* unhilight prev pixel */
			if (dsplWin->oldInd != -1 )
				gr_ImageSetPixel(dsplWin->imageWin,
						dsplWin->oldX,dsplWin->oldY,scale,dsplWin->oldPix);

		if (dsplWin->oldInd == index)
	 		{ 
			/* turn off the old pixel highlight box if previously highlited */
				gr_ImageSetPixel(dsplWin->imageWin,
					dsplWin->oldX,dsplWin->oldY,scale,dsplWin->oldPix);
				dsplWin->oldInd = -1;
			}
		else
		{
		 	/* save current pixel info, then highlight that pixel (white) */

				dsplWin->oldInd = index;
				dsplWin->oldX = x;
				dsplWin->oldY = y;
				dsplWin->oldPix = XGetPixel(dsplWin->image,x,y);

				gr_ImageSetPixel(dsplWin->imageWin,x,y,scale,
								WhitePixel(dpy,DefaultScreen(dpy)));
			}

		}

	else { /* traceon is 1, leave "points" highlighted - jng oct24 */

		if ( dsplWin->nselected >=MAX_TRACE_SELPTS) { 
        gr_TextMsgOut("Point rejected: Too many points selected\n");
			beep();
			return;
			}

		gr_ImageSetPixel(dsplWin->imageWin,x,y,scale,
						WhitePixel(dpy,DefaultScreen(dpy)));

		/* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& */
		if (orient.col < 0) tx  = dsplWin->xdim-nx-1;
		else	tx  = nx;
		if (orient.row > 0) ty = dsplWin->ydim-ny-1;
		else	ty  = ny;

		if (dsplWin->cull)
		{
			tx = tx * dsplWin->scale;
			ty = ty * dsplWin->scale;
		}
		/* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& */
		if ( dsplWin->nselected < MAX_TRACE_SELPTS-1) { 
			dsplWin->selectX[dsplWin->nselected] = tx;
			dsplWin->selectY[dsplWin->nselected] = ty;
			dsplWin->nselected ++;
		}

	}	
	/* in either case, scroll the data window and update scales */
		gr_VPortMoveChild(dsplWin->listVPort,&nx,&ny,xdim,ydim);
		gr_DsplListVScroll(dsplWin->listVPort,(caddr_t)dsplWin,(caddr_t)ny);
		gr_DsplListHScroll(dsplWin->listVPort,(caddr_t)dsplWin,(caddr_t)nx);

#ifdef MIRIADFMT
	gr_DsplMiriadValues (dsplWin);
#endif

}


/*
 * Called when mouse is clicked in image window.  Updates all
 * synchronized dspl windows.
 */
void
gr_DsplImageSelect(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t *dsplWin = (A_DsplWind_t *)client_data;
	A_BossWind_t *curboss = gr_topWin.bossWin;
	A_CubeWind_t *curcube;
	A_DsplWind_t *curdspl;

	if (dsplWin->synchronize == FALSE)
		gr_DsplImageSetPixel(dsplWin, call_data);
	else
	while (curboss != NULL)
	{
		curcube = curboss->cubeWin;
		while (curcube != NULL)
		{
			curdspl = curcube->dsplWin;
			while (curdspl != NULL)
			{
				if ((curdspl == dsplWin) || (curdspl->synchronize == TRUE))
					gr_DsplImageSetPixel(curdspl, call_data);

				curdspl = curdspl->next;
			}
			curcube = curcube->next;
		}
		curboss = curboss->next;
	}
}


/*
 * Called by gr_DsplListSelect to highlight and scroll the data window
 * in the dspl window together with the scales and also highlight the
 * corresponding raster image point.
 */
void
gr_DsplListSet(dsplWin, index, highlight)
A_DsplWind_t	*dsplWin;
int				index;
Boolean			highlight;
{
	A_Axes_t	 	orient;
	Display	*dpy=XtDisplay(dsplWin->imageWin);
	int		xlines,ylines;
	int		scale;
	int		newx,newy,x,y,xdim,ydim;

	orient= dsplWin->axesOrient;
	scale = dsplWin->scale;

	if (dsplWin->cull == TRUE)
		scale = 1;

	xdim = dsplWin->xdim;
	ydim = dsplWin->ydim;

	ylines = index/xdim;
	xlines = index - (ylines*xdim);

	newx = x = xlines*scale;
	newy = y = ylines*scale;

	gr_VPortMoveChild(dsplWin->listVPort,&newx,&newy,
		xdim*scale,ydim*scale);
	gr_DsplListVScroll(dsplWin->listVPort,(caddr_t)dsplWin,(caddr_t)newy);
	gr_DsplListHScroll(dsplWin->listVPort,(caddr_t)dsplWin,(caddr_t)newx);

	/* turn off previous highlight in raster image */
	if (dsplWin->oldInd != -1)
		gr_ImageSetPixel(dsplWin->imageWin,dsplWin->oldX,
			dsplWin->oldY,scale,dsplWin->oldPix);

	if (dsplWin->oldInd == index)
	{
		gr_ImageSetPixel(dsplWin->imageWin,dsplWin->oldX,
			dsplWin->oldY,scale,dsplWin->oldPix);
		dsplWin->oldInd = -1;
	}
	else
	{
		dsplWin->oldInd = index;
		dsplWin->oldX = x;
		dsplWin->oldY = y;
		dsplWin->oldPix = XGetPixel(dsplWin->image,x,y);
		gr_ImageSetPixel(dsplWin->imageWin,x,y,scale,
						 WhitePixel(dpy,DefaultScreen(dpy)));
	}

	if (highlight == TRUE)
		gr_ListHighlight(dsplWin->listWin,index);

	gr_ListHighlight(dsplWin->hScaleWin,xlines);
	gr_ListHighlight(dsplWin->vScaleWin,ylines);

	if (orient.col < 0) dsplWin->selX = dsplWin->xdim-xlines-1;
	else	dsplWin->selX = xlines;
	if (orient.row > 0) dsplWin->selY = dsplWin->ydim-ylines-1;
	else	dsplWin->selY = ylines;

	if (dsplWin->cull)
	{
		dsplWin->selX = dsplWin->selX*dsplWin->scale;
		dsplWin->selY = dsplWin->selY*dsplWin->scale;
	}

#ifdef MIRIADFMT
	gr_DsplMiriadValues (dsplWin);
#endif
}


/*
 * Called when a data item is selected in the data window.  Updates
 * all synchronized dspl windows.
 */
void
gr_DsplListSelect(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t *dsplWin = (A_DsplWind_t *)client_data;
	A_BossWind_t *curboss = gr_topWin.bossWin;
	A_CubeWind_t *curcube;
	A_DsplWind_t *curdspl;
	int	 index;

	gr_ListgetStruct(dsplWin->listWin,&index);

	if (dsplWin->synchronize == FALSE)
		gr_DsplListSet(dsplWin, index, FALSE); /* no need to highlite */
	else
	while (curboss != NULL)
	{
		curcube = curboss->cubeWin;
		while (curcube != NULL)
		{
			curdspl = curcube->dsplWin;
			while (curdspl != NULL)
			{
				/* if same window, then no need to re-highlight */
				if (curdspl == dsplWin)
					gr_DsplListSet(curdspl, index, FALSE);
				else
				if (curdspl->synchronize == TRUE)
					gr_DsplListSet(curdspl, index, TRUE);

				curdspl = curdspl->next;
			}
			curcube = curcube->next;
		}
		curboss = curboss->next;
	}
}


/*
 * Scroll the Vertical scale when either the vertical scroll bar of
 * the data window is clicked or when the data window is moved
 */
void
gr_DsplListVScroll(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t	*dsplWin=(A_DsplWind_t *)client_data;

	gr_VPortVertMove(dsplWin->vScaleVPort,(int)call_data);
}


/*
 * Scroll the Horizontal scale when either the horizontal scroll bar of
 * the data window is clicked or when the data window is moved
 */
void
gr_DsplListHScroll(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t	*dsplWin=(A_DsplWind_t *)client_data;


	gr_VPortHoriMove(dsplWin->hScaleVPort,(int)call_data);
}


/*
 * Turn on synchronization
 */
void
gr_DsplSetSynch(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t	*dsplWin=(A_DsplWind_t *)client_data;

	dsplWin->synchronize = TRUE;
}


/*
 * Turn off synchronization
 */
void
gr_DsplUnSetSynch(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t	*dsplWin=(A_DsplWind_t *)client_data;

	dsplWin->synchronize = FALSE;
}

/* ------------------------------------------------------------------ */
/*
 * Plot Histogram window
 */
void
gr_DsplHistogram(w, client_data, call_data)
Widget w;
caddr_t	client_data;
caddr_t	call_data;
{
	A_DsplWind_t	*dsplWin=(A_DsplWind_t *)client_data;
	A_HistWind_t	*tmp=dsplWin->histWin;

    if (dsplWin->numHistWins < MAX_HISTLEV_WINDS)
    {
        tmp = gr_InitHistLevel(tmp,"XTDwindow",gr_topLevel,dsplWin);

        if (tmp != NULL)
        {
            dsplWin->histWin = tmp;
            dsplWin->numHistWins++;
        }
    }
    else
    {
        sprintf(msg,"Only %d histogram windows are allowed!\n",
            MAX_TILLEV_WINDS);
        gr_TextMsgOut(msg);
    }
    return;
}

/* ------------------------------------------------------------------ */
/* rings the bell */
beep() {
fprintf(stderr,"%c",7); fflush(stderr);
}
/* ------------------------------------------------------------------ */


