This is Dictionaire.m in view mode; [Download] [Up]
/*
*
* copyright by Moritz Willers (willers@butp.unibe.ch)
*
* Fri Jan 20 16:41:18 GMT+0100 1995
*
*/
/*
* in ispell 3.1.12 the report of the offset has been changed.
* To be able to compile nextispell with any version of ispell
* here is a define which can be set to an integer value.
* It says in which direction the selection should be shifted
*
* e.g
*
* -1 is: shift one left
* +2 is: shift two right
*
* 0 is the correct value for 3.1.08 and earlier
* -1 is the correct value for 3.1.12 and up
*
*/
#define OFFSET_CORR -1
#import "Dictionaire.h"
#import "common.h"
FILE *fromIspell; // a stream
int toIspell; // a fd
int ispellpid, linesize;
char misspelled[BUFSIZ];
BOOL texmode, tersemode;
/* ******************** private functions ************************ */
int makepipe(int *rd, int *wrt)
{
int piperesult, fd[2];
piperesult = pipe(fd);
*rd = fd[0];
*wrt = fd[1];
return piperesult;
}
void empty_pipe(FILE *fileptr)
{
char buf[BUFSIZ];
while ( fgets(buf, BUFSIZ, fileptr) && (*buf != '\n') );
return;
}
void waitforispell(int pid)
{
union wait statusp;
while ( pid != wait3(&statusp, WUNTRACED, NULL) );
if ( kill(pid, SIGCONT) == -1 )
perror("SIG_CONT failed");
return;
}
BOOL parsefortex(char *language)
{
BOOL tex = NO;
char *tmp;
if ( (tmp = strrchr(language, '-')) ) {
// nextispell now has defaults for tex and non tex versions seperately
// Fri Jan 27 14:37:54 GMT+0100 1995, mw
// *tmp = '\0';
tmp++;
tex = (strcmp(tmp, "tex")) ? NO : YES;
}
return tex;
}
void changetexmode(BOOL tex)
{
if ( tex )
write(toIspell, "+\n", 2);
else
write(toIspell, "-\n", 2);
waitforispell(ispellpid);
}
void texcheck(BOOL tex)
{
// maybe we've been in the midst of a bracket the last time
// and ispell is ignoring everything. So switch out of
// and back into tex mode
if ( tex ) {
write(toIspell, "-\n", 2);
waitforispell(ispellpid);
write(toIspell, "+\n", 2);
waitforispell(ispellpid);
}
return;
}
/* ******************************************************************** */
@implementation Dictionaire
- init
{
return [self initForLanguage:"English"];
}
- initForLanguage:(const char *)language
{
int fromI, toI, fromD, toD;
char **argv;
char *buf, *bufptr;
int i;
[super init];
dictLanguage = (char *)malloc((strlen(language)+1)*sizeof(char));
strcpy(dictLanguage, language);
texmode = parsefortex(dictLanguage);
*misspelled = '\0';
if (makepipe(&fromI,&toD))
{
perror("nextispell: Couldn't create pipe");
[self free];
return nil;
}
if (makepipe(&fromD,&toI))
{
perror("nextispell: Couldn't create pipe");
[self free];
return nil;
}
switch (ispellpid = vfork())
{
case -1:
perror("nextispell: Couldn't fork");
[self free];
return nil;
case 0:
close(toI);
close(fromI);
if ( dup2(fromD, 0) == -1 ) {
perror("nextispell child: Error establishing read pipe");
exit(1);
}
if ( dup2(toD, 1) == -1 ) {
perror("nextispell child: Error establishing write pipe");
exit(1);
}
// determine how to start ispell
argv = (char **)malloc(5*sizeof(*argv));
if ( NXGetDefaultValue("nextispell", "ispell") )
newstringfrom(&argv[0], NXGetDefaultValue("nextispell", "ispell"));
else {
char ispellpath[MAXPATHLEN];
if ( *findispell(ispellpath) != '\0' )
newstringfrom(&argv[0], ispellpath);
else {
printf("nextispell child: Don't know how to exec ispell\n");
exit(1);
}
}
newstringfrom(&argv[1], "-a");
newstringfrom(&argv[2], "-s");
// parse the default value
i = 3;
newstringfrom(&buf, NXGetDefaultValue("nextispell", dictLanguage));
for ( bufptr = buf; *bufptr; bufptr++ ) {
if ( NXIsSpace(*bufptr) ) {
*bufptr = '\0';
newstringfrom(&argv[i], buf);
i++; buf = bufptr+1;
argv = (char **)realloc(argv, (i+3)*sizeof(*argv));
}
}
newstringfrom(&argv[i++], buf);
argv[i] = NULL;
// put child in another process group
// or the enire NeXT apps will hang
// they are all in the same pgrp
setpgrp(0, getpid());
// change child into ispell
execv(argv[0], argv);
perror("nextispell child: Failed to exec ispell");
exit(1);
default:
close(fromD);
close(toD);
fromIspell = fdopen(fromI, "r");
toIspell = toI;
// put ispell into terse mode, may speed things up
if ( (buf = (char *)NXGetDefaultValue("nextispell", "tersemode")) )
tersemode = ( strcmp(buf, "NO") ) ? YES : NO;
else
tersemode = NO;
if ( tersemode ) {
write(toIspell, "!\n", 2);
waitforispell(ispellpid);
}
// put ispell into tex mode
if ( texmode )
changetexmode(texmode);
// determine the size of lines which are send to ispell
if ( (buf = (char *)NXGetDefaultValue("nextispell", "linesize")) ) {
sscanf(buf, "%d", &linesize);
linesize = ( linesize > 900 ) ? 900 : linesize;
}
else
linesize = 127;
break;
}
return self;
}
- (const char*)language
{
return (const char*)dictLanguage;
}
- free
{
free(dictLanguage);
if (toIspell)
close(toIspell);
if (fromIspell)
fclose(fromIspell);
return [super free];
}
/* *********************** delegate methods ************************* */
- (BOOL)spellServer:(NXSpellServer *)sender
findMisspelledWord:(int *)start
length:(int *)length
inLanguage:(const char *)language
inTextStream:(id <NXReadOnlyTextStream>)textStream
startingAt:(int)startPosition
wordCount:(int *)number
countOnly:(BOOL)flag
{
char readbuf[BUFSIZ], writebuf[BUFSIZ];
char rest[128];
char *readbufptr;
int len;
int offset, linelength = 0;
char misspelledWord[BUFSIZ];
BOOL loop;
if (flag)
{
*number = -1; // is not able to do pure wordcounting
fprintf(stderr, "nextispell is not able to do pure wordcounting\n");
return NO;
}
if ([textStream isAtEOTS])
return NO;
// test whether ispell is around
if ( kill(ispellpid, 0) == -1 ) {
perror("nextispell: quitting service, ispell is gone");
[self free];
return NO;
}
readbufptr = readbuf;
*start = startPosition;
*rest = '\0';
if ( startPosition != 0 ) // set stream outside a word
do {
[textStream readCharacters:readbufptr count:1];
(*start)++;
} while (!NXIsSpace(*readbufptr) && ![textStream isAtEOTS]);
// check tex mode before entering the main loop
if ( texmode )
texcheck(texmode);
// main loop
do {
// read the next 'linesize' characters form the text stream
// and save the last bit (no word maybe) into 'rest'
strcpy(readbuf, rest);
len = strlen(rest);
readbufptr = &readbuf[len];
len += [textStream readCharacters:readbufptr count:linesize];
readbufptr = readbuf;
readbuf[len] = '\0';
// fill with spaces instead of newlines.
// We will send ispell only a single line
for (readbufptr = readbuf; *readbufptr != '\0'; readbufptr++) {
if (*readbufptr == '\n')
*readbufptr = ' ';
}
// set pointer back to the last white space
if ( ![textStream isAtEOTS] )
for ( readbufptr = &readbuf[len-1];
!NXIsSpace(*readbufptr) && (readbufptr != readbuf);
readbufptr--);
strcpy(rest, readbufptr); // save rest
*readbufptr++ = '\n'; // terminate with '\n' for ispell
*readbufptr = '\0'; // terminate string
linelength = strlen(readbuf)-1; // without '\n'
if ( linelength == 0 )
return NO;
// send ispell the the line
write(toIspell, "^", 1); // to protect the rest
write(toIspell, readbuf, strlen(readbuf));
waitforispell(ispellpid);
// read stuff from ispell line by line
loop = YES;
while (loop) {
if ( fgets(writebuf, BUFSIZ, fromIspell) )
switch(*writebuf)
{
case '*':
case '+':
case '-':
(*number)++;
break;
case '&':
case '?':
strcpy(misspelled, writebuf);
sscanf(writebuf, "%*s %s %*d %d", misspelledWord, &offset);
if ([sender isInUserDictionary:(const char *)misspelledWord caseSensitive:YES])
{
(*number)++;
break;
}
*length = strlen(misspelledWord);
*start += offset + OFFSET_CORR;
empty_pipe(fromIspell);
*number = ( tersemode ) ? -1 : *number;
return YES;
case '#':
strcpy(misspelled, writebuf);
sscanf(writebuf, "%*s %s %d", misspelledWord, &offset);
if ([sender isInUserDictionary:(const char *)misspelledWord caseSensitive:YES])
{
(*number)++;
break;
}
*length = strlen(misspelledWord);
*start += offset + OFFSET_CORR;
empty_pipe(fromIspell);
*number = ( tersemode ) ? -1 : *number;
return YES;
case '\n':
*start += linelength;
loop = NO;
default:
break;
} // switch
} // while (loop)
}
while (![textStream isAtEOTS]);
return NO; // no misspelled words found
}
- (void)spellServer:(NXSpellServer *)sender
suggestGuessesForWord:(const char *)word
inLanguage:(const char *)language
{
char buf[BUFSIZ];
char *bufptr, *guess;
if (*misspelled)
{
switch (*misspelled)
{
case '&':
case '?':
bufptr = strchr(misspelled, ':');
do
{
guess = bufptr + 2;
if ((bufptr = strchr(guess, ',')))
*bufptr = '\0';
else
{
bufptr = strchr(guess, '\n');
*bufptr = '\0';
bufptr = NULL;
}
[sender addGuess:guess];
} while (bufptr);
case '#':
; // no guesses
}
*misspelled = '\0';
return;
} // else
if ( texmode )
texcheck(texmode);
write(toIspell, "^", 1);
write(toIspell, word, strlen(word));
write(toIspell, "\n", 1);
waitforispell(ispellpid);
fgets(buf, BUFSIZ, fromIspell);
switch (*buf)
{
case '*':
case '+':
case '-':
[sender addGuess:word];
break;
case '\n': // we're in terse mode
[sender addGuess:word];
return;
case '&':
case '?':
bufptr = strchr(buf, ':');
do
{
guess = bufptr + 2;
if ( (bufptr = strchr(guess, ',')) )
*bufptr = '\0';
else
{
bufptr = strchr(guess, '\n');
*bufptr = '\0';
bufptr = NULL;
}
[sender addGuess:guess];
} while (bufptr);
case '#':
default :
; // no guesses
}
// read the empty line
fgets(buf, BUFSIZ, fromIspell);
return;
}
- (void)spellServer:(NXSpellServer *)sender
didForgetWord:(const char *)word
inLanguage:(const char *)language
{
// ispell can't take words out of the dictionary
fprintf(stderr, "nextispell: Can't take word \"%s\" out of personal dictionary. Please do it by hand.\n", word);
return;
}
- (void)spellServer:(NXSpellServer *)sender
didLearnWord:(const char *)word
inLanguage:(const char *)language
{
write(toIspell, "*", 1);
write(toIspell, word, strlen(word));
write(toIspell, "\n", 1);
waitforispell(ispellpid);
write(toIspell, "#\n", 2);
waitforispell(ispellpid);
return;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.