/* printPanel.c 
 *
 *  defines the GUIFront characteristics of the print panel
 */
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <stdio.h>  
#include <string.h>
#include <stdlib.h>
#include <intuition/gadgetclass.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include "amiCheck.h"
#include "printPanel.h"
#include "dataBase.h"
#include "enterPanel.h"
#include "regGadget.h"

/* prototypes */
BOOL PrintHandleGadget(struct IntuiMessage *);
void PrintInit(void);
void PrintBuildImage(entryNode *entry, checkForm *form,BOOL test);
void PrintClipImage(void);
BOOL PrintCheckImage(FILE *out,checkForm *fc, BOOL vouch, BOOL first, BOOL *page1);
void PrintBuildVoucher(entryNode *entry,checkForm *form,BOOL test);
void PrintBuildAmntStr(entryNode *entry, char *dest);
void PrintAutoVoid(entryNode *);
BOOL PrintGoodbye(struct IntuiMessage *);
void PrintGo(void);
filterNode *PrintCheckFind(int check);

printControl localPrint;
BOOL printEm;
BOOL needFeed;
/*
__far char checkImage[MAXCHECKLINES][MAXCHECKCOLS+1];
*/

ULONG alloccolumns;
char *checkImage;

char tempstr[MAXCHECKCOLS+1];
struct Window *printWin = NULL;
GUIFront *printGUI;
static BOOL done;
entryNode autovoid;

/* quick configure of some gadgets */
STRPTR prlabels[] =
{
	"Print Checks",
	"Mark As Printed",
	NULL,
};

struct TagItem  prcytags[] = {
	{GTCY_Labels,prlabels},
	{TAG_DONE},
};


/* define gadgetspec */
GadgetSpec PRgadgetspecs[] = 
{
	{CYCLE_KIND,10,0,{0,0,0,0,"_Mode:",NULL, GID_PRPRINTMODE,
		PLACETEXT_LEFT}, prcytags, GS_DefaultTags},

	{CHECKBOX_KIND,0,0,{0,0,0,0,"Auto_Void",NULL,GID_PRAUTOVOID,
		PLACETEXT_RIGHT},NULL,GS_DefaultTags},

	{INTEGER_KIND,4,0,{0,0,0,0,"Checks _First Sheet:", NULL, GID_PRCHECKPAGE,         
                PLACETEXT_LEFT}, TxtInt, GS_DefaultTags},

	{INTEGER_KIND,4,0,{0,0,0,0,"_Starting Check:", NULL, GID_PRCHECKSTART,         
                PLACETEXT_LEFT}, TxtInt, GS_DefaultTags},

	{BUTTON_KIND,0,0, {0,0,0,0,"_OK",NULL,GID_PROK,
		PLACETEXT_IN},NULL,GS_DefaultTags},

	{BUTTON_KIND,0,0, {0,0,0,0,"_Cancel",NULL,GID_PRCANCEL,
		PLACETEXT_IN},NULL,GS_DefaultTags},
};

/* set up array of pointers to our specs */
GadgetSpec *PR_PrintSpecs[] =
{
        &PRgadgetspecs[0],
        &PRgadgetspecs[1],
        &PRgadgetspecs[2],
        &PRgadgetspecs[3],
        &PRgadgetspecs[4],
        &PRgadgetspecs[5],
        NULL,
};


/* define the layout of this panel */
ULONG PR_PrintPanel[] =
{
   GUIL_Flags, GUILF_PropShare | GUILF_EqualWidth,
                                          
    GUIL_HorizGroup, 1,
        GUIL_Flags, GUILF_PropShare | GUILF_EqualHeight,
	GUIL_FrameType, GUILFT_Recess,

		GUIL_VertGroup,1,
			GUIL_Flags, GUILF_LabelAlign | GUILF_EqualWidth,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_FrameHeadline, "Print Options",
	
			GUIL_GadgetSpecID, GID_PRPRINTMODE,
			GUIL_GadgetSpecID, GID_PRCHECKSTART,
		TAG_DONE,

		GUIL_VertGroup,1,
			GUIL_Flags, GUILF_EqualWidth,
			GUIL_FrameType, GUILFT_Ridge,
			GUIL_FrameHeadline, "Sheet Feed Options",

			GUIL_GadgetSpecID, GID_PRAUTOVOID,
			GUIL_GadgetSpecID, GID_PRCHECKPAGE,
		TAG_DONE,
    TAG_DONE,
    
    GUIL_HorizGroup,1,
        GUIL_Flags, GUILF_EqualSize | GUILF_EqualWidth,
        
           GUIL_GadgetSpecID, GID_PROK,
	   GUIL_GadgetSpecID, GID_PRCANCEL,
           
    TAG_DONE,                                  
 TAG_DONE,       
};

