/*********************************************************************/
/*                                                                   */
/*                     Copyright (c) 1987                            */
/*                    Commodore-Amiga, Inc.                          */
/*                    All rights reserved.                           */
/*                                                                   */
/*								     */
/*	Unlimited non-comercial use of this program is given,  	     */
/*	provided this notice is left intact.			     */
/*			andy finkel				     */
/*								     */
/*********************************************************************/


#include "exec/types.h" 
#include "exec/memory.h" 
#include "exec/io.h"
#include "exec/libraries.h"
#include "exec/devices.h"
#include "libraries/dos.h"
#include "devices/printer.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
 
#define LVOBeginIO   DEV_BEGINIO
#define LVOExpunge   LIB_EXPUNGE

#define TASKNAME	"PRT-CONTROL"

#define OK 1
#define CANCEL 2
#define NUMBER1 3
#define NUMBER8 10

#define BLUE 0 
#define WHITE 1 
#define BLACK 2 
#define RED 3 

extern struct Task *FindTask();
extern struct Library *OpenLibrary();
extern struct Window *OpenWindow();
extern ULONG SysBase;

extern VOID aBeginIO();  /* The assembler entry */
extern VOID cBeginIO();
extern VOID aExpunge();

extern LONG convert();
extern VOID cputs();

extern struct Menu menus[];
extern struct Gadget CancelGadget;
extern struct Gadget bgadget[];
extern struct Gadget sGadget[];
extern char buffer1[];
extern char buffer2[];
extern char buffer3[];
extern char buffer4[];
extern char buffer5[];
extern char buffer6[];
extern char buffer7[];
extern char buffer8[];

struct IntuitionBase *IntuitionBase=NULL;

LONG  OldBeginIO, NewBeginIO, OldExpunge, NewExpunge;
char *OldName=NULL;;
struct Device *PrtDevice=NULL;
struct MsgPort replyMsgPort;
int WB;

union printerIO {
struct IOStdReq ios;
struct IODRPReq iodrp;
struct IOPrtCmdReq iopc;
} pIO;

struct NewWindow nw = {
        0, 10,        /* starting position (left,top) */
        320,160,        /* width, height */
        BLUE,WHITE,     /* detailpen, blockpen */
         /* idcmp flags */
        GADGETUP,
        /* window gadget flags */
        WINDOWDEPTH|WINDOWDRAG|SMART_REFRESH|ACTIVATE,
        &CancelGadget,  /* pointer to 1st user gadget */
        NULL,           /* pointer to user check */
        "Printer Control V1.0", /* title */
        NULL,           /* pointer to window screen */
        NULL,           /* pointer to super bitmap */
        0,0,  		/* min width, height */
        0,0,        	/* max width, height */
        NULL};

main(argc,argv)
int argc;
char *argv[];
{
    struct Task *task;
    LONG exitStatus=TRUE,file;

    WB=argc;
    Forbid();

    if (task = FindTask(TASKNAME))Signal(task, SIGBREAKF_CTRL_C);
    else {
	if(pOpen()) {
	    cputs("Error! Printer in Use\n");
	    exit(20);
	}
	OldName = (task = FindTask(0) )->tc_Node.ln_Name;
	FindTask(0)->tc_Node.ln_Name = TASKNAME;

   	PrtDevice = (struct Device *)pIO.ios.io_Device;
   	OldBeginIO = SetFunction(PrtDevice, LVOBeginIO, aBeginIO);
	OldExpunge = SetFunction(PrtDevice, LVOExpunge, aExpunge);
	pClose();
	while (exitStatus) {
	    Wait(SIGBREAKF_CTRL_C);
	    NewBeginIO=SetFunction(PrtDevice, LVOBeginIO, OldBeginIO);
	    NewExpunge=SetFunction(PrtDevice, LVOExpunge, OldExpunge);
	    if((NewBeginIO != (LONG)aBeginIO)||(NewExpunge != (LONG)aExpunge)) {
		/* someone else has replaced the vectors ! */
		/* we cannot exit safely now, until the vectors are back */
		SetFunction(PrtDevice, LVOBeginIO, NewBeginIO); /* new ones in */
		SetFunction(PrtDevice, LVOExpunge, NewExpunge); /* new ones in */
		cputs("Error! Can't exit now. Printer Vectors Changed !\n");
	    }
	    else {
	        task->tc_Node.ln_Name = OldName; /* reset the name */
	        exitStatus = FALSE;
	    }
	}
    }
    Permit();
}

VOID
cputs(s)
char *s;
{
LONG file;
	    	
    if(WB)file=Open("*",MODE_OLDFILE);
    else file=Open("CON:10/10/360/40/Error Window",MODE_NEWFILE);
    if(file) Write(file,s,strlen(s));
    if(!WB)Delay(250); /* wait if Workbench */
    Close(file);
}

int
strlen(s)
char *s;
{
   int i = 0;
   while(*s++) i++;
   return(i);
}

