/*
          Trunc - CR-LF conversion and simple formatting.

          Original effort by Fabio Rossetti. Inspired by the trunc program
          by Gary Brant found on <>< 179.

	  (c) 1989 by Fabio Rossetti

	  To compile under Lattice C v5.0x use:

		lc -O -v -cus  trunc
		blink lib:cres.o trunc.o to trunc lib lib:a.lib lib:lc.lib sd nd

*/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/arpbase.h>
#include <arpfunctions.h>
#include <proto/exec.h>
#include <proto/dos.h>		

struct ArpBase *ArpBase=NULL;
struct Process *Pr;

LONG argc;

#define NARGS 8

STRPTR argv[NARGS];

#define FROM	argv[0]
#define TO	argv[1]
#define LCL	argv[2]
#define SC	argv[3]
#define CL	argv[4]
#define LM	argv[5]
#define LC	argv[6]
#define RC	argv[7]

LONG lm,lc,rc;

TEXT *Buf,*OBuf,*Margin;

#define MAXLIN 1024
#define BFSIZE 512	

struct UserAnchor {
	struct	AnchorPath	ua_AP;
	BYTE	moremem[255];	/* extension */
};

struct	UserAnchor *Anchor=NULL;
TEXT *Lin[256];

/* Trick to keep code down to size */
VOID MemCleanup()
{
}

/* shutdown routine */
VOID Cleanup(r1,r2,msg)
LONG r1,r2;
STRPTR msg;
{
	if (ArpBase) CloseLibrary((struct Library *)ArpBase);
	Pr->pr_Result2 = r2;
	if (msg) Puts(msg);
	exit(r1);
}

/* output a line */
VOID PrOut (o)
BPTR o;
{

	if (LM) FPrintf(o,"%s%s",Margin,OBuf);
	if (LC) if (strlen(OBuf)> lc)
		FPrintf(o,"%s",(TEXT *)(OBuf+lc));
		else FPrintf(o,"\n");
	if (RC) if  (strlen(OBuf) > rc) {
			*(OBuf + rc) = '\000';
			FPrintf(o,"%s\n",OBuf);
			}
		else FPrintf(o,OBuf);
	if (!(RC || LC || LM)) FPrintf(o,"%s",OBuf);

}

/* perform CR-LF stuff */
VOID Trunc(Inp,Out)
BPTR Inp,Out;

{

REGISTER LONG count, bufp=0,fl=0;
REGISTER TEXT *i,*il = OBuf,c;

if (LM) {
	Margin = ArpAllocMem(lm+3,MEMF_CLEAR);
	for (i=Margin;(LONG)( i - Margin) < (LONG)lm; i++) *i=' ';
	}

	for (;;) {
	if (!bufp) if (!(count = Read(Inp,Buf,BFSIZE))) {		
			if(fl) {
			++bufp;	
			*il++ = '\n';
			*il = '\0';
			PrOut(Out);
			}
			return((VOID)0);	
			}
	fl = 1;
		/* check CTRL-C */
		if (SetSignal(0,0) & SIGBREAKF_CTRL_C) 
		Cleanup(RETURN_WARN,NULL,"***Break");


	if (((TEXT *)il - (TEXT *)OBuf) > MAXLIN) 
				Cleanup(RETURN_FAIL,"Buffer overflow");
	

	switch(c = *(Buf + bufp++)) {

		case '\012':
		fl=0;
		if (LCL) *il++ = '\015';
		*il++ = c;
		*il = '\0';
		PrOut(Out);
		il = OBuf;
		break;
		case '\015':
		if (CL) *il++ = '\012';
		if (!CL && !SC)	*il++ = c;
		break;

		default:
		*il++ = c;
	}
	

	if (bufp == count) bufp = 0;

	}
}

VOID _main(Line)
STRPTR Line;
{



	BPTR infh,outfh;

	Pr = (struct Process*)FindTask(NULL);
	
	if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
			Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY,NULL);
	
	/* parse command line */
	for (argc=0;argc < NARGS ;++argc)
		argv[argc] = (STRPTR) NULL;

	while(*Line > ' ')
		++Line;

	if((argc = GADS(++Line,
		strlen(Line),
		"Usage: Trunc [FROM Pattern] [TO Filename] LCL | SC | CL |\n       LM leftmargin | LC leftcolumn | RC rightcolumn\n\n       LCL : Linefeeds to CR+LFs\n       SC  : Strip CRs\n       CL  : CRs to Linefeeds",
		argv,
		"FROM,TO,LCL/S,SC/S,CL/S,LM,LC,RC" )) < 0)
			Cleanup(RETURN_WARN,NULL,FROM);

	if (!(Buf = ArpAllocMem(BFSIZE,MEMF_CLEAR)) || 
		!(OBuf = ArpAllocMem(MAXLIN+1,MEMF_CLEAR)))
				Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"Error: no memory");

	if ( Anchor = (struct UserAnchor *)ArpAlloc( (ULONG)sizeof( *Anchor )) )
	{
		Anchor->ua_AP.ap_Length = 255;	/* Want full path built */
		
	}
	else Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"Error:No memory");
	
	if (FROM)  {

	if (!(FindFirst(FROM,(struct AnchorPath*) Anchor)))
		if (Anchor->ua_AP.ap_Info.fib_DirEntryType < 0) {
			if(!(infh=ArpOpen(Anchor->ua_AP.ap_Buf,MODE_OLDFILE))) {
				Printf("Can't open %s\n",FROM);
				Cleanup(RETURN_ERROR,ERROR_OBJECT_NOT_FOUND,NULL);
				}
			}
		else {
			Printf("%s is a directory !\n",TO);
			Cleanup(RETURN_ERROR,ERROR_OBJECT_WRONG_TYPE,NULL);
			}
		else {
			Printf("Can't find %s\n",FROM);
			Cleanup(RETURN_ERROR,ERROR_OBJECT_NOT_FOUND,NULL);
			}
		}
	else infh = Input();

	if(TO) {
			if(!(outfh=ArpOpen(TO,MODE_NEWFILE))) {
				Printf("Can't open %s\n",TO);
				Cleanup(RETURN_ERROR,ERROR_OBJECT_NOT_FOUND,NULL);
				}
			}
	else outfh = Output();

/*	if((CL && SC && LCL) || (LC && RC && LM) || (LC && RC) || (LC && LM) || (RC && LM))
						Cleanup(RETURN_ERROR,NULL,"Bad args"); 
*/
	if	(( argc > 3 ) ||
		(( argc == 3) && !(FROM && TO)) || 
		(( argc == 2) && (!FROM && !TO)))	
					Cleanup(RETURN_ERROR,NULL,"Bad args");

	if (LM)
		if( ((lm=Atol(LM)) <=0 || Errno == ERRBADINT))
			Cleanup(RETURN_ERROR,NULL,"Bad args");

	if (LC)
		if( ((lc=Atol(LC)) <=0 || Errno == ERRBADINT))
			Cleanup(RETURN_ERROR,NULL,"Bad args");

	if (RC)
		if( ((rc=Atol(RC)) <=0 || Errno == ERRBADINT))
			Cleanup(RETURN_ERROR,NULL,"Bad args");
			
	Trunc(infh,outfh);

	Cleanup(NULL,NULL,NULL);

}