char amounts[31][10] = {
	"Zero",
	"One",
	"Two",
	"Three",
	"Four",
	"Five",
	"Six",
	"Seven",
	"Eight",
	"Nine",
	"Ten",
	"Eleven",
	"Twelve",
	"Thirteen",
	"Fourteen",
	"Fifteen",
	"Sixteen",
	"Seventeen",
	"Eightteen",
	"Nineteen",
	"Twenty",
	"Thirty",
	"Forty",
	"Fifty",
	"Sixty",
	"Seventy",
	"Eighty",
	"Ninety",
	"Hundred",
	"Thousand",
	"Million",
};

/****************************************************
* PrintGUI
*
*	create gui for this panel
*****************************************************/
void PrintGUI(void)
{
 UWORD ordinal;
 BOOL noreply; 
 ULONG signal;
 
   done = FALSE;

   AmiLock();
 
   /* bring up this gui */
   GF_SetGUIAttr(printGUI, GUI_OpenGUI, TRUE, TAG_DONE);
   
   /* grab window */
   GF_GetGUIAttr(printGUI,GUI_Window,&printWin,TAG_DONE);

   PrintInit();

   /* Process input events */
    while (!done)
       {
         struct IntuiMessage *imsg;
                    /* Wait for an event to occur */

                    signal = GF_Wait(guiapp,AmigaGuideSignal(agc));
		   if (signal & AmigaGuideSignal(agc)) {
			AmiHelpMsg();
			continue;
		    }

                    /* We only bother to listen for CLOSEWINDOW events.
                     * Of course, in a real application, you would be
                     * examining the Class field for IDCMP_GADGETUP
                     * messages and act accordingly.
                     */

                    while (imsg = GF_GetIMsg(guiapp))
                    {
			noreply = TRUE;
                        switch (imsg->Class) {
				case IDCMP_REFRESHWINDOW:
					RegRefresh(TRUE);
					break;

                                case IDCMP_CLOSEWINDOW:
                                        done = TRUE;
                                        break;

				case IDCMP_RAWKEY:
					AmiHelpKey(imsg,PRINT_PANEL);
					break;

				case IDCMP_GADGETUP:
					noreply = FALSE;
					done=PrintHandleGadget(imsg);
					break;

	            }

		    if (noreply) GF_ReplyIMsg(imsg);

         	}
  }

  /* close window */
  GF_SetGUIAttr(printGUI, GUI_OpenGUI, FALSE, TAG_DONE);            
  printWin = NULL;

  if (printEm == TRUE) 
	PrintGo();
      
  AmiUnlock();
}

/***************************************************
* PrintHandleGadget....
*
* 	double clicks change ord val.
****************************************************/
BOOL PrintHandleGadget(struct IntuiMessage *imsg)
{
BOOL done = FALSE;
struct Gadget *gad = (struct Gadget *)(imsg->IAddress);
UWORD code = imsg->Code;
UWORD temp;

 switch (gad->GadgetID) {
	case GID_PRAUTOVOID:
		localPrint.autoVoid = code;
		break;
	
	case GID_PRCHECKPAGE:
		temp = (UWORD)((struct StringInfo*)gad->SpecialInfo)->LongInt;
		if (temp == 0 || temp > checkForms.userForm.checks_page) {
			DisplayBeep(printWin->WScreen);
			DataAnnounce(printGUI, "Checks/page illegal.");
			GF_ReplyIMsg(imsg);
			DataSitNSpin(PR_PrintSpecs[GID_PRCHECKPAGE]->gs_Gadget,printWin);
			return (done);
		}
		else localPrint.checksPage1 = temp;
		break;
	
	case GID_PRCHECKSTART:
		localPrint.checkNumber = (UWORD)((struct StringInfo*)gad->SpecialInfo)->LongInt;
		break;

	case GID_PRPRINTMODE:
		localPrint.printMode = code;
		break;

	case GID_PRCANCEL:
		done = TRUE;
		break;

	case GID_PROK:
		if (PrintGoodbye(imsg) == TRUE) {
			memcpy(&checkPrint,&localPrint,sizeof(printControl));
			done = TRUE;
			printEm = TRUE;
		}
		else return(FALSE);
		break;
 }

 return (done);
}

