There's been some talk about this recently, so I finally got round to at least partially cleaning up what I'd done with this. This is code based on that made public by Erwin Andreasen to give an ispell command for online spellchecking. This version differs in that it only uses output functions found in base Rom, but more importantly has an ispell_string function which can be used to spellcheck room descs and such. The ispell.c file follows, and after it is info on how to add supprt to the string editor found in the ILAB OLC. I ported the 2.3 OLC to 2.4 myself, so I don't know how applicable this part is to OLC's such as Ivan's..suspect it works fine.. YMMV as always. Erwin's code gives a do_ispell command, which means you need to add a line in the command table for it. Additionally, the calls to the functions that initialise and shutdown the ispell engine need added. ispell_init should be before the call to boot_db in comm.c, and ispell_done is needed before a copyover is done if you have that coded added. Add appropriate function prototypes to make things happy here. The function ispell_string passes each word of a string to the ispell engine (avoiding duplicates though) and gathers the output which is then paged to the char. I turned this into a new dot command, insprationally called '.i'. A prototype for the ispell_string function also needs added, either in merc.h or string.c. Macros used: The first 2 should go into merc.h cause they are awfully useful..the second are for ispell only. #define IS_NULLSTR(str) ((str)==NULL || (str)[0]=='\0') #define MSL MAX_STRING_LENGTH #define Stringify(x) Str(x) #define Str(x) #x #include #include #include #include #include #include #include "merc.h" #include "recycle.h" #include static FILE *ispell_out; static ispell_pid = -1; static int to[2], from[2]; #define ISPELL_BUF_SIZE 1024 void ispell_init() { char ignore_buf[1024]; pipe(to); pipe(from); ispell_pid = fork(); if (ispell_pid < 0) { char *errmsg; sprintf(errmsg, "ispell_init: fork: %s", strerror(errno)); bug(errmsg, 0); } else if (ispell_pid == 0) /* child */ { int i; dup2(to[0], 0); /* this is where we read commands from - make it stdin */ close(to[0]); close(to[1]); dup2(from[1], 1); /* this is where we write stuff to */ close(from[0]); close(from[1]); /* Close all the other files */ for (i = 2; i < 255; i++) close(i); execlp("ispell", "ispell", "-a", (char *) NULL); exit(1); } else { /* ok ! */ close(to[0]); close(from[1]); ispell_out = fdopen(to[1], "w"); setbuf(ispell_out, NULL); #if !defined( sun ) /* that ispell on sun gives no (c) msg */ read(from[0], ignore_buf, 1024); #endif } } void ispell_done() { if (ispell_pid != -1) { fprintf(ispell_out, "#\n"); fclose(ispell_out); close(from[0]); waitpid(ispell_pid, NULL, 0); ispell_pid = -1; } } char *get_ispell_line(char *word) { static char buf[ISPELL_BUF_SIZE]; char buf2[MSL]; int len; if (ispell_pid == -1) return NULL; if (word) { fprintf(ispell_out, "^%s\n", word); fflush(ispell_out); } len = read(from[0], buf2, ISPELL_BUF_SIZE); buf2[len] = '\0'; /* Read up to max 1024 characters here */ if (sscanf(buf2, "%" Stringify(ISPELL_BUF_SIZE) "[^\n]\n\n", buf) != 1) return NULL; return buf; } void do_ispell(CHAR_DATA * ch, char *argument) { char *pc, buf[MSL]; if (ispell_pid <= 0) { send_to_char("ispell is not running.\n\r", ch); return; } if (!argument[0] || strchr(argument, ' ')) { send_to_char("Invalid input.\n\r", ch); return; } if (argument[0] == '+') { for (pc = argument + 1; *pc; pc++) if (!isalpha(*pc)) { sprintf(buf, "'%c' is not a letter.\n\r", *pc); send_to_char(buf, ch); return; } fprintf(ispell_out, "*%s\n", argument + 1); fflush(ispell_out); return; /* we assume everything is OK.. better be so! */ } pc = get_ispell_line(argument); if (!pc) { send_to_char("ispell: failed.\n\r", ch); return; } switch (pc[0]) { case '*': case '+': /* root */ case '-': /* compound */ send_to_char("Correct.\n\r", ch); break; case '&': /* miss */ sprintf(buf, "Not found. Possible words: %s\n\r", strchr(pc, ':') + 1); send_to_char(buf, ch); break; case '?': /* guess */ sprintf(buf, "Not found. Possible words: %s\n\r", strchr(pc, ':') + 1); send_to_char(buf, ch); break; case '#': /* none */ send_to_char("Unable to find anything that matches.\n\r", ch); break; default: sprintf(buf, "Weird output from ispell: %s\n\r", pc); send_to_char(buf, ch); } } /* * Function to add ispell support within an editor * It takes the string the char is currently editing as it's source, * and passes it a word at a time to ispell. A check is kept on * what words have been checked to prevent repetition of the same * 'error', mainly useful with proper names etc. */ void ispell_string(CHAR_DATA * ch) { char *result; char word[MSL]; char checked_list[MSL]; char buf[MSL]; char *str; int i = 0; bool errors = FALSE; BUFFER *buffer; buffer = new_buf(); strcpy(checked_list, ""); str = *ch->desc->pString; while (*str != '\0') { while (*str != ' ' && *str != '\0' && *str != '\n' && *str != '\r') { word[i++] = *str; str++; } word[i++] = '\0'; if (!is_exact_name(word, checked_list)) { sprintf(checked_list + strlen(checked_list), "%s ", word); result = get_ispell_line(word); if (!IS_NULLSTR(result)) { if (result[0] == '&') { sprintf(buf, "%s failed - Possible words : %s\n\r", word, strchr(result, ':')); errors = TRUE; add_buf(buffer, buf); } if (result[0] == '#') { sprintf(buf, "%s failed - no similar words found.\n\r", word); errors = TRUE; add_buf(buffer, buf); } } } str++; i = 0; } send_to_char("\n\r", ch); if (errors) page_to_char(buf_string(buffer), ch); else send_to_char("No errors found.\n\r", ch); free_buf(buffer); return; } ----- String.c addition --- This will make an additional command from within the string editor, .i, which can be used either as: .i < word> - do a check on the single word given or .i - spellcheck the whole string. In string_add, where all the conditions are for the various dot commands, add: if (!str_cmp(arg1, ".i")) { if (!IS_NULLSTR(arg2)) do_ispell(ch, arg2) ; else ispell_string(ch) ; } That should be it. Have fun :) Garry -- G.A. Turkington g.turkington@qub.ac.uk Tel: +44-(0)1232-274618