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

#ifndef DEMO
#undef DEMO
#endif

#ifdef DEMO
#define tprintf printf
#define tputc putchar

static unsigned char last[2];

void
tflush ()
{
	fflush (stdout);
}
#else
#include "usock.h"

void
myusflush (s)
int s;
{
register struct usock *up;
struct mbuf *bp;

	if((up = itop(s)) == NULLUSOCK)
		return;

	if(up->obuf == NULLBUF)
		return;
	if (len_p (up->obuf) < 220)
		return;
	usflush (s);
}
#endif


int
colorprintf (escapeflag, usecolor, str)
char *escapeflag, usecolor;
unsigned char *str;
{
unsigned char c;
int foundone = 0;


	while ((c = *str++) != 0)	{
		if (c == 0x1b)	{	/* escape sequence */
			if (usecolor)	{
				foundone = 1;
#ifdef DEMO
				tflush ();
#else
				myusflush(Curproc->output);
#endif
			}
			if (escapeflag)
				*escapeflag = 1;
		}
		else if (escapeflag && *escapeflag)	{
			if (!isdigit(c) && c != ';' && c != '[')
				*escapeflag = 0;
		}
		if (!escapeflag || (escapeflag && !*escapeflag) || usecolor)	{
			tputc (c);
		}
	}
	return (foundone);
}


static int
getcolor (color)
unsigned char color;
{
int retval = 30;

	switch (color)	{
		case '1': case '9':	retval += 4;	break;
		case '2': case 'A':	retval += 2;	break;
		case '3': case 'B':	retval += 6;	break;
		case '4': case 'C':	retval += 1;	break;
		case '5': case 'D':	retval += 5;	break;
		case '6': case 'E':	retval += 3;	break;
		case '7': case 'F':	retval += 7;
		default:		break;
	}
	return (retval);
}


static int
getone (fp)
FILE *fp;
{
int c;

	c = getc (fp);
	if (feof (fp))
		c = 0;
	return (c);
}


static void
getkeyword (input, fp)
unsigned char *input;
FILE *fp;
{
unsigned char c;
int k;

	do	{
		for (k = 0; k < 15; k++)	{
			input[k] = c = getone (fp);
			if (!c || (c == '@'))
				break;
		}
		input[k] = 0;
		if (!c)
			k++;
	} while (!k);
}


void
colorcls ()
{
#ifdef DEMO
	tflush ();
#else
	myusflush(Curproc->output);
#endif
	tprintf ("\x1b[2J");
}


static int
cmdmatch (input)
unsigned char *input;
{
int retval = 0;

	if (!strcmp ("CLS", input))	{
		colorcls();
		retval = 1;
	}
	return (retval);
}


static int
blinking (c)
unsigned char c;
{
	return ((c > '7') ? 1 : 0);
}


static int
bold (c)
unsigned char c;
{
	return ((c > '7') ? 1 : 0);
}


int
colorchange (input, last)
register char *input, *last;
{
int retval = 0, putone = 0, temp, putall = 0;


	if (!strncmp (input, last, 2))
		return (1);
	if ((strlen(input) == 2) && (isxdigit (input[0])) && (isxdigit (input[1])))	{
#ifdef DEMO
		tflush ();
#else
		myusflush(Curproc->output);
#endif
		tprintf ("\x1b[");
		retval = 2;
		if (!*last)
			putall++;
		if (putall || (blinking(*last) && !blinking(*input)) || (bold (last[1]) && !bold(input[1]))) {
			tputc ('0');
			retval++;
			putone++;
			putall++;
		}
		if (blinking(*input))	{
			tprintf ("%s5", putone ? ";" : "");
			putone++;
			retval++;
		}
		temp = getcolor(*input);
		if (putall || temp != getcolor (*last))		{
			tprintf ("%s%d", putone ? ";" : "", temp + 10);
			retval += (2 + putone);
			putone++;
		}
		if (putall || (input[1] != last[1]))	{
			tprintf ("%s%s%d", putone ? ";" : "", (input[1] > '7') ? "1;" : "",
				getcolor (input[1]));
			retval += (putone + 2 + ((input[1] > 7) ? 2 : 0));
		}
		tputc ('m');
		retval += 1;
		memcpy (last, input, 2);
	}
	return (retval);
}


void
colorfile (filenm, last)
char *filenm, *last;
{
FILE *fp;
unsigned char c, input[16];
char invalid = 0;

	if (!(fp = fopen (filenm, "rb")))
		return;
	while (!feof (fp))	{
		if (!(c = getone (fp)))
			continue;
		if (c == 0x1b)
			invalid = 1;
		if (c == '@')	{
			invalid = 0;
			getkeyword (input, fp);
			if (!colorchange (input, last))
				if (!cmdmatch (input))
					tprintf ("@%s@", input);
		} else
#ifndef DEMO
			if ((c != 0x0d) && (c != 0x1a))
#endif
				tputc (c);
	}
	fclose (fp);
	if (invalid)
		last[0] = 0;
}



#ifdef DEMO
void
main (argc, argv)
int argc;
char *argv[];
{
	last[0] = last[1] = 0;
	if (argc == 1)
		exit (0);
	colorfile (argv[1], last);
}
#endif