/***********************************************************
* PrintGoodbye()
*
*	collect user input
************************************************************/
BOOL PrintGoodbye(struct IntuiMessage *imsg)
{
 UWORD val;

 val =  (UWORD)((struct StringInfo*)(PR_PrintSpecs[GID_PRCHECKPAGE]->gs_Gadget)->SpecialInfo)->LongInt;
 if (val == 0 || val > checkForms.userForm.checks_page) {
	DisplayBeep(printWin->WScreen);
	DataAnnounce(printGUI, "Checks/page illegal.");
	GF_ReplyIMsg(imsg);
	DataSitNSpin(PR_PrintSpecs[GID_PRCHECKPAGE]->gs_Gadget,printWin);
	return (FALSE);
 }
 localPrint.checksPage1 = val;

 localPrint.checkNumber =  (UWORD)((struct StringInfo*)(PR_PrintSpecs[GID_PRCHECKSTART]->
				gs_Gadget)->SpecialInfo)->LongInt;

 return (TRUE);
}

/***********************************************************
* PrintInit()
*
*
************************************************************/
void PrintInit(void)
{
 printEm = FALSE;

 memcpy(&localPrint,&checkPrint,sizeof(printControl));
 localPrint.checksPage1 = checkForms.userForm.checks_page;

 /* fill in the details */
 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRAUTOVOID]->gs_Gadget,
	GTCB_Checked,localPrint.autoVoid,
	TAG_DONE);

 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRCHECKPAGE]->gs_Gadget,
	GTIN_Number, localPrint.checksPage1,
	TAG_DONE); 

 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRCHECKSTART]->gs_Gadget,
	GTIN_Number, localPrint.checkNumber,
	TAG_DONE);

 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRPRINTMODE]->gs_Gadget,
	GTCY_Active,localPrint.printMode,
	TAG_DONE);

 /* disable if appropriate */
 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRAUTOVOID]->gs_Gadget,
	GA_Disabled,!checkForms.userForm.sheet_feed,
	TAG_DONE);

 GF_SetGadgetAttrs (printGUI, PR_PrintSpecs[GID_PRCHECKPAGE]->gs_Gadget,
	GA_Disabled,!checkForms.userForm.sheet_feed,
	TAG_DONE); 
}

