/****************************************************************************/
/*                                                                          */
/*  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_fio_save.c
 *		      Author: Jiang(John) Qian
 *			Date: 6/7/93
 *		 Description: Motif Windowing Routines Of VolVis
 *			      Creates the file save window, displays icon
 *			      representation of the data file.
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <string.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#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/DrawingA.h>

#include <dirent.h>
/*
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <Xm/TextF.h>
#include <unistd.h>
#include <pwd.h>
*/

#include "C_volvis.h"
#include "MOTIF_windefs.h"
#include "C_fio.h"
#include "C_help.h"

#define	C_ICON_SPACING	10	    	/* The space between two icons */
#define C_BITMAP_PAD 	32	    	/* Bitmap pad of the image */
#define C_OFFSET 	0	    	/* offset of the image */

/* set the font for the file names on the icons */
#define C_FONT "-adobe-helvetica-bold-r-normal--14-140-75-75-p-82-iso8859-1"

#include "bitmaps/env_bitmap"		/* bitmap for the environment icon */ 

/* Global Variables For Motif Windowing */
extern Widget		vv_toplevel;	/* VolVis toplevel Shell Widget */
extern Widget		fio_bbdialog;	/* File I/O Bulletin Board Dialog */
extern Widget		fio_save_bbdialog;
extern C_WindowDefs	window_defs;	
extern C_ImageTable	image_table;
extern C_World		world;

C_FileIOInfo		fio_save_info;	/* Information containing save status*/
Icon_Info		save_icon_info[C_FIO_MAXFILES]; /*info for each icon */

/*
 *        Procedure Name: create_fio_save_window
 *          Return Value: none
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: save_data->path_text    - The path text widget
 *			  save_data->file_text    - The file text widget
 *			  save_data->mssage   	  - The message window to 
 *						    display header information
 *			  save_data->canvas   	  - The area to display icons
 *      Global Variables: save_data
 *           Description: This function will create the file save window.
 *			  That includes a widget allowing the user to enter
 *			  the path name, a widget allowing the user to enter
 *			  the file name, a pulldown menu allowing to user to
 *			  change file type, a scroll window containing all the 
 *			  icons , a message window for displaying header
 *			  information of the data file, and some buttons at
 *			  the bottom of the window.
 */
