#define TONE
#define global
#include "MacTeach1.h"

pascal void resume() /*Allows for return to Desktop on serious error*/
	
{	if (inpfile) fclose(inp);	
	ExitToShell(); }

void main(void)

{	initMac(); /*initialize various managers etc.*/

	initteach(); /*Does required initialization for the teach progs*/
	setshuf(0);  /*No automatic shuffle for Teach3*/
	eventloop(); /*Responds to user actions*/
	}

void blank(char *string, short n)

/* On entry, contains a flag n, and a sentence 'string'. Each word is replaced by a blank,
 whose length depends on flag n. In the distribution version, n is always 1. MT4
 however, uses n = 4 to provide a long blank for certain multiple word responses.
 At one time little words were distinguished from predicates, and 2 was used for this mode.
  Words joined by '-' are considered as separate words on recall,*/

{	char *sptr;
	sptr = string;
	(n=='1') ? strcat(instring,"____ ") : strcat(instring,"___________ ");
	// rrflag indicates whether recognition (1) or recall (2)
	if (rrflag == '2') while (*sptr++) if (*sptr=='-') 
		(n==1) ? strcat(instring,"_____ ") : strcat(instring,"__ ");
	}

void promote(short n, short count)

/* One entry, n is the card number, and count is the number of elements in a test sentence. On a correct response, tell the user, advance the rung and count of right responses. If in error box, check for return to the ladder */

{	short level; /*The current test level at this rung*/
	right += 1;	// Increment the number of correct responses.
	SetDialogItemText(gItemHdl[fAns],(unsigned char *)"\pCorrect!");
	HiliteControl ((ControlHandle) gItemHdl[CANERR],255);/*Disable cancel*/
	curflag = rrflag - '1'+2;
	level = flasharray[n].flag[curflag]-'0';

/* We want to cycle through all levels before moving to the next rung. This is true if there
 is more than one element, and the level is less than the number of elements, except when 
 in style 3 combined with other conditions (no longer used in distribution version) This was
  a style where in recall mode little words were shown all at once, then other words all at
   once, so only two levels were possible. It is still available for use.*/

	if (prog == '3'  && count != 1 && level < count &&
		(curflag != 3 || level !=3 || gStyleFlg !='3'))
		++flasharray[n].flag[curflag];  // MT4 never changes this value
//Above modified for MT 4 which never changes this value.
	curflag -= 2; /*Set to rung indicator*/

/*If not already on top, advance the rung. If out of the error box range, place on rung 1 */

	if (flasharray[n].flag[curflag] != '4') 
		flasharray[n].flag[curflag] += 1;
	if (flasharray[n].flag[curflag] == '5' + drillflg)
		flasharray[n].flag[curflag] = '1';
		
	}

void showcom(short num)

/* MT1 has a set of grammatical comments inserted at various places among the test sentences.  This routine displays comment num */

{	short ch,crflg;
	Rect Box;
	const short cmtID = 9;
	long ct;
	crflg = 0;
	ct = 0L;
	fseek (cmt,compos[num],0); /*Locate text position*/
	while (getc(cmt) !='}'){}  /*Locate its beginning*/
	while ((ch=getc(cmt)) > 0 && ch != '{') { /*Move it to buffer*/
		if (ch == '\n') continue;
		else bufr[ct++] = ch;
		}
	bufr[ct] = '\0';
	HideWindow(gMainDialog);
	gTestDialog = GetNewDialog(cmtID,&gTestRecord,(DialogPtr)-1L); /*Get comment window*/
	SetRect(&Box,10,5,400,330); /*Write text to a text box*/
	ShowWindow(gTestDialog);
	SetPort(gTestDialog);
	TextFont(3);
	TextSize(10);
	outlin(1,gTestDialog);
	TETextBox(bufr,ct,&Box,0);
	}

void showeng(short n,short m)

/* Show the English sentence. On entry n is the card number to display and m is a flag
 indicating whether the English alternatives, if present, should be displayed (1) or not (0)*/

{	char *start; /*Display test sentence without punctuation flags*/
	mainsent(instring,flasharray[n].engsent); 
	SetDialogItemText(gItemHdl[fEng],CtoPstr(instring));
	if (!m) return; /*Finished if no alternatives wanted*/

/*cflag is one if alternatives are present. Prepare the complete sentence with alternatives*/

	if (cflag==1) mycpy(instring,flasharray[n].engsent);

/*cflag is 2 if no alternatives are present, but a comment is present. Prepare the comment only for display*/

	else if (cflag==2) {
		start = flasharray[n].engsent;
		while (*start != '|' && *start++){}
		mycpy(instring,start);
		}
	if (cflag) SetDialogItemText(gItemHdl[fEngAlt],CtoPstr(instring));
	}


short showline(short count,short level,short backIndex)

/* Show a test line. On entry count is the number of words in the test sentence,
 level is the current test word index and backIndex is a back to front presentation index. 
 The value level is returned. */

