static char RCS_Amiga_ID[]=
  "$Id: amiga.c 1.7 1998/08/25 14:31:14 jskov-eburghar Exp $";

/*
 * $Log: amiga.c $
 * Revision 1.7  1998/08/25  14:28:20  eburghar
 * CHECK and QUICKCHECK now use strtoichar() instead of the own written routine
 * Now they handle accentuated words correctly (french dictionary)
 *
 * Revision 1.6  1995/09/21  15:39:06  jskov
 * Now compiles with includes 3.1
 *
 * Revision 1.5  1995/07/03  23:54:58  jskov
 * Removed #include "version.h" - version strings are now in an object
 *
 * Revision 1.4  1995/06/30  13:13:00  jskov
 * RCS version string is now in the object code for easy id of patch revision
 *
 * Revision 1.3  1995/06/30  12:40:21  jskov
 * Added initialization of ctoken
 *
 * Revision 1.2  1995/06/30  10:10:16  jskov
 * Added "ACCEPT" command - accepts word for the rest of the session.
 *
 * Revision 1.1  1995/06/30  00:03:56  jskov
 * Initial revision
 *
 */

#include <stdio.h>
#include <string.h>
#include "config.h"
#include "ispell.h"
#include "proto.h"
#include "msgs.h"
#include <dos/dos.h>

extern char * Version_ID[];

void rexxaccept (struct RexxMsg *msg, char *inword);

struct rexxCommandList rcl[] =
{
  {"add", &rexxadd},
  {"quickadd", &rexxquickadd},
  {"accept", &rexxaccept},
  {"check", &rexxcheck},
  {"quickcheck", &rexxquickcheck},
  {"lookup", &rexxlookup},
  {"filecheck", &rexxfilecheck},
  {"version", &rexxversion},
  {"exit", &rexxexit},
  {NULL, NULL}
};

SHORT KeepGoing = TRUE; /* main loop control value */

char rootword[BUFSIZ];

int wflag = 0;

struct RexxMsg *RexxMsg;

void servermode()
{
  long rexxbit;
  long returnbits;

  rexxbit = upRexxPort ("IRexxSpell", rcl, NULL, &disp);

  printf("Entered ARexx server mode!\n");
  printf("Pass commands through port 'IRexxSpell'\n");
  fflush (stdout);

  while (KeepGoing)
    {
      returnbits = Wait (rexxbit | SIGBREAKF_CTRL_C);
      if (returnbits & SIGBREAKF_CTRL_C)
        KeepGoing = 0;
      if (returnbits & rexxbit)
        dispRexxPort ();
    }
/*
 *   With Rexx, we need to bring the port down.  You might make this
 *   part of exit() for programs that have multiple paths to exit.
 */
  dnRexxPort ();
}


/*
 *   Now we get into the actual code necessary for our REXX port; functions
 *   that do the real work.  Note that this program was not structured
 *   particularly nicely for Rexx; I had to write each of these functions.
 *   Many programs have these subroutines already in place; they are called
 *   as part of the event loop.  This progam, however, just has one big
 *   switch statement with different actions . . .
 *
 *   First, our locals.
 */
/*
 *   This is our main dispatch function.
 */
void disp (struct RexxMsg *msg, struct rexxCommandList *dat, char *p)
{
  (*(dat->userdata)) (msg, p);
}

/*
 *   This handler adds a word to the `global personal dictionary.'
 *
 *   Now, in English, the word is added to whatever personal
 *   dictionary was found when ISpell was started up in ARexx
 *   server mode. (Under a multiuser system, we might want to
 *   restrict who can add words to this dictionary.  For now
 *   we just do it!  Yes, the AmigaOS is multiuser, hehe :-).
 *   No protection, the way true hackers like it, you (the 
 *   user) get more rope to hang yourself :-), err the system 
 *   with :-).
 */
void rexxadd (struct RexxMsg *msg, char *inword)
{
  if (*inword)
    treeinsert (ichartosstr (strtosichar (inword, 0), 1), ICHARTOSSTR_SIZE, 1);
  treeoutput ();
  replyRexxCmd (msg, 0L, 0L, "ok");
}

/*
 *   The quick version does not write the changes to disk.
 *   Useful if you will be adding many words.  Be sure to
 *   call rexxadd at the end of the list (pass a null word,
 *   or a valid new word to be added).
 */
void rexxquickadd (struct RexxMsg *msg, char *inword)
{
  if (*inword)
    treeinsert (ichartosstr (strtosichar (inword, 0), 1), ICHARTOSSTR_SIZE, 1);
  replyRexxCmd (msg, 0L, 0L, "ok");
}

/*
 * Accept word for the rest of this session. Obviously there is no need
 * for saving the tree.
 */

void rexxaccept (struct RexxMsg *msg, char *inword)
{
  if (*inword)
    treeinsert (ichartosstr (strtosichar (inword, 0), 1), ICHARTOSSTR_SIZE, 0);
  replyRexxCmd (msg, 0L, 0L, "ok");
}

