/*	sMOVIEparse.c - Function which scans a text file and builds lists
				 	in memory which are subsequently used to produce
					a view which essentially just smoothly scrolls the
					text from the file up through the view.

					(Runner up in the 1989 Silver Bogroll award for
					 long involved sentences.)

					 M. J. Round.	 7 - Oct - 1989.					*/
#include "sMOVIE.h"

extern struct GfxBase *GfxBase;

extern struct RastPort rp;

extern struct TextFont *tf[MAXFONTS+1], *font, *defaultfont;

extern char *txptr,fontname[MAXFONTS][MAXFONTNAMELENGTH];

extern char line[MAXLINE + 1],buff[MAXLINE * 2];

extern int pointsize[MAXFONTS],fonts,textsiz,cmdsiz,maxfontheight;

extern int height,width,maxheight,maxwidth,maxdepth,centring,ind,tab;

extern int no_text_or_lines;

extern short *cmdptr;

extern char esc;

extern int runningfromcli;

void getargs(int,char *);

int checksizes(int *,int *,short *,short *,short *);

void parse(fp,pass) 	/*  parse script file	*/
				
/*  1st pass (pass == 0) Build font table, calculate memory requirement	*/
/*  2nd pass (pass != 0) create *txptr and *cmdptr lists.				*/