void create_fio_save_window()
{
  extern void	  close_callback();
  void		  fio_set_save_type();
  void		  save_scrolled();
  void		  save_canvas_expose_CB(); 
  void		  get_save_path();
  void		  get_save_file();
  void		  accept_save_callback();
  void		  help_callback();

  Widget	  accept_button,
		  close_button,
		  help_button,
		  label1,label2,
		  scrollbar,
		  scrollwindow,
		  fio_save_pulld,
		  fio_save_options[3],
		  fio_save_menu,
		  rowcolumn,
		  frame;

  Arg		  args[20];
  XmString	  label_string;
  int		  n;
  XtPointer	  call_data;
  char            error_msg[C_MAX_STRING];
  char		  initial_path[C_MAX_STRING];

	if ((fio_save_info.save_data = (Fio_Dialog_Info *)  
				malloc(sizeof(Fio_Dialog_Info))) == NULL)
	{
        /* if not enough memory to malloc save_data, system exits */
            sprintf(error_msg,
               "Out of Memory When Starting File Load Window\nSystem must exit !!!\n");
            C_error_message(error_msg);
 
		exit(0);
	}

	/************************************************/
	/*     Create The file save dialog window	*/
	/************************************************/

	n=0;
        XtSetArg( args[n], XmNx, 0 ); n++;
        XtSetArg( args[n], XmNy, 0 ); n++;
	XtSetArg( args[n], XmNautoUnmanage, False ); n++;
	label_string = XmStringCreate( "File Save", XmSTRING_DEFAULT_CHARSET);
	XtSetArg( args[n], XmNdialogTitle, label_string ); n++;
	C_Set_Color_Dialog( args, n, window_defs );
	
	fio_save_bbdialog = XmCreateBulletinBoardDialog( vv_toplevel,
						"Save File Window", args, n );
	XmStringFree(label_string);

	/************************************************/
	/*     Create The path label			*/
	/************************************************/

	label_string = XmStringCreate("Path: ", XmSTRING_DEFAULT_CHARSET);
	n = 0;
	XtSetArg( args[ n ] , XmNx , 15 );			n++;
	XtSetArg( args[ n ] , XmNy , 25 );			n++;
	XtSetArg( args[ n ] , XmNlabelString ,label_string);    n++;
	C_Set_Color_Label( args, n, window_defs);
	label1 = XmCreateLabel( fio_save_bbdialog , "Label1" , args , n );
	XtManageChild( label1 );
	XmStringFree(label_string);

	/************************************************/
	/*     Create The path text area		*/
	/************************************************/

        /* set the initial path on the path widget */
	sprintf(initial_path, "%s/data/IMG", getenv("VOLVIS_HOME") );
	n = 0 ;
	XtSetArg( args[ n ] , XmNx , 75 );	n++;
	XtSetArg( args[ n ] , XmNy , 15 );	n++;
	XtSetArg( args[ n ] , XmNcolumns , 40 ); n++;
	C_Set_Color_Text(args,n,window_defs);
	fio_save_info.save_data->path_text = 
		XmCreateTextField( fio_save_bbdialog , "Text1" , args , n );
	XtManageChild( fio_save_info.save_data->path_text );
	XtAddCallback( fio_save_info.save_data->path_text, XmNactivateCallback, 
					get_save_path, fio_save_info.save_data);
	XmTextSetString(fio_save_info.save_data->path_text, initial_path);

	/************************************************/
	/*     Create The file label			*/
	/************************************************/

	label_string = XmStringCreate("File: ", XmSTRING_DEFAULT_CHARSET);
	n = 0;
	XtSetArg( args[ n ] , XmNx , 15 );			n++;
	XtSetArg( args[ n ] , XmNy , 70 );			n++;
	XtSetArg( args[ n ] , XmNlabelString , label_string);   n++;
	C_Set_Color_Label( args, n, window_defs);
	label2 = XmCreateLabel( fio_save_bbdialog , "Label2" , args , n );
	XtManageChild( label2 );
	XmStringFree(label_string);

	/************************************************/
	/*     Create The file text area		*/
	/************************************************/

	n = 0 ;
	XtSetArg( args[ n ] , XmNx , 75 );	n++;
	XtSetArg( args[ n ] , XmNy , 60 );	n++;
	XtSetArg( args[ n ] , XmNcolumns , 15 ); n++;
	C_Set_Color_Text(args,n,window_defs);
	fio_save_info.save_data->file_text = 
			XmCreateTextField( fio_save_bbdialog, "Text2", args,n);
	XtManageChild( fio_save_info.save_data->file_text );
	XtAddCallback( fio_save_info.save_data->file_text, XmNactivateCallback, 
				get_save_file , fio_save_info.save_data );

	/************************************************/
	/*     Create The Save Type Pulldown		*/
	/************************************************/
	n=0;
	C_Set_Color_PullDown( args, n, window_defs );
	fio_save_pulld = XmCreatePulldownMenu(fio_save_bbdialog,
						"fio_save_pulld", args, n );

	label_string = XmStringCreate( "Slice",  XmSTRING_DEFAULT_CHARSET);
	n=0;
	XtSetArg( args[n], XmNlabelString, label_string); n++;
	fio_save_options[0] = XmCreatePushButtonGadget( fio_save_pulld, 
				"Slice", args, n );
	XmStringFree( label_string );
	XtAddCallback( fio_save_options[0], XmNactivateCallback, 
		  fio_set_save_type, C_SLICE_FILE );

	label_string = XmStringCreate( "Image",  XmSTRING_DEFAULT_CHARSET);
	n=0;
	XtSetArg( args[n], XmNlabelString, label_string); n++;
	fio_save_options[1] = XmCreatePushButtonGadget( fio_save_pulld,
				"Image", args, n );
	XmStringFree( label_string );
	XtAddCallback( fio_save_options[1], XmNactivateCallback, 
		  fio_set_save_type, C_IMAGE_FILE );

        label_string = XmStringCreate( "Environment",XmSTRING_DEFAULT_CHARSET);
        n=0;
        XtSetArg( args[n], XmNlabelString, label_string); n++;
        fio_save_options[2] = XmCreatePushButtonGadget( fio_save_pulld,
                                "Environment", args, n );
        XmStringFree( label_string );
        XtAddCallback( fio_save_options[2], XmNactivateCallback,
                  fio_set_save_type, C_ENVIRONMENT_FILE );

	XtManageChildren( fio_save_options, 3 );

	label_string = XmStringCreate("Save Type:", XmSTRING_DEFAULT_CHARSET);
	n=0;
	XtSetArg( args[n], XmNx, 240 ); n++;
	XtSetArg( args[n], XmNy, 55 ); n++;
	XtSetArg( args[n], XmNlabelString, label_string ); n++;
	XtSetArg( args[n], XmNsubMenuId, fio_save_pulld ); n++;
	XtSetArg( args[n], XmNmenuHistory, fio_save_options[1] ); n++;
	C_Set_Color_OptionMenu( args, n, window_defs );

	fio_save_menu = XmCreateOptionMenu( fio_save_bbdialog, "fio_save_menu",
				args, n );
	XtManageChild( fio_save_menu );
	XmStringFree( label_string );

	fio_save_info.save_type = C_IMAGE_FILE;

	/****************************************************/
	/* Create A Scroll Window To Contain All The Icons  */
	/****************************************************/

	n = 0;
	XtSetArg( args[ n ], XmNx         , 15);		n++;
	XtSetArg( args[ n ], XmNy         , 105);		n++;
	XtSetArg( args[ n ], XtNheight    , 270);		n++;
	XtSetArg( args[ n ], XtNwidth     , 430);		n++;
	XtSetArg( args[ n ], XmNorientation, XmVERTICAL);	n++;
        XtSetArg( args[ n ], XmNscrollingPolicy, XmAPPLICATION_DEFINED);n++;
	XtSetArg( args[ n ], XmNvisualPolicy,XmVARIABLE);	n++;
	C_Set_Color_ScrollWindow(args,n,window_defs);
	scrollwindow = XmCreateScrolledWindow(fio_save_bbdialog, "scroll",
					    args,n);

	/****************************************************/
	/* Create A Drawing Area To Display All The Icons   */
	/****************************************************/

	n=0;
	XtSetArg(args[ n ], XmNresizePolicy,XmRESIZE_NONE);	n++;
	C_Set_Color_Canvas(args,n,window_defs);		
	fio_save_info.save_data->canvas = XtCreateManagedWidget("canvas",
					    xmDrawingAreaWidgetClass,
					    scrollwindow,
					    args,n);
	XtAddCallback( fio_save_info.save_data->canvas, XmNexposeCallback, 
			save_canvas_expose_CB, fio_save_info.save_type);

	XtManageChild(fio_save_info.save_data->canvas);

	/**********************************************************/
	/* Create A Scroll Bar to Scroll Through The Drawing Area */
	/**********************************************************/

	n = 0;
	XtSetArg( args[n], XmNmaximum, 1);		n++;
	XtSetArg( args[n], XmNsliderSize, 1);		n++;
	XtSetArg( args[n], XmNpageIncrement, 1);	n++;
	C_Set_Color_ScrollBar(args,n,window_defs);
	fio_save_info.save_data->scrollbar = XtCreateManagedWidget("scroll_bar",
			xmScrollBarWidgetClass, scrollwindow,args,n);
	XtManageChild(fio_save_info.save_data->scrollbar);

        /* adds callback when value changes */
        XtAddCallback(fio_save_info.save_data->scrollbar, 
			XmNvalueChangedCallback, save_scrolled, XmVERTICAL);

        /* adds callback when the user is draging the middle of scrollbar */
	XtAddCallback(fio_save_info.save_data->scrollbar, XmNdragCallback, 
			save_scrolled, XmVERTICAL);

	XtManageChild(scrollwindow);

        /* manages the scrollbar, drawing area, and the scrollwindow */
	XmScrolledWindowSetAreas(scrollwindow, NULL,
	  fio_save_info.save_data->scrollbar, fio_save_info.save_data->canvas);


	/********************************************************/
	/* Create A Message Area To Display Header Information  */
	/********************************************************/
        n=0;
        XtSetArg( args[ n ], XmNx         , 15);                n++;
        XtSetArg( args[ n ], XmNy         , 380);               n++;
        XtSetArg( args[ n ], XmNheight    , 110);               n++;
        XtSetArg( args[ n ], XmNwidth     , 430);               n++;
        XtSetArg( args[n], XmNeditMode, XmMULTI_LINE_EDIT);     n++;
        XtSetArg( args[n], XmNeditable, False);                 n++;
        XtSetArg( args[n], XmNcursorPositionVisible,   False);  n++;
        XtSetArg( args[n], XmNscrollVertical,   True);          n++;
        XtSetArg( args[n], XmNscrollHorizontal, False);         n++;
        C_Set_Color_Text( args, n, window_defs );

        fio_save_info.save_data->message = 
		XmCreateScrolledText(fio_save_bbdialog, "text_w", args, n);
        XtManageChild(fio_save_info.save_data->message);

	/************************************************/
	/*     Create A Frame To Hold The Buttons	*/
	/************************************************/

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

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

	/************************************************/
	/*     Create The Accept Button			*/
	/************************************************/

	n = 0 ;
	C_Set_Color_Button(args,n,window_defs);
	accept_button = XmCreatePushButton( rowcolumn , "Accept", args, n );
	XtAddCallback(  accept_button , XmNactivateCallback, 
			accept_save_callback , fio_save_info.save_data );
	XtManageChild ( accept_button );

	/************************************************/
	/*     Create The Close Button			*/
	/************************************************/

	n = 0;
	C_Set_Color_Button(args,n,window_defs);
	close_button = XmCreatePushButton( rowcolumn , " Close " , args , n );
	XtAddCallback( close_button , XmNactivateCallback, 
					close_callback , fio_save_bbdialog);
	XtManageChild ( close_button );

	/************************************************/
	/*     Create The Help Button			*/
	/************************************************/

	n = 0;
	C_Set_Color_Button(args,n,window_defs);
	help_button = XmCreatePushButton( rowcolumn , "  Help  ", args , n );
	XtAddCallback( help_button , XmNactivateCallback, 
				help_callback , C_FIO_SAVE_HELP );	
	XtManageChild ( help_button );

        /* manage the file i/o save window */
	XtManageChild(fio_save_bbdialog);
}
 
