/**
 **	$Header: /import/dev-vis/image/imtools/v2.0/imtools/src/RCS/imformats.c,v 1.7 92/12/01 14:05:01 nadeau Exp $
 **	Copyright (c) 1989-1992  San Diego Supercomputer Center (SDSC)
 **		San Diego, California, USA
 **
 **	Users and possessors of this source code are hereby granted a
 **	nonexclusive, royalty-free copyright and design patent license to
 **	use this code in individual software.  License is not granted for
 **	commercial resale, in whole or in part, without prior written
 **	permission from SDSC.  This source is provided "AS IS" without express
 **	or implied warranty of any kind.
 **
 **	For further information contact:
 **		E-Mail:		info@sds.sdsc.edu
 **
 **		Surface Mail:	Information Center
 **				San Diego Supercomputer Center
 **				P.O. Box 85608
 **				San Diego, CA  92138-5608
 **				(619) 534-5000
 **/

#define HEADER	"    $Header: /import/dev-vis/image/imtools/v2.0/imtools/src/RCS/imformats.c,v 1.7 92/12/01 14:05:01 nadeau Exp $"

/**
 **  FILE
 **	imformats.c	-  Image file known format listing
 **
 **  PROJECT
 **	IM		-  Image Manipulation Tools
 **
 **  DESCRIPTION
 **	imformats.c lists to stdout all of the image file formats currently
 **	understood by the image library.
 **
 **  PUBLIC CONTENTS
 **			d =defined constant
 **			f =function
 **			m =defined macro
 **			t =typedef/struct/union
 **			v =variable
 **			? =other
 **
 **	main		f  main program
 **
 **  PRIVATE CONTENTS
 **	toolCommand	g  command info for arg parsing pkg
 **	toolOptions	g  option info for arg parsing pkg
 **
 **	printFormat	f  print a format entry
 **
 **  HISTORY
 **	$Log:	imformats.c,v $
 **	Revision 1.7  92/12/01  14:05:01  nadeau
 **	Updated to use new ImFileFormats table structure.
 **	
 **	Revision 1.6  92/08/31  17:07:55  vle
 **	Updated copyright notice.
 **	
 **	Revision 1.5  92/05/28  12:54:07  vle
 **	Added a function prototype for printFormats().
 **	
 **	Revision 1.4  91/10/03  13:20:41  nadeau
 **	Update to version 2.0 of arg parsing package.
 **	Minor printing cosmetics.
 **	
 **	Revision 1.3  91/03/11  14:39:05  nadeau
 **	Updated to use new file formats table and print more info.
 **	
 **	Revision 1.2  91/02/05  16:41:55  nadeau
 **	Fixed a minor printing bug in lists of equivalent format names.
 **	
 **	Revision 1.1  90/07/02  13:16:42  nadeau
 **	Initial revision
 **	
 **/

#include "imtools.h"


extern int printFormat();



/*
 *  GLOBALS
 *	toolCommand		-  command info for arg parsing pkg
 *	toolOptions		-  option info for arg parsing pkg
 *
 *  DESCRIPTION
 *	toolCommand describes the command and gives the help text.
 *
 *	toolOptions lists the arg options accepted.
 */

private ArgCommand toolCommand =
{
	/* command name */		"imformats",

	/* major version # */		IMTOOLSMAJOR,
	/* minor version # */		IMTOOLSMINOR,
	/* subminor version # */	IMTOOLSSUBMINOR,

	/* -help pre-option list information				*/
"%command lists information on the image file formats supported by the SDSC\n\
Image Tools.\n\
",

	/* -help post-option list information				*/
	NULL,				/* filled in later on		*/

	/* -fullhelp pre-option list information			*/
	NULL,				/* Use same message as for -help*/
	/* -fullhelp post-option list information			*/
	NULL,				/* Use same message as for -help*/

	ARGFNONE,			/* No special flags		*/
	"[options...]",
	"[options...]",
	"SDSC Image Tools, October 1992.",
	"Copyright (c) 1989-1992  San Diego Supercomputer Center (SDSC), CA, USA",
	NULL,				/* filled in later on		*/
	NULL,				/* filled in later on		*/
};

