/*	PiShell.c - Edit 2

	LoadICE Version 4
	Copyright (C) 1990-99 Grammar Engine, Inc.
	All rights reserved
	
	NOTICE:  This software source is a licensed copy of Grammar Engine's
	property.  It is supplied to you as part of support and maintenance
	of some Grammar Engine products that you may have purchased.  Use of
	this software is strictly limited to use with such products.  Any
	other use constitutes a violation of this license to you.
*/

#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifndef UNIX
#include <conio.h>
#include <dos.h>
#endif
#include <stdlib.h>

#include "piconfig.h"
#include "piscript.h"
#include "pistruct.h"
#include "pierror.h"
#include "pihelp.h"

char utimes[32];

extern void (*psynf[])(void);
/*extern char *getenv(char *var); */
extern void piemu(void);
extern void pilod(void);
extern void pisetup(void);
extern void pcinit(void);
extern void pcexit(void);
extern void pcxinit(void);
extern void pcxminit(void);
extern void firemon(void);
static short pikeys(unsigned char c);
static void utime(short code);

struct	CM
{
	char ui[512];
	char vd;
} cm[PIC_CS];
short ci = 0;
short skipy = 0;
FILE *cf;

void pishell(void)
	{
	short i,j;
	short skip, dirty;
	unsigned char c;
	char *cstr,**hp;
	extern int errno;
	char ifile[PIC_FN];
	struct CM *cp = &cm[0];

	for (i=0; i<PIC_CS; i++)
		cm[i].vd = 0;
	if ((cf = fopen("loadice.dat","r")) != NULL)
	{
		for (i=0; i<PIC_CS; i++)
		{
			if (fgets(cm[i].ui,512,cf))
			{
				cm[i].ui[strlen(cm[i].ui)-1] = '\0';
				cm[i].vd++;
			}
			else
				break;
		}
		fclose(cf);
	}
	else
	{
		strcpy(cm[0].ui,"setup");
		strcpy(cm[1].ui,"restart");
		strcpy(cm[2].ui,"exit");
		cm[0].vd = 1;
		cm[1].vd = 1;
		cm[2].vd = 1;
		ci = 3;
	}

	utime(0);	/* init timer */

	/* if user did just 'loadice ?' or 'loadice help' */

	if (pxcline[0] == '?' || !strcmp(pxcline,"help"))
		{
		hp = piclhlp;
		while(*hp)
			{
			printf("\n %s",*hp);
			if (**hp == '-')
				(void)fgets(pxuline,PIC_CL,stdin);
			hp++;
			}
		return;
		}


	/* if 'ini' file is on the command line as '@inifile' */

	if (pxcline[0] == '@')
		{
		cstr = ifile;
		for (i=0; ((i<(short)strlen(pxcline)) && (i<(PIC_FN-1))); i++)
			{
			pxcline[i] = ' ';
			if (pxcline[i+1] == ' ')
				break;
			else
				ifile[i] = pxcline[i+1];
			}
		ifile[i] = '\0';
		pxcline[i+1] = ' ';
		}
	else		/* look for environment variable or use default */
		{
		cstr = getenv("LOADICE");
		if (cstr == NULL)
			cstr = "loadice.ini";
		}

	if (pxcline[0] != '.') /* if command line start with '.' then don't do it */
		{
		cf = fopen(cstr,"r");
		if (cf == NULL)
			{
			if (cstr == ifile)
				{
				for (i=0; i<(short)strlen(cstr); i++)
					if (ifile[i] == '.')
						break;
				if (i == (short)strlen(cstr))
					{
					strcat(cstr,".ini");
					cf = fopen(cstr,"r");
					}
				}
			}
		if (pxdisp&PXHI)
				printf("\n Opening initialization file '%s'",cstr);
		if (cf != NULL)
			{
			while (fgets(pxuline,PIC_CL,cf) != NULL)
				{
				if (pxuline[0] == '*')	/* ignore comment lines */
					continue;
				if (pxuline[0] == ';')	/* ignore comment lines */
					continue;
				if (pxuline[0] == '.')	/* execute command NOW */
					{
					pxuline[0] = ' ';
					piflags |= PiII;
					}
				else
					piflags &= ~PiII;
				pisyn(pxuline,pcmfsyn,psynf);	/* call parser */
				if (pxerror)
					{
					pierror();
					(void)fclose(cf);
					return;
					}
				pi_estr1 = (char *)0;
				}
			(void)fclose(cf);
			}
		else
			{
			if (pxdisp&PXHI)
				printf("\n File not found '%s'\n Try 'loadice -setup' to create one",cstr);
			}
		}
	else
		pxcline[0] = ' '; /* get rid of the '.' */

	if (pxcline[0] != '\0')
		{
		if (pxdisp&PXHI)
			printf("\n Parsing command line arguments'%s'",pxcline);
		piflags |= PiCM;
		pisyn(pxcline,pcmlsyn,psynf);
		piflags &= ~PiCM;
		pxcline[0] = '\0';
		}

	if (pxerror)
		pierror();
	else	/* possibly dialog mode */
		{
		/* if wants to load, has files and no dialog mode requested */

		if (!(pxflags&POXX) && (pxflags&POLO || (pxnfile && !(pxflags&POIX))))
			{
			if (!(pxsflags&SuSETUP))
				{
				piflags |= PiII;
				strcpy(pxuline,"l");
				pisyn(pxuline,pusrsyn,psynf);
				if (pxerror)
					{
					pierror();
					if (piflags&PiUP)
						{
						piemu();
						pcexit();
						}
					return;
					}
				}
			}

		/* if dialog mode requested or no files given (force dialog) */

		if (((pxflags&POIX) || (pxsflags&SuSETUP)) && !(pxflags&POXX))
			{
			if (pxdisp&PXHI)
					printf("\n Entering dialog mode");
			pxflags &= ~POXX;
			if (pxsflags&SuHOST && !(pxsflags&SuSETUP))
				pcinit();
			if (!pxerror)
				{
				piflags |= PiiX;
				for(;;)
					{
					if (pxsflags&SuSETUP)
						pisetup();
					pxsflags &= ~SuSETUP;
					if (pxerror)
						pierror();
					else
						piflags &= ~PiER;
					if (!(piflags&PiUP))
						{
						if (pxflags&POAR)
							{
							if (pxdisp&PXVH)
								printf(" Auto-recvery...");
							pisyn("restart",pusrsyn,psynf);
							if (pxerror)
								continue;
							}
						else
							if (pxdisp&PXVH)
								printf("\nTo Establish Link with the Emulators - type 'setup' or 'restart'");
						}
					if (pxflash[0].fiflags&FiFON)
						if (piflags&PiMU)
							firemon();
					if (pxdisp&PXVH)
						{
						utime(1);
						printf("\n\n%s",utimes);
							if (pxflash[0].fiflags&FiFON)
								{
								if (piflags&PiMU)
									printf("FlashICE: ");
								else
									printf("FLASHice: ");
								}
							else
								{
								if (piflags&PiMU)
									printf("LoadICE: ");
								else
									printf("LOADice: ");
								}
						}
					piflags &= ~PiCR;
					pibusy = 0;
#ifndef UNIX
					dirty = 0;
					skipy = 0;
					skip = 0;
					i = 0;
					if (pxflags&POXX)
						break;
					do
						{
#ifdef WIN32
						while (!(c = kbhit()))
							Sleep(100);
#endif
						c = (unsigned char)getch();
						if (c == '\b')		/* process back-space */
							{
							dirty++;
							if (i)
								{
								pxuline[i--] = '\0';
								putch('\b');
								putch(' ');
								putch('\b');
								}
							continue;
							}

						/* if any special key struck then we catch it here */

						if ((c == 0) || (c == 0x0E0) || (c == 0x1b))
							{
							if (c != 0x1b)
								c = (unsigned char)getch();
							switch (c)
								{
								case 0x1b:			/* ESC key - switch mode */
									if (!i)
										{
										if (!(piflags&PiUP))
											return;
										if (piflags&PiMU)
											{
											pilod();
											if (!pxerror)
												printf("\n Now in Load Mode!");
											}
										else
											{
											piemu();
											if (!pxerror)
												printf("\n Now Emulating!");
											}
										skip = 1;
										}
									else
									{
										for (j=0; j<i; j++)
											printf("\b");
										for (j=0; j<i; j++)
											printf(" ");
										for (j=0; j<i; j++)
											printf("\b");
										i = 0;
									}
									break;
								default:	/* FUNCTION keys */
									if (c<0x45 && c>0x3a)
										c -= 0x3b;
									else
										if (c<0x72 && c>0x67)
											c -= 0x5c;
										else
											if (c<0x08d && c>0x084)
												{
												c -= 0x085;
												if (c<2)
													c += 10;
												else
													c += 16;
												}
									if (!(skip = pikeys(c)))	/* process the key */
										i = strlen(pxuline);
								}
							}
						else		/* normal key - make line */
							{
							putch(c);
							if ((c != '\r') && (c != '\n'))
								{
								dirty++;
								pxuline[i++] = c;
								}
							}
						} while ((c != '\r') && (!skip));
					if (pxerror)
						pierror();
					if (skip)
						continue;
					if (!i)			/* if just CR typed, do last command */
						{
						pxuline[0] = pxfirst;
						piflags |= PiCR;
						}
					else
						pxuline[i] = '\0'; /* else make sure line is mt */
#else
					while (gets(pxuline) == NULL)
						continue;
					if (!strlen(pxuline))
						{
						pxuline[0] = pxfirst;
						piflags |= PiCR;
						}
#endif
					if (strlen(pxuline))
						{
						pibusy = 1;
						pxfirst = pxuline[0];
						if (pxuline[0] == '.')	/* '.' means immediate */
							piflags |= PiII;
						else
							piflags &= ~PiII;
						utime(0);				/* reset timer */
						pisyn(pxuline,pusrsyn,psynf);	/* do command */
						if (pxerror)
							pierror();
						if (dirty)
							{
							for (ci=0; ci<PIC_CS; ci++)
								if (!cm[ci].vd) break;
							strcpy(cm[ci].ui,pxuline);
							cm[ci].vd = 1;
							if (++ci == PIC_CS) ci = 0;
							cm[ci].vd = 0;
							}
						if (piflags&(PiHO|PiRQ|PiMO|PiAB))
							pcxinit();
						if (pxflags&POXM)
							pcxminit();
						}
					if (pxflags&POXX)
						break;
					pi_estr1 = (char *)0;
					}
				}
			else
				pierror();
			}
		pcexit();	/* shut down link to PROMICEs */
		if ((cf = fopen("loadice.dat","w")) != NULL)
			{
			for (i=0; i<PIC_CS; i++)
				{
				if (cm[i].vd)
					{
					strcat(cm[i].ui,"\n");
					fwrite(cm[i].ui,1,strlen(&cm[i].ui[0]),cf);
					}
				}
			fclose(cf);
			}
		}
	}

