/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *			File: MOTIF_hlp_ui.c
 *		      Author: Lisa Sobierajski
 *			Date: 10/2/92
 *		 Description: Motif Help Windowing Routines Of VolVis
 *			      This file contains the routines for creating
 *			      the help window, and for displaying 
 *			      help messages in that 
 *			      window.
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

/****			Standard C Includes   		****/
#include <stdio.h>
#include <string.h>

/****			X11 Includes			****/
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

/****			Motif Includes			****/
#include <Xm/Xm.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/BulletinB.h>
#include <Xm/LabelG.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/Frame.h>

/****			VolVis Includes			****/
#include "C_volvis.h"
#include "MOTIF_windefs.h"
#include "C_help.h"

/* Global Variables For Motif Windowing */
Widget			hlp_bbdialog = NULL;
Widget			hlp_text;


C_MoreHelpInfo		more_help_info;

/*
 *        Procedure Name: hlp_callback
 *          Return Value: void
 *       Input Variables: 
 *		
 *		w		-	The widget to which this callback
 *					is attached
 *		client_data     -	Unused
 *		call_data	-	Unused
 *
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables: 
 *
 *		hlp_bbdialog    -	The Bulletin Board Dialog for the
 *					help window      
 *
 *           Description:
 *		
 *		This routine is called when the help button is
 *		pressed, and should not be called for any other reason.
 *		The hlp_bbdialog variable is checked to see if the 
 *		help window has been created already.  If not, the
 *		help window is created.  If the help window exists,
 *		but is not managed (popped up on the display) then it is
 *		managed.  If the help window exists and is managed, it
 *		is unmanaged and then managed.  This causes the window to
 *		disappear and reappear (which will pop it to the top if
 *		it was burried under other windows)	
 */
void help_callback( w, client_data, call_data )
Widget		w;
int		client_data;
XtPointer	call_data;
{
	extern 	char	*help_file_name[C_NUM_HELP_OPTIONS];

	/****		Local Routines			****/
	void       	  create_hlp_window();  /* Window Create Routine */

	/* Determine if the hlp bboard dialog should be created      */
	/* If hlp_bbdialog does not exist, create it - otherwise if  */
	/* it is managed, unmanage it and then manage it (to pop it  */
	/* down and then pop it back up again so that the user can   */
	/* locate it.)  If it exists but is not managed, just manage */
	/* it.							     */
	if( !hlp_bbdialog )
		create_hlp_window();
	else 
	{
		if (XtIsManaged( hlp_bbdialog) )
		{
			XtUnmanageChild( hlp_bbdialog );
		}
		XtManageChild( hlp_bbdialog );
	}

	C_help( help_file_name[client_data], -1 );
}


/*
 *        Procedure Name: create_hlp_window
 *          Return Value: void
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables: 
 *		
 *		vv_toplevel	-	The top level widget of VolVis
 *		hlp_bbdialog	-	The bulletin board dialog for
 *					the hlpsage window which is to
 *					be created
 *		window_defs	-	Window appearance definitions
 *
 *           Description:
 *
 *		This routine is called once to create the hlp_bbdialog
 *		(help window bulletin board dialog).  
 */