/*
 *        Procedure Name: save_canvas_expose_CB
 *          Return Value: none
 *       Input Variables: w                     - widget
 *                        client_data           - the file type
 *                        call_data             - call data
 *      Output Variables: none
 *      Update Variables: save_data->path_text  - The path text widget
 *                        save_data->file_text  - The file text widget
 *                        save_data->mssage     - The message window to display
 *                                                header information
 *                        save_data->canvas     - The area to display icons
 *      Global Variables: fio_save_info, save_icon_info
 *      Description     : This function is called the first time canvas is
 *                        exposed, that means the first the first time file
 *                        save dialog is poped up.  This function creates
 *                        pixmaps for environment icons and
 *                        initilizes the data structions.  Then the icons
 *                        are displayed and the initial path is set.
 */

void save_canvas_expose_CB( w, client_data, call_data )
Widget                  *w;
C_FileType              client_data;
XtPointer               call_data;
{ 
  void clear_save_icons();
  void print_save_icon();

  static int  initilize = TRUE; 	/* make sure function is called once */
  int  i;
  XmAnyCallbackStruct	*cbs_temp = NULL;


	if (initilize == TRUE)
        /* the first time the canvas is expose */
	{
		fio_save_info.current_save_icon = 0;  

            	/*
               		create a pixmap based on an external bitmap file
               		for function file icons
            	*/
                fio_save_info.env_pixmap  =
                   XCreatePixmapFromBitmapData( XtDisplay( vv_toplevel ),
                        RootWindowOfScreen( XtScreen( vv_toplevel ) ),
                        env_bitmap_bits, env_bitmap_width, env_bitmap_height,
			window_defs.icon_foreground.pixel, 
                        window_defs.button_background.pixel,window_defs.depth);

            	/* initilize the icon buttons  to NULL */
		for (i = 0;i<C_FIO_MAXFILES; ++i)
			save_icon_info[i].button = NULL;
		clear_save_icons();
		fio_save_info.last_save_icon = 0;

		/* get the initial path  */
		get_save_path( fio_save_info.save_data->path_text,
					fio_save_info.save_data,cbs_temp);

		/* print all the icon according to the data type */
		print_save_icon();
		initilize = FALSE;
	}
}		

void fio_set_save_type( w, client_data, call_data )
Widget			*w;
C_FileType		client_data;
XtPointer		call_data;
{

  void clear_save_icons();
  void print_save_icon();

	/* set the file type to save */
	fio_save_info.save_type = client_data;

	clear_save_icons();
	fio_save_info.last_save_icon = 0;

	sprintf(fio_save_info.save_data->filename, "");
	XmTextSetString(fio_save_info.save_data->file_text,"");
	XmTextClearSelection(fio_save_info.save_data->file_text,1);
	XmTextSetString(fio_save_info.save_data->message,"");

	/* print the icon according the new save type */
	print_save_icon();
}

/*
 *        Procedure Name: save_scrolled
 *          Return Value: none
 *       Input Variables: scrollbar             - widget
 *                        orientation           - vertical or horizontal
 *                        cbs                   - scroll bar callback struct
 *      Output Variables: none
 *      Global Variables: fio_save_info, save_icon_info
 *      Description     : This function is called when the user clicks on the
 *                        Scroll bar.  It will reprint the icons on the
 *                        canvas in order to make it seem to user that he/she
 *                        is actually scrolling the drawing area.
*/