/***********************************************************
* PrintItem()
*
*	Print a page of checks out ( now wants a filterNode )
************************************************************/
BOOL PrintItem(FILE *out,filterNode *filt, formControl *form, BOOL test, BOOL page1, int *lastone)
{
 BOOL retval = TRUE;
 int checks;
 entryNode *entry, voidEntry;
 BOOL printpage1 = page1;
 needFeed = TRUE;
 
 /* empty list? */
 if (filt == NULL)
	return (TRUE);


 if (test == FALSE)
	amiChangedItems = TRUE;

 /* begin printing */
 entry = filt->entry;
 
 for (checks = 0;checks < form->userForm.checks_page;checks++) {

	/* pre-check voucher? */
	if (form->userForm.voucher_type == VT_ABOVEBELOW || form->userForm.voucher_type == VT_ABOVE) {
		PrintBuildVoucher(entry,&form->userForm,test);
		if (!PrintCheckImage(out,&form->userForm,FALSE, (checks == 0),&page1 ))
			return (FALSE);
	}

 	/* build & print check image */
	if (form->userForm.voucher_type == VT_LEFTRIGHT)
		PrintBuildVoucher(entry,&form->userForm,test);

 	PrintBuildImage(entry, &form->userForm,test);
	if (!PrintCheckImage(out,&form->userForm,
			(form->userForm.voucher_type == VT_LEFTRIGHT && checks == form->userForm.checks_page-1),
			(form->userForm.voucher_type != VT_ABOVEBELOW && form->userForm.voucher_type != VT_ABOVE 
                && checks == 0),&page1)) 
		return(FALSE);

	/* post-check voucher? */
	if (form->userForm.voucher_type == VT_ABOVEBELOW || form->userForm.voucher_type == VT_BELOW) {
		PrintBuildVoucher(entry,&form->userForm,test);
		if (!PrintCheckImage(out,&form->userForm,TRUE,FALSE,&page1))
			return(FALSE);
	}

	/* double-voucher? */
	else if (form->userForm.voucher_type == VT_TWOBELOW) {
		PrintBuildVoucher(entry,&form->userForm,test);
		if (!PrintCheckImage(out,&form->userForm,FALSE,FALSE,&page1))
			return(FALSE);
		if (!PrintCheckImage(out,&form->userForm,TRUE,FALSE,&page1)) 
			return(FALSE);
	}

	/* is there a next check? */
	if (test == FALSE && printpage1 == TRUE && checks == checkPrint.checksPage1-1)	
		break;
	else if (checks == form->userForm.checks_page-1)
		break;

	/* grab next node if not test */
	if (test == FALSE) {

		/* mark up current one */
		if (filt != NULL) {
			*lastone++;

			/* are we done? */
			filt->entry->flags |= PRINTED;
			filt = PrintCheckFind(filt->entry->check+1);
			if (filt != NULL) {
				if (filt->entry->flags & PRINTED) 
					filt = NULL;
				else	entry = filt->entry;
			}
		}
		
		/* test for next step */
		if (filt == NULL) {
			/* if last node, use autovoid? */
			if (checkPrint.autoVoid == TRUE) {
				/* create autovoid node */
 				PrintAutoVoid(&voidEntry);
				entry = &voidEntry;
			}
			else	break;
		}
	}
 }

 /* spit form out */
 if (form->userForm.sheet_feed) {
 	if (fprintf(out,"\f\n") != strlen("\f\n"))
		return (FALSE);
 }

 return (retval);
}

/***********************************************************
* PrintCheckAlloc()
*
*	Allocate the check field
************************************************************/
char *PrintCheckAlloc(checkForm *fc)
{
 alloccolumns = fc->columns+1;
 return ( (char *)malloc((fc->lines_check) * (fc->columns+1)));
}

/***********************************************************
* PrintCheckImage()
*
*	Print the actual image 
************************************************************/
BOOL PrintCheckImage(FILE *out,checkForm *form, BOOL lastvoucher, BOOL first, BOOL *page1)
{
 int x,start;
 int cols,lines = form->lines_check;

 PrintClipImage();

 if (form->sheet_feed == TRUE) {
 	if (first == TRUE) 
		start = form->top_lines;
 	else	start = 0;
 }
 else {
	if (*page1 == TRUE) {
		start = form->top_lines;
		*page1 = FALSE;
	}
	else	start = 0;
 }

 for (x=start;x<lines;x++) {
        
   /* fix the length up */
   cols = strlen(&CHECKGRID(x,0));
   if (cols > form->columns)
        cols = form->columns;
   if (cols < MAXCHECKCOLS) {
        CHECKGRID(x,cols)=0;
   }

	if (lastvoucher && x == lines-1)
		sprintf(tempstr,"%s",&CHECKGRID(x,0));
	else	sprintf(tempstr,"%s\n",&CHECKGRID(x,0));
   
	if (fprintf(out,tempstr) != strlen(tempstr))
		return (FALSE);
 }

 if (lastvoucher && strlen(tempstr) > 1)
	needFeed = FALSE;
 
 return (TRUE);
}

