 /*
  * Khoros: $Id: scroll_util.c,v 1.1 1991/05/10 15:58:30 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: scroll_util.c,v 1.1 1991/05/10 15:58:30 khoros Exp $";
#endif

 /*
  * $Log: scroll_util.c,v $
 * Revision 1.1  1991/05/10  15:58:30  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "editimage.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>            Creation of Scroll Bars For		      <<<<
   >>>>            Pseudo and Windowing/Thresholding          <<<<
   >>>>                                                       <<<<
   >>>>		   create_pseudo_scrollbar()		      <<<<
   >>>>		   create_threshold_scrollbar()		      <<<<
   >>>>		   update_scroll()		      	      <<<<
   >>>>		   check_scroll_vals()		      	      <<<<
   >>>>		   create_scroll_value()	      	      <<<<
   >>>>		   ident_pseudo_scroll()	      	      <<<<
   >>>>		   update_int_scroll()		      	      <<<<
   >>>>		   update_value_widget()	      	      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  */



/****************************************************************
*
* Routine Name:  create_pseudo_scrollbar
*
*
*      Purpose:  creates the scroll bars on the psuedocolor widget with which
*		 the user will be able to specify the desired color for 
*		 the specified range of pixels in the image
*
*        Input:  scroll     - scroll structure
*		 label      - label for the scroll bar
*		 color      - color value for label foreground (color)
*		 pixel      - pixel value for scroll bar foreground (color)
*		 parent     - parent of the scroll bar widget
*		 vertical   - widget from which to do vertical offset
*		 horizontal - widget from which to do horizontal offset
*		
*
*       Output:  returns the Widget backplane of the scroll bar
*
*   Written By:  Mark Young 
*
****************************************************************/


Widget create_pseudo_scrollbar(scroll, label, color, pixel, parent, vertical,
			       horizontal)
ScrollStruct  *scroll;
char	*label;
unsigned long color, pixel;
Widget	parent, vertical, horizontal;
{
	int	i;
	Arg	args[15];
	Widget	back, colorname;



	i = 0;
	XtSetArg(args[i], XtNwidth, 230);			i++;
	XtSetArg(args[i], XtNheight, 30);			i++;
	XtSetArg(args[i], XtNfromVert, vertical);		i++;
	XtSetArg(args[i], XtNfromHoriz, horizontal);		i++;
	XtSetArg(args[i], XtNforeground, black);		i++;
	XtSetArg(args[i], XtNbackground, white);		i++;
	XtSetArg(args[i], XtNborderColor, black);		i++;
	back = XtCreateManagedWidget(label, formWidgetClass,
				      parent, args, i);

	i = 0;
	XtSetArg(args[i], XtNlabel, label);			i++;
	XtSetArg(args[i], XtNfromVert, NULL);			i++;
	XtSetArg(args[i], XtNfromHoriz, NULL);			i++;
	XtSetArg(args[i], XtNforeground, color);  		i++;
	XtSetArg(args[i], XtNbackground, white);		i++;
	XtSetArg(args[i], XtNborderColor, black);		i++;
	colorname = XtCreateManagedWidget("colorname", labelWidgetClass,
				           back, args, i);
	
	i = 0;
	XtSetArg(args[i], XtNfromVert, NULL);			i++;
	XtSetArg(args[i], XtNfromHoriz, colorname);		i++;
	XtSetArg(args[i], XtNx, 0);				i++;
	XtSetArg(args[i], XtNy, 0);				i++;
	XtSetArg(args[i], XtNorientation, XtorientHorizontal);	i++;
	XtSetArg(args[i], XtNwidth, 140);			i++;
	XtSetArg(args[i], XtNheight, 16);			i++;
	XtSetArg(args[i], XtNshown, 1.0);			i++;
	XtSetArg(args[i], XtNtopOfThumb, 0.0);			i++;
	XtSetArg(args[i], XtNforeground, pixel);  		i++;
	XtSetArg(args[i], XtNbackground, black); 		i++;
	XtSetArg(args[i], XtNborderColor, white);		i++;
	scroll->scrollbar = XtCreateManagedWidget("scrollbar",
				scrollbarWidgetClass, back, args, i);

	scroll->string = xvf_strcpy(" 0   ");
	create_scroll_value(back, scroll, xvf_strlen(scroll->string));
	XtAddCallback(scroll->scrollbar, XtNscrollProc, update_pseudo_incr,
		      (caddr_t) scroll);
	XtAddCallback(scroll->scrollbar, XtNjumpProc, update_pseudo_cont,
		      (caddr_t) scroll);
	return(back);
}



