home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d3xx
/
d352
/
printhandler.lha
/
PrintHandler
/
Print-Handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-02
|
13KB
|
673 lines
/* $Revision Header *** Header built automatically - do not edit! ***********
*
* (C) Copyright 1990 by MXM
*
* Name .....: Print-Handler.c
* Created ..: Wednesday 11-Apr-90 09:51
* Revision .: 6
*
* Date Author Comment
* ========= ======== ====================
* 11-Apr-90 Olsen Created this file!
*
****************************************************************************
*
* Notez-bien: This version of Print-Handler will only compile under
* Aztec 'C' 5.0. Some effort must be taken to adapt it
* for Lattice 'C' 5.0.
*
* I've left all my debugs in and commented them out. This should
* compile fine now.
*
* $Revision Header ********************************************************/
/* Function prototypes (no includes this time). */
struct DataSeg * CreateSeg(APTR,LONG);
struct DataSeg * DeleteSeg(struct DataSeg *);
VOID ReturnPacket(struct DosPacket *,ULONG,ULONG);
struct DosPacket * TaskWait(VOID);
LONG PrintIt(APTR,LONG);
LONG PrintData(UBYTE *,LONG,struct PopSupport *);
VOID * SendCustomMsg(LONG);
VOID QueueEntryPoint(VOID);
LONG _main(VOID);
/* This structure is used to hold a fragment of the file to
* be printed.
*/
struct DataSeg
{
struct DataSeg *NextSeg;
APTR Buffer;
LONG Length;
};
/* Shared library structures. */
struct IntuitionBase *IntuitionBase;
struct MXMBase *MXMBase;
/*struct Library *FarBase;*/
extern struct ExecBase *SysBase;
/* This is the maximum length of a printer line. */
#define MAXPRINT 1024
/* This is the maximum number of available slots. */
#define MAXSLOT 128
/* Handshake signal. */
#define SIG_SHAKE SIGBREAKF_CTRL_D
/* Some more global data. */
struct Preferences *Preferences;
struct IOStdReq *PrinterDevice;
struct Process *QueueProc;
struct Process *HandlerProc;
struct DataSeg *DataSegs[MAXSLOT];
UBYTE Available[MAXSLOT];
UBYTE LineStack[MAXPRINT];
/* Working stats for the printer process. */
LONG LinesDone = 0,ColumnsDone = 0;
/* _main():
*
* This is the main entry point to the handler
* process.
*/
LONG
_main()
{
struct DosPacket *PrintPacket;
struct DeviceNode *PrintNode;
LONG OpenCount = 0,i;
/* Mark all buffers as vacant. */
memset(Available,TRUE,MAXSLOT);
HandlerProc = (struct Process *)SysBase -> ThisTask;
/* Started from CLI? */
if(HandlerProc -> pr_CLI)
return(-1);
/* Wait for parameter packet. */
PrintPacket = TaskWait();
/* Pointer to our own DeviceNode. */
PrintNode = (struct DeviceNode *)BADDR(PrintPacket -> dp_Arg3);
/* Open mxm.library. */
if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",34)))
{
ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
goto FallOff;
}
/* if(!(FarBase = OpenLibrary("farprint.library",0)))*/
/* {*/
/* ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);*/
/* goto FallOff;*/
/* }*/
/* Extract global library vector. */
IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
/* Create the printer process. */
if(!(QueueProc = CreateFuncProc("Print-Handler.queue",10,QueueEntryPoint,4096)))
{
ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
goto FallOff;
}
/* Wait for a reply. */
Wait(SIG_SHAKE);
/* Process quietly removed itself. */
if(!QueueProc)
{
ReturnPacket(PrintPacket,DOSFALSE,PrintPacket -> dp_Res2);
goto FallOff;
}
/* We're on the scene now. */
PrintNode -> dn_Task = &HandlerProc -> pr_MsgPort;
/* Return the compliment. */
ReturnPacket(PrintPacket,DOSTRUE,PrintPacket -> dp_Res2);
/* Go into loop. */
for(;;)
{
/* Wait for the packet. */
/* SendText("TaskWait");*/
PrintPacket = TaskWait();
/* SendText("Type = %ld",PrintPacket -> dp_Type);*/
switch(PrintPacket -> dp_Type)
{
/* Somebody Open()ed us. */
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
{
struct FileHandle *FileHandle = (struct FileHandle *)BADDR(PrintPacket -> dp_Arg1);
/* SendText("Open");*/
/* Assume failure. */
FileHandle -> fh_Port = DOSFALSE;
/* Look for an empty buffer. */
for(i = 0 ; i < MAXSLOT ; i++)
{
if(Available[i])
{
FileHandle -> fh_Port = (struct MsgPort *)DOSTRUE;
FileHandle -> fh_Arg1 = i;
Available[i] = FALSE;
/* SendText("Clean open! -> %ld.",i);*/
OpenCount++;
break;
}
}
ReturnPacket(PrintPacket,(LONG)FileHandle -> fh_Port,PrintPacket -> dp_Res2);
break;
}
/* A FileHandle got closed. */
case ACTION_END:
{
OpenCount--;
/* SendText("Close -> %ld",PrintPacket -> dp_Arg1);*/
SendCustomMsg(PrintPacket -> dp_Arg1);
ReturnPacket(PrintPacket,DOSTRUE,PrintPacket -> dp_Res2);
break;
}
/* We always read *nothing*. */
case ACTION_READ:
{
/* SendText("Read -> %ld",PrintPacket -> dp_Arg1);*/
ReturnPacket(PrintPacket,NULL,PrintPacket -> dp_Res2);
break;
}
/* Something gets written to a FileHandle. */
case ACTION_WRITE:
{
char *Buffer = (char *)PrintPacket -> dp_Arg2;
struct DataSeg *NextSlot;
/* SendText("Write -> %ld Bytes %ld Buffer %lx",PrintPacket -> dp_Arg1,PrintPacket -> dp_Arg3,Buffer);*/
PrintPacket -> dp_Res1 = PrintPacket -> dp_Arg3;
/* Add the new data. */
if(!DataSegs[PrintPacket -> dp_Arg1])
{
if(!(DataSegs[PrintPacket -> dp_Arg1] = CreateSeg((APTR)Buffer,PrintPacket -> dp_Arg3)))
{
PrintPacket -> dp_Res2 = ERROR_NO_FREE_STORE;
PrintPacket -> dp_Res1 = 0;
}
/* else*/
/* SendText("Created.");*/
}
else
{
NextSlot = DataSegs[PrintPacket -> dp_Arg1];
while(NextSlot -> NextSeg)
NextSlot = NextSlot -> NextSeg;
if(!(NextSlot -> NextSeg = CreateSeg((APTR)Buffer,PrintPacket -> dp_Arg3)))
{
PrintPacket -> dp_Res2 = ERROR_NO_FREE_STORE;
PrintPacket -> dp_Res1 = 0;
}
/* else*/
/* SendText("Appended.");*/
}
ReturnPacket(PrintPacket,PrintPacket -> dp_Res1,PrintPacket -> dp_Res2);
break;
}
/* We are to leave the town. */
case ACTION_DIE:
{
ReturnPacket(PrintPacket,DOSTRUE,0);
goto FallOff;
}
/* Say what? */
default:
{
ReturnPacket(PrintPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
break;
}
}
}
FallOff:PrintNode -> dn_Task = NULL;
/* SendText("FallOff");*/
/* Tell printer process to shut down. */
if(QueueProc)
{
SendCustomMsg(-1);
/* SendText("Handshake...");*/
Wait(SIG_SHAKE);
}
/* SendText("Close mxm");*/
/* Close the library. */
if(MXMBase)
CloseLibrary((struct Library *)MXMBase);
/* SendText("Close far");*/
/* if(FarBase)*/
/* CloseLibrary(FarBase);*/
}
/* SendCustomMsg(Slot):
*
* Send a message to the printer process.
*/
VOID *
SendCustomMsg(Slot)
LONG Slot;
{
struct Message *TempMsg = (struct Message *)AllocRem(sizeof(struct Message),MEMF_PUBLIC | MEMF_CLEAR);
if(TempMsg)
{
TempMsg -> mn_Node . ln_Name = (char *)Slot;
TempMsg -> mn_ReplyPort = NULL;
TempMsg -> mn_Length = sizeof(struct Message);
/* SendText("SendCustomMsg -> %ld",Slot);*/
PutMsg(&QueueProc -> pr_MsgPort,TempMsg);
}
return((VOID *)TempMsg);
}
/* QueueEntryPoint():
*
* The printer process. This revision now send the data
* to be printed to the process rather than to process
* the data itself. This saves some amount of time when
* calling processes send their files while the printer
* is still busy.
*/
VOID
QueueEntryPoint()
{
struct MsgPort *PrinterPort;
struct Message *QueueMsg;
LONG GoOn,Slot,i;
struct PopSupport PopSupport;
geta4();
/* We want the error pop-ups to beep. */
PopSupport . ps_Flags = PS_BEEP;
PopSupport . ps_TimeOut = 0;
/* Open everything this process needs. */
if(!(PrinterPort = (struct MsgPort *)CreatePort(NULL,0)))
goto FallOff;
if(!(PrinterDevice = (struct IOStdReq *)CreateStdIO(PrinterPort)))
goto FallOff;
if(OpenDevice("printer.device",0,PrinterDevice,0))
goto FallOff;
Preferences = &((struct PrinterData *)PrinterDevice -> io_Device) -> pd_Preferences;
/* We're running. */
Signal((struct Task *)HandlerProc,SIG_SHAKE);
/* SendText("Process running.");*/
/* Go into infinite loop. */
FOREVER
{
WaitPort(&QueueProc -> pr_MsgPort);
while(QueueMsg = GetMsg(&QueueProc -> pr_MsgPort))
{
GoOn = TRUE;
if((Slot = (LONG)QueueMsg -> mn_Node . ln_Name) != -1)
{
/* SendText("Slot %ld",Slot);*/
while(DataSegs[Slot])
{
if(GoOn)
{
if(!PrintData((UBYTE *)DataSegs[Slot] -> Buffer,DataSegs[Slot] -> Length,&PopSupport))
GoOn = FALSE;
}
DataSegs[Slot] = DeleteSeg(DataSegs[Slot]);
}
/* New: produce a working formfeed if last page
* wasn't 100% occupied.
*/
if(Preferences -> PaperType == SINGLE && LinesDone < Preferences -> PaperLength)
{
LONG ToDo = Preferences -> PaperLength - LinesDone;
for(i = 0 ; i < ToDo ; i++)
PrintIt((APTR)"\n",1);
}
GoOn = TRUE;
Available[Slot] = TRUE;
}
else
GoOn = FALSE;
FreeRem(QueueMsg);
LinesDone = ColumnsDone = 0;
if(!GoOn)
goto FallOff;
}
}
FallOff:if(PrinterDevice)
{
/* SendText("CloseDevice");*/
if(PrinterDevice -> io_Device)
CloseDevice(PrinterDevice);
/* SendText("DeleteStdIO");*/
DeleteStdIO(PrinterDevice);
}
/* SendText("DeletePort");*/
if(PrinterPort)
DeletePort(PrinterPort);
Forbid();
Signal((struct Task *)HandlerProc,SIG_SHAKE);
QueueProc = NULL;
}
/* PrintIt(Buffer,Length):
*
* The real printer interface.
*/
LONG
PrintIt(Buffer,Length)
APTR Buffer;
LONG Length;
{
if(Buffer && Length)
{
LONG Error;
PrinterDevice -> io_Command = CMD_WRITE;
PrinterDevice -> io_Data = Buffer;
PrinterDevice -> io_Length = Length;
Error = DoIO(PrinterDevice);
return(Error);
}
return(IOERR_BADLENGTH);
}
/* PrintData(Buffer,Length,PopSupport):
*
* This one send the data to the printer.
*/
LONG
PrintData(Buffer,Length,PopSupport)
UBYTE *Buffer;
LONG Length;
struct PopSupport *PopSupport;
{
LONG i,InBuff = 0,PaperWidth = Preferences -> PrintRightMargin - Preferences -> PrintLeftMargin;
/* SendText("Buffer %lx Length %ld",Buffer,Length);*/
memset(LineStack,0,MAXPRINT);
if(Buffer)
{
for(i = 0 ; i < Length ; i++)
{
LineStack[InBuff++] = Buffer[i];
ColumnsDone++;
if(ColumnsDone == PaperWidth || Buffer[i] == '\n')
{
if(ColumnsDone == PaperWidth || ColumnsDone == MAXPRINT)
{
LineStack[InBuff++] = '\n';
ColumnsDone++;
}
LineStack[InBuff] = 0;
if(PrintIt((APTR)LineStack,InBuff))
PopRequest(NULL,"Print-Handler Problem:","Error copying text to printer,\nplease check cables and\nsupplies.",NULL,"Continue?",FALSE,PopSupport);
if((++LinesDone) == Preferences -> PaperLength)
{
LinesDone = 0;
if(Preferences -> PaperType == SINGLE)
{
if(!PopRequest(NULL,"Print-Handler Request:","Finished with current page,\nplease insert next sheet of\npaper.","Continue","Abort",TRUE,NULL))
return(FALSE);
}
}
ColumnsDone = InBuff = 0;
memset(LineStack,0,MAXPRINT);
}
}
if(InBuff)
PrintIt((APTR)LineStack,InBuff);
}
return(TRUE);
}
/* CreateSeg(Buffer,Length):
*
* Create a new data segment.
*/
struct DataSeg *
CreateSeg(Buffer,Length)
APTR Buffer;
LONG Length;
{
struct DataSeg *NewSeg;
/* SendText("CreateSeg Length %ld",Length);*/
if(NewSeg = (struct DataSeg *)AllocRem(sizeof(struct DataSeg),MEMF_PUBLIC | MEMF_CLEAR))
{
if(NewSeg -> Buffer = (APTR)AllocRem(Length,MEMF_PUBLIC | MEMF_CLEAR))
{
CopyMem(Buffer,NewSeg -> Buffer,Length);
NewSeg -> Length = Length;
/* SendText("Buffer %lx",NewSeg -> Buffer);*/
return(NewSeg);
}
FreeRem(NewSeg);
}
return(NULL);
}
/* DeleteSeg(OldSeg):
*
* Delete a data segment.
*/
struct DataSeg *
DeleteSeg(OldSeg)
struct DataSeg *OldSeg;
{
struct DataSeg *NextSeg = NULL;
if(OldSeg)
{
NextSeg = OldSeg -> NextSeg;
if(OldSeg -> Buffer && OldSeg -> Length)
{
FreeRem(OldSeg -> Buffer);
OldSeg -> Buffer = NULL;
OldSeg -> Length = 0;
}
FreeRem(OldSeg);
}
return(NextSeg);
}
/* ReturnPacket(Packet,res1,res2):
*
* Returns a packet to a handler.
*/
VOID
ReturnPacket(Packet,Result1,Result2)
struct DosPacket *Packet;
ULONG Result1,Result2;
{
struct MsgPort *ReplyPort = Packet -> dp_Port;
/* Fill in the results and fill in the
* sender MsgPort.
*/
Packet -> dp_Res1 = Result1;
Packet -> dp_Res2 = Result2;
Packet -> dp_Port = &HandlerProc -> pr_MsgPort;
/* Link Message & Packet together. */
Packet -> dp_Link -> mn_Node . ln_Name = (char *)Packet;
Packet -> dp_Link -> mn_Node . ln_Succ = NULL;
Packet -> dp_Link -> mn_Node . ln_Pred = NULL;
/* Send the packet... */
PutMsg(ReplyPort,Packet -> dp_Link);
}
/* TaskWait():
*
* Lets the process wait for a DOS-Packet.
*/
struct DosPacket *
TaskWait()
{
struct Message *PrintMessage;
/* Wait for the packet. */
WaitPort(&HandlerProc -> pr_MsgPort);
/* Pick it up. */
PrintMessage = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort);
/* Return real pointer. */
return((struct DosPacket *)PrintMessage -> mn_Node . ln_Name);
}