void  save_scrolled(scrollbar, orientation, cbs)
Widget scrollbar;
int orientation;
XmScrollBarCallbackStruct *cbs;
{
  void icon_save_click();
  void draw_save_icon();
  void create_save_button();

  Widget  		w = NULL;
  int 			index,i,
			x = 0, y = 0,
			icon_x, icon_y,
			n;
  Arg   		args[20];
  Pixmap 		pixmap;
  XmAnyCallbackStruct 	*cbs_temp = NULL;

	for(i=fio_save_info.last_save_icon; 
			      i < fio_save_info.last_save_icon+6; ++i)
	{
	    if (save_icon_info[i].button != NULL)
	    {
		if (save_icon_info[i].file_type == C_ENVIRONMENT_FILE)
                /* free the pixmap that is on the icon */
		{
                        n=0;
                        XtSetArg( args[n], XmNlabelPixmap, &pixmap ); n++;
                        XtGetValues(save_icon_info[i].button, args, n);
                        XFreePixmap(XtDisplay(fio_save_info.save_data->canvas),
                                        pixmap);
                }
 		else
		{
                	XtRemoveCallback(save_icon_info[i].button,
  	        	                XmNexposeCallback,draw_save_icon,i);
		}
                XtRemoveCallback(save_icon_info[i].button, XmNactivateCallback,
        	                        icon_save_click, i);

		XtDestroyWidget(save_icon_info[i].button);
		save_icon_info[i].button = NULL;
	    }
	}

        for (i = 0; i < C_MAX_ICON_PER_WINDOW; ++i)
	/* print the new icons on the canvas */
        {
	    if ( x <= ((C_ICON_SPACING + C_ICON_WIDTH)*2) )
	    {
		icon_x = x + C_ICON_SPACING;
		x     += C_ICON_WIDTH + C_ICON_SPACING;
		icon_y = y + C_ICON_SPACING;

		/* find the correct six icons to print */
		if (cbs->value != 0)
		    index = i + cbs->value*3;
		else
		    index = i;

		if (index < fio_save_info.num_save_icon)
		{
                        /*
                         *  create the save button with position x = icon_x,
                         *  y = icon_y
                         */
			create_save_button(index, icon_x, icon_y,
				       save_icon_info[index].filename);
		}
	    }

	    if (x == ((C_ICON_SPACING + C_ICON_WIDTH) *3) ) 
	    /* there are three icons on one line, go to next line */
	    {
		x =  0;
		y += C_ICON_HEIGHT+C_ICON_SPACING;
	    }
	}

	fio_save_info.last_save_icon = cbs->value*3;
}


/*
 *        Procedure Name: clear_save_icons
 *          Return Value: none
 *       Input Variables: none
 *      Output Variables: none
 *      Global Variables: fio_save_info, save_icon_info
 *      Description     : This function clear the canvas of any icons, memory
 *                        associated with the icons are freed accordingly
*/

void clear_save_icons()
{
  void icon_save_click();
  void draw_save_icon();

  int 		i, n;
  Arg 		args[20];
  Pixmap 	pixmap;
  
	fio_save_info.current_save_icon = 0;
	for( i = 0; i < C_FIO_MAXFILES; ++i)
	{
	    if (save_icon_info[i].button != NULL)
	    {
		free(save_icon_info[i].filename);
		free(save_icon_info[i].path);
 
		if (save_icon_info[i].used_bitmap != TRUE)
                /* if we did not use a bitmap for the icon, free the icon data
                   memory
                */
		{
			if (machine_24_bit(save_icon_info[i].button))
				free(save_icon_info[i].icon_24_data);
			else
				free(save_icon_info[i].icon_8_data);
		}

		if(save_icon_info[i].file_type == C_ENVIRONMENT_FILE) 
                /* if we used a bitmap, free the bitmap */
		{
			
                        n=0;
                        XtSetArg( args[n], XmNlabelPixmap, &pixmap ); n++;
                        XtGetValues(save_icon_info[i].button, args, n);
                        XFreePixmap(XtDisplay(fio_save_info.save_data->canvas),
                                pixmap);
		}
		else
		{

                	XtRemoveCallback(save_icon_info[i].button,
                                XmNexposeCallback,draw_save_icon,i);
		}

                XtRemoveCallback(save_icon_info[i].button, XmNactivateCallback,
                                icon_save_click, i);

		XtDestroyWidget(save_icon_info[i].button);
		save_icon_info[i].button = NULL;
	    }
	}
}

/*
 *        Procedure Name: accept_save_callbak
 *          Return Value: none
 *       Input Variables: widget    - the accepth button
 *			  save_data - save_data
 *			  event	    - an X event
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables: none
 *           Description: This function is invoked when the user click on the
 *			  accept button of the save window is pressed.  It 
 *			  will find the full path name and save the file.
 */

void accept_save_callback( widget  , save_data, event)
Widget		widget;
Fio_Dialog_Info	*save_data;
XEvent		event;
{
  extern int C_save_file();

  char  file_name[C_MAX_STRING],
	path_name[C_MAX_STRING],
	filesave[C_MAX_STRING],
	temp_msg[C_MAX_STRING],
	temp_string[C_MAX_STRING];

  int	i,
	entry_number = fio_save_info.current_save_icon;

	/* get the file name to save */
	sprintf(temp_string , "%s",
			XmTextGetString(fio_save_info.save_data->path_text) );
        if (get_full_path(temp_string, path_name) != TRUE)
        {
            /* can't get full path name for the path beginning with ~ */
            sprintf(temp_msg, 
			"Can't get full directory name: %s  \n", temp_string);
            C_error_message( temp_msg);
        }
        else
        {
	    sprintf(file_name , "%s",	
			XmTextGetString(fio_save_info.save_data->file_text) );

	    /* get the full path name */
	    sprintf(filesave, "%s/%s",path_name,file_name);

	    /* save the file */
            C_save_file(filesave, fio_save_info.save_type,entry_number);
	}
}

/*
 *        Procedure Name: get_save_path 
 *          Return Value: none
 *       Input Variables: widget    - A text area
 *			  save_data - save_data
 *			  call_data - any callback structure
 *      Output Variables: none	  
 *      Update Variables: save_data->pathname -	path name
 *			  save_data->filename -	file name
 *			  save_icon_info      -	information about icons
 *
 *      Global Variables: save_icon_info      -	information about icons
 *           Description: This function is invoked when the user hit return
 *			  in data->path_text widget.  It will read the path
 *			  name and complete it if it starts with '~'.  Then
 *			  the filename will be cleared since we are working
 *			  with a new directory.  The drawing area which 
 *			  displays the icons will be refreshed and new icons
 *			  will be printed.
 */

void	get_save_path( widget , save_data , call_data )
Widget			widget;
Fio_Dialog_Info		*save_data;
XmAnyCallbackStruct	*call_data;
{
  extern int  get_full_path();
  
  char	temp_string[C_MAX_STRING], 
	temp_msg[C_MAX_STRING];
  int	i;

	/* get the path name from the path text widget */
	sprintf(temp_string , "%s", XmTextGetString(widget) );

	/* refresh the drawing area, clear the icon informations */
	sprintf(fio_save_info.save_data->pathname,"%s", temp_string);
	if (get_full_path(temp_string, 
			fio_save_info.save_data->pathname) != TRUE)
	{
	    /* can't get full path name for the path beginning with ~ */
	    sprintf(temp_msg, 
			"Can't get full directory name: %s\n", temp_string);
	    C_error_message( temp_msg);
	}
}