/****************************************************************
*
* Routine Name:  create_thres_scrollbar
*
*
*      Purpose:  creates the scroll bars on the threshold widget with which
*		 the user will be able to specify the desired threshold range.
*
*        Input:  scroll     - scroll structure
*		 label      - label for the scroll bar
*		 fg         - pixel value for scroll bar foreground (color)
*		 bg         - pixel value for scroll bar background (color)
*		 parent     - parent of the scroll bar widget
*		 vertical   - widget from which to do vertical offset
*		 horizontal - widget from which to do horizontal offset
*		
*       Output:  returns the Widget backplane of the scroll bar
*
*   Written By:  Mark Young 
*
****************************************************************/


Widget create_thres_scrollbar(thres, scroll, label, fg, bg, parent, vertical,
			       horizontal)
ThresStructure   *thres;
ScrollStruct     *scroll;
char	*label;
unsigned long fg;
unsigned long bg;
Widget	parent, vertical, horizontal;
{
	int	i;
	Arg	args[15];
	Widget	back, colorname;

	i = 0;
	XtSetArg(args[i], XtNwidth, 400);			i++;
	XtSetArg(args[i], XtNheight, 30);			i++;
	XtSetArg(args[i], XtNfromVert, vertical);		i++;
	XtSetArg(args[i], XtNfromHoriz, horizontal);		i++;
	back = XtCreateManagedWidget(label, formWidgetClass,
				      parent, args, i);

	i = 0;
	XtSetArg(args[i], XtNlabel, label);			i++;
	XtSetArg(args[i], XtNfromVert, NULL);			i++;
	XtSetArg(args[i], XtNfromHoriz, NULL);			i++;
	colorname = XtCreateManagedWidget("colorname", labelWidgetClass,
				           back, args, i);
	
	i = 0;
	XtSetArg(args[i], XtNfromVert, NULL);			i++;
	XtSetArg(args[i], XtNfromHoriz, colorname);		i++;
	XtSetArg(args[i], XtNx, 0);				i++;
	XtSetArg(args[i], XtNy, 0);				i++;
	XtSetArg(args[i], XtNorientation, XtorientHorizontal);	i++;
	XtSetArg(args[i], XtNwidth, 256);			i++;
	XtSetArg(args[i], XtNheight, 16);			i++;
	XtSetArg(args[i], XtNthumb, None);		        i++;
	XtSetArg(args[i], XtNforeground, fg);  		        i++;
	XtSetArg(args[i], XtNbackground, bg); 		        i++;
	XtSetArg(args[i], XtNborderColor, black);		i++;
	scroll->scrollbar = XtCreateManagedWidget("scrollbar",
				scrollbarWidgetClass, back, args, i);

	scroll->string = xvf_strcpy(" 0   ");
	create_scroll_value(back, scroll, xvf_strlen(scroll->string));
	scroll->pixel = fg;

	XtAddCallback(scroll->scrollbar, XtNscrollProc, update_thres_incr,
		      (caddr_t) thres);
	XtAddCallback(scroll->scrollbar, XtNjumpProc, update_thres_cont,
		      (caddr_t) thres);
	return(back);
}

/****************************************************************
*
* Routine Name:  update_scroll
*
*      Purpose:  This is the Action Procedure that gets called when
*		 the user hits <cr> in the value widget of the scroll
*		 selection.  It updates the scroll bar according to 
*		 the value entered.
*
*        Input:  widget     - the value widget
*		 event, params, num_params - not used
*		
*       Output:  updates the scroll bar
*
*   Written By:  Danielle Argiro
*
****************************************************************/