FILE *fp;
int pass;
{
	char *p,fname[MAXFONTNAMELENGTH];
	int i,j,fsize,depth;
	FILE *fil;
	
	while((p = fgets(line, MAXLINE, fp)) != NULL) {

		if(line[strlen(line)-1] != '\n')
			(void) strcat(line,"\n");

		if (*p++ == esc) {
			j =0;
			for (i=0; i<3; i++)
				/*  code 3 letter command to an integer value	*/
				j = j * 26 - 65 + toupper((int)*p++);

			switch (j) {

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 1655:  	/*  CLR: clear screen			*/
				case 1656:		/*	CLS: synonym				*/
					if (pass)
						*cmdptr++ = 7;  /*  command code	*/
					else
						cmdsiz += 1;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 1727:  	/*  COL: change pen colour  	*/
					if (pass) {
						*cmdptr++ = 3;  /*  command code	*/
						getargs(2,p);
						}
					else
						cmdsiz += 3;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 1728:  	/*  COM: comment				*/
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 2147:  	/*  DEP: change screen depth	*/
					if (pass) {
						p = strtok(stpblk(p)," ;");
						if (p != NULL && isdigit((int)*p))
							depth = atoi(p);
						if (depth > MAX_DEPTH)
							depth = MAX_DEPTH;
						if (depth < 1)
							depth = 1;
						if (depth > maxdepth)
							maxdepth = depth;
						}

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 2177:  	/*  DFT: default sizesn			*/
					if (pass) {
						short dummy;

						*cmdptr++ = 13;  /*  command code	*/
						width = GfxBase->NormalDisplayColumns;
						height = GfxBase->NormalDisplayRows;
						checksizes(&width,&height,&dummy,&dummy,&dummy);
						}
					else
						cmdsiz += 1;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 2338:  	/*  DLY: delay (jiffies)		*/
					if (pass) {
						*cmdptr++ = 5;  /*  command code	*/
						getargs(1,p);
						}
					else
						cmdsiz += 2;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 3174:  	/*  ESC: change esc character	*/
					p = stpblk(p);
					if (*p != '\0') {
						esc = *p;
						if (!pass && runningfromcli) {
							sprintf(buff,"Escape code changed to '%c'.\n",esc);
							print(buff);
							}
						}
					else
						if (!pass && runningfromcli) {
							sprintf(buff,"Corrupt ESC command:-\n%s\n",line);
							print(buff);
							}

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 3599:		/*	FIL: include a file			*/
					p = stpblk(p);
					if (isalpha((int)*p)) {
						if ((fil = fopen(strtok(p,",; \n"),"r")) == NULL) {
							if (!pass && runningfromcli) {
								sprintf(buff,"FIL can't open %s\n",p);
								print(buff);
								}
							}
						else {
							/*	isn't recursion wonderful?	*/
							parse(fil,pass);
							fclose(fil);
							}
						}
					else
						if (!pass && runningfromcli) {
							sprintf(buff,"Corrupt FIL command:-\n%s\n",line);
							print(buff);
							}

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 3737:  	/*  FNT: change font			*/
					fname[0] = '\0';
					/*  fetch name and pointsize	*/
					p = stpsym(stpblk(p),fname,MAXFONTNAMELENGTH);
					p = stpblk(p);
					if (isdigit((int)*p))
						fsize = atoi(p);
					else
						fsize = 0;

					if (pass) {
						*cmdptr++ = 4;  /*  command code	*/
						*cmdptr = 0;	/*	default code	*/
						font = defaultfont;
						for (i=0; i<fonts; i++)
							if (strcmp(fontname[i],fname) == 0 &&
								pointsize[i] == fsize) {
									*cmdptr = i;
									font = tf[i];
									}
						cmdptr++;
						}
					else {
						cmdsiz += 2;
						if (fonts >= MAXFONTS) {
							if (runningfromcli) {
								sprintf(buff,"Too many fonts:-\n%s\n",line);
								print(buff);
								}
							continue;
							}
						strcpy(fontname[fonts],fname);
						pointsize[fonts] = fsize;
							
						if (fontname[fonts][0] != '\0' 
							&& pointsize[fonts]) {
								++fonts;
							/*  check for duplications  */
								{
								for (i=0; i<(fonts-1); i++)
									if(strcmp(fontname[i],
										fontname[fonts-1]) == 0 &&
										pointsize[i] == pointsize[fonts-1])
											--fonts;
								}
							}
						else {
							if (runningfromcli) {
								sprintf("Corrupt FNT command:-\n%s\n",line);
								print(buff);
								}
							continue;
							}
						}
						
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 5749: 		/*  IND: set left margin		*/
					if (pass) {
						p = strtok(stpblk(p)," ;");
						if (p != NULL && isdigit((int)*p)) {
							ind = atoi(p);
							if (ind > width - 2)
								ind = 0;
							}
						else
							if (runningfromcli) {
								sprintf(buff,
									"Corrupt IND command:-\n%s\n",line);
								print(buff);
								}
						}
						
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/
				case 7792:  	/*  LNS: draw line(s)			*/
					if (pass) {
						*cmdptr++ = 2;  /*  command code	*/
						getargs(3,p);
						}
					else {
						cmdsiz += 4;
						no_text_or_lines = 0;
						}
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 9596:  	/*  OFC: turn off centring 	*/
					if (pass)
						centring = 0;
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 9804:  	/*  ONC: turn on centring  	*/
					if (pass)
						centring = 1;
					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 10445: 	/*  PLT: change pallette		*/
					if (pass) {
						*cmdptr++ = 10; /*  command code	*/
						getargs(4,p);
						}
					else
						cmdsiz += 5;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 11979:  	/*  RST: replay from start		*/
					if (pass)
						*cmdptr++ = 14;  /*  command code	*/
					else
						cmdsiz += 1;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 12401: 	/*  SIZ: screen size change 	*/
					if (pass) {
						*cmdptr++ = 11; /*  command code	*/
						p = stpblk(p);
						if (strnicmp(p,"HIRES",5) == 0)
							*cmdptr++ = 1;
						else if (strnicmp(p,"LORES",5) == 0)
							*cmdptr++ = 0;
						else {
							*cmdptr++ = 1;
							if (runningfromcli) {
								sprintf(buff,
									"Not 'HIRES' or 'LORES' :-\n%s\n",line);
								print(buff);
								}
							}
						p = strpbrk(p,", ");
						
						getargs(5,p);
						
						width = *(cmdptr-5);
						height = *(cmdptr-4);
						
						if(checksizes(&width,&height,
							cmdptr-3,cmdptr-2,cmdptr-1))
							*(cmdptr-6) = 1;	/*	must be HIRES	*/

						*(cmdptr-5) = width;
						*(cmdptr-4) = height;

						}
					else
						cmdsiz += 7;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 12560: 	/*  SPC: change text spacing	*/
					if (pass) {
						*cmdptr++ = 9;  /*  command code	*/
						getargs(1,p);
						}
					else
						cmdsiz += 2;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 12561: 	/*  SPD: change scroll speed	*/
					if (pass) {
						*cmdptr++ = 6;  /*  command code	*/
						getargs(1,p);
						}
					else
						cmdsiz += 2;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 12661:  	/*  SSZ: smooth sizing			*/
					if (pass) {
						*cmdptr++ = 12;  /*  command code	*/
						getargs(7,p);

						width = *(cmdptr-5);
						height = *(cmdptr-4);

						checksizes(&width,&height,
									cmdptr-3,cmdptr-2,cmdptr-1);

						*(cmdptr-5) = width;
						*(cmdptr-4) = height;

						}
					else
						cmdsiz += 8;

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				case 12845: 	/*  TAB: set tab expansion	*/
					p = strtok(stpblk(p)," ;");
					if (p != NULL && isdigit((int)*p)) {
						tab = atoi(p);
						if (tab > MAXLINE - 2)
							tab = 0;
						}
					else {
						tab = DEFAULTTABSIZE;
						if (pass && runningfromcli) {
							sprintf(buff,"Corrupt TAB command:-\n%s\n",line);
							print(buff);
							}
						}

					continue;
				
/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				default:
					if (!pass && runningfromcli) {
						sprintf(buff,"Bad code: Value: %d\n%s",j,line);
						print(buff);
						}

					continue;

/*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*	*/

				}	/*  end of switch	*/
				
			}	/* end of if	*/
			
		else {

			/*  handle lines NOT starting with escape code i.e. text	*/

			/*	expand tabs	*/
			if (strchr(line,'\t')) {

				char copy[MAXLINE + 1],last;
				register char *p, *t;
				register int n;
				int i;

				t = strcpy(copy,line); 
				p = line;

				for (n = 1; (last = *p++ = *t++) && (n <= MAXLINE); ++n) {
					if (last == '\t') {
						n--;
						p--;
						if (tab)
							for (i = tab - n % tab; i>0; i--) {
								*p++ = ' ';
								n++;
								if (n >= MAXLINE) break;
								}
						}
					}

				if (n >= MAXLINE)
					strcpy (line,copy);
				}

			if (pass) {
				*cmdptr++ = 1;
				*cmdptr++ = strlen(line)-1;

				if (centring) {
					SetFont(&rp,font);
					/*	print text at middle window height	*/
					Move(&rp,0,30+(font->tf_Baseline * 2 - font->tf_YSize)/2);
					Text(&rp,line,*(cmdptr-1));
					*cmdptr = (width - rp.cp_x)/2;
					if (*cmdptr < 0 || *cmdptr > width/2)
						*cmdptr = 0;
					++cmdptr;
					}
				else
					*cmdptr++ = ind;

				if(strlen(line) > 1)
					txptr = strncpy(txptr,line,strlen(line)-1);
				txptr += strlen(line)-1;
				}
			else {
				cmdsiz += 3;
				textsiz += strlen(line)-1;
				no_text_or_lines = 0;
				}

			}
		
		}	/* while	*/

}	/*  end of parse	*/