/***********************************************************
* PrintBuildVoucher()
*
*	Build a voucher
************************************************************/
void PrintBuildVoucher(entryNode *entry, checkForm *form, BOOL test)
{
 char str[STRINGSIZE];
 int x,y,z;
 int len;
 int vwidth = form->columns-1;
 int vmargin = (form->columns < 5)?form->columns:5;
 int vline = 5;
 int off = 1;

 /* only do voucher if requested */
 if (form->voucher_type == VT_NONE)
	return;

 if (form->voucher_type == VT_LEFTRIGHT) {
	vwidth = form->voucher_width;
	vmargin = form->voucher_margin;
 }

 /* build the page image */
 for (y=0;y<form->lines_check;y++) {
	/* initialize the check */
	memset(&CHECKGRID(y,0),' ',form->columns);
	CHECKGRID(y,form->columns)=0;

	/* fill test data */
	if (test == TRUE) {
		if (y == 0) {
			for (x=0;x<form->columns;x++)
				CHECKGRID(y,x) = ('0'+ (x%10));
		}
		else if (y == form->lines_check-1) {
			for (x=0;x<form->columns;x++)
				CHECKGRID(y,x) = ('0'+ (x%10));
		}
		
		CHECKGRID(y,0) = ('0'+(y%10));
	}

	for (x=0;x<form->columns;x++) {
		/* amount */
		if (y==(2*off)+vline && vmargin == x) {
			DataBuildAmnt(TRUE,&entry->amount,str);
			len = strlen(str);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}
		}

		/* date */
		if (y==(0*off)+vline && vmargin == x) {
			DataBuildDate(&entry->date,str);
			len = strlen(str);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}
		}

		/* name */
		if (y==(1*off)+vline && vmargin == x) {
			len = strlen(entry->name);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=entry->name[z];
			}
		}

		/* memo */
		if (y==(3*off)+vline && vmargin == x) {
			len = strlen(entry->memo);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=entry->memo[z];
			}		
		}

		/* category */
		if (y==(4*off)+vline && vmargin == x) {
			len = strlen(entry->category);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=entry->category[z];
			}		
		}

		/* state */
		if (y==(4*off)+1+vline && vmargin == x) {
			strcpy(str,"****");
			if (entry->flags & CLEARED) str[2]='C';
			if (entry->flags & VOIDED)  str[0]='V';
			if (entry->flags & TAXDEDUCT) str[1]='T';
			if (entry->flags & RECONCILED) str[3]='R';

			len = strlen(str);
			if (len > vwidth) len = vwidth;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}		
		}

		if (y<=(4*off)+1+vline && (test == TRUE && form->columns-x > len ) && y >= vline)
			for (z=len;z+x<vwidth && z < form->columns-x;z++)
				CHECKGRID(y,x+z)='*';
	}
 }
 
}

/***********************************************************
* PrintClipImage()
*
*	Clip excess spaces
************************************************************/
void PrintClipImage(void)
{
#if 0
 int x,y;

 for (y=0;y<MAXCHECKLINES;y++)
	for (x=form->columns-1;x>=0;x--) 
		if (CHECKGRID(y,x) != ' ') {
			CHECKGRID(y,x+1)=0;
			break;
		}
#endif
}

