home *** CD-ROM | disk | FTP | other *** search
- /* $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);
- }
-