int
pOpen()
{
    /* open the printer device */
    if (OpenDevice("printer.device", 0, &pIO, 0))return(1);	

    /* set up the message port in the I/O request */
    replyMsgPort.mp_Node.ln_Type = NT_MSGPORT;
    replyMsgPort.mp_Flags = 0;
    replyMsgPort.mp_SigBit = 0;
    replyMsgPort.mp_SigTask = 0;
    AddPort(&replyMsgPort);
    pIO.ios.io_Message.mn_ReplyPort = &replyMsgPort;
    return(0);
}

pClose()
{
    RemPort(&replyMsgPort);
    CloseDevice(&pIO);
}



/* REMEMBER, THIS CODE RUNS AS PART OF THE PRINTER TASK */
VOID cBeginIO(ior)
union printerIO *ior;
{
struct Window *window;
struct IntuiMessage *message;
struct Gadget *address;

int i,exitStatus=TRUE;
ULONG WakeUpBit=0;

if(ior->ios.io_Command == PRD_DUMPRPORT) {
    sprintf(buffer1,"0x%lx",ior->iodrp.io_ColorMap); /* fill the buffers */
    sprintf(buffer2,"0x%lx",ior->iodrp.io_Modes);
    sprintf(buffer3,"%ld",ior->iodrp.io_SrcX);
    sprintf(buffer4,"%ld",ior->iodrp.io_SrcY);
    sprintf(buffer5,"%ld",ior->iodrp.io_SrcWidth);
    sprintf(buffer6,"%ld",ior->iodrp.io_SrcHeight);
    sprintf(buffer7,"%ld",ior->iodrp.io_DestCols);
    sprintf(buffer8,"%ld",ior->iodrp.io_DestRows);

    for(i=0; i<12; i++) {
	if((ior->iodrp.io_Special)&(1<<i))bgadget[i].Flags |= SELECTED;
	else bgadget[i].Flags &= ~SELECTED;
    }
    if(!(IntuitionBase=
	(struct IntuitionBase *)OpenLibrary("intuition.library",0)))
		exitStatus=0;
    nw.Screen=IntuitionBase->FirstScreen;
    nw.Type = (USHORT)(((struct Screen *)nw.Screen)->Flags & SCREENTYPE);
    if(!(window=OpenWindow(&nw)))exitStatus=0;
    else {
        SetMenuStrip(window, &menus[0]);
        ActivateGadget(&sGadget[0],window,NULL);
    }
    while (exitStatus) {
        WakeUpBit= Wait((1<<window->UserPort->mp_SigBit));
        if(WakeUpBit & (1<<window->UserPort->mp_SigBit)) {
            while(message=(struct IntuiMessage *)GetMsg(window->UserPort)) {
                switch(message->Class) {
                    case GADGETUP:
			address=message->IAddress;
			exitStatus=DoGadget(address->GadgetID,ior,window);
                        ReplyMsg(message);
                        break;
                   default:
                        ReplyMsg(message);
		}
	    }
	}
    }
    if(window) {
	CloseWindow(window);
	ClearMenuStrip(window);
    }
    if(IntuitionBase)CloseLibrary(IntuitionBase);
    for(i=0; i<10000; i++); /* for dpaint */
}
}

DoGadget(id,ior,window)
LONG id;
union printerIO *ior;
struct Window *window;
{

int i;

    if(id == CANCEL) return(0);
    if(id == OK) {
	ior->iodrp.io_ColorMap = (struct ColorMap *)convert(buffer1);
	ior->iodrp.io_Modes = convert(buffer2);
	ior->iodrp.io_SrcX = convert(buffer3);
	ior->iodrp.io_SrcY = convert(buffer4);
	ior->iodrp.io_SrcWidth = convert(buffer5);
	ior->iodrp.io_SrcHeight = convert(buffer6);
	ior->iodrp.io_DestCols = convert(buffer7);
	ior->iodrp.io_DestRows = convert(buffer8);
	ior->iodrp.io_Special = 0;
        for(i=0; i<12; i++) {
	    if(bgadget[i].Flags&SELECTED)ior->iodrp.io_Special += (1<<i);
	}
	return(0); /* and exit */
    }
     if( (id>=NUMBER1) && (id<=NUMBER8)) { /* activate next string gadget */
	ActivateGadget(&sGadget[(id-NUMBER1+1)&7],window,NULL);
    }
    return(TRUE); /* keep going */
}

LONG
convert(buffer)
UBYTE *buffer;
{
UBYTE *point=buffer,c;
LONG sign=1,mult=10,value=0;	/* assume decimal */

while( (c= *point++)) {
     if(c=='x') {
	mult=16; /* oops, hex, start again */
	value=0;
     }
     else if(c=='-') {
	value=0; /* start again */
	sign = -1;
     }
     else if( ((c>='0') && (c <= '9')) || ((c>='A') && (c <= 'F'))) {
	    value *= mult;
	    value += ( (c>='0') && (c <= '9')) ? c-'0' : c - 'A' + 10;
     }
}
return(value*sign);
}



