/****************************************************************************/
/*                                                                          */
/*  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: C_motif_win.c
 *		      Author: Rick Avila & Morita
 *			Date: 03/07/92
 *		 Description: Motif Windowing Routines Of VolVis
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <malloc.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 <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <Xm/TextF.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>

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

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

/*
 *        Procedure Name: show_image
 *          Return Value: none
 *       Input Variables: icon	   -  the icon structure
 *			  pathname -  the pathname 
 *			  index    -  index of the file in the directory
 *      Output Variables: none
 *      Update Variables: icon
 *      Global Variables: none
 *           Description: This function sets up the image data information
 *			  so that it could created into an ximage, if an icon
 *			  file already exist, then the icon file is read. 
 *			  other wise, we read the actual data files and 
 *			  create an icon that way. Then a popup dialog will
 *			  ask the user if he/she want to save the icons to
 *			  a file. 
 */

void create_load_icon(icon,pathname,index)
Icon_Info *icon;
char  *pathname;
int   index;
{
  int		read_icon_data();
  int		get_slice_data();
  int		get_texture_data();
  int		get_image_data();
  int		create_icon_file();

  extern int 	C_popup_choices();
  extern char 	*get_extension();
  extern int 	image_conversion();
  extern void 	make_blank_icon();

  static int	create,
		first_non_icon;       /* used to decide if icon files 
					 should be created
				      */
  int       	i=0,j=0,              /* counter */
         	fd,                   /* file descriptor */
         	file_number=0,        /* counter number of file */
  	    	num_choices,          /* number of choices in the popup window*/
		level=0,	      /* user level */ 
  		STATUS;		      /* progress status */
  char      	*icon_filename,
  	    	*filename,
  	    	*extension,
  	    	message[C_MAX_STRING],/* the popup dialog message */
  	    	*choices[2];	      /* number of choices in popup dialog */
  C_VolTexture  *texture_data; 	      /* data for texture file */
  XGCValues 	values;               /* values for graphic context */
  C_Image       image_data;	      /* data for image file */
	
	if (index == 0) 
		first_non_icon = TRUE;

	if ( (read_icon_data(icon,pathname) == C_ERROR) &&
	     (icon->valid_file == TRUE ) )
	/* if there is no icon file for the file */
	{
	    extension = get_extension(icon->filename);

	    if (strcmp(extension,"slc")==0)
	    /* if its a slice file */
		STATUS = get_slice_data(icon,pathname);

	    else if(strcmp(extension,"tex")==0)
	    /* if its a texture file */
	    {
		STATUS = get_texture_data(icon,pathname, texture_data);
	    }
	    else
	    {
		if(strcmp(extension,"img")==0)
		/* if its an image file */
		    STATUS = get_image_data(icon, pathname, &image_data);
	    }

	    if (STATUS == C_OK)
	    {
		if (first_non_icon )
		/* if there is a file without an icon file, this is only
		   done once and all the succeeding files without an icon
		   file will be treated same as this file
  		*/
		{
		    num_choices = 2;
		    choices[0] = " Yes ";
		    choices[1] = " No ";
		    sprintf(message,"Icon File Not Found, Should I Write Icon To A File?");
		    /* popup the message, wait for use's response */
		    if ((create = C_popup_choices(message , num_choices ,
							choices,level)) == 0)
			create = TRUE;
		    else
			create = FALSE;

		    first_non_icon = FALSE;
		}
		if (create)
		/* if use responded create a icon file */
		    create_icon_file(*icon,pathname);
	    }
	    else
		make_blank_icon(icon);
	}
}

/*
 *        Procedure Name: get_slice_data
 *          Return Value: none
 *       Input Variables: icon	   -  the icon structure
 *			  pathname -  the pathname 
 *      Output Variables: none
 *      Update Variables: icon	   -  the icon structure
 *      Global Variables: slice_data
 *           Description: This function will read slice file data into
 *			  the globel variable slice_data
 *
 */
