/* CHR2PS.C */

#define VERSION "1.0 (beta)"

#include <stdio.h>
#include <string.h>
#ifndef AIX
#include <stdlib.h>
#endif
#include "defines.h"
#include "myopen.h"
#include "chr2ps.h"

void give_usage ()
{
	fprintf (stderr, "Usage: chr2ps [<somechr[.chr]|-]");
	fprintf (stderr, " [<someps>[.ps]]\n");
	exit (UNSUCCESSFUL);
}

#ifdef __STDC__
void preamble (int argc, char ** argv)
#else
void preamble (argc, argv)
int argc;
char ** argv;
#endif
{
	if (argc == 1) give_usage ();
	if (argc == 3)
	{
		if (strequ (argv [1], "-")) chr_file = stdin;
		else chr_file = my_open (argv [1], ".chr", "rb");
		ps_file = my_open (argv [2], ".ps", "w");
	}
	else
	{
		chr_file = my_open (argv [1], ".chr", "rb");
		ps_file = my_open (argv [1], ".ps", "w");
	}
}

void postamble ()
{
	fclose (chr_file);
	fclose (ps_file);
	fprintf (stderr, "Conversion done\n");
	exit (SUCCESSFUL);
}

#ifdef __STDC__
unsigned char ReadChar (void)
#else
unsigned char ReadChar ()
#endif
{
	char Inc;

	if (! HaveSavedChar)
	{
		fread (&Inc, 1, 1, chr_file);
		/* translate CR, LF or CR/LF to '\n' */
		if (Inc == '\r')  /* CR = 0x0D */
		{
			fread (&Inc, 1, 1, chr_file);
			if (Inc != '\n')  /* LF = 0x0A */
			{
				HaveSavedChar = TRUE;
				SavedChar = Inc;
			}
			Inc = '\n';
		}
	}
	else
	{
		Inc = SavedChar;
		HaveSavedChar = FALSE;
	}
	return (Inc);
}

#ifdef __STDC__
void ReadLine (void)
#else
void ReadLine ()
#endif
{
/* read another line (binary mode!)
   do not include the \r and \n characters
 */
/* assume a line is terminated by CR, LF or CR/LF */

	char_pos = in_buff;
	* in_buff = NULLCHAR;
	in_size = 0;
	while (! feof (chr_file))
	{
		inchar = ReadChar ();
		if (inchar != '\n')
		{
			in_buff [in_size] = inchar;
			in_size++;
		}
		else
		{
			break;
		}
	}
	in_buff [in_size] = NULLCHAR;
}

#ifdef __STDC__
unsigned char DeCrypt (unsigned char cipher)
#else
unsigned char DeCrypt(cipher)
unsigned char cipher;
#endif
{
	unsigned char plain;

	plain = (cipher ^ (cr >> 8));
	cr = (cipher + cr) * cc1 + cc2;
	return plain;
}

#ifdef __STDC__
void DecryptCharString (unsigned char * CS, int count)
#else
void DecryptCharString (CS, count)
unsigned char * CS;
int count;
#endif
{
	int i;
	unsigned char byte;
	long value;
	int out_size;

	cr = CR; cc1 = CC1; cc2 = CC2;
	out_size = 0;
	fputs("{ ", ps_file);
	for (i = 0; i < lenIV; i++) byte = DeCrypt (CS [i]);
	for (i = lenIV  ; i < count ;  )
	{
		byte = DeCrypt (CS [i ++]);
		if (byte == 11)
		{
			fprintf (ps_file, " %s", commands [byte] . command);
			break;
		}
		else if (byte == 12)
		{
			byte = DeCrypt (CS [i ++]);
			if (byte > MAX_ESCAPE)
			{
				out_size = out_size + 17;
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				fprintf (ps_file, " not_defined_e%d", byte);
			}
			else
			{
				out_size = out_size
				+ strlen (escapes [byte] . command);
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				fprintf (ps_file, " %s",
					 escapes [byte] . command);
			}
			continue;
		}
		else if (byte < 32)
		{
			out_size = out_size
			+ strlen (commands [byte] . command);
			if (out_size > out_break)
			{
				out_size = 0;
				fprintf (ps_file, "\n  ");
			}
			fprintf (ps_file, " %s", commands [byte] . command);
		}
		if (byte >= 32)
		{
			if (byte <= 246)
			{
				out_size = out_size + 4;
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				fprintf (ps_file, " %d", byte  - 139);
			}
			else if ((byte >= 247) && (byte <= 250))
			{
				out_size = out_size + 7;
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				fprintf (ps_file, " %d", (byte  - 247) * 256
					 + DeCrypt (CS [i ++]) + 108);
			}
			else if ((byte >= 251) && (byte <= 254))
			{
				out_size = out_size + 7;
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				fprintf (ps_file, " %d", -(byte  - 251) * 256
					 - DeCrypt(CS[i++]) - 108);
			}
			else if (byte == 255)
			{
				out_size = out_size + 9;
				if (out_size > out_break)
				{
					out_size = 0;
					fprintf (ps_file, "\n  ");
				}
				value = DeCrypt (CS [i ++]);
				value <<= 8;
				value += DeCrypt (CS [i ++]);
				value <<= 8;
				value += DeCrypt (CS [i ++]);
				value <<= 8;
				value += DeCrypt (CS [i ++]);
				fprintf (ps_file, " %d", value);
			}
		}
	}
	fprintf (ps_file, " } ");
}

