/*
 *----------------------------------------------------------------------
 *
 * PROGRAM	: gksmc
 *
 * FILE		: main.c
 *
 * CONTENTS	: The main body of the program, plus routines to read the
 *		  Annex E metafile header and write a CGM metafile and
 *		  picture header.
 *
 * GLOBALS USED : variables used to hold information from Annex E
 *		  header, Encoding, vdc_type, VDC_lower, VDC_upper,
 *		  NumColrBits, NumColrDefs, MinInt, MaxInt, MaxIntBits,
 *		  NumExpBits, SigPlaces, MinReal, MinRealCode, MaxReal,
 *		  MaxRealCode.
 *
 * DATE		: 24th April 1988
 *
 *---------------------------------------------------------------------
 */
#include <stdio.h>
#include <math.h>
#include "defns.h"
#include "tables.h"

char	GKSM_string[5];			/* GKSM in the Annex E definition */
char	author_string[41];		/* N	 */
char	date_string[9];			/* D	 */
int	version_number;			/* V    */
int	GKSM_bytes;			/* H    */
int	item_field_width;		/* T    */
int	data_length_field_width;	/* L    */
int	int_field_width;		/* I    */
int	real_field_width;		/* R    */
int	number_format;			/* F    */
int	real_rep;			/* RI   */
int	int_ZERO;			/* ZERO */
int	int_ONE;			/* ONE  */

FILE	*MF_infile,
	*MF_outfile;


/*
 *-------------------------------------------------------------------------
 * main:
 *	Opens the input and output metafiles and handles any flags given
 * on the command line. Any parameters set on the command line override
 * a setting in the defaults file.
 *	The item name tables are set up correctly for the encoding
 * selected, headers are read and written, then create_cgm is called to
 * perform the main body of the translation.
 *-------------------------------------------------------------------------
 */
main(argc, argv)
	int	argc;
	char	*argv[];
{
	FILE	*fopen();
	char	*in_name,
		*out_name;
	int	lcase_flg = 0,
		enc_flg = 0,
		arg_no;

	arg_no = 1;
	while (arg_no < argc)
	{
		argv++;
		if (argv[0][0] != '-')
		{
			if (MF_infile == NULL)
			{
				if ((MF_infile = fopen((in_name = *argv), "r"))
								== NULL)
				{
					fprintf(stderr,
						"Can't open %s for input\n",
						in_name);
					exit(1);
				}
			}
			else if (MF_outfile == NULL)
			{
				if ((MF_outfile=fopen((out_name = *argv),"w"))
								== NULL)
				{
					fprintf(stderr,
						"Can't open %s for output\n",
						out_name);
					exit(1);
				}
			}
			else
			{
				command_line_error();
			}
		}
		else
		{
			switch (argv[0][1])
			{
				case 'l':
					lcase_flg = 1;
					break;
				case 'd':
					read_defaults(*++argv);
					arg_no++;
					break;
				case 'c':
					if (argv[0][2] == 't')
						enc_flg = CLEAR_TEXT;
					else if (argv[0][2] == 'e')
						enc_flg = CHARACTER;
					else
						write_error(15);
					break;
				default:
					command_line_error();
			}
		}
		arg_no++;
	}
	if (MF_infile == NULL || MF_outfile == NULL)
		command_line_error();
	if (enc_flg)
		Encoding = enc_flg;
	if (lcase_flg && Encoding == CLEAR_TEXT)
		lower_tables();
	setup_item_tables();
	read_AE_header();
	write_CGM_header();
	create_cgm();
	fclose(MF_infile);
	fclose(MF_outfile);
}


/*
 *-------------------------------------------------------------------------
 * command_line_error:
 *	Called if the program is run with incorrect or missing arguments.
 *-------------------------------------------------------------------------
 */
command_line_error()
{
	fprintf(stderr, "usage : gksmc ");
	fprintf(stderr, "[ -l ]");
	fprintf(stderr, "[ -d defaults-file ]");
	fprintf(stderr, "[ -ct | -ce]\n");
	fprintf(stderr, "        input-metafile output-metafile\n");
	exit(1);
}


/*
 *-------------------------------------------------------------------------
 * read_AE_header:
 *	Reads in the header at the start of the Annex E metafile,
 * containing information about the source, date, and field widths for the
 * different types of data following. Various constraints fnd precisions
 * for data in the CGM are calculated.
 *-------------------------------------------------------------------------
 */
