/*
 *----------------------------------------------------------------------
 *
 * PROGRAM	 : gksmc
 *
 * FILE		 : annexe_5.c
 *
 * CONTENTS	 : Routines to read items from an Annex E metafile
 *		   which are in groups E.5 and E.6 - control items and
 *		   items for output primitives respectively.
 *
 * ANNEX E ITEMS : End Item
 *		   Clear Workstation
 *		   Redraw All Segments
 *		   Set Deferral State
 *		   Message
 *		   Escape
 *		   Polyline
 *		   Polymarker
 *		   Fill Area
 *		   Text
 *		   Cell Array
 *		   General Drawing Primitive (GDP)
 *
 * GLOBALS USED  : MF_infile, MF_outfile, item_no, Encoding,
 *		   PointListForm
 *
 * DATE		 : 26th April 1988
 *
 *----------------------------------------------------------------------
 */

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

extern FILE *MF_infile,
       *MF_outfile;
extern int item_no;


/*
 *-------------------------------------------------------------------------
 * AEend_item:
 *	Last item in an Annex E metafile. End of Picture and End of
 * Metafile items written to the CGM metafile.
 *-------------------------------------------------------------------------
 */
AEend_item()
{
	write_item_name(MF_outfile, CGM_TABLE, ENDPIC);
	write_separator(MF_outfile, TERMINATOR);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
}


/*
 *-------------------------------------------------------------------------
 * AEclear_wks:
 *	Clear workstation. This translates to the CGM sequence :-
 * Make Picture Current ; Prepare View Surface ; Delete All Segments.
 *-------------------------------------------------------------------------
 */
AEclear_wks()
{
	int     cc_flag;	/* Clearing control flag */

	read_string_int(MF_infile, &cc_flag, DEFAULT);
	check_param_range(cc_flag, 0, 1, 31);
	write_item_name(MF_outfile, CGM_TABLE, MAKEPICCUR);
	write_separator(MF_outfile, TERMINATOR);
	CGMprep_surface(cc_flag);
	write_item_name(MF_outfile, CGM_TABLE, DELETEALLSEG);
}


/*
 *-------------------------------------------------------------------------
 * AEredraw_segs:
 *	Redraw all segments. Translates to the CGM sequence :-
 * Make Picture Current ; Prepare View Surface ; Redraw All Segments.
 *-------------------------------------------------------------------------
 */
AEredraw_segs()
{
	write_item_name(MF_outfile, CGM_TABLE, MAKEPICCUR);
	write_separator(MF_outfile, TERMINATOR);
	CGMprep_surface(CONDITIONAL);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
}


/*
 *-------------------------------------------------------------------------
 * AEset_enum_param:
 *	Used for all items which have have a single enumerated parameter.
 * The parameter for this procedure gives the row in the enumeration
 * table to be used, the parameter read from the input metafile gives the
 * entry in that row, which is a character string. The string is written
 * to the file for clear text, the actual value for character encoding.
 * Annex E Items : Update Workstation,
 *		   Text Path,
 *		   Fill Area Interior Style
 *-------------------------------------------------------------------------
 */
AEset_enum_param(enum_no)
	int     enum_no;
{
	int     param;

	read_string_int(MF_infile, &param, DEFAULT);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, enum_no, param);
}


/*
 *-------------------------------------------------------------------------
 * AEdef_state:
 *	Set Deferral State. This translates to the CGM sequence :-
 * Deferral Mode ; Implicit Segment Regeneration Mode.
 * The first parameter of the Annex E item can take values :-
 * 0 = ASAP ; 1 = BNIG ; 2 = BNIL ; 3 = ASTI
 * The CGM deferral mode parameter can take values :- ASAP, BNI and ASTI.
 * BNIG and BNIL are both mapped to BNI.
 *-------------------------------------------------------------------------
 */
AEdef_state()
{
	int     def_mode,
	        regen_mode;

	read_string_int(MF_infile, &def_mode, DEFAULT);
	check_param_range(def_mode, 0, 3, 32);
	read_string_int(MF_infile, &regen_mode, DEFAULT);
	check_param_range(regen_mode, 0, 1, 33);
	if (regen_mode > 1)
		regen_mode--;
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, E_DEFMODE, def_mode);
	write_separator(MF_outfile, TERMINATOR);
	write_item_name(MF_outfile, CGM_TABLE, IMPLSEGREGENMODE);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, E_DEFREGEN, regen_mode);
}


/*
 *-------------------------------------------------------------------------
 * AEmessage:
 *	The Annex E Message item does not have an action parameter. The
 * CGM message item is written with the action parameter set to No Action.
 *-------------------------------------------------------------------------
 */
AEmessage()
{
	int     string_len;
	char   *message_string;

	read_string_int(MF_infile, &string_len, DEFAULT);
	message_string = (char *) calloc(string_len + 1, sizeof(char));
	read_string(MF_infile, message_string, string_len);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_enum_value(MF_outfile, E_MESSAGE, NOACTION);
	write_separator(MF_outfile, HARDSEP);
	write_CGM_string(MF_outfile, message_string, DEFAULT);
	cfree(message_string);
}


/*
 *-------------------------------------------------------------------------
 * AEescape:
 *	The lists of reals and integers in the Annex E item do not occur
 * in the CGM escape item. These are written in the 'datarecord' string.
 * For details of the format of this string see write_datarecord in
 * CGMutils.c
 *-------------------------------------------------------------------------
 */