int get_slice_data(icon,pathname)
Icon_Info *icon;
char *pathname;
{
	extern C_Voxel_8bit *decode_8bit_data();
	extern void C_error_message();
	extern int resize_image();

	int	file_id;
	char	full_name[C_MAX_STRING];
	char	temp_msg[C_MAX_STRING];
	int	i,j;
	C_UnitType	unit_type;	/* Measurement Type For Units	*/
	float		unit_amount;	/* Amount Equal To 1 VolVis Unit*/
	int	x_voxels;	/* Width Of Slices In Voxels 		*/
	int	y_voxels;	/* Height Of Slices In Voxels 		*/
	int	z_voxels;	/* Number Of Slices In Voxels 		*/
	float	x_units;	/* Width Of A Single Voxel In Units 	*/
	float	y_units;	/* Height Of A Single Voxel In Units 	*/
	float	z_units;	/* Depth Of A Single Voxel In Units 	*/
	int	data_size;	/* Number Of Bytes Needed To Store Data	*/
	int	plane_size;	/* Number Of Bytes In A Padded Plane 	*/
	int	x_counter;	/* Steps Through X Scan Lines 		*/
	int	y_counter;	/* Steps Through Y Planes		*/
	int	z_counter;	/* Steps Through Z Planes		*/
	C_Voxel_8bit	*voxel_ptr;	/* Points To Scanned Data Array	*/
	C_Voxel_8bit	*plane_ptr;	/* Pointer To Plane In Data Array */
	C_Voxel_8bit	*scan_ptr; 	/* Pointer To Scan Line In Data Array */
	C_Voxel_8bit	*max_ptr; 	/* the maximum slice */
	C_Voxel_8bit	*sptr;
	C_Voxel_8bit	*pptr;
	C_Voxel_8bit	*compressed_ptr;

	C_Voxel_8bit	*temp_max_ptr; 	 	/* the maximum slice */	
	C_Voxel_8bit	*temp_scan_ptr;		/* temp plane ptr    */
	C_Voxel_8bit	*column_scan_ptr;	/* reads one column  */
	C_Voxel_8bit	*row_scan_ptr;		/* reads one row     */
	C_Voxel_8bit	*temp_8_icon_ptr;	 
	unsigned int	*temp_24_icon_ptr;

	int	compressed_size;
	int	magic_num;
	int	bits_per_voxel;
	int	code;
	C_DataOrigin		data_origin;
	C_DataModification	data_modification;
	C_CompressionType	data_compression;
	char	string[256];
	int	STATUS;
	int SUCCESS = TRUE;


	voxel_ptr = NULL;

	/* find the full name for the file */
	sprintf( full_name, "%s/%s", pathname, icon->filename);

	if((file_id = open(full_name, O_RDONLY) ) <= 0 )
	{
		sprintf( temp_msg, "Can NOT Open File %s !!!\n", full_name );
		C_error_message( temp_msg );
		return( C_ERROR );
	}

	/****    Read the first four bytes and compare with     ****/
        /****    C_SLICE_MAGIC                                ****/
        read( file_id, &magic_num, sizeof(int) );

        /****    If the magic numbers do not match, this is not ****/
        /****    a slice file - print the appropriate error     ****/
        /****    message and return C_ERROR                     ****/
        if ( magic_num != C_SLICE_MAGIC )
        {
	    close ( file_id );
	    /* a blank icon will be made if we can not read the slice file */
	    return C_ERROR;
        }
	
	read( file_id, &x_voxels, sizeof(int) );
	read( file_id, &y_voxels, sizeof(int) );
	read( file_id, &z_voxels, sizeof(int) );
	read( file_id, &bits_per_voxel, sizeof(int) );
	read( file_id, &x_units, sizeof(float) );
	read( file_id, &y_units, sizeof(float) );
	read( file_id, &z_units, sizeof(float) );
	read( file_id, &unit_type, sizeof(C_UnitType) );
	read( file_id, &data_origin, sizeof(C_DataOrigin) );
	read( file_id, &data_modification, sizeof(C_DataModification) );
	read( file_id, &data_compression, sizeof(C_CompressionType) );

	icon->slice_info.x_voxels = x_voxels;
	icon->slice_info.y_voxels = y_voxels;
	icon->slice_info.z_voxels = z_voxels;
	icon->slice_info.bits_per_voxel = bits_per_voxel;
	icon->slice_info.x_units = x_units;
	icon->slice_info.y_units = y_units;
	icon->slice_info.z_units = z_units;
	icon->slice_info.unit_type = unit_type;
	icon->slice_info.data_origin = data_origin;
	icon->slice_info.data_modification = data_modification;
	icon->slice_info.data_compression = data_compression;
 
	/* Read In Data With Correct Interpolation */
	
	switch( bits_per_voxel )
	{
	  case 8:
		/* find the direction to move into the slice file */
                code = decide_axis(   icon->slice_info.x_voxels,
                                      icon->slice_info.y_voxels,
                                      icon->slice_info.z_voxels   );
 	        if (code == C_XY_Z)
		/* if we should be moving in Z direction */
        	{
                	max_ptr = (C_Voxel_8bit *) malloc(x_voxels * y_voxels);
                	if (!max_ptr)
                	{
                        	C_error_message("Out Of Memory Finding maximum projection !!!\n");
                        	return( C_ERROR );
                	}
                	bzero(max_ptr, 
				sizeof(C_Voxel_8bit) * x_voxels * y_voxels);
        	}
        	else if (code == C_XZ_Y)
		/* if we should be moving in Y direction */
        	{
                	max_ptr = (C_Voxel_8bit *) malloc(x_voxels * z_voxels);
                	if (!max_ptr)
                	{
                        	C_error_message("Out Of Memory Finding maximum projection !!!\n");
                        	return( C_ERROR );
                	}
                	bzero(max_ptr, 
				sizeof(C_Voxel_8bit) * x_voxels * z_voxels);
        	}
         	else if (code == C_YZ_X)
		/* if we should be moving in X direction */
        	{
                	max_ptr = (C_Voxel_8bit *) malloc(z_voxels * y_voxels);
                 	if (!max_ptr)
                	{
                        	C_error_message("Out Of Memory Finding maximum projection !!!\n");
                        	return( C_ERROR );
                	}
                	bzero(max_ptr, 
				sizeof(C_Voxel_8bit) * z_voxels * y_voxels);
        	}

        	if (!max_ptr)
        	{
            		C_error_message("Out Of Memory Finding maximum projection !!!\n");
            		return( C_ERROR );
        	}

		scan_ptr = NULL;
		temp_max_ptr = max_ptr;

		for( z_counter = 0; z_counter < z_voxels; z_counter++ )
		{
		  switch ( data_compression )
		  {
		    case C_NO_COMPRESSION:
		      if (!scan_ptr)
		      {
			scan_ptr = (C_Voxel_8bit *)malloc(x_voxels * y_voxels);
			if (!scan_ptr)
			{
			    C_error_message("Out of memory When reading one slice\n");
			    return(C_ERROR);
			}
		      }

		      /* data was not compressed, read a slice at a time */
		      read( file_id, scan_ptr, x_voxels * y_voxels );
		      break;

		    case C_RUN_LENGTH_ENCODE:
		      if ( scan_ptr )
			      free( scan_ptr );
		      read( file_id, &compressed_size, sizeof( int ) );
		      compressed_ptr = (C_Voxel_8bit *)malloc(compressed_size);
		      read( file_id, compressed_ptr, compressed_size );

		      /* decode a slice and save it in scan_ptr */
		      scan_ptr = decode_8bit_data( compressed_ptr, x_voxels * 
							y_voxels, SUCCESS );
		      if (!SUCCESS)
			      return(C_ERROR);

		      if (!compressed_ptr)
			      free( compressed_ptr );
		      break;

		    default:

		      break;
		  }

		  temp_scan_ptr = scan_ptr;

		  if (code == C_XY_Z)
		  /* if we want to move in Z direction */
		  {
		      /* we are moving oppsite of the direction we read 
			 the slice 
		      */ 
		      temp_scan_ptr = scan_ptr + x_voxels * y_voxels;
		      temp_max_ptr  = max_ptr;
		      for (y_counter = y_voxels; y_counter >0; y_counter--)
		      {
			  /* go to beginning of the next row */
			  temp_scan_ptr -= x_voxels;
			  for(x_counter = 0; x_counter < x_voxels; x_counter++)
			  {
			      if (*temp_scan_ptr > *temp_max_ptr)
			 		*temp_max_ptr = *temp_scan_ptr;
			      temp_max_ptr++;
		              temp_scan_ptr++;
			  }
			  /* go back to beginning of  a row */
			  temp_scan_ptr -= x_voxels;
		      }
		  }
		  else if (code == C_XZ_Y)
		  /* if we want to move in Y direction */
		  {
		    /* we don't have to worry about the direction in which
		       we are reading the slice because we could be looking 
		       from either the top or the bottom
		    */
		    temp_scan_ptr = scan_ptr;
		    for ( y_counter = 0; y_counter < y_voxels; y_counter++ )
		    {
		      for ( x_counter = 0; x_counter < x_voxels; x_counter++ )
		      {
			  if (*temp_scan_ptr > *temp_max_ptr)
				*temp_max_ptr = *temp_scan_ptr;
			  temp_max_ptr++;
			  temp_scan_ptr++;
		      }
		      /* keep comparing one row */
		      temp_max_ptr -= x_voxels;
		    }
		    /* finds one row of the max ptr at a time */
		    temp_max_ptr += x_voxels;
		  }
		  else if (code == C_YZ_X)
		  /* if we want to move in X direction */
		  {
                    /* we don't have to worry about the direction in which
                       we are reading the slice because we could be looking 
                       from either the left side or the right
                    */  
		    temp_scan_ptr = scan_ptr;
		    for ( x_counter = 0; x_counter < x_voxels; x_counter++ )
		    {
		      /* we are reading a column at a time */
		      column_scan_ptr = temp_scan_ptr;
		      for ( y_counter = 0; y_counter < y_voxels; y_counter++ )
		      {
			if (*column_scan_ptr > *temp_max_ptr)
				*temp_max_ptr = *column_scan_ptr;
			temp_max_ptr++;
			/* goto the next row with the same column position*/
			column_scan_ptr += x_voxels;
		      }
		      temp_max_ptr -= y_voxels;
		      temp_scan_ptr++;
		    }
		    temp_max_ptr += y_voxels;
		  }
		}/* end of for loop, for z counter */
		break;

	  case 16:
		C_error_message("Can't handle 16 bit data yet !!!\n");
		return C_ERROR;
		break;

	  case 32:
		C_error_message("Can't handle 32 bit data yet !!!\n");
		return C_ERROR;
		break;

	  default:
		C_error_message("Internal Error !!!\n");
		return C_ERROR;
		break;
	}
	close( file_id );

	/* resize the image to C_ICON_IMAGE_WIDTH by C_ICON_IMAGE_HIEGHT */
	if ( code == C_XY_Z )
	    STATUS =resize_image(icon, max_ptr, icon->slice_info.x_voxels,
			   	icon->slice_info.y_voxels);
	else if ( code == C_XZ_Y )
	    STATUS =resize_image(icon, max_ptr, icon->slice_info.x_voxels,
			   	icon->slice_info.z_voxels);
	else if ( code == C_YZ_X) 
	    STATUS =resize_image(icon, max_ptr, icon->slice_info.y_voxels,
			       	icon->slice_info.z_voxels);
	else
	    STATUS = C_ERROR;

	free(max_ptr);
	if (scan_ptr)
		free(scan_ptr);

	return(STATUS);
}



