/*   ---------------------------------      -------     
 *   |\  | | | | |  |.| |   \|  |/ /|\      |||||||     
 *   | | | |/  | |\ |/  |/|  |\ |/  |    ?  ---+---  =< 
 *   | | | |   | |  |     |  |  |   |     \qqqqqqqqq/   
 *   ---------------------------------  ~~~~~~~~~~~~~~~~
 *  Prepare - Splits text files into words
 *  Copyright (C) 1993 Torsten Poulin
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  The author can be contacted by s-mail at
 *    Torsten Poulin
 *    Banebrinken 99, 2, 77
 *    DK-2400 Copenhagen NV
 *    DENMARK
 *
 * $Id: Prepare.c,v 37.4 93/03/01 12:55:03 Torsten Rel $
 * $Log:	Prepare.c,v $
 * Revision 37.4  93/03/01  12:55:03  Torsten
 * Changed all occurrences of "struct DosBase *" to "struct DosLibrary *"
 * 
 * Revision 37.3  93/02/24  16:56:39  Torsten
 * Added HYPHEN switch. When given hyphenated compounds will be
 * considered one word.
 * 
 * Revision 37.2  93/02/24  11:56:44  Torsten
 * Can fold characters to lower or upper case.
 * 
 * Revision 37.1  93/02/24  00:27:26  Torsten
 * initial revision.
 * 
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#ifdef __SASC
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#endif
#include "tastlib.h"
#include "prepare_rev.h"

#define PROGNAME "Prepare"
#define TEMPLATE "FROM/M,TO/K,TOLOWER/S,TOUPPER/S,HYPHEN/S"
#define OPT_FROM  0
#define OPT_TO    1
#define OPT_LOWER 2
#define OPT_UPPER 3
#define OPT_HYPH  4

char const versionID[] = VERSTAG;
char const copyright[] = "$COPYRIGHT:Copyright © 1993 Torsten Poulin$";

typedef struct {
  struct DosLibrary *DOSBase;
  BOOL tolower;
  BOOL toupper;
  BOOL hyphen;
  BPTR output;
} Global;

LONG prepare(UBYTE *filename, Global *global);


LONG entrypoint(VOID)
{
  struct DosLibrary *DOSBase;
  struct RDArgs *args;
  Global *global;
  LONG arg[5];
  LONG rc = RETURN_OK;

  if (!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
    return RETURN_FAIL;

  if (!(global = AllocVec(sizeof(Global), MEMF_PUBLIC | MEMF_CLEAR)))
  {
    PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
    rc = RETURN_FAIL;
  }
  else
  {
    global->DOSBase = DOSBase;

    arg[OPT_FROM] = arg[OPT_TO] =
      arg[OPT_LOWER] = arg[OPT_UPPER] = arg[OPT_HYPH] = 0L;
    
    if (!(args = ReadArgs(TEMPLATE, arg, NULL)))
    {
      printerror(PROGNAME, global);
      rc = RETURN_ERROR;
    }
    else
    {
      global->hyphen  = (BOOL) arg[OPT_HYPH];
      global->tolower = (BOOL) arg[OPT_LOWER];
      global->toupper = (BOOL) arg[OPT_UPPER];
      if (global->tolower && global->toupper)
      {
	PutStr("TOLOWER and TOUPPER are mutually exclusive\n");
	rc = RETURN_ERROR;
      }
      else
      {
	if (!arg[OPT_TO])
	  global->output = Output();
	else if (!(global->output=Open((UBYTE *)arg[OPT_TO], MODE_NEWFILE)))
	{
	  PutStr("Cannot open ");
	  PutStr((UBYTE *) arg[OPT_TO]);
	  PutStr("\n");
	  rc = RETURN_ERROR;
	}

	if (global->output)
	  if (!arg[OPT_FROM])
	    rc = prepare(NULL, global);
	  else
	    rc = foreach((UBYTE **) arg[OPT_FROM], prepare, global);
	if (arg[OPT_TO])
	  Close(global->output);
      }
      FreeArgs(args);

      if (rc == ERROR_BREAK)
      {
	PrintFault(ERROR_BREAK, NULL);
	rc = RETURN_WARN;
      }
      else if (rc == ERROR_NO_FREE_STORE)
      {
	PrintFault(ERROR_NO_FREE_STORE, PROGNAME);
	rc = RETURN_FAIL;
      }
      else if (rc != RETURN_OK)
	printerror(PROGNAME, global);
    }
    FreeVec(global);
  }
  CloseLibrary((struct Library *) DOSBase);
  return rc;
}


/*
 * Valid only for the ISO Latin 1 character set.
 */
BOOL isletter(LONG c)
{
  return ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>=0xC0 && c<=0xFF))
    && c != 0xD7 && c != 0xF7;
}


LONG prepare(UBYTE *filename, Global *global)
{
  struct DosLibrary *DOSBase = global->DOSBase;
  register UBYTE breakcheck = 0;
  LONG c;
  BOOL inword = FALSE;
  LONG rc = RETURN_OK;
  BPTR input = Input();
    
  if (filename)
    if (!(input = Open(filename, MODE_OLDFILE)))
    {
      PutStr("Cannot open ");
      printerror(filename, global);
      return RETURN_ERROR;
    }

  while ((c = FGetC(input)) != EOF)
  {
    if (isletter(c))
    {
      inword = TRUE;
      if (global->tolower && c != 0xDF)
	c |= 0x20;
      else if (global->toupper && c!= 0xFF)
	c &= ~0x20;
      FPutC(global->output, c);
    }
    else if (inword)
    {
      if (c == '\'')
      {
	/* Don't strip an in-word apostrophe */
	c = FGetC(input);
	if (isletter(c))
	  FPutC(global->output, '\'');
	UnGetC(input, c);
      }
      else if (global->hyphen && c == '-')
      {
	/* Don't strip a hyphen */
	c = FGetC(input);
	if (isletter(c))
	  FPutC(global->output, '-');
	UnGetC(input, c);
      }
      else
      {
	inword = FALSE;
	FPutC(global->output, '\n');
      }
    }

    if (!(breakcheck -= 4) && CheckSignal(SIGBREAKF_CTRL_C))
    {
      rc = ERROR_BREAK;
      break;
    }
  }
  if (filename)
    Close(input);
  return rc;
}
