#include <stdio.h>
#include <prodos.h>
#include <string.h>
#include <types.h>
#include <quickdraw.h>
#include <qdaux.h>
#include <window.h>
#include <menu.h>
#include <memory.h>
#include <dialog.h>
#include <control.h>
#include <desk.h>
#include <event.h>
#include <lineedit.h>
#include <misctool.h>
#include <locator.h>
#include <intmath.h>
#include "sc.h"
#include "sp.h"
#include "th.h"
#include <texttool.h>

#define ScreenMode 0x80
#define MaxX 640


int ToolTable[] = {8,
                4, 0x100,          /* QuickDraw II */
                5, 0x100,          /* Desk Manager */
                6, 0x100,          /* Event Manager */
                14, 0x100,         /* Window Manager */
                16, 0x100,         /* Control Mnager */
                18, 0x100,         /* QDAux */
                20, 0x100,         /* Line Edit */
                21, 0x100};        /* Dialog Manager */

extern int _SPErrNum[];
extern pascal char *THDlg();
extern pascal int SPDlg();
extern pascal void SPCloseDlg();
pascal unsigned handler();

char *dictpath;

main(argc,argv)
int argc;
char *argv[];
{
char query[200];
char *z, *junk;
int spelling=1;

	if (argc != 2) {
		fprintf(stderr,"usage: %s dictionary-directory/\r\n",argv[0]);
		exit(1);
	}
	c2pstr(argv[1]);
	dictpath = argv[1];

    MTStartUp();
    LoadTools(ToolTable);
    z = *NewHandle(0x700L, _ownerid, 0xc005, 0L);
    QDStartUp((int) z, ScreenMode, 160, _ownerid);
    QDAuxStartUp();
    EMStartUp((int) (z + 0x300), 20, 0, MaxX, 0, 200, _ownerid);
    WindStartUp(_ownerid);
    CtlStartUp(_ownerid, (int) (z + 0x500));
    LEStartUp((int) (z + 0x600), _ownerid);
    DialogStartUp(_ownerid);
    DeskStartUp();
    IMStartUp();
    RefreshDesktop(0L);
    ShowCursor();
    GrafOff();

    SPStartUp(_ownerid, dictpath);
    if (_SPErrNum[0])
        report_err("SP", _SPErrNum[0]);
	
	printf("Welcome to the Proximity SP/TH demo.\r\nType ! for help\r\n");
    while (printf(": "), mygets(query))
    {
		if (query[0] == '@')
			break;
        if (query[0] == '#') {
			if (!spelling) {
				THShutDown();
				spelling=1;
				printf("Loading spell checker\r\n");
				SPStartUp(_ownerid, dictpath);
				if (_SPErrNum[0]) {
					report_err("SP", _SPErrNum[0]);
					continue;
				}
			}
            udictcommand(query);
		}
        else if (query[0] == '%')
        {
			if (spelling) {
				SPShutDown();
				spelling=0;
				printf("Loading thesaurus\r\n");
				THStartUp(_ownerid, dictpath);
				if (_THErrNum[0]) {
					report_err("TH", _THErrNum[0]);
					continue;
				}
			}
			
            query[0] = strlen(query) - 1;
            GrafOn();
            junk = THDlg(query);
            GrafOff();
        }
		else if (query[0] == '!')
			printf("To spell-check, simply type a sentence.\r\nTo thesaurize, type %%word.\r\n\nUser dictionary commands:\r\n#open:pathname\r\n#new:pathname\r\n#close:refnum\r\n#edit:refnum\r\n#add:refnum:word\r\n\nTo quit, type ^@ or @ <cr>\r\n\n");
        else
        {
			if (!spelling) {
				THShutDown();
				spelling=1;
				printf("Loading spell checker\r\n");
				SPStartUp(_ownerid, dictpath);
				if (_SPErrNum[0]) {
					report_err("SP", _SPErrNum[0]);
					continue;
				}
			}
            GrafOn();
            SPCheck(query, NULL, SPMSENT, handler);
            SPCloseDlg();
            GrafOff();
            if (_SPErrNum[0])
                report_err("SP", _SPErrNum[0]);
        }
    }

    SPShutDown();
    THShutDown();

    GrafOff();
    IMShutDown();
    DeskShutDown();
    MenuShutDown();
    DialogShutDown();
    LEShutDown();
    CtlShutDown();
    WindShutDown();
    EMShutDown();
    QDAuxShutDown();
    QDShutDown();
    MTShutDown();

    DisposeHandle(FindHandle(z));

    exit(0);
}

fixpath(fname)
char *fname;
{
	char tmp[64];
	
	if ((*fname >= '0' && *fname <= '9') || *fname == '/')
		return;
	
	strcpy(tmp,fname);
	p2cstr(dictpath);
	strcpy(fname,dictpath);
	c2pstr(dictpath);
	strcat(fname,tmp);
}