read_AE_header()
{
	double	tmp,
		power;
	int	i,
		int_pwr;
	char	str[5];
	char	dummy[23];

	read_string(MF_infile, GKSM_string, 4);
	read_string(MF_infile, author_string, 40);
	read_string(MF_infile, date_string, 8);
	read_string_int(MF_infile, &version_number, 2);
	read_string_int(MF_infile, &GKSM_bytes, 2);
	read_string_int(MF_infile, &item_field_width, 2);
	read_string_int(MF_infile, &data_length_field_width, 2);
	read_string_int(MF_infile, &int_field_width, 2);
	read_string_int(MF_infile, &real_field_width, 2);
	read_string_int(MF_infile, &number_format, 2);
	read_string_int(MF_infile, &real_rep, 2);

	if (real_rep == REAL_AS_INT)
	{
		read_string_int(MF_infile, &int_ZERO, 11);
		read_string_int(MF_infile, &int_ONE, 11);

		vdc_type    = VDC_INT;
		VDC_lower.x = int_ZERO;
		VDC_lower.y = int_ZERO;
		VDC_upper.x = int_ONE;
		VDC_upper.y = int_ONE;
	}
	else	/* ignore int-ONE and int-ZERO fields */
		read_string(MF_infile,dummy,22);

	strcpy(str, GKSM_string);
	conv_string_to_lcase(str);
	if (strcmp(str, "gksm"))
		write_error(22);
	GKSM_string[GKSM_bytes] = '\0';	/* GKSM string used in m'file */
	if (number_format == BINARY_FORMAT)
		write_error(2);
	int_pwr = (int) (power = log((double) colr_prec) / log((double) 2.0));
	NumColrBits = (int_pwr == power) ? int_pwr : int_pwr + 1;
	MaxInt = 0;
	for (i = 0; i < int_field_width; i++)
		MaxInt = MaxInt * 10 + 9;
	MinInt = -MaxInt / 10.0;
	tmp = log((double) MaxInt) / log((double) 2.0);
	MaxIntBits = ((int) tmp == tmp) ? (int) tmp : (int) tmp + 1;
	SigPlaces = real_field_width - 3;
	tmp = SigPlaces * LOG_10_ON_LOG_2;
	NumExpBits = ((int) tmp == tmp) ? (int) tmp : (int) tmp + 1;
	MaxReal = 0;
	for (i = 0; i < SigPlaces; i++)
		MaxReal = MaxReal * 10.0 + 9;
	MinReal = -MaxReal;
	tmp = log((double) MaxReal) / log((double) 2.0);
	MaxRealCode = ((int) tmp == tmp) ? (int) tmp : (int) tmp + 1;
	MinRealCode = NumExpBits;
}


/*
 *-------------------------------------------------------------------------
 * write_CGM_header:
 *	Writes the 'header' at the start of the CGM metafile. This
 * consists of 'begin metafile', setting various parameters then calling
 * start_picture.
 *-------------------------------------------------------------------------
 */
write_CGM_header()
{
	CGMbegin_metafile();
	CGMmetafile_version();
	if (include_mf_descr)
		CGMmetafile_description();
	if (include_mf_cat)
		CGMmetafile_category();
	CGMmetafile_element_list();
	CGMchar_coding_announcer();
	CGMinteger_precision();
	CGMreal_precision();
	CGMindex_precision();
	CGMcolour_precision();
	CGMsegment_priority_extent();
	CGMvdc_type();
	CGMmax_colour_index();
	start_picture();
	write_separator(MF_outfile, TERMINATOR);
}


/*
 *-------------------------------------------------------------------------
 * start_picture:
 *	Writes a 'picture header' to the CGM metafile. This consists of
 * 'begin picture', setting various parameters, then opening the picture.
 *-------------------------------------------------------------------------
 */
start_picture()
{
	CGMbegin_picture();
	CGMscaling_mode();
	CGMcolour_selection_mode();
	CGMline_width_spec_mode();
	CGMmarker_size_spec_mode();
	CGMvdc_extent();
	CGMbegin_picture_body();
	if (vdc_type == VDC_INT)
		CGMvdc_integer_precision();
	else
		CGMvdc_real_precision();
	CGMclip_rectangle(VDC_lower, VDC_upper);
	if (NumColrDefs > 0)
		write_colour_list(MF_outfile);
}
