/**********************************************************************
 * Nano-GUI -- a Nano-X environment for Linux                         *
 *                          By Darran D. Rimron <darran@rimron.co.uk> *
 *                                                                    *
 * Based on Nano-Term, a Nano-X demo                                  *
 *                                         By Al Riddoch & Greg Haerr *
 *                                                                    *
 * ---------+--------+---------+------------------------------------- *
 * Date     | Author | Version | Reason                               *
 * ---------+--------+---------+------------------------------------- *
 * 19991112 | Rimron | 0.0.1   | Start Application                    *
 * 19991226 | Rimron | 0.0.2   | Add clock, improve terminal          *
 * ---------+--------+---------+------------------------------------- *
 * See NanoGUI.CHANGES and CHANGELOG for full and graphic change info *
 * ------------------------------------------------------------------ *
 *                                                                    *
 *      Best viewed with console-vim & a tabstop of 3 (:set ts=3)     *
 **********************************************************************/

GR_SIZE     width;      /* width of character */
GR_SIZE     height;     /* height of character */
GR_SIZE     base;       /* height of baseline */

void save_esc_param(int incr)
{	/* Save the current NPAR to the array, reset pointer, and return */
	npar[npar_part]=atoi(esc_string);
	esc_pos=0;
	if(incr)
		npar_part++;
}

