#include <qd.h>
#include <qdvars.h>
#include <res.h>
#include <mem.h>
#include <event.h>
#include <desk.h>
#include <menu.h>
#include <stdio.h>
#include <string.h>
#include <toolbox.h>
#include <te.h>
#include <dialog.h>
#include <win.h>
#include <control.h>
#include <file.h>
#include <pack.h>
#include <misc.h>

char firstword[16], lastword[16];
char dictprefix[16];
extern long dictroot, dictlookup ();

rect drect;
rect dviewrect;
rect dterect;
rect dteoutrect;
rect dfliprect;
rect dscrollrect;

windowptr dictwin;
windowrecord dwrecord;
tehandle dictte;
rgnhandle junkrgn;
controlhandle dscrollbar;

long dtickle;
#define TICKS		10

#define DICTX		333
#define DICTY		97
#define DICTLINES	7
#define DICTLHEIGHT	16
#define DICTWIDTH	120
#define HFUDGE		3
#define VFUDGE		12
#define SBW			16
#define	XX			16
#define TEHEIGHT	(DICTLHEIGHT+2*HFUDGE)

#define	DMIN	0
#define DMAX	27*26+1

windowptr newdictwindow ()
{
    int dictref;
	long dictsize;
	ptr space;
	char apname[100];
	handle apparam;

	dictwin = NULL;
	getappparms (apname, &dictref, &apparam);
	fsopen (apname, 0, &dictref);
	geteof (dictref, &dictsize);
	space = newptr (dictsize);
	fsread (dictref, &dictsize, space);
	fsclose (dictref);
	setdawg (space, dictsize);
	dictwinsetup ();
	return dictwin;
}

dicttask ()
{
	if (dictwin)
		teidle (dictte);
}

dictactivate (yesno) int yesno;
{
	if (yesno)
		teactivate (dictte);
	else
		tedeactivate (dictte);
}

dictupdate ()
{
	drawcontrols (dictwin);
	teupdate (&dterect, dictte);
	dictdraw ();
}

dictdisplay ()
{
	static int firsttime = 1;
	static char crab[] = "scrabble";

	if (firsttime) {
		setprefix ();
		mapdown (crab);
		setdict (crab);
		setdscroll ();
		firsttime = 0;
		showwindow (dictwin);
	}
	selectwindow (dictwin);
}

dictwinsetup ()
{
	grafptr saveport;

	getport (&saveport);
	setrect (&drect, DICTX, DICTY, 
		DICTX + 1 + 2 * XX + DICTWIDTH + SBW,
		DICTY + 2 + 3 * XX + DICTLINES * DICTLHEIGHT + TEHEIGHT);
	dictwin = newwindow (&dwrecord, &drect, "Dictionary", 0,
		nogrowdocproc, NULL, 1, (long) 0);
	setport (dictwin);
	textfont (systemfont);
	dfliprect = dictwin -> portrect;
	insetrect (&dfliprect, XX, XX);
	dteoutrect = dfliprect;
	dteoutrect.a.top = dteoutrect.a.bottom - TEHEIGHT;
	dteoutrect.a.right = dteoutrect.a.left + DICTWIDTH + 2;
	dterect = dteoutrect;
	insetrect (&dterect, HFUDGE, HFUDGE);
	dfliprect.a.bottom -= TEHEIGHT + XX;
	dscrollrect = dfliprect;
	dscrollrect.a.left = dscrollrect.a.right - SBW;
	dviewrect = dfliprect;
	insetrect (&dviewrect, 1, 1);
	dviewrect.a.right = dviewrect.a.left + DICTWIDTH;
	dscrollbar = newcontrol (dictwin, &dscrollrect, "", 1,
		DMIN, DMIN, DMAX, scrollbarproc, (long) 0);
	dictte = tenew (&dterect, &dterect);
	junkrgn = newrgn ();
	setport (saveport);
}

dictclick (where, mods) point *where; int mods;
{
	int dictscroll ();
	int part;
	controlhandle cntl;
	char x[4];

	if (part = findcontrol (where, dictwin, &cntl)) {
		if (cntl == dscrollbar) 
			switch (part) {
				case inupbutton:
				case inpageup:
				case indownbutton:
				case inpagedown:
					dtickle = tickcount () + TICKS;
					trackcontrol (dscrollbar, where, dictscroll);
					break;
				case inthumb:
					if (trackcontrol (dscrollbar, where, NULL)) {
						valstring (getctlvalue (dscrollbar), x);
						setdict (x);
						setdscroll ();
						dictdraw ();
					}
					break;
			}
	}
	else if (ptinrect (where, &dterect))
		teclick (where, mods & shiftkey, dictte);
}