#ifdef __STDC__
void main (int argc, char ** argv)
#else
void main(argc, argv)
int argc;
char ** argv;
#endif
{
	int lusteller;
	char ch;

	fprintf (stderr, "This is chr2ps, version: %s\n", VERSION);
	preamble (argc, argv);
	HaveSavedChar = FALSE; in_size = 0;
	fprintf (stderr, "  Conversion of charstring to postscript \n");
	fprintf (stderr, "  Copying inputfile until /Subrs entry \n");
	for (;;)
	{
		ReadLine ();
		fprintf (ps_file, "%s\n", in_buff);
		if (strnequ ((char *) in_buff, "/lenIV", 6))
		{
			lenIV = atoi ((char *) in_buff + 7);
		}
		if (strstr ((char *) in_buff, "/Subrs") != NULL) break;
	}
	tp = 0; in_size = 0; inchar= ' ';
	fprintf (stderr, " Decrypting charstring data now  (This may take a while...)\n");
	for (lusteller = 0;; lusteller ++)
	{
		if (! (lusteller % 20)) fprintf (stderr, ".");
		if (feof (chr_file)) break;
		prevchar = inchar;
		inchar = ReadChar ();
		in_size ++;
		if (in_size > TEMPSIZE) fputc (temp_buff [tp], ps_file);
		temp_buff [tp] = inchar;
		if (tp == (TEMPSIZE - 1)) tp = 0;
		else tp++;
		if ((inchar != '-') && (inchar != 'R')) continue;
		if (prevchar != ' ') continue;
		if (inchar == '-') testchar = '|';
		else testchar = 'D';
		inchar = ReadChar ();
		if (inchar != testchar)
		{
			in_size++;
			if (in_size > TEMPSIZE) fputc (temp_buff [tp], ps_file);
			temp_buff[tp] = inchar;
			if (tp == (TEMPSIZE - 1)) tp = 0;
			else tp++;
			continue;
		}
		inchar = ReadChar ();
		testchar = ' ';
		if (inchar != testchar)
		{
			in_size++;
			if (in_size > TEMPSIZE) fputc (temp_buff [tp], ps_file);
			temp_buff [tp] = inchar;
			if (tp == (TEMPSIZE - 1)) tp = 0;
			else tp++;
			continue;
		}
		if (in_size > 20) restcount = 20;
		else
		{
			restcount = in_size;
			tp = 0;
		}
		for (i = 0 ; i < restcount ; i++)
		{
			in_buff [i] = temp_buff [tp];
			if (tp == (TEMPSIZE - 1)) tp = 0;
			else tp++;
		}
		in_buff [restcount] = NULLCHAR;
		count_pos = & in_buff [restcount - 2];
		do count_pos --;
		while (* count_pos != ' ');
		count_pos ++;
		count = atoi ((char *) count_pos);
		* count_pos = NULLCHAR;
		fprintf (ps_file, "%s", in_buff);
		in_size = 0; tp = 0;
		fread (CharString, 1, count, chr_file);
		CharString [count] = NULLCHAR;
		DecryptCharString (CharString, count);
	}
	fprintf (stderr, "\n");
	if (in_size > 20) restcount = 20;
	else
	{
		restcount = in_size;
		tp = 0;
	}
	for (i = 0 ; i < restcount ; i ++)
	{
		in_buff [i] = temp_buff [tp];
		if (tp == (TEMPSIZE - 1)) tp = 0;
		else tp++;
	}
	in_buff [restcount] = NULLCHAR;
	fprintf (ps_file, "%s", in_buff);
	postamble ();
}