/* EZGEM
   This program converts GEM files generated by UniTerm into the
   format wanted by EasyDraw.  The changes include rescaling and
   joining vectors into polylines.
   Don Rice / FXDDR@ALASKA.bitnet / CIS 72337,3417
*/

#include <stdio.h>
#include <fcntl.h>

#define XSCALE	6
#define XOFFS	2730
#define YSCALE	5
#define YOFFS	3276

short	inbuf[256], outbuf[256] =
{
#include <gemhead.h>
};

short	inptr, outptr;

struct
{
	short op, vert, parms, subop, x[128], y[128], p[128];
} incode;

short	newx[128], newy[128], nxy;
short	nvecs, nlines, nreads, nwrites;

short	startline[5] = { 5, 0, 1, 99, 80 },
	polyfill[17] = { 5, 0, 2, 99, 155, 1, 5, 0, 2, 99, 157, 0, 23,
	  0, 1, 99, 0 },
	polyline[4] = { 6, 2, 0, 99 },
	endline[5] = { 5, 0, 1, 99, 81 };
main()
{
	int old, new;
	short getmeta(), op;
	char fname[80];

	printf( "Name of UniTerm GEM file: " );
	gets( fname );
	if( (old = open( fname, O_RDONLY | O_RAW )) == -1 )
		terminate( "Unable to open input file." );
	printf( "Name of new GEM file: " );
	gets( fname );
	if( (new = open( fname, O_WRONLY | O_CREAT | O_RAW )) == -1 )
		terminate( "Unable to open output file." );

	init_files( old, new );
	while( (op = getmeta( old )) != 6 ) ;	/* Skip old header */
	wrvect( new );
	while( (op = getmeta( old )) != 4 )
	{
		if( op == -1 ) break;	/* EOF */
		if( op == 6 ) wrvect( new );
	}
	close( old );
	finish( new );
	close( new );
	printf( "\n%d vectors read; %d polylines written.\n", nvecs, nlines );
	terminate( "File conversion completed." );
}	/* main */

cpyvert( new )	/* Copy vertices to polyline list */
int new;
{
	short i, j;

	j = (nxy ? nxy-1 : 0 );
	for( i=0; i<incode.vert; i++ )
	{
		if( j > 127 )
		{
			wrpoly( new );
			newx[0] = newx[127];
			newy[0] = newy[127];
			j = 1;
		}
		newx[j] = incode.x[i];
		newy[j++] = incode.y[i];
	}
	nxy = j;
}	/* cpyvert */

finish( new )	/* Flush output buffer, write end of file */
int new;
{
	if( nxy > 0 ) wrpoly( new );
	wrshort( new, -1 );
	wrshort( new, 0 );
	wrshort( new, 0 );
	wrshort( new, 0 );
	if( outptr > 0 ) write( new, outbuf, 512 );
}	/* finish */

short getmeta( old )	/* Read new metafile operation */
int old;
{
	short i, getshort();

	incode.op = getshort( old );
	if( incode.op == -1 ) return( -1 );
	incode.vert = getshort( old );
	incode.parms = getshort( old );
	incode.subop = getshort( old );
	for( i=0; i<incode.vert; i++ )
	{
		incode.x[i] = getshort( old );
		incode.y[i] = getshort( old );
	}
	for( i=0; i<incode.parms; i++ ) incode.p[i] = getshort( old );
	return( incode.op );
}	/* getmeta */

short getshort( old )
int old;
{
	short x, l;

	x = ((inbuf[inptr]>>8)&0x0FF) | (inbuf[inptr]<<8);
	if( ++inptr >= 256 )
	{
		l = read( old, inbuf, 512 );
		printf( "%dK read, %dK written\r", (++nreads)/2, nwrites/2 );
		while( l < 512 )
			if( l >= 0 ) inbuf[l++] = -1;
			else l=0;
		inptr = 0;
	}
	return( x );
}	/* getshort */

init_files( old, new )	/* Set up i/o buffers */
int old, new;
{
	read( old, inbuf, 512 );
	inptr = 16;
	outptr = 172;
	nxy = nwrites = nvecs = nlines = 0;
	nreads = 1;
}	/* init_files */

terminate( str )
char *str;
{
	char ans[80];

	puts( str );
	printf( "Press RETURN to quit: " );
	gets( ans );
	exit();
}	/* terminate */

wrpoly( new )	/* Write polyline to output */
int new;
{
	short i;

	polyline[1] = nxy;
	for( i=0; i<5; i++ ) wrshort( new, startline[i] );
	if( nxy > 2 )	/* true polyline */
		for( i=0; i<17; i++ ) wrshort( new, polyfill[i] );
	for( i=0; i<4; i++ ) wrshort( new, polyline[i] );
	for( i=0; i<nxy; i++ )
	{
		wrshort( new, newx[i] );
		wrshort( new, newy[i] );
	}
	for( i=0; i<5; i++ ) wrshort( new, endline[i] );
	nlines++;
	nxy = 0;
}	/* wrpoly */

wrshort( new, i )	/* Write short int to output */
int new;
short i;
{
	i = ((i>>8)&0x0FF) | (i<<8);	/* Swap byte order */
	outbuf[outptr++] = i;
	if( outptr >= 256 )
	{
		write( new, outbuf, 512 );
		printf( "%dK read, %dK written\r", nreads/2, (++nwrites)/2 );
		outptr = 0;
	}
}	/* wrshort */

wrvect( new )	/* Add vector to polyline buffer */
int new;
{
	short i;

	for( i=0; i<incode.vert; i++ )
	{
		incode.x[i] = incode.x[i]/XSCALE - XOFFS;
		incode.y[i] = incode.y[i]/YSCALE - YOFFS;
	}
	if( nxy == 0 ) cpyvert( new );
	else if( newx[nxy-1] == incode.x[0] && newy[nxy-1] == incode.y[0] )
		cpyvert( new );
	else
	{
		wrpoly( new );
		cpyvert( new );
	}
	nvecs++;
}	/* wrvect */