void update_scroll(widget, event, params, num_params)
Widget widget;
XEvent *event;
String *params;
Cardinal *num_params;
{
    int i, num;
    double  value, atof();
    ScrollStruct *pseudo_scroll, *ident_pseudo_scroll();
    Arg args[MaxArgs];
    char *string_return;

    int pixelmin = xvdisplay->pixelmin;
    int pixelmax = xvdisplay->pixelmax;
    ScrollStruct *lower = thres->lower;
    ScrollStruct *upper = thres->upper;
    ScrollStruct *range = thres->range;

    /*
     *  its the lower value scrollbar on the threshold display
     */
    if (widget == thres->lower->value)
    {
         i = 0;
         XtSetArg(args[i], XtNstring, &string_return);    i++;
         XtGetValues(lower->value, args, i);
	 lower->num = atoi(string_return);

	 check_scroll_vals(lower);
         update_int_scroll(lower, lower->num, pixelmax, pixelmin, pixelmax);
	 if (lower->num > upper->num)
         {
             upper->num = lower->num;
             update_int_scroll(upper, upper->num, pixelmax, pixelmin, pixelmax);
         }
	 range->num = lower->num;
	 update_int_scroll(range, lower->num, upper->num, pixelmin, pixelmax);
         update_thres();
    }

    /*
     *  its the upper value scrollbar on the threshold display
     */
    else if (widget == thres->upper->value)
    {
	 i = 0;
         XtSetArg(args[i], XtNstring, &string_return);    i++;
         XtGetValues(upper->value, args, i);
	 upper->num = atoi(string_return);

	 check_scroll_vals(upper);
         update_int_scroll(upper, upper->num, pixelmax, pixelmin, pixelmax);
	 if (upper->num < lower->num)
         {
             lower->num = upper->num;
             update_int_scroll(lower, lower->num, pixelmax, pixelmin, pixelmax);
         }
	 range->num = lower->num;
	 update_int_scroll(range, lower->num, upper->num, pixelmin, pixelmax);
         update_thres();
    }

    /*
     *  its the range value scrollbar on the threshold display
     */
    else if (widget == thres->range->value)
    {
	 i = 0;
         XtSetArg(args[i], XtNstring, &string_return);    i++;
         XtGetValues(upper->value, args, i);
	 num = atoi(string_return);

	 lower->num += num - range->num;
	 upper->num += num - range->num;
	 range->num = lower->num;
         update_int_scroll(lower, lower->num, pixelmax, pixelmin, pixelmax);
         update_int_scroll(upper, upper->num, pixelmax, pixelmin, pixelmax);
	 update_int_scroll(range, lower->num, upper->num, pixelmin, pixelmax);
         update_thres();
    }

    /*
     *  its one of the color scrollbars on the pseudo display
     */
    else
    {
         pseudo_scroll = ident_pseudo_scroll(widget);

	 i = 0;
         XtSetArg(args[i], XtNstring, &string_return);    i++;
         XtGetValues(pseudo_scroll->value, args, i);

         if (pseudo->model == RGB || pseudo->model == CMY ||
             pseudo->model == GREY)
         {
            value = (double) atoi(string_return);
	    value *= 256;
	 }
	 else
	 {
            value = (double) atof(string_return);
	 }
	 update_pseudo(pseudo_scroll, value, True);
     }
}

/****************************************************************
*
* Routine Name:  check_scroll_vals
*
*      Purpose:  All scroll bars used by editimage must have values
*		 between 0 and 255. This routine is called so
*		 that no other values can be entered.
*
*        Input:  scrolldata - the ScrollStruct of the current scrollbar 
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/

check_scroll_vals(scrolldata)

ScrollStruct *scrolldata;
{
	if (scrolldata->num < 0)
	   scrolldata->num = 0;
	else if (scrolldata->num > 255)
	   scrolldata->num = 255;
}


/****************************************************************
*
* Routine Name:  create_scroll_value
*
*      Purpose:  Creates the value widget to the right of a scroll
*		 bar which has the value represented by the scroll
*		 bar.  The value can be when the user enters a new
*		 value in the text widget and hits <cr>
*
*        Input:  parent - backplane of the value widget
*		 scroll - the ScrollStruct of the current scrollbar 
*		 length - the length of the value widget in characters
*		
*       Output:  none
*
*   Written By:  Danielle Argiro & Mark Young
*
****************************************************************/

create_scroll_value(parent, scroll, length)

Widget parent;
ScrollStruct *scroll;
int    length;
{
	int i;
	Arg args[MaxArgs];

	XtTranslations  scroll_trans;
	static char scroll_trans_table[] =
			"<Key>0xff0d:   update_scroll() \n\
			Ctrl<Key>x:    beginning-of-file()";

	void update_scroll();
	static XtActionsRec scroll_actionTable[] = {
		  { "update_scroll",  update_scroll}, };

	/*
	 *  Create the scroll's value widget.
	 */
	i = 0;
        XtSetArg(args[i], XtNeditType,XawtextEdit);                     i++;
        XtSetArg(args[i], XtNtype,XawAsciiString);                      i++;
        XtSetArg(args[i], XtNstring, scroll->string);                  	i++;
        XtSetArg(args[i], XtNfromVert, NULL);                           i++;
        XtSetArg(args[i], XtNfromHoriz, scroll->scrollbar);            	i++;
        XtSetArg(args[i], XtNinsertPosition, xvf_strlen(scroll->string)); i++;
        XtSetArg(args[i], XtNwidth, length*xvf_font_width);		i++;
        XtSetArg(args[i], XtNforeground, black);                        i++;
        XtSetArg(args[i], XtNbackground, white);                        i++;
        XtSetArg(args[i], XtNborderColor, black);                       i++;
	scroll->value = XtCreateManagedWidget("value", asciiTextWidgetClass,
                                       parent, args, i);

	XtAppAddActions(xvf_app_context, scroll_actionTable,
                        XtNumber(scroll_actionTable));
        scroll_trans = XtParseTranslationTable(scroll_trans_table);
        XtOverrideTranslations(scroll->value, scroll_trans);
}



