#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <dos/dosextens.h>
#include <dos/stdio.h>

#include <proto/exec_protos.h>
#include <proto/dos_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>

#ifndef __COMMODORE_DATE__
#define __COMMODORE_DATE__ __DATE__
#endif

#define BASENAME "Strings"
#define MAXPATHLEN 256

const STATIC char VER[] = "\0$VER: " BASENAME " 1.0 (" __COMMODORE_DATE__ ")";
const STATIC char Basename[] = BASENAME;

STATIC BOOL stop = FALSE;

STATIC BOOL CheckBreak(VOID)
{
   if (stop)
      return TRUE;

   if (stop = (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
      SetIoErr(ERROR_BREAK);

   return stop;
}

STATIC VOID Strings(BPTR file,UBYTE *buffer,LONG len,BOOL showoffs)
{
ULONG offs = 0,oldoffs = 0;
LONG c;
UBYTE *bp = buffer;

   while ((c = FGetC(file)) != -1 && !CheckBreak())
      {
      offs++;

      if (c>=32 && c<127)
	 {
	 if (bp==buffer)
	    oldoffs = offs;
	 *bp++ = c;
	 if (bp == buffer+len)
	    {
	    *bp = 0;
	    if (showoffs)
	       Printf("%ld : ",oldoffs-1);
	    PutStr(buffer);

	    while ((c = FGetC(file)) != -1 && !CheckBreak())
	       {
	       offs++;
	       if (c>=32 && c<127)
		  WriteChar(c);
	       else
		  break;
	       };

	    WriteChar('\n');
	    bp = buffer;
	    };
	 }
      else
	 bp = buffer;
      };
}

__stkargs void _main(int unused_arglen, char *unused_argptr)
{
int ret = RETURN_FAIL;

   if ((DOSBase->lib_Version>=37) && (SysBase->lib_Version >= 37))
      {
      if (Input() && Output())
	 {
	 LONG array[] = { NULL, NULL, FALSE, FALSE };
	 struct RDArgs *rdargs = ReadArgs("PATTERN/M,LENGTH/N/K,OFFS/S,ALL/S", array, NULL);
	 if (rdargs)
	    {
	    LONG len = 10;
	    if (array[1])
	       len = *(LONG *)array[1];
	    if (len<2)
	       len = 2;

	    UBYTE *buffer = AllocVec(len+1,MEMF_ANY);
	    if (buffer)
	       {
	       STRPTR *multi = (STRPTR *)array[0];
	       if (!*multi)
		  Strings(Input(),buffer,len,array[2]);
	       else
		  {
		  struct AnchorPath *anchorpath = AllocVec(sizeof(struct AnchorPath)+MAXPATHLEN,MEMF_CLEAR);
		  if (anchorpath)
		     {
		     anchorpath->ap_BreakBits = SIGBREAKF_CTRL_C;
		     anchorpath->ap_Strlen   = MAXPATHLEN;

		     ret = RETURN_OK;

		     while (*multi && !CheckBreak())
			{
			LONG mferr = MatchFirst(*multi,anchorpath);
			while (mferr == 0 && !CheckBreak())
			   {
			   if (anchorpath->ap_Flags &  APF_DIDDIR)
			      anchorpath->ap_Flags &= ~(APF_DIDDIR | APF_DODIR);
			   else
			      {
			      if (anchorpath->ap_Info.fib_DirEntryType > 0) /* directory */
				 {
				 if (array[3])
				    anchorpath->ap_Flags |= APF_DODIR;
				 }
			      else if (anchorpath->ap_Info.fib_DirEntryType < 0) /* file */
				 {
				 BPTR file = Open(anchorpath->ap_Buf, MODE_OLDFILE);
				 if (file)
				    {
				    Printf("%ls\n",anchorpath->ap_Buf);
				    Strings(file,buffer,len,array[2]);
				    Close(file);
				    }
				 else
				    {
				    PrintFault(ret = IoErr(),anchorpath->ap_Buf);
				    break;
				    };
				 };
			      };
			   mferr = MatchNext(anchorpath);
			   };
			multi++;
			if (mferr != ERROR_NO_MORE_ENTRIES)
			   {
			   PrintFault(ret = IoErr(),Basename);
			   break;
			   };
			if (mferr == ERROR_BREAK)
			   stop = TRUE;
			};

		     FreeVec(anchorpath);
		     }
		  else
		     PrintFault(ret = ERROR_NO_FREE_STORE,Basename);
		  };

	       if (CheckBreak())
		  PrintFault(ret = ERROR_BREAK,Basename);
	       }
	    else
	       PrintFault(ret = ERROR_NO_FREE_STORE,Basename);

	    FreeArgs(rdargs);
	    }
	 else
	    PrintFault(ret = IoErr(),Basename);
	 }
      else
	 PrintFault(ret = IoErr(),Basename);
      }
   else
      {
      if (DOSBase->lib_Version >= LIBRARY_MINIMUM)
	 {
	 if (Output())
	    {
	    Write(Output(),Basename,sizeof(Basename)-1);
	    Write(Output(),": Can't open dos.library v37 (OS 2.04)\n",39);
	    };
	 ret = ERROR_INVALID_RESIDENT_LIBRARY;
	 };
      };

   _exit(ret);
}