/* `pikeys` - process function keys */

static short pikeys(unsigned char c)
	{
	short i;
	short xi = ci;

	if (c>23)	/* if not function keys then list keys */
	{
		switch(c)
		{
		case 0x47:	/* Home */
			break;
		case 0x48:	/* Up Arrow */
			do
			{
				if (--ci<0) ci=PIC_CS-1;
			} while (!cm[ci].vd);
			break;
		case 0x49:	/* Page Up */
			break;
		case 0x4B:	/* Left Arrow */
			break;
		case 0x4D:	/* Right Arrow */
			break;
		case 0x4F:	/* End */
			break;
		case 0x50:	/* Down Arrow */
			do
			{
				if (++ci==PIC_CS) ci=0;
			} while (!cm[ci].vd);
			break;
		case 0x51:	/* Page Down */
			break;
		case 0x52:	/* Insert */
			break;
		case 0x53:	/* Delete */
			break;
		default:
			for (i=0; i<24; i++)
				{
				if (i<12)
					printf("\n    F%d\t= ",i+1);
				else
					printf("\n AltF%d\t= ",i-11);
				if (pxkeys[i])
					printf("%s",pxkeys[i]);
				else
					printf("...unassigned!");
				}
		}
		if (skipy)
		{
			for (i=0; i<(signed)strlen(cm[xi].ui); i++)
				printf("\b");
			for (i=0; i<(signed)strlen(cm[xi].ui); i++)
				printf(" ");
			for (i=0; i<(signed)strlen(cm[xi].ui); i++)
				printf("\b");
		}
		printf("%s",cm[ci].ui);
		strcpy(pxuline,cm[ci].ui);
		skipy++;
		return(0);
	}
	else
		{
		if (pxkeys[c] == NULL)	/* assigned */
			pxerror = PGE_KEY;
		else
			{
			printf("%s",pxkeys[c]);	/* echo command */
			pisyn(pxkeys[c],pusrsyn,psynf);	/* do command */
			}
		return(1);
		}
	}


/* `utime` - time stamp the prompt */

static void utime(short code)
	{
	static time_t t;
	time_t tt;
	short day,hour,minute;

	if (!code)
		t = time(NULL);
	else
		{
		day = hour = minute = 0;
		tt = time(NULL) - t;
		if (tt >= 86400)
			{
			day = tt/86400;
			tt %= 86400;
			}
		if (tt >= 3600)
			{
			hour = tt/3600;
			tt %= 3600;
			}
		if (tt >= 60)
			{
			minute = tt/60;
			tt %= 60;
			}
		if (day)
			{
			sprintf(utimes,"%03d|%02d:%02d:%02d:",day,hour,minute,tt);
			return;
			}
		if (hour)
			{
			sprintf(utimes,"%02d:%02d:%02d:",hour,minute,tt);
			return;
			}
		if (minute)
			{
			sprintf(utimes,"%02d:%02d:",minute,tt);
			return;
			}
		sprintf(utimes,"%02d:",tt);
		}
	}