/*
 *        Procedure Name: get_image_data
 *          Return Value: none
 *       Input Variables: icon	   	-  the icon structure
 *			  pathname 	-  the pathname 
 *			  image_data  	-  image data information
 *      Output Variables: none
 *      Update Variables: icon	   	-  the icon structure
 *      Global Variables: none 
 *           Description: This function will read image file data into image
 *			  data.
 */

int get_image_data(icon,pathname,image_data)
Icon_Info *icon;
char *pathname;
C_Image   *image_data;
{
  extern C_Byte		*decode_8bit_data();
  extern void 		C_error_message();
  int			image_conversion();

  int			fd;
  C_CompressionType	compress_type;
  int			rle_size;
  C_Byte		*encode_ptr;
  int			magic_num;
  char			string[256];
  char			filename[C_MAX_STRING];
  char			temp_msg[C_MAX_STRING];
  int			SUCCESS = TRUE;
  C_VolTexture  	*texture_data;

	sprintf(filename,"%s/%s",pathname,icon->filename);

	fd = open( filename, O_RDONLY );
	if (fd < 0)
	{
	    sprintf(temp_msg,"Could Not Open Image File %s !!!\n",filename);
	    C_error_message(temp_msg);
	    return C_ERROR;
	}

	read( fd, &magic_num, sizeof(int) );		

        /****    If the magic numbers do not match, this is not ****/
        /****    an image  file - print the appropriate error   ****/
        /****    message and return C_ERROR                     ****/
        if ( magic_num != C_IMAGE_MAGIC )
        {
            close ( fd );
	    /* will make an blank icon */ 
            return C_ERROR;
        }

	read( fd, &(icon->image_info.width), sizeof(int) );		
	read( fd, &(icon->image_info.height), sizeof(int) );		
	read( fd, &(icon->image_info.depth), sizeof(int) );		
	read( fd, &(icon->image_info.image_accuracy), sizeof(C_ImageAccuracy));
	read( fd, &(icon->image_info.compute_time), sizeof(float) );
	read( fd, &(icon->image_info.render_type), sizeof( C_RenderingType ) );
	
	switch ( icon->image_info.render_type )
	{
	    case C_RAYTRACE_RENDERING:
	    case C_PARC_RAYTRACE_RENDERING:
		read( fd, &(icon->image_info.compute_shadows), sizeof(int) );
		read( fd, &(icon->image_info.levels_of_reflection), 
								sizeof(int) );
		read( fd, &(icon->image_info.levels_of_transmission),
								sizeof(int) );
		read( fd, &(icon->image_info.levels_of_indirect_light), 
								sizeof(int) );
		break;
	}

	read(fd, &(icon->image_info.compress_type), sizeof(C_CompressionType));

	switch ( icon->image_info.compress_type )
	{
	  case C_NO_COMPRESSION:

		if ((image_data->red =(C_Byte *) malloc(icon->image_info.width *
  						icon->image_info.height * 
						sizeof( C_Byte ))) == NULL)
		{
		    C_error_message("Not Enough Memory To Read The Image !!\n");
		    return C_ERROR;			
		}
		
		read( fd, &(image_data->red), icon->image_info.width * 
				icon->image_info.height * sizeof( C_Byte ) );

		if ( icon->image_info.depth == 3 )
		{
		    if ((image_data->green=(C_Byte *) malloc( 
						icon->image_info.width * 
						icon->image_info.height * 
						sizeof( C_Byte ))) == NULL)
		    {
			C_error_message("Not Enough Memory To Read Image !!\n");
			return C_ERROR;			
		    }
		
		    read( fd, &(image_data->green), icon->image_info.width * 
				icon->image_info.height * sizeof( C_Byte ) );

		    if ((image_data->blue=(C_Byte * ) malloc( 
						icon->image_info.width * 
						icon->image_info.height * 
						sizeof( C_Byte ))) == NULL)
		    {
			C_error_message("Not Enough Memory To Read Image !!\n");
			return C_ERROR;			
		    }

		    read( fd, &(image_data->blue), icon->image_info.width * 
				icon->image_info.height * sizeof( C_Byte ) );
		}
		break;
	
	case C_RUN_LENGTH_ENCODE:

		read( fd, &rle_size, sizeof(int) );

		if ((encode_ptr = ( C_Byte * ) 
				malloc( rle_size * sizeof(C_Byte))) == NULL)
		{
		    C_error_message("Not Enough Memory To Read Image!!!\n");
		    return C_ERROR;			
		}

		read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

		image_data->red = decode_8bit_data( encode_ptr, 
					icon->image_info.width 	* 
					icon->image_info.height, SUCCESS );
		if (!SUCCESS)
		    return(C_ERROR);

		free( encode_ptr );

		if ( icon->image_info.depth == 3 )
		{
		    read( fd, &rle_size, sizeof(int) );

		    if ((encode_ptr = ( C_Byte * ) malloc( 
					rle_size * sizeof(C_Byte))) == NULL)
		    {
			C_error_message("Not Enough Memory To Read Image!!!\n");
			return C_ERROR;			
		    }

		    read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

		    image_data->green = decode_8bit_data( encode_ptr, 
					icon->image_info.width * 
					icon->image_info.height,SUCCESS );
		    if (!SUCCESS)
			return(C_ERROR);

		    free( encode_ptr );

		    read( fd, &rle_size, sizeof(int) );

		    if ((encode_ptr = ( C_Byte * ) 
				  malloc( rle_size * sizeof(C_Byte))) == NULL)
		    {
			C_error_message("Not Enough Memory To Read Image!!!\n");
			return C_ERROR;			
		    }

		    read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

		    image_data->blue = decode_8bit_data( encode_ptr, 
					icon->image_info.width * 
					icon->image_info.height,SUCCESS );
		    if (!SUCCESS)
			return(C_ERROR);
		    free( encode_ptr );
		}
		break;
	}
        close ( fd );

	/* store the image into the icon data */
	if (image_conversion(icon,texture_data,*image_data) == C_OK)
		return(C_OK);
	else
		return(C_ERROR);
}


