/*
 *----------------------------------------------------------------------
 *
 * PROGRAM       : gksmc
 *
 * FILE          :  annexe_7.c
 *
 * CONTENTS	 : Routines to read items from an Annex E metafile which
 *	           are in group E.7 of the Annex - items for output
 *	           primitive attributes.
 *
 * ANNEX E ITEMS : Text Font and Precision
 *		   Character Vectors
 *		   Text Alignment
 *		   Fill Area Style Index
 *		   Pattern Vectors
 *		   Fill Pattern Reference Point
 *		   Aspect Source Flags
 *		   (see set_int_param and set_real_param for remaining
 *		    items)
 *
 * GLOBALS USED  : MF_infile, MF_infile, Encoding
 *
 * DATE          : 26th April 1988
 *
 *----------------------------------------------------------------------
 */

#include <stdio.h>
#include <math.h>
#include "annexe.h"
#include "cgm.h"
#include "defns.h"
#include "tables.h"

extern FILE *MF_infile,
       *MF_outfile;


/*
 *-------------------------------------------------------------------------
 * AEset_int_param:
 *	Used for all items which have just one integer valued parameter.
 * The procedure's parameter is used to specify the range of legal values
 * the item's parameter can take :-
 *	NON_NEGATIVE >= 0,  POSITIVE > 0 ,  ANY any values
 * Annex E items : Line Index, Line Type, Line Colour
 *		   Marker Index, Marker Type, Marker Colour
 *		   Text Index, Text Colour, Fill Index, Fill Colour
 *		   Pick Identifier, Create Segment, Delete Segment
 *-------------------------------------------------------------------------
 */
AEset_int_param(range)
	int     range;
{
	int     param;

	read_string_int(MF_infile, &param, DEFAULT);
	if (range == POSITIVE && param < 1)
		write_error(27);
	else if (range == NON_NEGATIVE && param < 0)
		write_error(28);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, param);
}


/*
 *-------------------------------------------------------------------------
 * AEset_real_param:
 *	Used for all items which have just one real valued parameter.
 * The procedure's parameter is used to specify the range of legal values
 * for the item's parameter :-
 *	NON_NEGATIVE >= 0,  POSITIVE > 0 ,  ANY any values
 * Annex E items : Line Width, Marker Size,
 *		   Character Expansion Factor, Character Spacing
 *-------------------------------------------------------------------------
 */
AEset_real_param(range)
	int     range;
{
	double  param;

	read_string_real(MF_infile, &param, DEFAULT);
	if (range == POSITIVE && param <= 0.0)
		write_error(29);
	else if (range == NON_NEGATIVE && param < 0.0)
		write_error(30);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_real(MF_outfile, param);
}


/*
 *-------------------------------------------------------------------------
 * AEtext_font_prec:
 *	The Annex E item Set Text Font and Precision is translated to the
 * separate CGM items : Set Text Font, and Set Text Precision.
 *-------------------------------------------------------------------------
 */
AEtext_font_prec()
{
	int     font,
	        precision;

	read_string_int(MF_infile, &font, DEFAULT);
	read_string_int(MF_infile, &precision, DEFAULT);
	check_param_range(precision, 0, 2, 34);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, font);
	write_separator(MF_outfile, TERMINATOR);
	write_item_name(MF_outfile, CGM_TABLE, TEXTPREC);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, E_TEXTPREC, precision);
}


/*
 *-------------------------------------------------------------------------
 * sqr:
 *	Returns the square of its argument. Used by AEchar_vectors.
 *-------------------------------------------------------------------------
 */
double
sqr(value)
	double  value;
{
	return (value * value);
}


/*
 *-------------------------------------------------------------------------
 * AEchar_vectors:
 *	The Annex E item Character Vectors is translated to the CGM items :
 * Character Height, and Character Orientation.
 *-------------------------------------------------------------------------
 */