/***********************************************************
* PrintBuildImage()
*
*	Build the check image
************************************************************/
void PrintBuildImage(entryNode *entry, checkForm *form,BOOL test)
{
 char str[STRINGSIZE];
 int x,y,z,t;
 int len;

 /* build the page image */
 for (y=0;y<form->lines_check;y++) {
	/* initialize the check */
	if (form->voucher_type != VT_LEFTRIGHT) memset(&CHECKGRID(y,0),' ',form->columns);
	CHECKGRID(y,form->columns)=0;

	/* fill test data */
	if (test == TRUE && form->voucher_type != VT_LEFTRIGHT) {
		if (y == 0) {
			for (x=0;x<form->columns;x++)
				CHECKGRID(y,x) = ('0'+ (x%10));
		}
		else if (y == form->lines_check-1) {
			for (x=0;x<form->columns;x++)
				CHECKGRID(y,x) = ('0'+ (x%10));
		}
		
		CHECKGRID(y,0) = ('0'+(y%10));
	}

	for (x=0;x<form->columns;x++) {

		/* amount */
		if (form->amnt_line == y && form->amnt_margin == x) {
			if (entry->flags & VOIDED || entry->amount == 0 )
				strcpy(str,"0.00");
			else 	DataBuildAmnt(TRUE,&entry->amount,str);
			len = strlen(str);

			/* right justify */
			memset(tempstr,' ',form->columns);
			tempstr[form->columns]=0;
			
			if (len > form->amnt_width) len = form->amnt_width;
			if (len > form->columns-x) len = form->columns-x;

			t=form->amnt_width<form->columns-x?form->amnt_width:form->columns-x;
			if (len > 0) {	
				if (test == TRUE)
					memset(tempstr,'*',t);

				for (z=0;z<len;z++)
					tempstr[t-z-1]=str[strlen(str)-z-1]; 

				for (z=0;z<t;z++){
					CHECKGRID(y,x+z)=tempstr[z];
				}

			}
		}

		/* date */
		if (form->date_line == y && form->date_margin == x) {
			DataBuildDate(&entry->date,str);
			len = strlen(str);
			if (len > form->date_width) len = form->date_width;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}

			if (test == TRUE && form->columns-x > len)
				for (z=len;z<form->date_width && z < form->columns-x;z++)
					CHECKGRID(y,x+z)='*';

		}

		/* name */
		if (form->pay_line == y && form->pay_margin == x) {
			if (entry->flags & VOIDED)
				strcpy(str,"VOIDED CHECK");
			else	strcpy(str,entry->name);

			len = strlen(str);
			if (len > form->pay_width) len = form->pay_width;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}

			if (test == TRUE && form->columns-x > len)
				for (z=len;z<form->pay_width && z < form->columns-x;z++)
					CHECKGRID(y,x+z)='*';

		}

		/* memo */
		if (form->memo_line == y && form->memo_margin == x) {
			if (entry->flags & VOIDED)
				strcpy(str,entry->name);	
			else 	strcpy(str,entry->memo);

			len = strlen(str);
			if (len > form->memo_width) len = form->memo_width;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=str[z];
			}		

			if (test == TRUE && form->columns-x > len)
				for (z=len;z<form->memo_width && z < form->columns-x;z++)
					CHECKGRID(y,x+z)='*';
		}

		/* amnt string */
		if (form->str_line == y && form->str_margin == x) {
			PrintBuildAmntStr(entry,tempstr);
			len = strlen(tempstr);
			if (len > form->str_width) len = form->str_width;
			if (len > form->columns-x) len = form->columns-x;

			for (z=0;z<len;z++){
				CHECKGRID(y,x+z)=tempstr[z];
			}		

			if (form->columns-x > len)
				for (z=len;z<form->str_width && z < form->columns-x;z++)
					CHECKGRID(y,x+z)='*';

		}

	}
 }

}

/****************************************************************
* PrintBuildAmntStr()
*
*	build the amount text
*****************************************************************/
void PrintBuildAmntStr(entryNode *entry, char *dest)
{
 ULONG places[4][2];
 ULONG temp;
 int ctr;
 int tens;
 ULONG dollar = entry->amount/100;
 ULONG cent = entry->amount%100;
 BOOL place = FALSE;

 if (entry->flags & VOIDED) {
	dollar = 0;
	cent = 0;
 }

 temp = dollar;

 /* record the places */
 for (ctr=0;ctr<4;ctr++) {
	places[ctr][0] =  temp%1000;
	places[ctr][1] =  places[ctr][0]%100;
	places[ctr][0] -= places[ctr][1];
	places[ctr][0] /= 100; /* move places over */
#if 0
	places[ctr][2] = places[ctr][1] % 10;
	places[ctr][1] -= places[ctr][2];
	places[ctr][1] /= 10; /* move places over */
#endif

	temp /= 1000;
 }

 if (temp > 0) {
	sprintf(dest,"ERROR: AMOUNT TOO LARGE");
	return;
 }

 /* spit it out */
 for (ctr=3;ctr>=0; ctr--) {
	if (places[ctr][0] != 0) {
		sprintf(dest,"%s %s ",amounts[places[ctr][0]],amounts[28]);
		dest += strlen(dest);
		place = TRUE;
	}
	if (places[ctr][1] != 0) {
		if (places[ctr][1] > 19) {
			tens = places[ctr][1] / 10;
			sprintf(dest,"%s",amounts[20+tens-2]);
			dest += strlen(dest);
			if (places[ctr][1]%10)
				sprintf(dest,"-%s ",amounts[places[ctr][1]%10]);
			else 	sprintf(dest," ");
			dest += strlen(dest);
		}
		else 	{
			sprintf(dest,"%s ",amounts[places[ctr][1]]);
			dest += strlen(dest);
		}
		place = TRUE;

	}

	if (place == TRUE && ctr >= 1) {
		sprintf(dest,"%s ",amounts[29+ctr-1]);
		dest += strlen(dest);
	}
	place = FALSE;
 }

 /* check again for zero */
 if (dollar == 0) {
	sprintf(dest,"zero ");
 	dest += strlen("zero ");
 }

 /* stuff in cents */
 if (cent > 0) 
	sprintf(dest,"+ %d/100 ",entry->amount%100);
 else	sprintf(dest,"+ zero/100 ");
}

