#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>

#define TRUE  (0==0)
#define FALSE (0!=0)

int lastread;
int pos_x,pos_y;
char cmd_s=FALSE,cmd_t=FALSE;
FILE *filehandle;

void make_the_work(char *);
unsigned int read_till_escape(char);
unsigned int handle_csi(void);
void handle_command(unsigned int);
int readnum(int *);
void new_position(int,int);
void update_position(int);

void make_the_work(filename)
char *filename;
{
	register unsigned int escresult;

	pos_x=pos_y=1;
	if ((filehandle=fopen(filename,"r"))==NULL)
	{
		fprintf(stderr,"Unable to open file %s.\n",filename);
		exit(30);
	};
	lastread=fgetc(filehandle);
	while (lastread!=EOF)
	{
		if ((escresult=read_till_escape(TRUE))!=EOF)
			handle_command(escresult);
	};
	putchar(10);
	fclose(filehandle);
}

unsigned int read_till_escape(do_write)
/* reads the file till an escape sequence and returns the type of the escape */
/* could be EOF, x<<8+y, style<<16 or 0 in case of an unsupported escape     */
/* writes out non-escape characters if do_write is TRUE                      */
char do_write;
{
	while ((lastread!=27) && (lastread!=EOF))
	{
		if ((do_write==TRUE) && (isprint(lastread) || (lastread=='\n')))
		{
			putchar(lastread);
			update_position(lastread);
		};
		lastread=fgetc(filehandle);
	};
	if (lastread==EOF)
		return(EOF);
	else
	{
		lastread=fgetc(filehandle);
		if (lastread=='[')
			return(handle_csi());
		else
		{
			lastread=fgetc(filehandle);
			return(0);
		};
	};
}

unsigned int handle_csi(void)
/* last characters were CSI : read the command, reply result. at exit time,  */
/* lastread must be the one following the control sequence                   */
{
	unsigned int resu;
	int ch;
	int num1,num2;

	ch=fgetc(filehandle);
	if (isdigit(ch))
	{
		num1=readnum(&ch);
		if (ch==';')
		{
			ch=fgetc(filehandle);
			num2=readnum(&ch);
			if (ch=='H')
				resu=num1+(num2<<8);
			else
			{
				while (!isalpha(ch))
					ch=fgetc(filehandle);
				resu=0;
			};
		}
		else
			resu=(num1+1)<<16;
	}
	else
		resu=0;
	lastread=fgetc(filehandle);
	return(resu);
}

int readnum(ch)
int *ch;
{
	int resu=0;

	while (isdigit(*ch))
	{
		resu*=10;
		resu+=*ch-'0';
		*ch=fgetc(filehandle);
	};
	return(resu);
}

void handle_command(cmd)
unsigned int cmd;
{
	if (cmd!=0)
	{
		if ((cmd&0xffff)!=0)
			new_position(cmd>>8,cmd & 0xff);
		else
			if (cmd_t==TRUE)
				printf("\033[%dm",(cmd>>16)-1);
	};
}

void new_position(x,y)
int x;
int y;
{
	register unsigned int resultat=!EOF;

	if ((cmd_s==TRUE)&&(y>=24))
	{
		while (resultat!=EOF)
		{
			resultat=read_till_escape(FALSE);
			if ((resultat & 0xffff)==0)
				handle_command(resultat);
			else
				if ((resultat & 0xff)<24)
				{
					y=resultat & 0xff;
					x=resultat>>8;
					resultat=EOF;
				};
		};
	};
	if (y!=pos_y)
	{
		if (y<pos_y)
		{
			putchar(12);
			putchar(10);
			pos_y=2;
		}
		else
			putchar(10);
		pos_y=y;
		pos_x=1;
	};
	if (x!=pos_x)
	{
		if (x<pos_x)
		{
			putchar(10);
			pos_x=1;
		};
		while (pos_x++<x)
			putchar(' ');
		pos_x--;
	};
}

void update_position(ch)
int ch;
{
	if ((ch==13)||(ch==10)||(ch==12))
		pos_x=1;
	if (ch==10)
		pos_y++;
	if (ch==12)
		pos_y=1;
	if (ch==8)
		pos_y=(pos_y==1)?1:((pos_y+7)&(-8));
	if (ch>=32)
		pos_x++;
}

main(argc,argv)
int argc;
char *argv[];
{
	int i;

	fprintf(stderr,\
"\033[1mANSIconvert\033[0m ©1993 by Jean-François Stenuit\n\
Prints out the contents of an ANSI formated file as bare text.\n");
	if (argc==0)
	{
		fprintf(stderr,"Runs from the shell only\n");
		exit(30);
	};
	if (argc<2)
	{
		fprintf(stderr,"Usage: ANSIconvert [options] InputFile\n");
		exit(30);
	};
	if ((argc==2) && (strcmp(argv[1],"?")==0))
	{
		fprintf(stderr,"\
prints to the standard output with the following options :\n\
\t -s : strips out the status lines (24 and further)\n\
\t -t : does not strip out the characters attributes (bold, ...)\n\
This program if shareware, if you use it, please send $10 to :\n\
\t\tStenuit Jean-François\n\
\t\tAvenue de Falichamp, 10\n\
\t\tB - 5100 JAMBES\n\
\t\tBELGIUM\n");
		exit(0);
	};
	if (argc==3)
	{
		if (argv[1][0]!='-')
		{
			fprintf(stderr,"Invalid argument : %s\n",argv[1]);
			exit(30);
		}
		else
			for (i=1;argv[1][i]!='\0';i++)
				switch(argv[1][i])
				{
					case 's' : cmd_s=TRUE;
					           break;
					case 't' : cmd_t=TRUE;
					           break;
					default :
fprintf(stderr,"Invalid option : %c\n",argv[1][i]);
					           break;
				};
		argv[1]=argv[2];
	};
	make_the_work(argv[1]);
	return(0);
}   
