/**************************************************************************/
// ispell.cpp - intergrated spell checker
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with all the licenses *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************
* >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. *
* >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to *
* you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), *
* Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) *
* >> Oblivion 1.2 is copyright 1996 Wes Wagner *
**************************************************************************/
#include "include.h"
#ifdef unix
/**************************************************************************/
#include <sys/wait.h>
static FILE *ispell_out;
static int 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 = NULL;
sprintf(errmsg, "ispell_init: fork: %s", strerror(errno));
bug(errmsg);
}
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);
logf("starting ispell....");
execlp("ispell", "ispell", "-a", (char *)
NULL);
logf("ispell_init(): error starting ispell.");
logf("ispell startup error\n");
exit(1);
}
else
{ // ok !
close(to[0]);
close(from[1]);
ispell_out = fdopen(to[1], "w");
setbuf(ispell_out, NULL);
read(from[0], ignore_buf, 1024);
if(strstr(ignore_buf, "ispell startup error")){
int status;
logf("Ispell not started, getting child process result to avoid zombie.");
wait(&status);
logf("Status result = %d", status);
}
}
}
/**************************************************************************/
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;
if (ispell_pid <= 0)
{
ch->println("ispell is not running.");
return;
}
if (!argument[0] || strchr(argument, ' '))
{
ch->println("Invalid input.");
return;
}
if (argument[0] == '+')
{
for (pc = argument + 1; *pc; pc++)
if (!is_alpha(*pc))
{
ch->printlnf("'%c' is not a letter.", *pc);
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)
{
ch->println("ispell: failed.");
return;
}
switch (pc[0])
{
case '*':
case '+': /* root */
case '-': /* compound */
ch->println("Correct.");
break;
case '&': /* miss */
ch->printlnf("Not found. Possible words: %s", strchr(pc, ':') + 1);
break;
case '?': /* guess */
ch->printlnf("Not found. Possible words: %s", strchr(pc, ':') + 1);
break;
case '#': /* none */
ch->println("Unable to find anything that matches.");
break;
default:
ch->printlnf("Weird output from ispell: %s", pc);
}
}
/**************************************************************************/
/*
* 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;
// strip the colour from the string before processing
// this function uses temp_HSL_workspace to do its thing
if(!IS_NULLSTR(str)){
convertColour(str, temp_HSL_workspace, CT_NOCOLOUR, false);
str=temp_HSL_workspace;
}
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 + str_len(checked_list), "%s ", word);
result = get_ispell_line(word);
if (!IS_NULLSTR(result))
{
if (result[0] == '&')
{
sprintf(buf, "%s failed - Possible words : %s\r\n",
word, strchr(result, ':'));
errors = true;
add_buf(buffer, buf);
}
if (result[0] == '#')
{
sprintf(buf, "%s failed - no similar words found.\r\n", word);
errors = true;
add_buf(buffer, buf);
}
}
}
str++;
i = 0;
}
ch->println("");
if (errors){
ch->sendpage(buf_string(buffer));
}else{
ch->println("No errors found.");
}
free_buf(buffer);
return;
}
/**************************************************************************/
#else
/**************************************************************************/
#include "include.h"
void do_ispell(char_data * ch, char *)
{
ch->println("Sorry ispell is available in unix only.");
return;
}
/**************************************************************************/
#endif