private char *toolHelp = "\n\
Typical Invocations:\n\
    List formats supported:\n\
        %command\n\
    List details of support for TIFF and GIF formats:\n\
        %command -long -tiff -gif\n\
    List extensive details on support for TIFF and GIF formats:\n\
        %command -long -long -tiff -gif\n\
";

private char *toolFullHelp = "\n\
Output:\n\
    With no options, %command prints a table to stdout listing the names of\n\
    all formats supported by the SDSC Image Tools.\n\
\n\
    -long expands the table to include information on the format's creator,\n\
    other names the format is known by, and a summary of what format variants\n\
    are supported for read and write operations.\n\
\n\
    Given twice, -long further expands on the format table by exchanging the\n\
    format variant summary for an explicit and detailed list of what variants\n\
    of the file format can be read and written.\n\
";

private char *toolNote = "\n\
Additional Help:\n\
    This is an abbreviated help listing.  For a full listing of options,\n\
    including a list of image file formats supported, type:\n\
        %command -fullhelp\n\
";

private ArgOption toolOptions[] =
{
	{ "long", NULL, "Show a long form of the information",
	  ARGFMULTIPLE, 0, 0, ARGTNONE },
};
#define TOOLNOPTIONS	1

#define TOOLNEQUIVS	0
#if TOOLNEQUIVS == 0
private ArgEquiv *toolEquivs;
#else
private ArgEquiv toolEquivs[TOOLNEQUIVS] =
{
};
#endif






/*
 *  FUNCTION
 *	main	-  main program
 *
 *  DESCRIPTION
 *	The file format list is walked and printed to stdout.
 */

main( argc, argv )
	int argc;			/* Argument count		*/
	char *argv[];			/* Argument vector		*/
{
	int            longForm;	/* Use long form?		*/
	ImFileFormat **ppFmt;		/* Format list pointer		*/
	char          *pName;		/* Format name to get		*/
	char         **pNames;		/* Format name list pointer	*/
	int            i;		/* Counter			*/
	int            nOpt;		/* Number of options		*/
	int            nEquiv;		/* Number of equivalences	*/
	int	       noccur;		/* Number of occurrences	*/
	ArgOption     *options;		/* Argument options		*/
	ArgEquiv      *equivs;		/* Argument equivalent keywords	*/
	char	      *tmp;		/* Temp string			*/


	/*
	 *  Use the standard Image Tools user registration and feedback forms.
	 */
	toolCommand.arg_register = ImToolsRegister;
	toolCommand.arg_feedback = ImToolsFeedback;


	/*
	 *  Allocate space for the total help string for the tool.  Copy the
	 *  tool-specific help in, then concatenate on the generic help text
	 *  used by most of the image tools.
	 */
	if ( (tmp = (char *)malloc( sizeof( char ) * (strlen( toolNote ) +
		strlen( toolHelp ) + 1) )) == NULL )
	{
		perror( ImToolsProgram );
		exit( 1 );
	}
	strcpy( tmp, toolHelp );
	strcat( tmp, toolNote );
	toolCommand.arg_help2 = tmp;

	if ( (tmp = (char *)malloc( sizeof( char ) * ( strlen( toolHelp ) +
		strlen( toolFullHelp ) + 1) )) == NULL )
	{
		perror( ImToolsProgram );
		exit( 1 );
	}
	strcpy( tmp, toolHelp );
	strcat( tmp, toolFullHelp );
	toolCommand.arg_fullhelp2 = tmp;


	/*
	 *  Add the file formats to the argument and equivalences list
	 *  and parse the command-line arguments.
	 */
	ImToolsProgram = argv[0];
	nOpt = ImFileFormatOptions( TOOLNOPTIONS, toolOptions, &options );
	if ( nOpt == -1 )
	{
		ImPError( ImToolsProgram );
		exit( 1 );
	}
	nEquiv = ImFileFormatEquivs( 0, NULL, &equivs );
	if ( nEquiv == -1 )
	{
		ImPError( ImToolsProgram );
		exit( 1 );
	}
	nOpt = ArgParse( argc, argv, &toolCommand, nOpt, options,
		nEquiv, equivs );
	i = nOpt;
	longForm = ArgQNOccur( "long" );
	i -= longForm;


	/*
	 *  Print information on each selected format, or all of them if
	 *  none was selected.
	 */
	if ( i == 0 )
	{
		/*
		 *  No explicit list given.  Show everything.
		 */
		printf( "Format  Description\n" );
		printf( "------------------------------------------------------------------------\n" );
		for ( ppFmt = ImFileFormats; *ppFmt; ppFmt++ )
		{
			printFormat( *ppFmt, longForm );
		}
		exit( 0 );
	}

	/*
	 *  Explicit list given.  List them in the order given.
	 */
	if ( i != 1 )
	{
		printf( "Format  Description\n" );
		printf( "------------------------------------------------------------------------\n" );
	}

	for ( i = 0; i < nOpt; i++ )
	{
		pName = ArgQOpt( i, &noccur );

		if ( strcmp( pName, "long" ) == 0 )
			continue;

		for ( ppFmt = ImFileFormats; *ppFmt; ppFmt++ )
		{
			pNames = &(*ppFmt)->format_names[0];
			for ( ; *pNames; pNames++ )
			{
				if ( strcmp( *pNames, pName ) == 0 )
				{
					printFormat( *ppFmt, longForm );
					break;
				}
			}
			if ( *pNames )
				break;
		}
	}
}