void getargs(number,p)
int number;
char *p;

{
	char *t;
	int fail;
	
	strcpy(buff,line);  /*  take copy 'cos strtok() changes string  */
	
	fail = 0;

	if (--number) 
		t = strtok(stpblk(p)," ,");
	else
		t = strtok(stpblk(p)," ;");
		
	if (t != NULL && isdigit(*t))
		*cmdptr++ = (short) atoi(t);
	else {
		*cmdptr++ = 0;
		fail = 1;
		}
	while (number--)
		if (fail)
			*cmdptr++ = 0;
		else {
			if (number)
				t = strtok(NULL," ,");
			else
				t = strtok(NULL," ;");

			if (t != NULL && *t == '-' || isdigit(*t))
				*cmdptr++ = (short) atoi(t);
			else {
				*cmdptr++ = 0;
				fail = 1;
				}
			}
	if (fail && runningfromcli) {
		strcpy(line,buff);
		sprintf(buff,"Corrupt command:-\n%s\n",line);
		print(buff);
		}

}	/*	end of getargs	*/

int checksizes(w,h,x,y,ox)

int   *w,*h;
short *x,*y,*ox;

{
	int hires = 0;

	if (*w > MAX_WIDTH)
		*w = MAX_WIDTH;

	if (*w < MIN_WIDTH)
		*w = MIN_WIDTH;

	if (*w > 352)
		hires=1;	/*	must be HIRES	*/

	if (*h > MAX_HEIGHT)
		*h = MAX_HEIGHT;

	if (*h < MIN_HEIGHT)
		*h = MIN_HEIGHT;

	if (*w > maxwidth)
		maxwidth = *w;

	if (*h > maxheight)
		maxheight = *h;

	if (*x > 703)
		*x = 703;

	if (*x > 351)
		hires=1;	/*	must be HIRES	*/

	if (*y > 200)
		*y = 200;

	if (*x < -16)
		*x = -16;

	if (*y < -16)
		*y = -16;

	if (*ox < 0)
		*ox = 0;

	if (*ox > 640)
		*ox = 640;
	
	return (hires);
}