static char RCS_Amiga_ID[]=
  "$Id: amiga.c 1.6 1995/09/21 15:39:06 jskov Exp $";

/*
 * $Log: amiga.c $
 * 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 <dos/dos.h>

extern char * Version_ID[];

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;

  for (i=0;i<=strlen(inword);i++){
	ctoken[i]=inword[i];
	itoken[i]=chartoichar(inword[i]);
  }

  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)
{
  int	i;

  for (i=0;i<=strlen(inword);i++)
	itoken[i]=chartoichar(inword[i]);

  currentchar = inword;						/* Global ISpell vars */

  if (good (itoken, 0, 0, 0, 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");
}