/*
 *        Procedure Name: get_texture_data
 *          Return Value: none
 *       Input Variables: icon	   	-  the icon structure
 *			  pathname 	-  the pathname 
 *			  texture_data 	-  the texture data information
 *      Output Variables: none
 *      Update Variables: icon	   	-  the icon structure
 *			  texture_data	-  the texture data information
 *      Global Variables: none 
 *           Description: This function will read texture file data into
 *			  the globel variable texture_data
 *
 */
int get_texture_data(icon, pathname,texture_data)
Icon_Info     *icon;
char	      *pathname;
C_VolTexture  *texture_data;
{
  extern int C_read_volume_texture();
  extern int image_conversion();

  int 		fd;
  char 		filename[C_MAX_STRING];
  C_Image 	image_data;

	sprintf(filename,"%s/%s",pathname,icon->filename);

	texture_data =  C_New( C_VolTexture );
	if (C_read_volume_texture( filename, texture_data ) == C_OK)
	{
	    icon->texture_info.xres = texture_data->xres;
	    icon->texture_info.yres = texture_data->yres;
	    icon->texture_info.zres = texture_data->zres;
	    icon->texture_info.references = texture_data->references;

	    /* store the texture image into the icon data */
	    if (image_conversion(icon,texture_data,image_data) == C_OK)
	    	return(C_OK);
	    else
		return(C_ERROR);
	}
	else
		return(C_ERROR);
}