void char_out(GR_CHAR ch)
{	/* and so begins the time for clever thinking, is this a new ESC sequence
		with nothing else in time or space that concerns us or is this a new
		ESC sequence that marks the end of an old one, therefore giving us
		something to do before we start writing this one into the buffer which,
		of course, contains data we need to act on and haven't or is this a
		control key that needs special attention or is this just a pointer to a
		glyph so I just need to dump the glyph to the "console"? */

	int npar_process_loop=0;

	if (is_esc_seq==1)
	{
		
		if((ch>47) && (ch<58)) /* or use ISDIGIT(3), I dunno.... Anyone? */
		{
			esc_string[esc_pos]=ch;
			esc_pos++;
			esc_string[esc_pos]='\0';
		}
		
		if(((ch<48) || (ch>57)) 
		 && (ch!=63) 			/* Question-mark */
		 && (ch!=91))			/* Open Square Bracket */
		{	/* If we get in here, we've probably hit an ESC terminator */
			switch(ch) { 	/* so what type of escape sequence have we hit? */
			case 59:			/* 59 or ;, not an ESC term, but it's NPAR time */
				save_esc_param(TRUE);
				return;		/* Don't terminate the sequence.... not yet */
			case 72:			/* 72 or H, reset cursor to the option[s] fed */
				if (npar_part==0) /* without options, reset to origin */
				{	
					save_esc_param(FALSE);
					text_xpos=0;
					text_ypos=0;
					break;
				}
				save_esc_param(FALSE);
				text_ypos=(npar[0]*height)-height;
				text_xpos=(npar[1]*width)-width;
				break;
			case 74:			/* 74 or J, erase display, how depends on option fed */
				GrSetGCForeground(gc3, MAIN_PAPER_COLOR);
				GrFillRect(main_window, gc3, text_xpos, text_ypos + 1, si.cols, height);
				GrFillRect(main_window, gc3, 0, text_ypos + height + 1, si.cols, si.rows);
				GrSetGCForeground(gc3, MAIN_PEN_COLOR);
					break;
			case 104:	/* 104 or h, SET Mode. DECSET Private modes, etc */
				/* we're not gonna do this yet.... */ 
				break;
			case 108:	/* 108 or l, RESET Mode. DECRST Private modes, etc */
				/* we're not gonna do this yet.... */ 
				break;
			case 109:	/* 109 or m, set attributes, BOLD, color, etc.... */
				save_esc_param(FALSE);
				for(npar_process_loop=0;npar_process_loop<=npar_part;npar_process_loop++)
				{
				switch(npar[npar_process_loop]) {
					case 0:
						GrSetGCForeground(gc3, MAIN_PEN_COLOR);
						GrSetGCBackground(gc3, MAIN_PAPER_COLOR);
						break;
					case 1:
						break;
					case 30:
						GrSetGCForeground(gc3, BLACK);	
						break;
					case 31:
						GrSetGCForeground(gc3, RED);	
						break;
					case 32:
						GrSetGCForeground(gc3, GREEN);	
						break;
					case 33:
						GrSetGCForeground(gc3, BROWN);	
						break;
					case 34:
						GrSetGCForeground(gc3, BLUE);	
						break;
					case 35:
						GrSetGCForeground(gc3, MAGENTA);	
						break;
					case 36:
						GrSetGCForeground(gc3, CYAN);	
						break;
					case 37:
						GrSetGCForeground(gc3, WHITE);	
						break;
					case 38:
						/* Turn underscore on, set default color */
						break;
					case 39:
						/* Turn underscore off, set default color */
						break;
					case 40:
						GrSetGCBackground(gc3, BLACK);	
						break;
					case 41:
						GrSetGCForeground(gc3, RED);	
						break;
					case 42:
						GrSetGCForeground(gc3, GREEN);	
						break;
					case 43:
						GrSetGCForeground(gc3, BROWN);	
						break;
					case 44:
						GrSetGCForeground(gc3, BLUE);	
						break;
					case 45:
						GrSetGCForeground(gc3, MAGENTA);	
						break;
					case 46:
						GrSetGCForeground(gc3, CYAN);	
						break;
					case 47:
						GrSetGCForeground(gc3, MAGENTA);	
						break;
					case 49:
						GrSetGCForeground(gc3, MAIN_PAPER_COLOR);	
						break;
					}
				}
				if(npar[npar_part]==1)
				break;
			}

			/* All sequences are processed, reset ready for another one.... */
			is_esc_seq=0;
			esc_pos=0;
			return;
		}
		return;
	}

	if (ch==27)								/* The key is ESC - reset the sequence*/
	{
		is_esc_seq=1;
		npar_part=0;
		esc_pos=0;
		return;
	}
/* If we have got this far, we're processing a single char, and it looks like
	it may be a glyph, but we still have special case single char's, lik BEL so
	one final switch statement to handle all those.... */

	switch(ch) {
	case '\r':
		text_xpos = 0;
		return;
	case '\n':
		text_ypos += height;
		if(text_ypos > si.rows - 60 - height) {
			text_ypos -= height;
#if HAVEBLIT
			GdBlit(main_window, 1, 100, si.cols, 379, main_window, 1, 68, main_window);
			GrFillRect(main_window, gc3, 50, text_ypos, si.cols-120, height);
#else
			/* FIXME: changing FALSE to TRUE crashes nano-X*/
			/* clear screen, no scroll*/
			text_ypos = 0;
			GrClearWindow(main_window, FALSE);
#endif
		}
		return;
	case '\007':			/* FIXME: bel - Easiest way is use stderr. BAD!*/
		fprintf(stderr,"\007");
		return;
	case '\t':
		text_xpos += width;
		while((text_xpos/width) & 7)
			char_out(' ');
		return;
	case '\b':			/* We're running a termemu so assume fixed width font*/
		if (text_xpos <= 0)
			return;
		char_del(text_xpos, text_ypos);
		return;
	}
	GrText(main_window, gc3, text_xpos, text_ypos + height, &ch, 1);
	text_xpos += width;
}

void char_del(GR_COORD x, GR_COORD y)
{
	text_xpos -= width;
/* With this turned on, using DELETE resets the pen to the default colour	
	GrSetGCForeground(gc3, MAIN_PAPER_COLOR);
	GrFillRect(main_window, gc3, x, y + 1, width, height);
	GrSetGCForeground(gc3, MAIN_PEN_COLOR);
Does NanoX have an option to return the current pen colour so I can store it? */
}

void poll_second_functions(void)
{
	/* This would flash a cursor, generally */
}

void printg(char * text, int PEN_COLOR, int PAPER_COLOR)
{
	int i;

	GrSetGCForeground(gc1, PEN_COLOR);
	GrSetGCBackground(gc1, PAPER_COLOR);
	for(i = 0; i < strlen(text); i++) {
		char_out(text[i]);
	}
}