AEchar_vectors()
{
	Point   char_height,
	        char_width;
	double  height,
	        sqr(),
	        sqrt();

	read_point(MF_infile, &char_height);
	read_point(MF_infile, &char_width);
	height = sqrt(sqr(char_height.x) + sqr(char_height.y));
	write_item_name(MF_outfile, CGM_TABLE, CHARHEIGHT);
	write_separator(MF_outfile, SOFTSEP);
	write_vdc(MF_outfile, height);
	write_separator(MF_outfile, TERMINATOR);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_delta_pair(MF_outfile, char_height);
	write_separator(MF_outfile, SEP);
	write_delta_pair(MF_outfile, char_width);
}


/*
 *-------------------------------------------------------------------------
 * AEtext_align:
 *	The CGM Text Alignment item has the first two parameters the same
 * as Annex E, but continuous alignment can be selected - the last two
 * parameters being real values for horizontal and vertical alignment,
 * in that order. Since continuous alignment will never be selected these
 * are just set with dummy values (0.0).
 *-------------------------------------------------------------------------
 */
AEtext_align()
{
	int     horiz_align,
	        vert_align;

	read_string_int(MF_infile, &horiz_align, DEFAULT);
	check_param_range(horiz_align, 0, 3, 35);
	read_string_int(MF_infile, &vert_align, DEFAULT);
	check_param_range(horiz_align, 0, 5, 36);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, E_HORIZ, horiz_align);
	write_separator(MF_outfile, SEP);
	write_enum_value(MF_outfile, E_VERT, vert_align);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, 0.0);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, 0.0);
}


/*
 *-------------------------------------------------------------------------
 * AEfill_style_ind:
 *	The Annex E item Fill Area Style Index is used to set the Pattern
 * Index or Hatch Index, depending on the fill area interior style
 * selected. CGM has two separate items Pattern Index and Hatch Index,
 * these are both called with the parameter from the Annex E item.
 *-------------------------------------------------------------------------
 */
AEfill_style_ind()
{
	int     style_index;

	read_string_int(MF_infile, &style_index, DEFAULT);	/* PATINDEX */
	if (style_index < 1)
		write_error(26);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, style_index);
	write_separator(MF_outfile, TERMINATOR);
	write_item_name(MF_outfile, CGM_TABLE, HATCHINDEX);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, style_index);
}


/*
 *-------------------------------------------------------------------------
 * AEpatt_vectors:
 *	The Pattern Vectors Annex E item translates into the Pattern Size
 * CGM item, with the parameters unchanged.
 *-------------------------------------------------------------------------
 */
AEpatt_vectors()
{
	Point   patt_width,
	        patt_height;

	read_point(MF_infile, &patt_height);
	read_point(MF_infile, &patt_width);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_delta_pair(MF_outfile, patt_height);
	write_separator(MF_outfile, SEP);
	write_delta_pair(MF_outfile, patt_width);
}


/*
 *-------------------------------------------------------------------------
 * AEpatt_ref_point:
 *	Pattern Reference Point has the same form in Annex E and CGM.
 *-------------------------------------------------------------------------
 */
AEpatt_ref_point()
{
	Point   pt;

	read_point(MF_infile, &pt);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_point(MF_outfile, pt);
}


/*
 *-------------------------------------------------------------------------
 * AEasf:
 *	Annex E has 13 Aspect Source Flags, CGM has 18.
 * Annexe E : LineType, LineWidth, LineColour, MarkerType, MarkerSize,
 *	      MarkerColour, TextFontandPrec, CharExp, CharSpace,
 *	      TextColour, IntStyle, FillColour, IntStyleInd.
 * CGM      : LineType, LineWidth, LineColour, MarkerType, MarkerSize,
 *	      MarkerColour, TextFont, TextPrec, CharExp, CharSpace,
 *	      TextColour, IntStyle, FillColour, HatchIndex, PatIndex,
 *	      EdgeType, EdgeWidth, EdgeColour.
 *-------------------------------------------------------------------------
 */
AEasf()