void create_hlp_window()
{
	extern void	     close_callback();
	void		     help_callback();
	void		     hlp_text_refresh_underline();

	extern Widget	     vv_toplevel;  /* VolVis toplevel Shell Widget */
	extern C_WindowDefs  window_defs;  /* widget colors                */

	void		     hlp_morehelp_callback();
	
	Arg		     args[40];	   /* Argument List                */
	int		     n;		   /* Argument Count               */
	Widget		     frame;        /* The frame widget		   */
        Widget		     rowcolumn;    /* A rowcolumn for the buttons  */
	Widget		     button;	   /* A button widget		   */ 
	XmString	     label_string;
	static XmTextScanType	     selection_array[1];


	/* Initialize The more_help_info Structure */
	more_help_info.num_entries = 0;

	/* Create The Help Bulletin Board */
	n=0;
	XtSetArg( args[n], XmNx, 0 ); n++;
	XtSetArg( args[n], XmNy, 0 ); n++;
	XtSetArg( args[n], XmNautoUnmanage, False ); n++;
	XtSetArg( args[n], XmNnoResize, True ); n++;
	label_string = XmStringCreate( "Help", XmSTRING_DEFAULT_CHARSET);
	XtSetArg( args[n], XmNdialogTitle, label_string ); n++;
	C_Set_Color_Dialog( args, n, window_defs );
	hlp_bbdialog = XmCreateBulletinBoardDialog( vv_toplevel,
		       "help", args, n );

        n = 0;
        XtSetArg( args[n], XmNx, 0 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
        C_Set_Color_Frame( args, n, window_defs );
        frame = XmCreateFrame( hlp_bbdialog, "frame", args, n );
        XtManageChild( frame );

	selection_array[0] = XmSELECT_WORD;

	/* Create The Scrolled Text Widget = Message Area */
	n=0;
	XtSetArg( args[n], XmNcolumns, 50 ); n++;
	XtSetArg( args[n], XmNrows, 30 ); n++;
	XtSetArg( args[n], XmNscrollVertical, True ); n++;
	XtSetArg( args[n], XmNscrollHorizontal, False ); n++;
	XtSetArg( args[n], XmNeditMode, XmMULTI_LINE_EDIT ); n++;
	XtSetArg( args[n], XmNeditable, False ); n++;
	XtSetArg( args[n], XmNcursorPositionVisible, FALSE ); n++;
	XtSetArg( args[n], XmNsensitive, True ); n++;
	XtSetArg( args[n], XmNselectThreshold, 9999 ); n++;
	XtSetArg( args[n], XmNselectionArrayCount, 1 ); n++;
	XtSetArg( args[n], XmNselectionArray, selection_array ); n++;
	C_Set_Color_Text( args, n, window_defs );
	hlp_text = XmCreateScrolledText( frame, "hlp_text", args, n );
	XtManageChild( hlp_text );

	XtAddCallback( hlp_text, XmNmotionVerifyCallback, 
		       hlp_text_refresh_underline, NULL );

        n = 0;
        XtSetArg( args[n], XmNx, 0 ); n++;
        XtSetArg( args[n], XmNy, 550 ); n++;
        C_Set_Color_Frame( args, n, window_defs );
        frame = XmCreateFrame( hlp_bbdialog, "frame", args, n );
        XtManageChild( frame );

        n = 0;
        C_Set_Color_RowColumn( args, n, window_defs );
	XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
        rowcolumn = XmCreateRowColumn(frame, "rowcolumn", args, n);
        XtManageChild (rowcolumn);

        /************************************************/
        /*     Create The More Help Button              */
        /************************************************/
        n=0;
        C_Set_Color_Button( args, n, window_defs );
        button = XtCreateManagedWidget( "More Help",
                xmPushButtonWidgetClass, rowcolumn, args, n );
        XtAddCallback( button, XmNactivateCallback,
                       hlp_morehelp_callback, NULL );
 
        /************************************************/
        /*     Create The Close Button                  */
        /************************************************/
        n=0;
        C_Set_Color_Button( args, n, window_defs );
        button = XtCreateManagedWidget( "Close",
                xmPushButtonWidgetClass, rowcolumn, args, n );
        XtAddCallback( button, XmNactivateCallback,
                       close_callback, hlp_bbdialog );
 
        /************************************************/
        /*     Create The Help Button                   */
        /*********************************************]***/
        n=0;
        C_Set_Color_Button( args, n, window_defs );
        button = XtCreateManagedWidget( "Help",
                xmPushButtonWidgetClass, rowcolumn, args, n );
        XtAddCallback( button, XmNactivateCallback,
                       help_callback, C_HLP_HELP );

	XtManageChild( hlp_bbdialog );
}

void hlp_text_refresh_underline( w, client_data, call_data )
Widget			w;
XtPointer		client_data;
XtPointer		call_data;
{
	int		loop;
	Boolean		status;
	XmTextPosition  left, right;

	status = XmTextGetSelectionPosition( hlp_text, &left, &right );

	for ( loop = 0; loop < more_help_info.num_entries; loop++ )
	{
	    if ( ( left  >  more_help_info.entry[loop].right &&
	           right >  more_help_info.entry[loop].right ) ||  
	         ( left  <  more_help_info.entry[loop].left &&
	           right <  more_help_info.entry[loop].left ) )
	    {
	        XmTextSetHighlight( hlp_text, more_help_info.entry[loop].left,
				    more_help_info.entry[loop].right,
				    XmHIGHLIGHT_SECONDARY_SELECTED );
	    }
	    else if ( left  >=  more_help_info.entry[loop].left &&
                      right <=  more_help_info.entry[loop].right )
	    {
	        XmTextSetHighlight( hlp_text, more_help_info.entry[loop].left, 
				    more_help_info.entry[loop].right,
				    XmHIGHLIGHT_SELECTED );
	    }
	}

	for ( loop = 0; loop < more_help_info.num_entries; loop++ )
	{
		if ( left  >=  more_help_info.entry[loop].left &&
		     right <=  more_help_info.entry[loop].right )
			break;
	}

	if ( loop >= more_help_info.num_entries )
	{
	        XmTextSetHighlight( hlp_text, left, right,
				    XmHIGHLIGHT_NORMAL );
	}

}

void hlp_morehelp_callback( w, client_data, call_data )
Widget			w;
XtPointer		client_data;
XtPointer		call_data;
{
	Boolean		status;
	XmTextPosition  left, right;
	int		loop;

	status = XmTextGetSelectionPosition( hlp_text, &left, &right );

	for ( loop = 0; loop < more_help_info.num_entries; loop++ )
	{
		if ( left  >=  more_help_info.entry[loop].left &&
		     right <=  more_help_info.entry[loop].right )
			break;
	}

	if ( loop < more_help_info.num_entries )
	{
		C_help( more_help_info.entry[loop].help_file, 
		        more_help_info.entry[loop].tag );
	}
	else
	{
		C_error_message("Please highlight an underlined word only!");
	}

}

C_help( help_file, tag )
char 	*help_file;
int	tag;
{
	extern C_WindowDefs	window_defs;

	XmTextPosition    curr_pos;
	XmTextPosition    begin_highlight;
	XmTextPosition    end_highlight;
	int		  in_highlight;
	Arg		  args[1];
	char		  string[256];
	char		  final_help_file[256];
	char		  one_line[256];
	int		  int_lookahead[256];
	char		  char_lookahead[256];
	int		  la_index;
	int		  index;
	int		  loop;
	int		  eof_found;
	FILE		  *fp;
	Dimension	  width;
	Dimension	  width1;
	Dimension	  width2;
	Dimension	  width_so_far;
	Dimension	  height1;
	Dimension	  height2;
	XmString	  string1;
	XmString	  string2;
	int		  current_tag;
	XmTextPosition	  show_position;


	/* Clear Out The more_help_info Structure */
	for ( loop = 0; loop < more_help_info.num_entries; loop++ )
	{
		if ( more_help_info.entry[loop].help_file )
			free ( more_help_info.entry[loop].help_file );
	}
	more_help_info.num_entries = 0;

	XtSetArg( args[0], XmNvalue, "" );
	XtSetValues( hlp_text, args, 1 );

	XtSetArg( args[0], XmNwidth, &width );
	XtGetValues( hlp_text, args, 1 );

	sprintf( final_help_file, "%s/%s/%s", getenv("VOLVIS_HOME"),
		C_HELP_PATH, help_file );

	fp = fopen( final_help_file, "r" );
	if( !fp )
	{
		return;
	}

	index = 0;
	
	in_highlight = FALSE;
	width_so_far = 0;
	eof_found = FALSE;

	show_position = 0;

	
	while ( fscanf( fp, "%s", string ) != EOF && !eof_found )
	{
	  
	  if ( strcmp( string, C_TAG_TOKEN ) == 0 )
	  {
		fscanf( fp, "%s", string );
		sscanf( string, "%d", &current_tag );
		if ( current_tag == tag )
		  show_position = XmTextGetLastPosition( hlp_text );
	  }
	  else if ( strcmp( string, C_HIGHLIGHT_TOKEN ) == 0 )
	  {
		if ( in_highlight )
		{
		    one_line[index] = '\0';
		    curr_pos = XmTextGetLastPosition( hlp_text );
		    XmTextInsert( hlp_text, curr_pos, one_line );
		    index = 0;
		    end_highlight = XmTextGetLastPosition( hlp_text );
		    in_highlight = FALSE;
		    XmTextSetHighlight( hlp_text, begin_highlight,
					end_highlight,
					XmHIGHLIGHT_SECONDARY_SELECTED );
		    string1 = XmStringCreate( one_line, 
					      XmSTRING_DEFAULT_CHARSET );
		    XmStringExtent( window_defs.font_list, string1, &width1,
				    &height1 );
		    width_so_far += width1;
		    one_line[index++] = ' '; 

		    fscanf( fp, "%s", string );
		    more_help_info.entry[more_help_info.num_entries].help_file = 
				(char *) malloc( strlen(string) + 1 );
		    sprintf( 
	                more_help_info.entry[more_help_info.num_entries].help_file, 
			"%s", string );
		
		    fscanf( fp, "%s", string );
                    sscanf( string, "%d", 
			&(more_help_info.entry[more_help_info.num_entries].tag) );

		    more_help_info.entry[more_help_info.num_entries].left = 
								begin_highlight;

		    more_help_info.entry[more_help_info.num_entries].right = 
								end_highlight;

		    more_help_info.num_entries++;
		}
		else
		{
		    one_line[index++] = ' ';
		    one_line[index] = '\0';
		    curr_pos = XmTextGetLastPosition( hlp_text );
		    XmTextInsert( hlp_text, curr_pos, one_line );
		    index = 0;
		    begin_highlight = XmTextGetLastPosition( hlp_text );
		    in_highlight = TRUE;
		    string1 = XmStringCreate( one_line, 
					      XmSTRING_DEFAULT_CHARSET );
		    XmStringExtent( window_defs.font_list, string1, &width1,
				    &height1 );
		    width_so_far += width1;
		}
	  }
	  else
	  {
		one_line[index] = '\0';
		string1 = XmStringCreate( one_line, XmSTRING_DEFAULT_CHARSET );
		XmStringExtent( window_defs.font_list, string1, &width1,
				&height1 );
		string2 = XmStringCreate( string, XmSTRING_DEFAULT_CHARSET );
		XmStringExtent( window_defs.font_list, string2, &width2,
				&height2 );

		if ( (width1 + width2 + width_so_far) > (width-25) )
		{
			one_line[index++] = '\n';
			one_line[index] = '\0';
			curr_pos = XmTextGetLastPosition( hlp_text );
			XmTextInsert( hlp_text, curr_pos, one_line );
			index = 0;
			for (loop=0; loop < strlen(string); loop++)
				one_line[index++] = string[loop];
			width_so_far = 0;
		}
		else	
		{
			if ( index != 0 )
				one_line[index++] = ' ';
			for (loop=0; loop < strlen(string); loop++)
				one_line[index++] = string[loop];
		}
		XmStringFree( string1 );
		XmStringFree( string2 );
	  }

	  int_lookahead[0] = getc( fp );
	  char_lookahead[0] = int_lookahead[0];
	  la_index = 0;

	  if ( char_lookahead[0] == '\n' )
	  {
	    int_lookahead[1] = getc( fp );
	    char_lookahead[1] = int_lookahead[1];
	    la_index = 1;

	    while ( char_lookahead[la_index] == '\n' )
	    {
		int_lookahead[++la_index] = getc( fp );
		char_lookahead[la_index] = int_lookahead[la_index];
	    }

	    ungetc( int_lookahead[la_index], fp ); 

	  }
	  else
	  {
	    ungetc( int_lookahead[0], fp );
	  }

	  if ( la_index >  1 )
	  {
	    one_line[index++] = '\n';
	    one_line[index] = '\0';
	    curr_pos = XmTextGetLastPosition( hlp_text );
	    XmTextInsert( hlp_text, curr_pos, one_line );
	    index = 0;
	    char_lookahead[la_index-1] = '\0';
	    curr_pos = XmTextGetLastPosition( hlp_text );
	    XmTextInsert( hlp_text, curr_pos, char_lookahead );
	    width_so_far = 0;
	  }
			
	}

	one_line[index++] = '\n';
	one_line[index] = '\0';
	curr_pos = XmTextGetLastPosition( hlp_text );
	XmTextInsert( hlp_text, curr_pos, one_line );

	XmTextSetTopCharacter( hlp_text, show_position );
}