/*
 *    Procedure Name: create_icon_file
 *      Return Value: none
 *   Input Variables: icon	-  the icon structure 
 *                    pathname	-  the path name of the icon data
 *  Output Variables: none
 *  Update Variables: none
 *  Global Variables: none
 *       Description: This function will save the icon image into a file
 *		      so the next time we can just retrieve it and create
 *		      an icon with it.
 *
 */
int create_icon_file(icon,pathname)
Icon_Info icon;
char  *pathname;
{
  extern void 	C_error_message();
  extern char 	*get_extension();
  extern int 	machine_24_bit();

  int	fd;
  char	command[C_MAX_STRING];
  char	iconfile[C_MAX_STRING];
  char	temp_msg[C_MAX_STRING];
  char	*extension;
  int	magic_num;

	/* create the file according to the machine */
	if(machine_24_bit(icon.button))
	    sprintf(iconfile,"%s/.icon.24.%s",pathname,icon.filename);
	else
	    sprintf(iconfile,"%s/.icon.8.%s",pathname,icon.filename);

	extension = get_extension(icon.filename);

	if ((fd = open(iconfile, O_WRONLY | O_CREAT)) < 0) 
	{
	    sprintf(temp_msg,
			"File %s can not be saved as icon file !!!\n",iconfile);
	    C_error_message(temp_msg);
	    return C_ERROR;			
	}
	if (strcmp(extension,"slc") == 0) 
	{
	    /* write the magic number and the slice header information */
	    magic_num = C_SLICE_MAGIC;
	    write(fd,&magic_num, sizeof(int));
	    write(fd,&icon.slice_info, sizeof(Slice_Header_Info));
	}
	else 
	{
	    if (strcmp(extension,"tex") == 0) 
	    {
		/* write the magic number and the texture header information*/ 
		magic_num = C_TEXTURE_MAGIC;			
		write(fd,&magic_num, sizeof(int));
		write(fd,&icon.texture_info, sizeof(Texture_Header_Info));
	    }
	    else 
	    {
		/* write the magic number and the image header informatino */ 
		magic_num = C_IMAGE_MAGIC;
		write( fd, &magic_num, sizeof(int) );		
		write( fd, &(icon.image_info.width),sizeof(int));  
       		write( fd, &(icon.image_info.height),sizeof(int));
       		write( fd, &(icon.image_info.depth), sizeof(int) );
       		write( fd, &(icon.image_info.image_accuracy), 
						sizeof(C_ImageAccuracy));
       		write( fd, &(icon.image_info.compute_time), sizeof(float) );
       		write( fd, &(icon.image_info.render_type),  
						sizeof(C_RenderingType) );

		switch ( icon.image_info.render_type )
		{
		  case C_RAYTRACE_RENDERING:
		  case C_PARC_RAYTRACE_RENDERING:
			write( fd, &(icon.image_info.compute_shadows), 
						sizeof(int) );
			write( fd, &(icon.image_info.levels_of_reflection), 
						sizeof(int) );
			write( fd, &(icon.image_info.levels_of_transmission), 
						sizeof(int) );
			write( fd, &(icon.image_info.levels_of_indirect_light), 
						sizeof(int) );
			break;
		}
		write(fd, &(icon.image_info.compress_type), 
						sizeof(C_CompressionType));
	    } 
	}

	/* write the image data into the file */
	if (machine_24_bit(icon.button))
	    write(fd,icon.icon_24_data, C_ICON_IMAGE_WIDTH*C_ICON_IMAGE_HEIGHT*
		      sizeof(unsigned int));
	else
	    write(fd,icon.icon_8_data, C_ICON_IMAGE_WIDTH*C_ICON_IMAGE_HEIGHT*
		      sizeof(unsigned char));
	close(fd);

	/* make sure the newly created file is readable */
	sprintf(command,"chmod 555 %s",iconfile);
	system(command);
	return (C_OK);
}    