/*
 *        Procedure Name: get_save_file 
 *          Return Value: none
 *       Input Variables: widget    - a text area
 *			  save_data - save data
 *			  call_data - any callback structure
 *      Output Variables: none
 *      Update Variables: 
 *      Global Variables: save_data - save data
 *           Description: This function is called when the user hit enter
 *			  on the data->file_text widget. User have just entered
 *			  the file name.  Full path name is found in this
 *			  function and the file is saveed.
 */
void	get_save_file( widget , save_data , call_data )
Widget			widget;
Fio_Dialog_Info		*save_data;
XmAnyCallbackStruct	*call_data;
{
  extern int C_save_file(); 

  char  file_name[C_MAX_STRING],
	path_name[C_MAX_STRING],
	filesave[C_MAX_STRING], 
	temp_msg[C_MAX_STRING],
	temp_string[C_MAX_STRING];

  int	i,
	entry_number = fio_save_info.current_save_icon;

	/* get the file name to save */
	sprintf(temp_string,"%s", 
			XmTextGetString(fio_save_info.save_data->path_text ));
        if (get_full_path(temp_string, path_name) != TRUE)
        {
            /* can't get full path name for the path beginning with ~ */
            sprintf(temp_msg, 
		"Can't get full directory name: %s  \n", temp_string);
            C_error_message( temp_msg);
        }
        else
        {
	    sprintf(file_name,"%s", XmTextGetString(widget) );
	    /* get the full path name */
	    sprintf(filesave, "%s/%s", path_name,file_name);

	    /* save the file */
            C_save_file(filesave, fio_save_info.save_type,entry_number);
	}
}

/*
 *        Procedure Name: create_save_button
 *          Return Value: none
 *       Input Variables: i             - index indicating with icon to create
 *                        icon_x        - the x position of the icon
 *                        icon_y        - the y position of the icon
 *                        filename      - the filename which icon represents
 *      Output Variables: none
 *      Update Variables: save_icon_info
 *      Global Variables: fio_save_info.save_data - save data
 *           Description: This function will create a button which is actually
 *                        the icon according to the x y positions passed in.
 *                        The filename that the icon represents will be
 *                        displayed at the bottom of the icon.  For function
 *                        and environment files, a standard pixmap is put on
 *                        the button.  But for others, expose callback is
 *                        defined so that the icon image could be drawn.
*/

void create_save_button(i,icon_x,icon_y,filename)
int i;
int icon_x;
int icon_y;
char  *filename;
{
  extern void set_colormap();
  void	icon_save_click();
  void	draw_save_icon();

  int 		n;
  Arg 		args[20];
  XGCValues 	values;               /* values for graphic context */
  GC		gc;
  Pixmap 	pixmap;
  XGCValues     gcv;
  Font          font;
  int           mask = GCForeground | GCBackground;


	/************************************/
	/* Create A Drawn Button As A Icon  */    
	/************************************/
	n=0;
	XtSetArg(args[n], XmNx, icon_x);n++;
	XtSetArg(args[n], XmNy, icon_y);n++;
	XtSetArg(args[n], XmNwidth, C_ICON_WIDTH);n++;
	XtSetArg(args[n], XmNheight,C_ICON_HEIGHT);n++;
	XtSetArg(args[n], XmNborderWidth,0);n++;
	XtSetArg(args[n], XmNshadowThickness,0);n++;
	C_Set_Color_DrawnButton(args,n,window_defs);
        /* create a drawn button so we could put the icon image on top */
	save_icon_info[i].button = 
			XmCreateDrawnButton(fio_save_info.save_data->canvas, 
				filename, args,n);
	XtManageChild(save_icon_info[i].button);

        /* adds callback when the user clicks on the button */
	XtAddCallback(save_icon_info[i].button, XmNactivateCallback,
			      	icon_save_click, i);


	if (fio_save_info.save_type != C_ENVIRONMENT_FILE)
	{
	    save_icon_info[i].used_bitmap = FALSE;
	    XtAddCallback(save_icon_info[i].button,
				XmNexposeCallback,draw_save_icon,i);
	}	
	else
	{
            /* use a bitmap for icon image */
	    save_icon_info[i].used_bitmap = TRUE;
 
            /* create a gc with foreground and background color same as
               the drawn button.
            */
            gc = XCreateGC(XtDisplay( fio_save_info.save_data->canvas),
                                XtWindow( fio_save_info.save_data->canvas),
				NULL, NULL);

            /* set the font for the filename on the icon */
	    font = XLoadFont( XtDisplay(fio_save_info.save_data->canvas ) ,
				C_FONT);

            XSetFont(XtDisplay( fio_save_info.save_data->canvas ), 
				gc, font);
            XSetForeground (XtDisplay(fio_save_info.save_data->canvas),
                                gc, window_defs.icon_foreground);
            XSetBackground (XtDisplay(fio_save_info.save_data->canvas),
                                gc, window_defs.button_background);


            pixmap = XCreatePixmap(
                                XtDisplay( fio_save_info.save_data->canvas ) ,
                                XtWindow(  fio_save_info.save_data->canvas ),
                                C_ICON_WIDTH, C_ICON_HEIGHT, window_defs.depth);

            XCopyArea(XtDisplay( fio_save_info.save_data->canvas),
                                fio_save_info.env_pixmap, pixmap, gc,
                                0,0,C_ICON_WIDTH, C_ICON_HEIGHT, 0,0);

            /* draw the file name on the icon */
            XDrawString( XtDisplay( fio_save_info.save_data->canvas), pixmap,
                                gc, 10, 113, save_icon_info[i].filename,
                                strlen(save_icon_info[i].filename));

            /* set the label of the button to the pixmap */
 	    n = 0;
            XtSetArg( args[n], XmNlabelType, XmPIXMAP ); n++;
            XtSetArg( args[n], XmNlabelPixmap, pixmap ); n++;
            XtSetValues(save_icon_info[i].button, args,n);

	    XUnloadFont(XtDisplay(fio_save_info.save_data->canvas ) , font);
            XFreeGC(XtDisplay(fio_save_info.save_data->canvas ), gc);
	}
}

/*
 *        Procedure Name: print_save_icon
 *          Return Value: none
 *       Input Variables: none
 *      Output Variables: none
 *      Update Variables: save_icon_info  - information about icons
 *      Global Variables: save_icon_info  - information about icons
 *			  save_data	  - save data
 *           Description: This function will print the icons on the drawing
 *			  area already set up.  If the path name is valid,
 *			  then it updates save_icon_info, a button is created
 *			  for each file and a image is put on the button. 
 *			  The file name is drawn on to the button.  There
 *			  are three buttons on each row and they are called
 *			  icons.  If the directory name is not valid, then
 *			  an error message is display and nothing happens.
 */