/****************************************************************
*
* Routine Name:  ident_pseudo_scroll
*
*      Purpose:  The problem with Action Procedures under X11R4 is
*		 that we can't figure out how to pass parameters 
*		 correctly.  So this routine is necessary to figure
*		 out (if the scroll bar in question was on the psuedo display)
*		 which scrollbar initiated the Action Procedure update_scroll()
*
*        Input:  widget - the scrollbar widget to be identified
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/


ScrollStruct *ident_pseudo_scroll(widget)
Widget widget;
{
           if (widget == pseudo->rgb[0].value) return(&pseudo->rgb[0]);
      else if (widget == pseudo->rgb[1].value) return(&pseudo->rgb[1]);
      else if (widget == pseudo->rgb[2].value) return(&pseudo->rgb[2]);

      else if (widget == pseudo->cmy[0].value) return(&pseudo->cmy[0]);
      else if (widget == pseudo->cmy[1].value) return(&pseudo->cmy[1]);
      else if (widget == pseudo->cmy[2].value) return(&pseudo->cmy[2]);

      else if (widget == pseudo->hsv[0].value) return(&pseudo->hsv[0]);
      else if (widget == pseudo->hsv[1].value) return(&pseudo->hsv[1]);
      else if (widget == pseudo->hsv[2].value) return(&pseudo->hsv[2]);

      else if (widget == pseudo->hls[0].value) return(&pseudo->hls[0]);
      else if (widget == pseudo->hls[1].value) return(&pseudo->hls[1]);
      else if (widget == pseudo->hls[2].value) return(&pseudo->hls[2]);

      else if (widget == pseudo->yiq[0].value) return(&pseudo->yiq[0]);
      else if (widget == pseudo->yiq[1].value) return(&pseudo->yiq[1]);
      else if (widget == pseudo->yiq[2].value) return(&pseudo->yiq[2]);

      else if (widget == pseudo->xyz[0].value) return(&pseudo->xyz[0]);
      else if (widget == pseudo->xyz[1].value) return(&pseudo->xyz[1]);
      else if (widget == pseudo->xyz[2].value) return(&pseudo->xyz[2]);

      else if (widget == pseudo->uvw[0].value) return(&pseudo->uvw[0]);
      else if (widget == pseudo->uvw[1].value) return(&pseudo->uvw[1]);
      else if (widget == pseudo->uvw[2].value) return(&pseudo->uvw[2]);

      else if (widget == pseudo->grey[0].value) return(&pseudo->grey[0]);

}



/************************************************************
*
*  MODULE NAME: update_int_scroll
*
*      PURPOSE: Updates the scrollbar thumb and the scrollbar value
*		to reflect the current value stored in num.
*
*        INPUT: scroll -  the ScrollStruct of the current scroll bar
*
*       OUTPUT: none
*
*   WRITTEN BY: Danielle Argiro & Mark Young
*
*
*************************************************************/


update_int_scroll(scroll, lower, upper, min, max)

ScrollStruct *scroll;
int	     lower, upper, min, max;
{
	float   start, end, length;


	/*
	 *  Make sure that the lower & upper are within the min & max values.
	 */
	if (lower < min) lower = min;
	else if (lower > max) lower = max;

	if (upper < min) upper = min;
	else if (upper > max) upper = max;

	/*
	 *  Update the string in the value label to reflect the
	 *  new pixel.
	 */
	sprintf(scroll->string,"%d", lower);
	update_value_widget(scroll->string, scroll->value);

	/*
	 *  Update the scrollbar to reflect the new threshold value.
	 */
        if (max == min)
        {
	   start = 0.0;
	   end   = 1.0;
        }
        else
	{
	   start = (((float) lower-min)/(max-min));
	   end = (((float) upper-min)/(max-min));
        }
	length = end - start;
	XawScrollbarSetThumb(scroll->scrollbar, start, length);
}



/****************************************************************
*
* Routine Name:  update_value_widget
*
*      Purpose:  Updates the value appearing in the value widget
*		 according to the number passed in.
*
*        Input:  number - the number to appear in the value widget
*		 widget - the value widget to be updated.
*		
*       Output:  none
*
*   Written By:  Danielle Argiro
*
****************************************************************/

update_value_widget(string, widget)

char   *string;
Widget widget;
{
	int  status;
	XawTextBlock text_block;

	text_block.firstPos = 0;
	text_block.length = xvf_strlen(string);
   	text_block.ptr = string;
   	text_block.format = FMT8BIT;
   	status = XawTextReplace(widget, (XawTextPosition)0,
                         (XawTextPosition)(5), &text_block);
   	XawTextDisplay(widget);

   	if (status == XawPositionError)
   	{
            fprintf(stderr, "\nupdate_value_widget:\n");
            fprintf(stderr,"    position error\n");
   	}
   	else if (status == XawEditError)
   	{
            fprintf(stderr, "\nupdate_value_widget:\n");
            fprintf(stderr,"    edit error\n");
   	}
}