dictkey (what) char what;
{
	char whole[16];

	strcpy (whole, dictprefix);
	if (dictroot && what != ' ' && what != '\r')
		strcat (whole, firstword);
	if (what != '\b' && what != ' ' && what != '\r'
		&& (what < 'a' || what > 'z')) {
		if (what < 'A' || what > 'Z') {
			sysbeep (3);
			return;
		}
		what += 'a' - 'A';
	}
	if (what == '\r') {
		tesettext ("", 0L, dictte);
		eraserect (&dterect);
	}
	else if (what != ' ')
		tekey (what, dictte);
	setprefix ();
	trackword (whole);
	setdscroll ();
	dictdraw ();
}

dictdraw ()
{
	int i;
	char word[16];

	framerect (&dfliprect);
	framerect (&dteoutrect);
	if (dictroot) {
		eraserect (&dviewrect);
		strcpy (word, firstword);
		for (i = 0; i < DICTLINES; i++) {
			dictline (i, word);
			if (!nextword (word, word))
				break;
		}
	}
	else
		fillrect (&dviewrect, &gray);
	hilitecontrol (dscrollbar, 
		(nextword (lastword, word) || prevword (firstword, word))
		? 0 : 255);	
}

dictline (i, w) int i; register char *w;
{
	char buf[16];

	moveto (dviewrect.a.left + HFUDGE,
			dviewrect.a.top + i * DICTLHEIGHT + VFUDGE);
	strcpy (buf, dictprefix);
	strcat (buf, w);
	mapup (buf);
	drawstring ((qdptr) buf);
}

pascal dictscroll (sb, part) controlhandle sb; int part;
{
	switch (part) {
		case inupbutton:
			if (prevword (firstword, firstword)) {
				prevword (lastword, lastword);
				scrollrect (&dviewrect, 0, DICTLHEIGHT, junkrgn);
				dictline (0, firstword);
			}
			break;
		case inpageup:
			if (prevword (firstword, lastword)) {
				fixup ();
				dictdraw ();
			}
			break;
		case indownbutton:
			if (nextword (lastword, lastword)) {
				nextword (firstword, firstword);
				scrollrect (&dviewrect, 0, -DICTLHEIGHT, junkrgn);
				dictline (DICTLINES - 1, lastword);
			}
			break;
		case inpagedown:
			if (nextword (lastword, firstword)) {
				fixdown ();
				dictdraw ();
			}
			break;
	}
	setdscroll ();
	while (dtickle > tickcount ())
		systemtask ();
}

setdscroll ()
{
	char junk[16];

	setctlvalue (dscrollbar,
		(!nextword (lastword, junk)) ? DMAX :
		(!prevword (firstword, junk)) ? DMIN :
		stringval (firstword));
}

setprefix ()
{
	int i;
	char *p;

	i = (*dictte) -> telength;
	if (i > 15)
		i = 15;
	p = *((char **) (*dictte) -> htext);
	strncpy (dictprefix, p, i);
	dictprefix[i] = '\0';
	mapdown (dictprefix);
	dictroot = dictlookup (dictprefix);
}

trackword (old) char *old;
{
	char *p;
	char x[4];
	
	p = dictprefix;
	while (*p)
		if (*p++ != *old++) {
			valstring ((*--p > *--old) ? DMIN : DMAX, x);
			setdict (x);
			return;
		}
	setdict (old);
}

setdict (s) char *s;
{
	strcpy (firstword, s);
	if (isword (firstword) || 
		nextword (firstword, firstword) ||
		prevword (firstword, firstword))
		fixdown ();
}

fixdown () 
{
	int i;

	strcpy (lastword, firstword);
	for (i = 1; i < DICTLINES; i++)
		if (!nextword (lastword, lastword))
			prevword (firstword, firstword);
}

fixup () 
{
	int i;

	strcpy (firstword, lastword);
	for (i = 1; i < DICTLINES; i++)
		if (!prevword (firstword, firstword))
			nextword (lastword, lastword);
}

stringval (s) char *s;
{
	return *s ? (27 * (s[0] - 1) + s[1] + 1) : 0;
}

valstring (i, s) int i; char *s;
{
	char *p = s;

	if (i--) {
		*p++ = i / 27 + 1;
		*p++ = i % 27;
	}
	*p = '\0';
}

mapdown (s) register char *s;
{
	while (*s)
		*s++ -= ('a' - 1);
}

mapup (s) register char *s;
{
	while (*s)
		*s++ += ('a' - 1);
}
