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.