/********************************************************************
* PrintAutoVoid()
*
*	Handle voiding checks
*********************************************************************/
void PrintAutoVoid(entryNode *entry)
{
 filterNode *filt = NULL;

 entry->flags = VOIDED | PRINTED;
 entry->type = CHECKTYPE;
 entry->amount = 0;
 memcpy(&entry->date,&currDate,sizeof(dateType));
 strcpy(entry->name,"AUTOVOIDED");
 strcpy(entry->memo,"Check Printed");
 strcpy(entry->category,"None");

 entry->check = amntState.currCheckNumber;

 /* bump up and insert! */
 amntState.currCheckNumber++;
 DataAddEntry(entry,&entries,&filt); 

 if (filt != NULL) {
	RegAddEntry(filt);
	AmiDisableSel(TRUE);
 }
}

/********************************************************************
* PrintGo()
*
*	Print checks or mark as needed
*********************************************************************/
void PrintGo(void)
{
 filterNode *filt = NULL;
 int curr = checkPrint.checkNumber;
 int lastcheck=curr,firstcheck=curr;
 FILE *out;
 char msg[100];
 BOOL fail=FALSE,first = TRUE;

 if (usrAccount.decimal != 2) {
	AmiAnnounce("Printing requires two-decimal amounts.\nIf you need otherwise please contact me.");
	return;
 }

 /* find first non-printed check */
 while ( (filt = PrintCheckFind(curr)) != NULL && filt->entry->flags & PRINTED) {
		curr++;
		continue;
 }

 if (filt == NULL)
	return;

 /* now open the check device */
 if ( (out = fopen(checkForms.device,"w")) == NULL) {
	AmiAnnounce("Device Failure.\nCannot open device.");
	return;
 }

 GF_LockGUI(printGUI);


 /* allocate the check */
 if (!(checkImage = PrintCheckAlloc(&checkForms.userForm))) {
	AmiAnnounce("Could not allocate RAM for check printing");
	return;
 }


 /* now, from here lets print! */
 do {
	if (filt->entry->flags & PRINTED)
		break;

	/* print or mark? */
	if (checkPrint.printMode == 0) {
			
			if (!PrintItem(out,filt,&checkForms,FALSE,first,&lastcheck)) {			
				fail=TRUE;
				break;
			}
			first = FALSE;

			/* bump forward xxx times */
			curr += checkForms.userForm.checks_page-1;
			lastcheck = curr;
	}
	else filt->entry->flags |= PRINTED;

	curr++;

 } while ( (filt = PrintCheckFind(curr)) != NULL);

 /* free up check image */
 free (checkImage);

 GF_UnlockGUI(printGUI); 
 fclose(out);

 if (fail) {
	AmiAnnounce("Printer Failure.\nOperation cancelled.");

 	if (firstcheck == lastcheck)
		sprintf(msg,"Printing Information:\nStarting Check: %d\nNo checks printed.",firstcheck);
 }
 else	sprintf(msg,"Printing Information:\nStarting Check: %d\nEnding Check: %d",firstcheck,lastcheck);

 if (strlen(msg))
 	AmiAnnounce(msg);
 msg[0]=0;
}

/********************************************************************
* PrintCheckFind()
*
*	Find the next check to print
*********************************************************************/
filterNode *PrintCheckFind(int check)
{
 filterNode *filt = NULL;

 while ( (filt = (filterNode *)DataGetNext((struct List *)&filtered,(struct Node *)filt)) != NULL)
	if (filt->entry->type == CHECKTYPE && filt->entry->check == check) {
/*
		if (filt->entry->flags & PRINTED)
			return (NULL);
*/

		return (filt);
	}

 return (NULL);
}