{	short i,k,l,m;
	char tmpwd[150];
	l = 0;
	instring[0] = '\0';
	for (k=0; k<count; ++k) {
		mainsent(tmpwd,wordptr[k]); /*Remove punctuation from words*/
		strcat(tmpwd," ");	/*Insert a space*/

/*Styleflag 1 replaces words 1 at a time from the rear with blanks;
  Styleflag 2 adds one new blank word each time starting at the rear;
  Styleflag 3 replaces all LW with blanks at once, then all predas*/

		switch (gStyleFlg) { /*Replace(s) test word with blank(s)*/
		case '1':
		case '4':
			if (l != backIndex) strcat(instring,tmpwd);
			else blank(wordptr[k],gStyleFlg);
			break;
		case '2':
			if (l < backIndex)  strcat(instring,tmpwd);
			else blank(wordptr[k],gStyleFlg); // Altered for MT4
			break;
		case '3':
			if (rrflag=='2') {
				m = 0;
				for (i=0; i<count; ++i) if (pred(wordptr[i])) ++m;
				switch (level) {
				case 0:
					if (m==count) level=1;
					else {
						if (pred(wordptr[k])) strcat(instring,tmpwd);
						else blank(wordptr[k],2);
						break;
						}
				case 1:
					if (!m) level =2;
					else {
						if (!pred(wordptr[k])) strcat(instring,tmpwd);
						else blank(wordptr[k],1);
						break;
						}
				case 2:
					if (m==0 || m==count) level=3;
					else {
						if (pred(wordptr[k])) blank(wordptr[k],1);
						else blank(wordptr[k],2);
						break;
						}
				default: 
					instring[0] = '\0';
					strcat(instring,BIGSP);
					if (cmmt) strcat(instring,cmmt);
					(rrflag=='1')?SetDialogItemText(gItemHdl[fEng],CtoPstr(instring)) :
						SetDialogItemText(gItemHdl[fLog],CtoPstr(instring));
					return level;
					}
				}
			else 
				if (l != backIndex) strcat(instring,tmpwd);
				else blank(wordptr[k],1);
			break;
		default: break;
			}
		++l;
		}
	if (rrflag=='1') SetDialogItemText(gItemHdl[fEng],CtoPstr(instring));
	else {
		if (cmmt) strcat(instring,cmmt);
		SetDialogItemText(gItemHdl[fLog],CtoPstr(instring));
		}
	return level;
	}

void showlog(short n,short m)

/* Show the Loglan sentence for card n.  If m is not zero, show the sentence with
 alternatives present as well as the main sentence */

{	//char *start; /*Display test sentence without punctuation flags*/
	mainsent(instring,flasharray[n].logsent); 
	SetDialogItemText(gItemHdl[fLog],CtoPstr(instring));
	if (!m) return; /*Finished if no alternatives wanted*/

/*cflag is one if alternatives are present. Prepare the complete sentence with alternatives*/

	if (cflag==1) mycpy(instring,flasharray[n].logsent);
	if (cflag) SetDialogItemText(gItemHdl[fEngAlt],CtoPstr(instring));
	}

short showsel(short n)

/*Show card n for selection purposes. Display the number selected. Returns a code for stop,
pass over, or next card. */

{	char mystr[20];
	short itemHit;
	if (!strlen(flasharray[n].logsent)) showcom(getn(n));
	else {
		showcard(cSelect);
		if (rrflag == '2') {
			showlog(n,1);
			showeng(n,0);
			}
		else {
			showlog(n,0);
			showeng(n,1);
			}
		sprintf(mystr,"%3d Selected.",selection);
		SetDialogItemText(gItemHdl[3],CtoPstr(mystr));
		++selection;
		}
	ModalDialog(0L,&itemHit);
	CloseDialog(gTestDialog);
	return (itemHit);
	}

short showtest(short n,short dlgid)

/* Display item n for review or test, using Dialog resource # dlgid */