AEescape()
{
	int     function_id,
	        num_ints,
	        num_reals;
	int    *int_data;
	double *real_data;

	read_string_int(MF_infile, &function_id, DEFAULT);
	read_string_int(MF_infile, &num_ints, DEFAULT);
	read_string_int(MF_infile, &num_reals, DEFAULT);
	int_data = (int *) calloc(num_ints, sizeof(int));
	read_int_list(MF_infile, int_data, num_ints);
	real_data = (double *) calloc(num_reals, sizeof(double));
	read_real_list(MF_infile, real_data, num_reals);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, function_id);
	write_separator(MF_outfile, HARDSEP);
	write_datarecord(MF_outfile, num_ints, int_data, num_reals, real_data);
	cfree(real_data);
	cfree(int_data);
}


/*
 *-------------------------------------------------------------------------
 * AEpolypoint:
 *	Handles Polymarker, Polyline and Fill Area items - these translate
 * to Marker, Line and Polygon respectively. In the Clear Text encoding,
 * the incremental forms of these items can be selected using a defaults
 * file. See defaults.c for details.
 *-------------------------------------------------------------------------
 */
AEpolypoint()
{
	int     num_points;
	Point  *point_list;

	read_string_int(MF_infile, &num_points, DEFAULT);
	point_list = (Point *) calloc(num_points, sizeof(Point));
	read_point_list(MF_infile, point_list, num_points);
	if ((num_points < 1 && item_no == POLYMARKER) ||
		(num_points < 2 && item_no == POLYLINE) ||
		(num_points < 3 && item_no == FILL_AREA))
		write_error(1);
	if (Encoding == CLEAR_TEXT && PointListForm == LIST_INCR)
		write_item_name(MF_outfile, CGM_TABLE, 47 + item_no);
	else
		write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_point_list(MF_outfile, point_list, num_points);
	cfree(point_list);
}


/*
 *-------------------------------------------------------------------------
 * AEtext:
 *	The only difference between the Text item in Annex E and CGM is
 * that the CGM item has an extra parameter which says whether further
 * text can be appended. This is set to FINAL since Annex E does not
 * have an Append Text item.
 *-------------------------------------------------------------------------
 */
AEtext()
{
	int     num_chars;
	Point   start_pt;
	char   *text_string;

	read_point(MF_infile, &start_pt);
	read_string_int(MF_infile, &num_chars, DEFAULT);
	text_string = (char *) calloc(num_chars + 1, sizeof(char));
	read_string(MF_infile, text_string, num_chars);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_point(MF_outfile, start_pt);
	write_separator(MF_outfile, SEP);
	write_enum_value(MF_outfile, E_TEXTEND, FINAL);
	write_separator(MF_outfile, HARDSEP);
	write_CGM_string(MF_outfile, text_string, DEFAULT);
	cfree(text_string);
}


/*
 *-------------------------------------------------------------------------
 * AEcell_array:
 *	Cell Array in Annex E maps straight to the same element in CGM.
 *-------------------------------------------------------------------------
 */
AEcell_array()
{
	Point   P,
	        Q,
	        R;
	int     num_cols,
	        num_rows,
	        num_indices;
	int    *colr_indices;

	read_point(MF_infile, &P);
	read_point(MF_infile, &Q);
	read_point(MF_infile, &R);
	read_string_int(MF_infile, &num_cols, DEFAULT);
	read_string_int(MF_infile, &num_rows, DEFAULT);
	num_indices = num_cols * num_rows;
	colr_indices = (int *) calloc(num_indices, sizeof(int));
	read_int_list(MF_infile, colr_indices, num_indices);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_point(MF_outfile, P);
	write_separator(MF_outfile, SEP);
	write_point(MF_outfile, Q);
	write_separator(MF_outfile, SEP);
	write_point(MF_outfile, R);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, num_cols);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, num_rows);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, 0);	/* use default colr precision */
	write_cell_row(MF_outfile, colr_indices, num_indices);
	cfree(colr_indices);
}


/*
 *-------------------------------------------------------------------------
 * AEgdp:
 *	The CGM gdp item is the same as the Annex E, except that is has
 * a 'datarecord' parameter where Annex E has a list of reals and a list
 * of integers. These lists are written in the datarecord string. See
 * write_datarecord in CGMutils.c for details of the format of this string.
 *-------------------------------------------------------------------------
 */
AEgdp()
{
	int     gdp_id,
	        num_points,
	        num_ints,
	        num_reals,
	       *int_data;
	Point  *point_list;
	double *real_data;

	read_string_int(MF_infile, &gdp_id, DEFAULT);
	read_string_int(MF_infile, &num_points, DEFAULT);
	read_string_int(MF_infile, &num_ints, DEFAULT);
	read_string_int(MF_infile, &num_reals, DEFAULT);
	read_point_list(MF_infile, point_list, num_points);
	int_data = (int *) calloc(num_ints, sizeof(int));
	read_int_list(MF_infile, int_data, num_ints);
	real_data = (double *) calloc(num_reals, sizeof(double));
	read_real_list(MF_infile, real_data, num_reals);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, gdp_id);
	write_separator(MF_outfile, SEP);
	write_point_list(MF_outfile, point_list, num_points);
	write_separator(MF_outfile, HARDSEP);
	write_datarecord(MF_outfile, num_ints, int_data, num_reals, real_data);
	cfree(int_data);
	cfree(real_data);
}
