mirror of
https://github.com/antoinevignau/source.git
synced 2024-11-16 19:05:36 +00:00
1 line
19 KiB
C
Executable File
1 line
19 KiB
C
Executable File
|
||
/* SP.C Robert A. Hearn */
|
||
|
||
#include <types.h>
|
||
#include <memory.h>
|
||
#include "sp.h"
|
||
#include "spdef.h"
|
||
#include "sc.h"
|
||
#include "scparam.h"
|
||
#include "string.h"
|
||
/*#include "ctype.h"*/
|
||
#include "stdio.h"
|
||
#include "query.h"
|
||
#include "clam.h"
|
||
#include "lex.h"
|
||
#include "corelex.h"
|
||
#include "driver.h"
|
||
|
||
/* SP.C: This file contains the SP routines, which interface to the Proximity
|
||
routines. The assembly language interface to these routines is in spint.src.
|
||
Unless I hand-code some of these, which seems fairly probable. */
|
||
|
||
extern char *SPJumpLoc[];
|
||
extern unsigned _SPActive[];
|
||
extern unsigned _THActive;
|
||
|
||
/* SP private globals */
|
||
|
||
unsigned _SPListAlts;
|
||
unsigned _SPXVal;
|
||
unsigned _SPID;
|
||
long _SPHandler;
|
||
char *_SPdir;
|
||
char *WcurDoc; /* so it can be updated */
|
||
char *SPCancelled = "\pSpell checking was cancelled.";
|
||
char *SPBroken = "\pCould not open the user dictionary.\rIt may be corrupt.";
|
||
|
||
/* Stuff local to sp.c */
|
||
|
||
static unsigned inhyph; /* In hypenated word to scan word-by-word */
|
||
static unsigned mustbecap; /* This word must be capitalized */
|
||
static unsigned repeating; /* Calling GetWord at same place as before */
|
||
static unsigned wantperiod; /* GetWord should attach ending pd to word */
|
||
static unsigned firsttime; /* First time through SPCheck? */
|
||
static char *cmndtab; /* Command char table */
|
||
static char lastword[MAXWORD]; /* Previous word */
|
||
static unsigned lastflags; /* Previous word's flags */
|
||
static unsigned cancelled; /* Cancelled? */
|
||
static unsigned errcode; /* What spelling error occurred? */
|
||
static unsigned result;
|
||
|
||
/* These are maintained by lots of things. */
|
||
|
||
static char *sp; /* Word start ptr */
|
||
static char *ep; /* Word end ptr */
|
||
static char *rp; /* Ptr to rest of text (after endpunc) */
|
||
char *prevp; /* pointer to the end of the previous word */
|
||
|
||
/* These are maintained by GetWord. */
|
||
|
||
static char wbuf[MAXWORD]; /* Word buffer */
|
||
static unsigned flags; /* Word characteristics */
|
||
static char epfirst; /* First chararacter in end punctuation */
|
||
static char eplast; /* Last character in end punctuation */
|
||
static char epnum; /* Number of end punctuation chars */
|
||
|
||
/* This is maintained by CheckWord. */
|
||
|
||
static char corbuf[MAXWORD]; /* Corrected word if SPCMISPUNC or SPCHYPH. */
|
||
|
||
/* This is for the udict stuff */
|
||
|
||
CLAM *_SPudtable[SPMAXUDICT]; /* CLAM ptrs */
|
||
char **_SPudpn[SPMAXUDICT]; /* Pathname handles */
|
||
|
||
/* Static declarations for wimpy C compiler */
|
||
|
||
static int NextChar();
|
||
static unsigned EatWhite();
|
||
static unsigned GetWord();
|
||
static unsigned CheckWord();
|
||
static void MakeLower();
|
||
static unsigned GetUDSlot();
|
||
|
||
extern pascal unsigned _SPMetaHandler();
|
||
|
||
|
||
/* Startup the spell checker. */
|
||
|
||
pascal void _SPStartUp(mmid, spdir)
|
||
unsigned mmid;
|
||
char *spdir;
|
||
{
|
||
unsigned len;
|
||
unsigned x;
|
||
|
||
if (_SPActive[0])
|
||
SPErr2(SPACTIVE, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
_SPID = _SPTHID[0] = mmid + SPTHID;
|
||
toolErr[0] = &_toolErr; /* &%^$%$!@@!@!! */
|
||
|
||
if (!meminit())
|
||
SPErr2(SPNOMEM, 0);
|
||
|
||
len = *(unsigned *) spdir;
|
||
_SPdir = spdir+2;
|
||
_SPdir[len] = '\0';
|
||
|
||
if (!clxopen(1, SP_CORRECT + SP_DETECT))
|
||
if (*toolErr[0])
|
||
{
|
||
SPErr2(SPPRODOS, *toolErr[0]);
|
||
}
|
||
else
|
||
{
|
||
SPErr2(SPCANTDOIT, 0);
|
||
}
|
||
|
||
strcat(_SPdir, "Dictionary");
|
||
|
||
if (!lexopen(2, SP_CORRECT + SP_DETECT, _SPdir))
|
||
{
|
||
if (*toolErr[0])
|
||
{
|
||
SPErr2(SPPRODOS, *toolErr[0]);
|
||
}
|
||
else
|
||
{
|
||
SPErr2(SPCANTDOIT, 0);
|
||
}
|
||
}
|
||
|
||
for (x = 0; x < SPMAXUDICT; ++x)
|
||
_SPudtable[x] = NULL;
|
||
|
||
_SPActive[0] = 1;
|
||
}
|
||
|
||
/* Shut down SP */
|
||
|
||
pascal void _SPShutDown()
|
||
{
|
||
unsigned x;
|
||
|
||
if (!_SPActive[0])
|
||
SPErr2(SPINACTIVE, 0);
|
||
|
||
/* Close the dictionaries */
|
||
|
||
for (x = 0; x < SPMAXUDICT; ++x)
|
||
if (_SPudtable[x])
|
||
{
|
||
clamclose(_SPudtable[x]);
|
||
DisposeHandle(_SPudpn[x]);
|
||
}
|
||
clxclose();
|
||
|
||
lexclose();
|
||
|
||
_SPErrNum[0] = 0;
|
||
_SPActive[0] = 0;
|
||
}
|
||
|
||
/* Spell-check the text at tp. */
|
||
|
||
pascal void _SPCheck(tp, ct, mode, h, curdoc, wcancel)
|
||
char *tp; /* Ptr to to text */
|
||
char *ct; /* Ptr to command table */
|
||
unsigned mode; /* Initial mode */
|
||
long h; /* Error handler - must lie to the compiler
|
||
about type. 'pascal' keyword not valid here. */
|
||
char *curdoc; /* in case it has to be updated */
|
||
unsigned *wcancel; /* if you cancel, let WP know about it */
|
||
{
|
||
|
||
if (!_SPActive[0])
|
||
SPErr2(SPINACTIVE, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
WcurDoc = curdoc;
|
||
|
||
if (!*Clxdata)
|
||
{
|
||
clxfree();
|
||
if (!getacorelex())
|
||
SPErr2(SPNOMEM, 0);
|
||
}
|
||
|
||
if (mode == SPMSENT)
|
||
mustbecap = 1;
|
||
else if (mode == SPMNOSENT)
|
||
mustbecap = 0;
|
||
else
|
||
SPErr2(SPBADMODE, 0);
|
||
|
||
inhyph = repeating = wantperiod = 0;
|
||
|
||
lastword[0] = 0;
|
||
flags = 0;
|
||
sp = tp;
|
||
_SPHandler = h; /* make it global */
|
||
cmndtab = ct ? ct : _SPdeftab;
|
||
|
||
while (1)
|
||
{
|
||
asm {
|
||
jsl D_BEACHBALL
|
||
bcc OK
|
||
}
|
||
*wcancel = 1;
|
||
(void) D_ALERTBOX(okBox,SPCancelled);
|
||
return;
|
||
OK:
|
||
if (!EatWhite())
|
||
SPErr2(_SPErrNum[0], _SPXVal); /* _SPErrNum may be 0 */
|
||
|
||
/* GetWord gets a word and determines its flags. */
|
||
|
||
prevp = ep;
|
||
if (!GetWord())
|
||
{
|
||
if (_SPErrNum[0])
|
||
SPErr2(_SPErrNum[0], _SPXVal);
|
||
|
||
/* Hit a final break... quit if cancel or buf empty. */
|
||
|
||
if (cancelled || !wbuf[0])
|
||
return;
|
||
}
|
||
|
||
|
||
/* See if adding a period is required and we have one to attach
|
||
(determined in CheckWord). If so, there may still be other
|
||
punctuation errors. */
|
||
|
||
if ((errcode = CheckWord()) == WANTPD)
|
||
{
|
||
strcat(wbuf, ".");
|
||
if (isword(wbuf))
|
||
{
|
||
/* Rescan the word, taking final period this time. May seem
|
||
a little extreme, but the state information is needed, and
|
||
other errors may occur. */
|
||
|
||
wantperiod = repeating = 1;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
wbuf[strlen(wbuf) - 1] = 0;
|
||
errcode = SPCMISSPELL;
|
||
}
|
||
}
|
||
|
||
if (errcode)
|
||
{
|
||
/* If it has hyphens and its unhyphenated version is not a
|
||
word, try looking at it word by word. */
|
||
|
||
if (flags & THYPHEN && errcode != SPCHYPH)
|
||
{
|
||
repeating = inhyph = 1;
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
switch((result = _SPMetaHandler(errcode, sp, ep, corbuf, prevp)) &
|
||
CODEMASK)
|
||
{
|
||
case SPHACCEPT:
|
||
break;
|
||
case SPHREPLACE:
|
||
repeating = 1;
|
||
case SPHJUMP:
|
||
if (SPJumpLoc[0])
|
||
{
|
||
sp = SPJumpLoc[0];
|
||
SPJumpLoc[0] = NULL;
|
||
}
|
||
continue;
|
||
case SPHCANCEL:
|
||
case SPHFINISH:
|
||
return;
|
||
default:
|
||
SPErr2(SPBADRESULT, result);
|
||
}
|
||
}
|
||
}
|
||
|
||
strcpy(lastword, wbuf);
|
||
MakeLower(lastword);
|
||
lastflags = flags;
|
||
|
||
inhyph = inhyph && flags & BEFOREHYPH;
|
||
mustbecap = !(flags & BEFOREHYPH + BEFORESLASH) && (eplast == '.' ||
|
||
eplast == '?' || eplast == '!') && (epnum == 1);
|
||
repeating = 0;
|
||
|
||
sp = rp;
|
||
}
|
||
}
|
||
|
||
/* Suggest correct spellings for wptr (presumed incorrect). Return corrections
|
||
in Pascal format. */
|
||
|
||
static char *justcor[2];
|
||
|
||
pascal char **_SPSuggest(wptr, listalts)
|
||
char *wptr;
|
||
unsigned listalts;
|
||
{
|
||
char **result;
|
||
char **rp;
|
||
|
||
if (!_SPActive[0])
|
||
SPErr(SPINACTIVE, 0, NULL);
|
||
_SPErrNum[0] = 0;
|
||
|
||
if (!*Clxdata)
|
||
{
|
||
clxfree();
|
||
if (!getacorelex())
|
||
SPErr(SPNOMEM, 0, NULL);
|
||
}
|
||
|
||
if ((_SPListAlts = listalts) > MAXLISTALTS)
|
||
SPErr(SPTOOMANY, 0, NULL);
|
||
|
||
if (wptr == NULL)
|
||
{
|
||
/* Use the word SPCheck gave to the handler. If SPCMISPUNC or
|
||
SPCHYPH, just give corbuf (already in Pascal format). */
|
||
|
||
if ((errcode == SPCMISPUNC) || (errcode == SPCHYPH) || (errcode ==
|
||
SPCCAP))
|
||
{
|
||
justcor[0] = corbuf;
|
||
justcor[1] = NULL;
|
||
return(justcor);
|
||
}
|
||
|
||
result = correct(wbuf);
|
||
}
|
||
else
|
||
{
|
||
p2cstr(wptr);
|
||
result = correct(wptr);
|
||
c2pstr(wptr);
|
||
}
|
||
|
||
for (rp = result; *rp; ++rp)
|
||
c2pstr(*rp);
|
||
|
||
return(result);
|
||
}
|
||
|
||
/* Open a previously created user dictionary */
|
||
|
||
pascal unsigned _SPOpenUDict(name)
|
||
char *name; /* this is already a C string */
|
||
{
|
||
unsigned refnum;
|
||
|
||
if (!_SPActive[0])
|
||
SPErr(SPINACTIVE, 0, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
_SPTHID[0] = _SPID;
|
||
|
||
/* Find an unused udict slot if there is one */
|
||
|
||
for (refnum = 0; refnum < SPMAXUDICT; ++refnum)
|
||
if (!_SPudtable[refnum])
|
||
break;
|
||
|
||
if (_SPudtable[refnum])
|
||
SPErr(SPTOOMANY, 0, 0);
|
||
|
||
|
||
if (!(_SPudtable[refnum] = clamopen(refnum + 3, SP_CORRECT + SP_DETECT,
|
||
name, 0, 0L)))
|
||
{
|
||
if (*toolErr[0])
|
||
{
|
||
SPErr(SPPRODOS, *toolErr[0], 0);
|
||
}
|
||
else
|
||
{
|
||
SPErr(SPCANTDOIT, 0, 0);
|
||
}
|
||
}
|
||
|
||
_SPudpn[refnum] = (char **) NewHandle((long) strlen(name) + 1, _SPID,
|
||
0x0010, 0L);
|
||
strcpy(*_SPudpn[refnum], name);
|
||
|
||
|
||
return(refnum + 1); /* Publicly, refnums begin at 1 */
|
||
}
|
||
|
||
|
||
|
||
/* <20><><EFBFBD> Dead Code
|
||
|
||
/* Close a user dictionary *
|
||
|
||
pascal void _SPCloseUDict(refnum)
|
||
unsigned refnum;
|
||
{
|
||
if (!_SPActive[0])
|
||
SPErr2(SPINACTIVE, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
--refnum;
|
||
if (refnum < 0 || refnum >= SPMAXUDICT)
|
||
SPErr2(SPBADREF, 0);
|
||
if (!_SPudtable[refnum])
|
||
SPErr2(SPBADREF, 0);
|
||
|
||
clamclose(_SPudtable[refnum]);
|
||
_SPudtable[refnum] = NULL;
|
||
DisposeHandle(_SPudpn[refnum]);
|
||
}
|
||
|
||
*/
|
||
|
||
|
||
/* Create a new user dictionary */
|
||
|
||
pascal void _SPNewUDict(name, ftype, atype)
|
||
char *name; /* already a C string */
|
||
unsigned ftype;
|
||
long atype;
|
||
{
|
||
CLAM *cp;
|
||
|
||
if (!_SPActive[0])
|
||
SPErr2(SPINACTIVE, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
_SPTHID[0] = _SPID;
|
||
|
||
|
||
/* Possible list #s are 1 - 10; use 11 */
|
||
|
||
if (!(cp = clamopen(11, CL_INIT, name, ftype, atype)))
|
||
{
|
||
SPErr2(SPPRODOS, *toolErr[0]);
|
||
}
|
||
|
||
clamclose(cp);
|
||
|
||
}
|
||
|
||
/* Add a word to a user dictionary */
|
||
|
||
pascal void _SPAddWord(refnum, word)
|
||
unsigned refnum;
|
||
char *word;
|
||
{
|
||
char buf[2*MAXWORD];
|
||
unsigned flags;
|
||
char *thePath, *pos;
|
||
HANDLE f;
|
||
|
||
extern char *c2pstr1();
|
||
extern HANDLE stdcreate();
|
||
extern void stdclose();
|
||
|
||
|
||
|
||
if (!_SPActive[0])
|
||
SPErr2(SPINACTIVE, 0);
|
||
_SPErrNum[0] = 0;
|
||
|
||
_SPTHID[0] = _SPID;
|
||
|
||
if (refnum < 1 || refnum > SPMAXUDICT)
|
||
SPErr2(SPBADREF, 0);
|
||
if (!_SPudtable[refnum - 1])
|
||
SPErr2(SPBADREF, 0);
|
||
|
||
/* see if we have some disk space */
|
||
|
||
thePath = *_SPudpn[refnum-1];
|
||
if (pos = strrchr(thePath,':'))
|
||
pos++;
|
||
else
|
||
pos = thePath;
|
||
strcpy(pos, "bobo.temp");
|
||
if ((f = stdcreate(thePath, 0, 0L)) != H_ERROR) {
|
||
char *path1;
|
||
|
||
stdclose(f);
|
||
f = 0;
|
||
if ((path1 = c2pstr1(thePath)) != (char *) 0xFFFFFFFFL) {
|
||
D_DESTROY2(path1);
|
||
D_DISPOSEPTR(path1);
|
||
}
|
||
} else
|
||
D_ALERTBOX(okBox,"\pThe word could not be added.");
|
||
strcpy(pos,"User.Dictionary");
|
||
if (f)
|
||
return;
|
||
|
||
|
||
p2cstr(word);
|
||
flags = doflags(word, buf, MAXWORD);
|
||
|
||
if (clamadd(buf, flags, _SPudtable[refnum - 1]) != OKAY)
|
||
{
|
||
c2pstr(word);
|
||
if (*toolErr[0])
|
||
{
|
||
_SPErrNum[0] = SPPRODOS;
|
||
_SPXVal = *toolErr[0];
|
||
}
|
||
else
|
||
{
|
||
_SPErrNum[0] = SPCANTDOIT;
|
||
_SPXVal = 0;
|
||
}
|
||
}
|
||
c2pstr(word);
|
||
/* force a flush of any buffers */
|
||
clamclose(_SPudtable[refnum-1]);
|
||
if (!(_SPudtable[refnum-1] = clamopen(refnum+2, SP_DETECT+SP_CORRECT, *_SPudpn[refnum-1], 0xD0, 0x8001L)))
|
||
D_ALERTBOX(okBox,SPCancelled);
|
||
|
||
}
|
||
|
||
|
||
/* */
|
||
/* Support routines follow */
|
||
/* */
|
||
|
||
|
||
/* NextChar finds the next real character from a specified position. Positions
|
||
the pointer there and returns the char, or -1 if nonrecoverable break.
|
||
Char may be different from what is pointed to (if SPHSUBST). Sets cancelled
|
||
if cancelled. */
|
||
|
||
static int NextChar(tpp)
|
||
char **tpp;
|
||
{
|
||
unsigned isreal;
|
||
|
||
while (1)
|
||
{
|
||
if ((isreal = cmndtab[(unsigned) **tpp]) > 1)
|
||
{
|
||
*tpp += isreal - 1;
|
||
continue;
|
||
}
|
||
if (isreal)
|
||
return((unsigned) **tpp);
|
||
switch ((result = _SPMetaHandler(SPCBREAK, *tpp, 0L, NULL, 0L)) & CODEMASK)
|
||
{
|
||
case SPHJUMP:
|
||
*tpp = SPJumpLoc[0];
|
||
SPJumpLoc[0] = NULL;
|
||
continue;
|
||
case SPHSUBST: /* this shouldn't be possible. The handler in WP isn't capable */
|
||
return (result & DATAMASK);
|
||
case SPHCANCEL:
|
||
cancelled = 1;
|
||
case SPHFINISH:
|
||
return(-1);
|
||
default:
|
||
SPErr(SPBADRESULT, 0, -1);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Eat (optional) white space characters. Leave sp pointing to the char we
|
||
stopped on. If we run into a break we can't skip, return 0. */
|
||
|
||
static unsigned EatWhite()
|
||
{
|
||
int c;
|
||
|
||
while (1)
|
||
{
|
||
if ((c = NextChar(&sp)) == -1)
|
||
return (0);
|
||
if (!(chartype[c] & TWSPACE))
|
||
return (1);
|
||
++sp;
|
||
}
|
||
}
|
||
|
||
/* Put the next word into wbuf. Set flags. */
|
||
|
||
static unsigned GetWord()
|
||
{
|
||
int c;
|
||
unsigned buflen;
|
||
unsigned endpos;
|
||
unsigned stop;
|
||
unsigned sawchar;
|
||
unsigned endtypes = 0;
|
||
unsigned finished = 0;
|
||
unsigned ctype;
|
||
unsigned apost=0;
|
||
|
||
if (repeating)
|
||
flags &= AFTERSLASH + AFTERHYPH + HASBEGINPUNC;
|
||
else if (flags & BEFORESLASH)
|
||
flags = AFTERSLASH;
|
||
else if (flags & BEFOREHYPH)
|
||
flags = AFTERHYPH;
|
||
else flags = 0;
|
||
|
||
/* Empty the buffer now, in case we exit early */
|
||
|
||
wbuf[0] = 0;
|
||
|
||
/* Skip beginning punctuation. OK if we end here, because isolated
|
||
punctuation is a special case of a nonalphanumeric word, which we
|
||
accept. */
|
||
|
||
for (c = NextChar(&sp); c != -1 && chartype[c] & TBPUNC; ++sp, c =
|
||
NextChar(&sp))
|
||
flags |= HASBEGINPUNC;
|
||
if (c == -1)
|
||
return (0);
|
||
|
||
ctype = chartype[c];
|
||
|
||
stop = TWSPACE + TSLASH + (inhyph ? THYPHEN : 0);
|
||
rp = sp;
|
||
sawchar = 0;
|
||
ep = NULL;
|
||
buflen = 0;
|
||
|
||
/* Find the end of the word (ep) and of the token (rp), building the
|
||
buffer and the flags. */
|
||
|
||
while (!(ctype & stop))
|
||
{
|
||
if (!sawchar && ctype & (TLETTER + TDIGIT))
|
||
{
|
||
ep = NULL;
|
||
epfirst = eplast = epnum = 0;
|
||
sawchar = 1;
|
||
flags |= endtypes;
|
||
}
|
||
else if (sawchar && (ctype & TEPUNC) && !(wantperiod && c == '.'))
|
||
{
|
||
ep = rp;
|
||
if (buflen >= MAXWORD)
|
||
endpos = MAXWORD-1;
|
||
else
|
||
endpos = buflen;
|
||
|
||
epfirst = eplast = c;
|
||
epnum = 1;
|
||
sawchar = endtypes = 0;
|
||
}
|
||
else if (ctype & TEPUNC)
|
||
{
|
||
eplast = c;
|
||
++epnum;
|
||
endtypes |= ctype;
|
||
}
|
||
|
||
if (buflen < MAXWORD)
|
||
wbuf[buflen] = (char) c;
|
||
++buflen;
|
||
|
||
if (c == '\'' || c == '<EFBFBD>') {
|
||
apost = 1; /* we've seen "<22>" */
|
||
} else if (c == 's' && apost == 1) {
|
||
apost = 2; /* we've seen "<22>s" */
|
||
} else if (apost == 2) {
|
||
if (!(ctype & TEPUNC)) {
|
||
apost = 0; /* we've seen "<22>sx", so blow it off */
|
||
flags |= chartype['\''] | chartype['s'];
|
||
} else
|
||
apost = 2;
|
||
} else /* nothin... */
|
||
apost = 0;
|
||
|
||
if (sawchar)
|
||
{
|
||
if (!apost) /* This way, the flags for "<22>" and "s" don't get */
|
||
flags |= ctype; /* erroneously set. E.g., "123<32>s" */
|
||
|
||
if (buflen >= MAXWORD)
|
||
flags |= OVERFLOW;
|
||
}
|
||
|
||
++rp;
|
||
if ((c = NextChar(&rp)) == -1)
|
||
if (cancelled)
|
||
return(0);
|
||
else
|
||
{
|
||
++finished;
|
||
break;
|
||
}
|
||
ctype = chartype[c];
|
||
}
|
||
|
||
if (!ep)
|
||
{
|
||
ep = rp;
|
||
if (buflen >= MAXWORD)
|
||
endpos = MAXWORD-1;
|
||
else
|
||
endpos = buflen;
|
||
}
|
||
else
|
||
flags |= HASENDPUNC;
|
||
|
||
if (c == '/' || c == '<EFBFBD>' || c == '<EFBFBD>')
|
||
{
|
||
++rp;
|
||
flags |= BEFORESLASH;
|
||
}
|
||
else if (c == '-' || c == '<EFBFBD>' || c == '<EFBFBD>')
|
||
{
|
||
flags |= BEFOREHYPH;
|
||
++rp;
|
||
}
|
||
flags &= ~(TBPUNC + TEPUNC);
|
||
|
||
wbuf[endpos] = '\0';
|
||
|
||
/* Strip 's and set HASPOSS */
|
||
|
||
if (endpos > 2 && ((c = wbuf[endpos - 2]) == '\'' || c == '<EFBFBD>') && wbuf[endpos - 1] == 's')
|
||
{
|
||
flags |= HASPOSS;
|
||
ep -= 2;
|
||
wbuf[endpos - 2] = '\0';
|
||
}
|
||
|
||
wantperiod = 0;
|
||
|
||
return (!finished);
|
||
}
|
||
|
||
static unsigned CheckWord()
|
||
{
|
||
char *p, *q, c;
|
||
|
||
/* Pass it if it's non-alphabetic */
|
||
|
||
if (!(flags & TLETTER))
|
||
return(0);
|
||
|
||
if (flags & OVERFLOW)
|
||
{
|
||
wbuf[MAXWORD-1] = 0;
|
||
return (SPCMISSPELL);
|
||
}
|
||
|
||
strcpy(corbuf, wbuf);
|
||
|
||
if (!(flags & (BEFORESLASH + AFTERSLASH + BEFOREHYPH + AFTERHYPH +
|
||
HASBEGINPUNC + OVERFLOW)) && !(lastflags & (BEFORESLASH + AFTERSLASH
|
||
+ BEFOREHYPH + AFTERHYPH + HASENDPUNC + OVERFLOW)))
|
||
{
|
||
MakeLower(corbuf);
|
||
if (!strcmp(lastword, corbuf))
|
||
return(SPCREPEAT);
|
||
}
|
||
|
||
if (strlen(wbuf) == 1 && (epfirst == '.' || epfirst == ')'))
|
||
return(0);
|
||
|
||
if (!isword(wbuf))
|
||
{
|
||
/* See if it has spurious hyphens */
|
||
|
||
if (flags & THYPHEN)
|
||
{
|
||
for (p = wbuf, q = corbuf; *p; ++p)
|
||
if ((c = *p) != '-' && c != '<EFBFBD>' && c != '<EFBFBD>')
|
||
*q++ = *p;
|
||
*q = 0;
|
||
if (isword(corbuf))
|
||
{
|
||
c2pstr(corbuf);
|
||
return(SPCHYPH);
|
||
}
|
||
}
|
||
|
||
/* See if we just need to add a period */
|
||
|
||
if (!(Quflags & (IW_ENDDOT + IW_ALLDOT)) && epfirst == '.')
|
||
return (WANTPD);
|
||
else if (Quwlist > 0)
|
||
{
|
||
undoflags(Qulookup, Quwflags, corbuf);
|
||
if ((Quwflags & IW_CASE) < (Quflags & IW_CASE))
|
||
undoflags(corbuf, Quflags & IW_CASE, corbuf);
|
||
c2pstr(corbuf);
|
||
return(SPCMISPUNC);
|
||
}
|
||
|
||
return(SPCMISSPELL);
|
||
}
|
||
|
||
if (mustbecap && islower(wbuf[0]))
|
||
{
|
||
corbuf[0] = _toupper(corbuf[0]);
|
||
c2pstr(corbuf);
|
||
return(SPCCAP);
|
||
}
|
||
|
||
return(SPNOERR);
|
||
}
|
||
|
||
static void MakeLower(s)
|
||
char *s;
|
||
{
|
||
--s;
|
||
while (*++s)
|
||
*s = tolower(*s);
|
||
}
|
||
|
||
|
||
SPCloseFiles()
|
||
{
|
||
unsigned x;
|
||
|
||
setbank;
|
||
|
||
/* Close main dict */
|
||
|
||
stdclose(Lexfile);
|
||
|
||
/* Close the udicts */
|
||
|
||
for (x = 0; x < SPMAXUDICT; ++x)
|
||
if (_SPudtable[x])
|
||
stdclose(_SPudtable[x]->cl_file);
|
||
|
||
restorebank;
|
||
}
|
||
|