void print_save_icon()
{

  extern void create_save_icon();

  char	    	temp_msg[C_MAX_STRING];
  Arg	    	args[20];
  int	    	x = 0, y = 0,
		icon_x,icon_y,
  		i=0, j, k=0,
		n,
  		max_loop,
		position=0;
  Pixmap    	pixmap,icon_pixmap;
  XmString  	str;
  DIR	    	*dirp;
  struct dirent	*dp;

	fio_save_info.current_save_icon = 0;

	/* calculate how many image or slice files are there */
	if ( fio_save_info.save_type == C_IMAGE_FILE)
	{ 
	    	max_loop = image_table.num_images;
	}
	else if (fio_save_info.save_type == C_SLICE_FILE)
	{
	    	max_loop = world.num_volumes;
	}
	else if (fio_save_info.save_type == C_ENVIRONMENT_FILE)
	/* there is only one environment file icon */
	    	max_loop = 1;

	for (i=0;i<max_loop;++i)
	{
	    if ( x <= ((C_ICON_SPACING + C_ICON_WIDTH)*2) )
	    {
		icon_x	=   x + C_ICON_SPACING;
		x	+=  C_ICON_WIDTH + C_ICON_SPACING;
		icon_y	=   y +	C_ICON_SPACING;

		save_icon_info[i].filename = (char *)
				    malloc(C_MAX_STRING * sizeof(char));

		if ( fio_save_info.save_type == C_IMAGE_FILE)
		    sprintf(save_icon_info[i].filename,"%s.img",
				image_table.image_entry[i]->image_name);
		else if ( (fio_save_info.save_type == C_SLICE_FILE) ||
				(fio_save_info.save_type == C_FUNCTION_FILE) )
		/* slice and function files are both saved as slc files */
		    sprintf(save_icon_info[i].filename,"%s.slc",
				world.volume[i]->volume_name);
		else if (fio_save_info.save_type == C_ENVIRONMENT_FILE)
		/* give a default filename for environment files */
		    sprintf(save_icon_info[i].filename, "current.env");		    	
		save_icon_info[i].file_type = fio_save_info.save_type;

		if ( i < C_MAX_ICON_PER_WINDOW )
		{
		    create_save_button(i,icon_x,icon_y, 
				save_icon_info[i].filename);
		}
 
		if (fio_save_info.save_type != C_ENVIRONMENT_FILE)
		/* save in the image data for drawing the icon image */
		{
		    create_save_icon(&(save_icon_info[i]), i);
		}

		if (x == ((C_ICON_SPACING + C_ICON_WIDTH) *3) ) 
		/* there are three icons on one line, go to next line */
		{
		    x =  0;
		    y += C_ICON_HEIGHT + C_ICON_SPACING;
		}
	    }
	}


	fio_save_info.num_save_icon = max_loop;
	
        /* updating the scrollbar's values */
	n = 0;
	XtSetArg( args[n], XmNvalue, 0);  n++;

	if (fio_save_info.num_save_icon/3 != 0) 
        /* if number of icon is greater than 3 */
	    if (( fio_save_info.num_save_icon % 3 == 0) && 
				      (fio_save_info.num_save_icon != 3)) 
                /*
                   if the number is not 3 but multiples of 3, set the max
                   value of the scrollbar to num_load_icon/3 -1
                */

		XtSetArg( args[n], XmNmaximum, 
				      fio_save_info.num_save_icon / 3 -1);
	    else
		XtSetArg( args[n], XmNmaximum, 
				      fio_save_info.num_save_icon / 3);	
	else
		XtSetArg( args[n], XmNmaximum, 1);		

	n++;

	XtSetArg( args[n], XmNsliderSize, 1);		n++;
	XtSetArg( args[n], XmNpageIncrement, 2);	n++;
	XtSetValues(fio_save_info.save_data->scrollbar, args, n);
}

/*
 *        Procedure Name: icon_save_click
 *          Return Value: none
 *       Input Variables: widget  - a button
 *			  index	  - index into save_icon_info
 *			  cbs	  - drawn button callback structure
 *      Output Variables: none
 *      Update Variables: 
 *      Global Variables: save_icon_info  - information about icons
 *			  save_data	  - save data
 *           Description: This function is invoked when the user presses
 *			  on a icon.  If the user only clicked once, then
 *			  data->file_text widget is set to the file name just
 *			  click, and the header information of this file 
 *			  is displayed in the data->message widget.  If the
 *			  user double clicked, we save the file.
 */
void
icon_save_click(w,index, cbs)
Widget	w;
int   index;
XmDrawnButtonCallbackStruct *cbs;
{
  extern int  C_save_file();
  void	  print_save_header();

  char 	filesave[C_MAX_STRING],
  	file_name[C_MAX_STRING], 
	path_name[C_MAX_STRING],
   	temp_msg[C_MAX_STRING], 
	temp_string[C_MAX_STRING];
  int	i;

	/* set the filename of the file text widget the filename of the 
	   clicked icon 
	*/
	XmTextSetString(fio_save_info.save_data->file_text, 
				save_icon_info[index].filename);

	/* print the header information of the file */
	print_save_header(save_icon_info[index],
				fio_save_info.save_data->message);

	fio_save_info.current_save_icon = index;

	if(cbs->click_count == 2)
	/* if user double clicked on the icon, then save the file */
	{
	    sprintf(temp_string,"%s",
			XmTextGetString(fio_save_info.save_data->path_text)); 
            if (get_full_path(temp_string, path_name) != TRUE)
            {
                /* can't get full path name for the path beginning with ~ */
                sprintf(temp_msg, "  Can't get full directory name: %s  \n",
                                                                temp_string);
                C_error_message( temp_msg);
            }
            else
            {
	        sprintf(filesave,"%s/%s",path_name,
					  save_icon_info[index].filename);

	        C_save_file(filesave, fio_save_info.save_type,index);
	    }
	}
}

/*
 *        Procedure Name: print_save_header
 *          Return Value: none
 *       Input Variables: icon	      -	the icon that was clicked
 *			  text_window -	text widget display header information
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables: save_data	  - save data
 *			  save_icon_info  - information about icons
 *           Description: print the header information of the current icon.
 *			  The header format  differs according to the 
 *			  file type.
 */