/*
 *   This handler checks the spelling of a word.
 */

void rexxcheck (struct RexxMsg *msg, char *inword)
{
  char buf[512];
  char aWord[INPUTWORDLEN + MAXAFFIXLEN];
  int i;

  if (strtoichar (itoken, inword, INPUTWORDLEN * sizeof (ichar_t), 0))
      (void) fprintf (stderr, WORD_TOO_LONG (ctoken));

  currentchar = inword;                                         /* Global ISpell vars */

  if (good (itoken, 0, 0, 0, 0)){
        if (hits[0].prefix == NULL && hits[0].suffix == NULL){
          /* perfect match */
          strcpy (buf, "*");
        } else {
          /* matched because of root */
          sprintf (buf, "+ %s", hits[0].dictent->word);
        }
  } else if (compoundgood (itoken, 0)){
        /* compound-word match */
        strcpy (buf, "-");
  }     else {
        makepossibilities (itoken);
        if (pcount){
          /*
          ** print &  or ?, ctoken, then
          ** character offset, possibility
          ** count, and the possibilities.
          */
          sprintf (buf, "%c %s %d", easypossibilities ? '&' : '?',ctoken, easypossibilities);
          for (i = 0;  i < MAXPOSSIBLE;  i++){
                if (possibilities[i][0] == 0)
                  break;
                sprintf (aWord, "%c %s",i ? ',' : ':', possibilities[i]);
          strcat(buf, aWord);
          }
        } else {
          /*
          ** No possibilities found for word TOKEN
          */
          (void) sprintf (buf, "# %s", ctoken);
        }
  }
  replyRexxCmd (msg, 0L, 0L, buf);
}


/*
 *   This handler checks the spelling of a word, it does
 *   not try to find replacement words as above.  It only
 *   determines whether or not the word is in the dictoinary.
 */
void rexxquickcheck (struct RexxMsg *msg, char *inword)
{

  if (strtoichar (itoken, inword, INPUTWORDLEN * sizeof (ichar_t), 0))
      (void) fprintf (stderr, WORD_TOO_LONG (ctoken));

  currentchar = inword;                                         /* Global ISpell vars */

  if (good (itoken, 0, 0, 0, 0) || compoundgood(itoken, 0))
    replyRexxCmd (msg, 0L, 0L, "ok");
  else
    replyRexxCmd (msg, 0L, 0L, "bad");
}

/*
 * Find words matching a regular expression
 */
void rexxlookup (struct RexxMsg *msg, char *p)
{
  char buf[512];
  char cmd[512];
  char *rval;
  int whence = 0;
  int bufend = 1;
  int lookupsize;

  strcpy (buf, "&");
  sprintf (cmd, "^%s$", p);
  while ((rval = do_regex_lookup (cmd, whence)) != NULL){
        whence=1;
        lookupsize = strlen(rval);
        if ((lookupsize + bufend) > 511)
          break;
        strcpy (&(buf[bufend++]), " ");
        strcpy (&(buf[bufend]), rval);
        bufend += lookupsize;
  }
  replyRexxCmd (msg, 0L, 0L, buf);
}

/*
 *   This handler checks the spelling of a file.
 */
void rexxfilecheck (struct RexxMsg *msg, char *p)
{
  char *cp;

  currentfile = p;

  if ((infile = fopen (p, "r")) == NULL){
        replyRexxCmd (msg, 0L, 0L, "Error: Can't open input file");
        return;
  }

  tmpnam (tempfile);

  if ((outfile = fopen (tempfile, "w")) == NULL){
        replyRexxCmd (msg, 0L, 0L, "Error: Can't open output file");
        return;
  }

  quit = 0;

  /* See if the file is a .tex file.  If so, set the appropriate flag. */
  if ((cp = (char *) strrchr (p, '.')) != NULL && strcmp (cp, ".tex") == 0)
    tflag = 1;
  else
    tflag = 0;

  lflag = 1;

  checkfile ();

  fclose (infile);
  fclose (outfile);

  replyRexxCmd (msg, 0L, 0L, tempfile);
}

/*
 *   This handler returns the version of the program.
 */
void rexxversion (struct RexxMsg *msg, char *p)
{
  char buf[512];
  int bufend;
  int namesize;
  int i;

  sprintf(buf, "%s\n%s\n", Version_ID[0], Version_ID[2]);
  bufend=strlen(buf);
  for (i = 0; rcl[i].name != NULL; i++){
        namesize = strlen(rcl[i].name);
        if ((namesize + bufend) > 511)
          break;
        bufend=+namesize+1;
        strcat (buf, " ");
        strcat (buf, rcl[i].name);
  }
  replyRexxCmd (msg, 0L, 0L, buf);
}

/*
 *   This handler sets the exit flag.
 */
void rexxexit (struct RexxMsg *msg, char *p)
{
  KeepGoing = 0;
  replyRexxCmd (msg, 0L, 0L, "bye");
}