/*
 *  FUNCTION
 *	printFormat	-  print a format entry
 *
 *  DESCRIPTION
 *	The format's information is printed out nicely.
 */

private int				/* Returns status		*/
printFormat( pFmt, longForm )
	ImFileFormat *pFmt;		/* Format list pointer		*/
	int           longForm;		/* Use long form?		*/
{
	char        **pNames;		/* Equivalenet names pointer	*/
	int           i;		/* Counter			*/
	char          buffer[80];	/* Output buffer		*/
	char	     *pBuffer;		/* Buffer pointer		*/
	char	     *pSupport;		/* Support message pointer	*/
	char	     *pSupport2;	/* Support message pointer	*/
	ImFileFormatReadMap *pRead;	/* Read map info		*/
	ImFileFormatWriteMap *pWrite;	/* Read map info		*/

	printf( "%-7s %s\n", pFmt->format_names[0], pFmt->format_help );

	if ( longForm == 0 )
		return ( 0 );

	pNames = &pFmt->format_names[1];
	if ( pNames != NULL && *pNames != NULL )
	{
		sprintf( buffer, "        a.k.a.:   %s",
			*pNames++ );
		for ( ; *pNames; pNames++ )
		{
			if ( (strlen( buffer )+2+strlen( *pNames )) >80)
			{
				printf( "%s,\n", buffer );
				strcpy( buffer, "          " );
			}
			else
				strcat( buffer, ", " );
			strcat( buffer, *pNames );
		}
		printf( "%s\n", buffer );
	}

	printf( "        Creator:  %s\n", pFmt->format_creator );

	if ( longForm == 1 )
	{
		/* Print the summary.					*/
		printf( "        Read support:\n" );
		pSupport = pFmt->format_readSupport;
		if ( pSupport == NULL )
			printf( "          None.\n" );
		else
			while ( *pSupport != '\0' )
			{
				pSupport2 = pSupport;
				while ( *pSupport != '\0' && *pSupport != '\n' )
					pSupport++;
				if ( *pSupport == '\0' )
					printf( "          %s\n", pSupport2 );
				else
				{
					*pSupport = '\0';
					printf( "          %s\n", pSupport2 );
					*pSupport = '\n';
					pSupport++;
				}
			}

		printf( "        Write support:\n" );
		pSupport = pFmt->format_writeSupport;
		if ( pSupport == NULL )
			printf( "          None.\n" );
		else
			while ( *pSupport != '\0' )
			{
				pSupport2 = pSupport;
				while ( *pSupport != '\0' && *pSupport != '\n' )
					pSupport++;
				if ( *pSupport == '\0' )
					printf( "          %s\n", pSupport2 );
				else
				{
					*pSupport = '\0';
					printf( "          %s\n", pSupport2 );
					*pSupport = '\n';
					pSupport++;
				}
			}
		printf( "\n" );
		return ( 0 );
	}

	/* Print the exact format read and write map.			*/
	printf( "        Read support:\n" );
	pRead = pFmt->format_readMap;
	if ( pRead == NULL )
		printf( "            None.\n" );
	else
	{
		printf( "            Type   #chan  #bits  CLT?  Alpha?  Compression  Interleaving\n" );
		printf( "            -----  -----  -----  ----  ------  -----------  -----------\n" );
		for ( ; pRead->map_inType != -1; pRead++ )
		{
			printf( "            " );
			switch ( pRead->map_inType )
			{
			case IMTYPEINDEX:
				printf( "index " );
				break;
			case IMTYPERGB:	
				printf( "rgb   " );
				break;
			case IMTYPE2D:	
				printf( "2D geometry\n" );
				continue;
			default:
				printf( "unknown?\n" );
				continue;
			}
			printf( " %-5d  %-5d", pRead->map_inNChannels,
				pRead->map_inChannelDepth );
			if ( pRead->map_inAttributes & IMCLTYES )
				printf( "  yes " );
			else
				printf( "  no  " );
			if ( pRead->map_inAttributes & IMALPHAYES )
				printf( "  yes    " );
			else
				printf( "  no     " );
			switch ( pRead->map_inAttributes & IMCOMPMASK )
			{
			case IMCOMPNO:	printf( " none       " ); break;
			case IMCOMPRLE:	printf( " RLE        " ); break;
			case IMCOMPLZW:	printf( " LZW        " ); break;
			case IMCOMPPB:	printf( " PackBits   " ); break;
			case IMCOMPDCT:	printf( " DCT        " ); break;
			}
			switch ( pRead->map_inAttributes & IMINTERMASK )
			{
			case IMINTERNO:	printf( "  none" ); break;
			case IMINTERLINE:printf( "  scanline" ); break;
			case IMINTERPLANE:printf( "  plane" ); break;
			}
			printf( "\n" );
		}
	}

	printf( "        Write support:\n" );
	pWrite = pFmt->format_writeMap;
	if ( pWrite == NULL )
		printf( "            None.\n" );
	else
	{
		printf( "            Type   #chan  #bits  CLT?  Alpha?  Compression  Interleaving\n" );
		printf( "            -----  -----  -----  ----  ------  -----------  -----------\n" );
		for ( ; pWrite->map_outType != -1; pWrite++ )
		{
			printf( "            " );
			switch ( pWrite->map_outType )
			{
			case IMTYPEINDEX:
				printf( "index " );
				break;
			case IMTYPERGB:	
				printf( "rgb   " );
				break;
			case IMTYPE2D:	
				printf( "2D geometry\n" );
				continue;
			default:
				printf( "unknown?\n" );
				continue;
			}
			printf( " %-5d  %-5d", pWrite->map_outNChannels,
				pWrite->map_outChannelDepth );
			if ( pWrite->map_outAttributes & IMCLTYES )
				printf( "  yes " );
			else
				printf( "  no  " );
			if ( pWrite->map_outAttributes & IMALPHAYES )
				printf( "  yes    " );
			else
				printf( "  no     " );
			switch ( pWrite->map_outAttributes & IMCOMPMASK )
			{
			case IMCOMPNO:	printf( " none       " ); break;
			case IMCOMPRLE:	printf( " RLE        " ); break;
			case IMCOMPLZW:	printf( " LZW        " ); break;
			case IMCOMPPB:	printf( " PackBits   " ); break;
			case IMCOMPDCT:	printf( " DCT        " ); break;
			}
			switch ( pWrite->map_outAttributes & IMINTERMASK )
			{
			case IMINTERNO:	printf( "  none" ); break;
			case IMINTERLINE:printf( "  scanline" ); break;
			case IMINTERPLANE:printf( "  plane" ); break;
			}
			printf( "\n" );
		}
	}

	printf( "\n" );
	return ( 0 );
}