void print_save_header(icon,text_window)
Icon_Info icon;
Widget  text_window;
{
  extern char 	*get_extension();

  XmTextPosition   position;
  int   file_id;
  int   x_voxels , y_voxels , z_voxels ,
        image_width, image_height, image_depth;
  float x_units ,  y_units ,  z_units ;

  char 	*temp_msg, *extension, *full_name, 
	voxels[C_MAX_STRING],
	units[C_MAX_STRING],
	unit_type[C_MAX_STRING],
	data_origin[C_MAX_STRING], 
	data_modification[C_MAX_STRING], 
	data_compression[C_MAX_STRING],
	data_modif[C_MAX_STRING],
	render_type[C_MAX_STRING],
	image_accuracy[C_MAX_STRING],
	image_info[C_MAX_STRING],
	compute_shadows[C_MAX_STRING],
	level_of_reflection[C_MAX_STRING],  
	transmission[C_MAX_STRING],
	bits_per_voxel[C_MAX_STRING],
	compute_time[C_MAX_STRING],
	texture_info[C_MAX_STRING],
	line[C_MAX_STRING];

	/* get the file extension */
        extension = get_extension(icon.filename);
        XmTextSetString(text_window, "");

        if (strcmp(extension,"slc")==0)
	/* if the file has a slc extension */
        {
                if (icon.slice_info.data_origin == C_BIORAD_CONFOCAL_DATA)
                        sprintf(data_origin, "Data Origin: Biorad Confocal");
                else if (icon.slice_info.data_origin ==
                                                C_MAGNETIC_RESONANCE_DATA)
                        sprintf(data_origin, "Data Origin: Magnetic Resonance");                else if (icon.slice_info.data_origin ==
                                                C_COMPUTED_TOMOGRAPHY_DATA)
                        sprintf(data_origin,"Data Origin: Computed Tomography");                else if (icon.slice_info.data_origin == C_SIMULATION_DATA)
                        sprintf(data_origin, "Data Origin: Simulation");
                else if (icon.slice_info.data_origin == C_BINARY_VOXELIZED_DATA)                        sprintf(data_origin, "Data Origin: Binary Voxelized");
                else if (icon.slice_info.data_origin == C_FUZZY_VOXELIZED_DATA)
                        sprintf(data_origin, "Data Origin: Fuzzy Voxelized");
                else if (icon.slice_info.data_origin == C_FUN_VOXELIZED_DATA)
                        sprintf(data_origin,"Data Origin: Function Voxelized");
                else if (icon.slice_info.data_origin == C_OTHER_DATA_ORIGIN)
                        sprintf(data_origin, "Data Origin: Other");
                else
                        sprintf(data_origin, "Data Origin: Unknown");
                sprintf(line,"%s\n", data_origin);

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                if (icon.slice_info.unit_type == C_METER_UNIT)
                        sprintf(unit_type, "Unit: Meter");
                else if (icon.slice_info.unit_type == C_MILLIMETER_UNIT)
                        sprintf(unit_type, "Unit: Millimeter");
                else if (icon.slice_info.unit_type ==  C_MICRON_UNIT)
                        sprintf(unit_type, "Unit: Micorn");
                else if (icon.slice_info.unit_type == C_FOOT_UNIT)
                        sprintf(unit_type, "Unit: Foot");
                else if (icon.slice_info.unit_type == C_INCH_UNIT)
                        sprintf(unit_type, "Unit:Inch");
                else 
                        sprintf(unit_type, "Unit Type: Unknown");

		if (icon.slice_info.data_modification == C_ORIGINAL_DATA)
                        sprintf(data_modif, "Data Modification: Original");
                else if (icon.slice_info.data_modification == C_RESAMPLED_DATA)
                        sprintf(data_modif, "Data Modification: Resampled");
                else if (icon.slice_info.data_modification
                                                == C_RESAMPLED_FILTERED_DATA)
                        sprintf(data_modif,
                                "Data Modification: Resampled Filtered");
                else if (icon.slice_info.data_modification == C_FILTERED_DATA)
                        sprintf(data_modif, "Data Modification: Filtered");
                else if (icon.slice_info.data_modification
                                                == C_OTHER_DATA_MODIFICATION)
                        sprintf(data_modif, "Data Modification: Other");
                else
                        sprintf(data_modif, "Data Modification: Unknown");

                sprintf(line,"%-22s\t%-30s\n", unit_type, data_modif);

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                if (icon.slice_info.data_compression == C_NO_COMPRESSION)
                        sprintf(data_compression, "Data Compression:  None");
                else if (icon.slice_info.data_compression
                                                == C_RUN_LENGTH_ENCODE)
                        sprintf(data_compression, "Data Compression: RLE");
                else
                        sprintf(data_compression,"Data Compression: Unknown");
                sprintf(bits_per_voxel, "Bits Per Voxel: %d",
                        icon.slice_info.bits_per_voxel);

                sprintf(line, "%-21s\t%-30s\n",
                        bits_per_voxel, data_compression);

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                sprintf(line,
                "X Voxels: %d\tY Voxels: %d\tZ Voxels: %d\n",
                        icon.slice_info.x_voxels, icon.slice_info.y_voxels,
                        icon.slice_info.z_voxels);
                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                sprintf(line, "X Units: %5.2f\tY Units: %5.2f\tZ Units: %5.2f",
                        icon.slice_info.x_units,icon.slice_info.y_units,
                        icon.slice_info.z_units);
                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);
	}
        else if(strcmp(extension,"img")==0)
	/* if the file has an img extension */
        {
                if (icon.image_info.image_accuracy == C_LOW_IMAGE_ACCURACY)
                        sprintf(line, "Image Accuracy: Low\n");
                else if (icon.image_info.image_accuracy
                                                == C_MEDIUM_IMAGE_ACCURACY)
                        sprintf(line, "Image Accuracy: Medium\n");
                else if (icon.image_info.image_accuracy==C_HIGH_IMAGE_ACCURACY)
                        sprintf(line, "Image Accuracy: High\n");
                else
                        sprintf(line, "Image Accuracy: Unknown");

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                if (icon.image_info.render_type == C_PARC_RENDERING)
                        sprintf(render_type, "Render Type: Parc");
                else if (icon.image_info.render_type == C_RAYTRACE_RENDERING)
                        sprintf(render_type, "Render Type: Raytrace");
                else if (icon.image_info.render_type
                                                == C_PARC_RAYTRACE_RENDERING)
                        sprintf(render_type, "Render Type: Parc Raytrace");
                else if (icon.image_info.render_type == C_NAVIGATOR_RENDERING)
                        sprintf(render_type, "Render Type: Navigator");
                else if (icon.image_info.render_type == C_RADIOSITY_RENDERING)
                        sprintf(render_type, "Render Type: Radiosity");
                else
                        sprintf(render_type, "Render Type: Unknown");

                sprintf(compute_time, "Compute Time: %5.2f",
                        icon.image_info.compute_time);

                sprintf(line, "%s\t%s\n", render_type, compute_time);
                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                sprintf(compute_shadows, "Compute Shadows %5.2f",
                        icon.image_info.compute_shadows);
                sprintf(level_of_reflection, " Level Of Reflection: %d",
                        icon.image_info.levels_of_reflection);

                sprintf(line, "%s\t%s\n", compute_shadows,
                        level_of_reflection);
                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                sprintf(transmission, "Leval Of Transmission: %d",
                        icon.image_info.levels_of_transmission);

                sprintf(line, "%-25s\tIndirect Light: %d\n",
                              transmission,
                              icon.image_info.levels_of_indirect_light);

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);

                sprintf(line," Width: %d\tHeight: %d\tDepth: %d",
                              icon.image_info.width,
                              icon.image_info.height,
                              icon.image_info.depth);

                position = XmTextGetLastPosition(text_window);
                XmTextInsert(text_window,position,line);
	}
}