{
	int     asf_list[13],
	        flag,
	        i;

	read_int_list(MF_infile, asf_list, 13);
	for (i = 0; i < 13; i++)
		check_param_range(asf_list[i], 0, 1, 37);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	if (same_flags(asf_list, 0, 12, &flag))
	{
		if (Encoding == CLEAR_TEXT)
			write_enum_value(MF_outfile, E_PSEUDOASF, 0);
		else
			write_int(MF_outfile, CE_ALL_ASF);
		write_separator(MF_outfile, SEP);
		write_enum_value(MF_outfile, E_ASFTYPE, flag);
	}
	else
	{
		check_flags(asf_list, 0, 2, 1);
		check_flags(asf_list, 3, 5, 2);
		check_flags(asf_list, 6, 9, 3);
		check_flags(asf_list, 10, 12, 4);
	}
}


/*
 *-------------------------------------------------------------------------
 * same_flags:
 *	Checks whether the ASF's in the range lower-upper are the same, if
 * so the flag setting is stored in val, and 'true' is returned, 'false'
 * otherwise.
 *-------------------------------------------------------------------------
 */
same_flags(list, lower, upper, val)
	int    *list,
	        lower,
	        upper,
	       *val;
{
	int     i,
	        eq_flag = 1;

	*val = list[lower];
	for (i = lower + 1; i <= upper; i++)
		eq_flag = (list[i] != *val) ? 0 : eq_flag;
	return (eq_flag);
}


/*
 *-------------------------------------------------------------------------
 * check_flags:
 *	Checks whether the ASF's in the range lower-upper are the same,
 * if so the Pseudo ASF indexed by the parameter Eno is used, else each
 * flag within the range is set separately.
 *-------------------------------------------------------------------------
 */
check_flags(list, lower, upper, Eno)
	int    *list,
	        lower,
	        upper,
	        Eno;
{
	int     val,
	        i;

	if (same_flags(list, lower, upper, &val))
	{
		if (Encoding == CLEAR_TEXT)
			write_enum_value(MF_outfile, E_PSEUDOASF, Eno);
		else
			write_int(MF_outfile, CE_ALL_ASF - Eno);
		write_separator(MF_outfile, SEP);
		write_enum_value(MF_outfile, E_ASFTYPE, val);
		if (upper != 12)
			write_separator(MF_outfile, SEP);
	}
	else
	{
		for (i = lower; i <= upper; i++)
		{
			if (Encoding == CLEAR_TEXT)
			{
				write_enum_value(MF_outfile, E_ASFNAME, i);
				write_separator(MF_outfile, SEP);
				write_enum_value(MF_outfile, E_ASFTYPE, list[i]);
				if (i != 12)
					write_separator(MF_outfile, SEP);
				if (i == 6)
				{	/* Text font and precision */
					write_enum_value(MF_outfile, E_ASFNAME, 13);
					write_separator(MF_outfile, SEP);
					write_enum_value(MF_outfile, E_ASFTYPE, list[i]);
					write_separator(MF_outfile, SEP);
				}
				if (i == 11)
				{	/* Style index -> Hatch and pattern */
					write_enum_value(MF_outfile, E_ASFNAME, 14);
					write_separator(MF_outfile, SEP);
					write_enum_value(MF_outfile, E_ASFTYPE, list[i]);
					write_separator(MF_outfile, SEP);
				}
			}
			else
			{
				if (i < 6)
				{
					write_int(MF_outfile, i);
					write_int(MF_outfile, list[i]);
				}
				else if (i == 6)
				{	/* Text font and precision */
					write_int(MF_outfile, i);
					write_int(MF_outfile, list[i]);
					write_int(MF_outfile, 7);
					write_int(MF_outfile, list[i]);
				}
				else if (i < 11)
				{
					write_int(MF_outfile, i + 1);
					write_int(MF_outfile, list[i]);
				}
				else if (i == 11)
				{	/* Style index */
					write_int(MF_outfile, 13);
					write_int(MF_outfile, list[i]);
					write_int(MF_outfile, 14);
					write_int(MF_outfile, list[i]);
				}
				else
				{	/* Fill Colr Asf */
					write_int(MF_outfile, 12);
					write_int(MF_outfile, list[i]);
				}
			}
		}
	}
}