udictcommand(q)
char *q;
{
int refnum;
char *p;

    if (!strncmp(q + 1, "new:", 4))
    {
		fixpath(q+5);
        c2pstr(q + 5);
        SPNewUDict(q + 5, 4, 0L);   /* 4 = TXT */
        if (_SPErrNum[0])
            report_err("SP", _SPErrNum[0]);
        else
            printf("ok\n", refnum);
    }
    else if (!strncmp(q + 1, "open:", 5))
    {
		fixpath(q+6);
        c2pstr(q + 6);
        refnum = SPOpenUDict(q + 6);
        if (_SPErrNum[0])
            report_err("SP", _SPErrNum[0]);
        else
            printf("refnum = %d\n", refnum);
    }
    else if (!strncmp(q + 1, "close:", 6))
    {
        sscanf(q + 7, "%d:", &refnum);
        SPCloseUDict(refnum);
        if (_SPErrNum[0])
            report_err("SP", _SPErrNum[0]);
        else
            printf("ok\n");
    }
    else if (!strncmp(q + 1, "add:", 4))
    {
        sscanf(q + 5, "%d:", &refnum);
        p = strchr(q + 5, ':') + 1;
        c2pstr(p);
        SPAddWord(refnum, p);
        p2cstr(p);
        if (_SPErrNum[0])
            report_err("SP", _SPErrNum[0]);
        else
            printf("ok\n");
    }
    else if (!strncmp(q + 1, "edit:", 5))
    {
        sscanf(q + 6, "%d", &refnum);
        GrafOn();
        SPEditUDict(refnum);
        GrafOff();
        if (_SPErrNum[0])
            report_err("SP", _SPErrNum[0]);
        else
            printf("ok\n");
    }
    else
        printf("Unknown udict command: %s\n", q + 1);
}

pascal unsigned handler(err, start, end, cor)
int err;
char *start, *end, *cor;
{
char theword[100];
char **rankptr;
int junk;

   if (err == SPCBREAK)                        /* Break means we're done */
       return(SPHFINISH);

   setbank;
   strncpy(theword + 1, start, end - start);
   theword[0] = end - start;

   switch (err)
   {
        case SPCMISSPELL:
        case SPCMISPUNC:
        case SPCCAP:
        case SPCHYPH:
            junk = SPDlg(50, theword, err, theword, NULL, 1);
            restorebank;
			if (junk == 2)
				return(SPHFINISH);
			else if (junk == 1) {
				p2cstr(theword);
				printf("^%s^\n",theword);
			}
            return(SPHACCEPT);
        case SPCREPEAT:
            p2cstr(theword);
            printf("Repeat: %s\n", theword);
            restorebank;
            return(SPHACCEPT);
        default:
            printf("Unknown spelling error (%d).\n", err);
            restorebank;
            exit(1);
   }
}

static char *SPErrList[10] = { "No error", "is active", "not active",
							  "out of memory", "too many", "bad result",
							  "bad mode", "bad refnum", "ProDOS error", "can't do it"
							};
static char *THErrList[6] = { "No error", "is active", "not active",
							  "ProDOS error", "bad meaning", "out of memory"
							};

report_err(which, what)
char *which;
int what;
{
    fprintf(stderr, "%s err: #%d %s\n", which, what,
					(*which == 'S') ? SPErrList[what] : THErrList[what]);
}

mesg(str)
char *str;
{
    c2pstr(str);
    WriteString(str);
    ReadChar(0);
    p2cstr(str);
}

mesg2(str)
char *str;
{
    c2pstr(str);
    WriteString(str);
    p2cstr(str);
}

hexmesg(num)
long num;
{
char thenum[9];

    Long2Hex(num, thenum, 8);
    thenum[8] = 0;
    mesg2(thenum);
}

mygets(s)
char *s;
{
	unsigned i;
	EventRecord evt;
	char c;
	
	for (i=0;i<200;i++) {
		fflush(stdout);
		
evtloop:
		while (!GetNextEvent(0xFFFF,&evt))
			;
		
		if (evt.what != keyDownEvt && evt.what != autoKeyEvt)
			goto evtloop;
		
		switch (c = (char) evt.message) {
			case '\r':
				s[i] = '\0';
				printf("\n");
				goto exit;

			case '\004':
				s[i] = c;
				goto exit;
			
			case '\177':
				if (i) {
					i--;
					printf("\b \b");
					fflush(stdout);
				}
				goto evtloop;
				
			default:
				s[i] = c;
				if (c > 0x7f)
					c = 0x7f;	/* print a DEL char for high-ascii. */
				putchar(c);


		}
	}

exit:
	if (i >= 200)
		s[199] = '\0';
		
	if (s[i] == '\004') {
		s[i] = '\0';
		return 0;
	} else
		return 1;
}