/*
 *        Procedure Name: draw_save_icon
 *          Return Value: none
 *       Input Variables: widget  - a button 
 *			  index	  - index into save_icon_info
 *			  cbs	  - any callback structure
 *      Output Variables: none
 *      Update Variables: none
 *      Global Variables: save_icon_info
 *           Description: This function will put a ximage on a button.  It 
 *			  will first determine which type of machine the user
 *			  is working with.  It could either be 24 bit, or 8.
 */
void draw_save_icon(w,index,cbs)
Widget  w;
int     index;
XmAnyCallbackStruct *cbs;
{
  extern void set_color_8_bit();
  extern char *get_extension();

  XImage 	*image;
  unsigned int  *iptr,
		*temp_ptr;
  unsigned char *optr,
 		*image_ptr;
  char 		*extension;
  int 		i=0,
		scan_unit;
  GC  		gc;
  int 		mask = GCForeground | GCBackground, n;
  Arg           args[20];
  XGCValues     gcv;
  Font          font;

	image_ptr = NULL;

 	extension = get_extension(save_icon_info[index].filename);	

	if(machine_24_bit(save_icon_info[index].button))
	/* if we are working with a 24 bit machine */
	{
	    /* malloc space for a 24 bit image */
	    if ((iptr =(unsigned int *)
		malloc(C_ICON_IMAGE_WIDTH * C_ICON_IMAGE_HEIGHT * 
						sizeof(unsigned int))) == NULL)
	    {
		C_error_message("Not enough memeory to draw icon image\nSystem must exit !!!");
		exit(0);
	    }

	    /* bytes per line in multiples of 4*/
	    scan_unit = 4;
	    temp_ptr = iptr;

	    while (i < C_ICON_IMAGE_WIDTH * C_ICON_IMAGE_HEIGHT)
	    {
		/* shift the bits, conversion of unsigned 
		   char to unsigned int 
		*/
		if ( (save_icon_info[index].icon_24_data[i] == 0) ||
		     (save_icon_info[index].icon_24_data[i] == 65793) )
                        /*
                           The HP window manager works incorrectly with those
                           two values, it uses the background color instead
                           so we will just set the value to 3, which is very
                           close to zero
                        */
			*(temp_ptr++) = (3 << 16) + (3 << 8) + 3;
		else
			*(temp_ptr++) = 
			    save_icon_info[index].icon_24_data[i];
		i++;
	    }
	    image_ptr = (unsigned char *) iptr;
	}
	else
	/* if we are working with a eight bit machine, this might have to be
	   changed if we are working with other kind of machines
	*/
	{
	    if ((image_ptr =(unsigned char *)
		malloc(C_ICON_IMAGE_WIDTH * C_ICON_IMAGE_HEIGHT * 
					sizeof(unsigned char))) == NULL)
	    {
		C_error_message("Not enough memeory to draw icon image\nSystem must exit !!!");
		exit(0);
	    }

	    scan_unit = 1;
	    optr = image_ptr;

	    while (i < C_ICON_IMAGE_WIDTH*C_ICON_IMAGE_HEIGHT)
	    {
		*(optr++) = save_icon_info[index].icon_8_data[i];
		i++;
	    }
	    if (strcmp(extension, "slc") ==0)
             	set_color_slc_8_bit(save_icon_info[index].filename,image_ptr);

	}

	/* create an image with image_ptr defining the image */
	image = XCreateImage(XtDisplay(save_icon_info[index].button),
			window_defs.visual, window_defs.depth,
			ZPixmap,C_OFFSET,image_ptr,
			C_ICON_IMAGE_WIDTH,C_ICON_IMAGE_HEIGHT,
			C_BITMAP_PAD,C_ICON_IMAGE_WIDTH*scan_unit);

        gc = XCreateGC(XtDisplay(save_icon_info[index].button),
                       	XtWindow(save_icon_info[index].button),
			NULL, NULL);

        font = XLoadFont( XtDisplay(save_icon_info[index].button), C_FONT);
        XSetFont( XtDisplay(save_icon_info[index].button)  , gc, font);
        XSetForeground (XtDisplay(fio_save_info.save_data->canvas),
			gc, window_defs.icon_foreground);
        XSetBackground (XtDisplay(fio_save_info.save_data->canvas),
                       	gc, window_defs.button_background);


	/* put the image on to the button */
	XPutImage(XtDisplay(save_icon_info[index].button),
			XtWindow(save_icon_info[index].button),
		  	gc, image,
		  	0,0,10,0,C_ICON_IMAGE_WIDTH,C_ICON_IMAGE_HEIGHT);
	
	XDrawString(XtDisplay(save_icon_info[index].button),
		    	XtWindow(save_icon_info[index].button),
		    	gc, 10,110, save_icon_info[index].filename,
		    	strlen(save_icon_info[index].filename));

	/* free memory */
	XDestroyImage(image);
	free(image_ptr);
	XUnloadFont(XtDisplay(save_icon_info[index].button), font);
        XFreeGC(XtDisplay(save_icon_info[index].button), gc);
}