{	short count,level,index,ind4,itemHit;
	char brstring[MAXSENT]; /*Input line broken into words*/
	char mystr[15];
	showcard(dlgid);
	if (reviewflag) { /*Show number left to review*/
		sprintf(mystr,(char *)"%3d Left",left);
		SetDialogItemText(gItemHdl[3],CtoPstr(mystr));
		--left;
		}
	if (rrflag=='1') {/*Show the appropriate display for recog or recall*/
		showlog(n,0);
		strcopy(brstring,flasharray[n].engsent);
		strcopy(gSentence,flasharray[n].engsent);
		}
	else {
		showeng(n,0);
		strcpy(brstring,flasharray[n].logsent);
		strcopy(gSentence,flasharray[n].logsent);
		}
	count = breakup(brstring,wordptr); /*Identify the test pieces*/
	level = flasharray[n].flag[rrflag-'0'+1] - '0';
	index = ind4 = count-level-1;

/*Showtest does both review and test. This is test. Only one level of a sentence is tested
 at a time, and all sentences on the rung are tested at this level before proceding to the
  next*/

	if (!reviewflag || prog == '5') {
		countflag(); /*Recalculate the number on each rung*/
		sprintf(mystr,(char *)"%3d Left",r[rungflag-'0']);
		if (!reviewflag) SetDialogItemText(gItemHdl[7],CtoPstr(mystr));

/*Identify the appropriate words to blank out and do so*/

		if (count==1 || level==count || (gStyleFlg=='3' && rrflag == '2'	
			&& level==3)) {  /*Whole sentence must be requested*/
				instring[0] = '\0';
				strcat(instring,BIGSP);
				if (cmmt) strcat(instring,cmmt);
				(rrflag=='1') ? SetDialogItemText(gItemHdl[fEng],CtoPstr(instring)) :
					SetDialogItemText(gItemHdl[fLog],CtoPstr(instring));
			}
		else level = showline(count,level,index); /*Select style*/
		flasharray[n].flag[rrflag-'0'+1] = level + '0';
		if (reviewflag) {
//			SetDialogItemText(gItemHdl[fEngAlt],(unsigned char *)"\p  ");
//			ModalDialog(NULL,&itemHit);
//			(rrflag=='1') ? showeng(n,1) : showlog(n,1);
//			ModalDialog(NULL,&itemHit);
			(rrflag=='1') ? showlog(n,1) : showeng(n,1); /*Show blanks*/
			if (itemHit==STOPF ) {
				CloseDialog(gTestDialog);
				return itemHit;
				 }
			ModalDialog(NULL,&itemHit);
			(rrflag-'1') ? showlog(n,1) : showeng(n,1); /*Display right answer*/
			ModalDialog(NULL,&itemHit);
			CloseDialog(gTestDialog);
			return itemHit;
			}
		macticks = TickCount(); /*Get start time*/
		ind1 = 0;
		ModalDialog(NewModalFilterProc((ProcPtr)Timeget),&itemHit);
		if (itemHit==STOPF) { /*Stopping allowed before test*/
			CloseDialog(gTestDialog);
			return itemHit;
			}
		GetDialogItemText(gItemHdl[fIn],(unsigned char *)instring);
		PtoCstr((unsigned char *)instring);
		statdo(ticks); /* update the statistics */
		marktest(n,count,level,index); /*check answer for correctness*/
		(rrflag-'1') ? showlog(n,1) : showeng(n,1); /*Display right answer*/
		ModalDialog(NULL,&itemHit);
		CloseDialog(gTestDialog);
		return itemHit;
		}
	else {

/*During review, all levels of a given sentence are displayed before moving on to the next*/

		for (level=0; level<count+1; ++level) { 
			index = count-level-1;
			if (count==1 || level==count ||(gStyleFlg=='3' && rrflag=='2' 
				&& level>2)) {
				instring[0] = '\0';
				strcat(instring,BIGSP);
				if (cmmt) strcat(instring,cmmt);
				(rrflag=='1') ? SetDialogItemText(gItemHdl[fEng],CtoPstr(instring)) :
					SetDialogItemText(gItemHdl[fLog],CtoPstr(instring));
				SetDialogItemText(gItemHdl[fEngAlt],(unsigned char *)"\p  ");
				ModalDialog(NULL,&itemHit);
				if (itemHit==STOPF) {
					CloseDialog(gTestDialog);
					return itemHit;
					}
				(rrflag=='1') ? showeng(n,1) : showlog(n,1); /*Show blanks*/
				ModalDialog(NULL,&itemHit);
				CloseDialog(gTestDialog);
				return itemHit;
				}
			else level = showline(count,level,index); /*Select style*/
			SetDialogItemText(gItemHdl[fEngAlt],(unsigned char *)"\p  ");
			ModalDialog(NULL,&itemHit);
			(rrflag=='1') ? showeng(n,1) : showlog(n,1);
			ModalDialog(NULL,&itemHit);
			if (itemHit==STOPF ||(gStyleFlg=='3' && rrflag=='2' 
					&& level>2)) {
				CloseDialog(gTestDialog);
				return itemHit;
				}
			}
		}
	return 0;
	}

short showwarning(void)

/* This shows a special dialog warning the user not to cancel an error
unless it was an inadvertent spelling error*/

{	short itemHit;
	const short wngDlg = 10;
	DialogPtr dDialog;	/*used in warning dialog for MT1 only*/
	DialogRecord inRecord;	/*Dialog record storage*/
	dDialog = GetNewDialog(wngDlg,&inRecord,(DialogPtr)-1L);
	ShowWindow(dDialog);
	outlin(1,dDialog);
	ModalDialog(0L,&itemHit);
	DisposeDialog(dDialog);
	return itemHit;
	}