/*
 *    Procedure Name: read_icon_data
 *      Return Value: int
 *   Input Variables: icon     - the icon structure
 *                    pathname - the path name of the icon data
 *
 *  Output Variables: none
 *  Update Variables: icon
 *  Global Variables: none
 *       Description: This function will read in a icon file which contains
 *		      the icon of the current file.
 *
 */

int read_icon_data(icon,pathname)
Icon_Info *icon;
char *pathname;
{
  extern int 	machine_24_bit();
  extern char 	*get_extension();
  extern void 	C_error_message();

  int	fd;
  char  icon_filename[C_MAX_STRING];
  char	*extension;
  char	temp_msg[C_MAX_STRING];
  int	magic_num;
  
	extension = get_extension(icon->filename);

	if(machine_24_bit(icon->button))
            sprintf(icon_filename, "%s/.icon.24.%s", 
			pathname, icon->filename );
	else
	    sprintf( icon_filename, "%s/.icon.8.%s", 
		        pathname, icon->filename );

	if ((fd = open(icon_filename,O_RDONLY)) < 0) 
	/* no error message needed because its only icon file */
	{
	    return(C_ERROR);
	}

	if (strcmp(extension,"slc")==0)
	{
	    read(fd, &(magic_num), sizeof(int));

	    /* return if the magic number didn't match */
	    if (magic_num != C_SLICE_MAGIC)
	    {
		close(fd);
		return C_ERROR;
	    }

	    /* read the slice header information */
	    read(fd,&(icon->slice_info), sizeof(Slice_Header_Info));
	}
	else if(strcmp(extension,"tex") == 0)
	{
	    read(fd, &(magic_num), sizeof(int));

            /* return if the magic number didn't match */
	    if (magic_num != C_TEXTURE_MAGIC)
	    {
		close(fd);
		return C_ERROR;
	    }
	    /* read the texture header information */
	    read(fd,&(icon->texture_info),sizeof(Texture_Header_Info));
	}
	else if ((strcmp(extension,"img") == 0) || (strcmp(extension,"fun")==0))
	{
	    read( fd, &magic_num, sizeof(int) );		
            /* return if the magic number didn't match */
	    if (magic_num != C_IMAGE_MAGIC)
	    {
		close(fd);
		return C_ERROR;
	    }

	    read( fd, &(icon->image_info.width), sizeof(int) );
	    read( fd, &(icon->image_info.height), sizeof(int) );
	    read( fd, &(icon->image_info.depth), sizeof(int) );		
	    read( fd, &(icon->image_info.image_accuracy), 
						sizeof(C_ImageAccuracy));
	    read( fd, &(icon->image_info.compute_time), sizeof(float) );
	    read( fd, &(icon->image_info.render_type), 
						sizeof( C_RenderingType ) );
	
	    switch ( icon->image_info.render_type )
	    {
		case C_RAYTRACE_RENDERING:
		case C_PARC_RAYTRACE_RENDERING:
		    read( fd, &(icon->image_info.compute_shadows),sizeof(int));
		    read( fd, &(icon->image_info.levels_of_reflection), 
					sizeof(int) );
		    read( fd, &(icon->image_info.levels_of_transmission), 
					sizeof(int) );
		    read( fd, &(icon->image_info.levels_of_indirect_light), 
					sizeof(int) );
		    break;
	    }

	    read( fd, &(icon->image_info.compress_type), 
						sizeof(C_CompressionType) );
	} 

	if (machine_24_bit(icon->button))
	{
	    if ((icon->icon_24_data = (unsigned int *) malloc(
						C_ICON_IMAGE_WIDTH *
				    		C_ICON_IMAGE_HEIGHT *
						sizeof(unsigned int)))==NULL)
	    {
		C_error_message("Not enough memory to store icon data !!! \n");
		return(C_ERROR);
	    }
	    /* read the 24 bit image data */
	    read(fd,icon->icon_24_data,
		 C_ICON_IMAGE_WIDTH*C_ICON_IMAGE_HEIGHT*sizeof(unsigned int));
	}
	else
	{
	    if ((icon->icon_8_data =(unsigned char *) malloc(
						C_ICON_IMAGE_WIDTH * 
				  		C_ICON_IMAGE_HEIGHT *
						sizeof(unsigned char)))==NULL)
	    {
		C_error_message("Not enough memory to store icon data !!!\n");
		return(C_ERROR);
	    }
	    /* read the 8 bit image data */ 
	    read(fd,icon->icon_8_data,
		 C_ICON_IMAGE_WIDTH*C_ICON_IMAGE_HEIGHT*sizeof(unsigned char));
	}
	close(fd);
	return(C_OK);
}

