/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* PRINTPOP - A "popup" printer setup program */ /* */ /* by Robbie J Akins, Wellington, NEW ZEALAND */ /* */ /* Version 1.0 */ /* August 1987 */ /* */ /* Thanks for help and inspiration for this program must go to: */ /* */ /* Charles Tyson..................for "Purty" (Fred Fish #66) */ /* The Software Distillery........for "PopCLI" */ /* Rob Peck.......................for the examples in RKM */ /* Willy Langeveld................for "MXGads" (Fred Fish #52) */ /* and especially to Harriet Maybeck Tolly (of TollySoft) and her */ /* article in Amazing Computing about Mutual Exclude gadgets..... */ /* ...that really helped me to stop tearing my hair out! */ /* */ /* To compile: LC:lc1 -iINCLUDE: printpop.c */ /* LC:lc2 -v printpop.c */ /* */ /* To link: Alink with link_printpop */ /* */ /* where "link_printpop" contains: FROM WBC.o,+* */ /* printpop.o */ /* TO PrintPop */ /* LIBRARY lib:lc.lib+lib:amiga.lib */ /* */ /* SPECIAL NOTE: The way this program has been written (the easy way!) */ /* means that either "printpop.o" (generated by the */ /* compiler) must be 'run through' ATOM, or else the */ /* final executable "printpop" must be run through */ /* FIXHUNK (available on Fred Fish #36) for the program */ /* to run correctly (that is, not crash!) on an Amiga */ /* equipped with expansion memory. Sorry. Maybe the */ /* next version of Lattice C will make this a bit easier! */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include /* Visual components of program window */ /*********************** CONSTANTS **********************/ #define F1_KEY 0x50 #define SIGNON "\x1b[33mPRINTPOP\x1b[0m by Robbie J Akins, Wellington NEW ZEALAND\n" #define DRAFTBUTTON 1 #define NLQBUTTON 2 #define SETTABBUTTON 3 #define CLEARTABBUTTON 4 #define RESETBUTTON 5 #define TENBUTTON 6 #define TWELVEBUTTON 7 #define FIFTEENBUTTON 8 #define PSBUTTON 9 #define ENLARGEDBUTTON 10 #define LMDOWNBUTTON 11 #define LMUPBUTTON 12 #define RMDOWNBUTTON 13 #define RMUPBUTTON 14 /********************** GLOBAL VARIABLES **********************/ struct task *PopUpTask; struct Interrupt handlerStuff; ULONG popupsig; struct MemEntry me[20]; struct IntuitionBase *IntuitionBase = NULL; struct GfxBase *GfxBase = NULL; long DOSBase = 0; struct Window *PopWin; BOOL success; int openError; union printerIO { struct IOStdReq ios; struct IODRPReq iodrp; struct IOPrtCmdReq iopc; }; union printerIO *request; struct MsgPort *printerPort; UBYTE LeftMargBuf[4]; UBYTE RightMargBuf[4]; UBYTE SetMarginsBuffer[12]; /* Buffer for set margins command */ int LeftMargData = 15; /* Initial value of left margin */ int RightMargData = 95; /* Initial value of right margin */ SHORT LeftOffset; SHORT RightOffset; /********************** EXTERNAL ROUTINES **********************/ extern struct MsgPort *CreatePort(); extern struct IOStdReq *CreateStdIO(); extern void HandlerInterface(); extern struct task *FindTask(); /************************************************************************ * The handler subroutine - called through the handler stub *************************************************************************/ struct InputEvent *myhandler(ev, mydata) struct InputEvent *ev; /* and a pointer to a list of events */ struct MemEntry *mydata[]; /* system will pass me a pointer to my * own data space. */ { register struct InputEvent *ep, *laste; /* scan the list of events to see if "pop-up" key pressed */ for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent) { if ((ep->ie_Class == IECLASS_RAWKEY) && (ep->ie_Code == F1_KEY) && (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND)) { /* Able to handle this event so take it off the chain */ if (laste == NULL) ev = ep->ie_NextEvent; else laste->ie_NextEvent = ep->ie_NextEvent; /* Signal to "pop-up" task */ Signal(PopUpTask, popupsig); } else laste = ep; } /* pass on the pointer to the event */ return(ev); } /************************************************************************ * The main program to do the printpop stuff *************************************************************************/ void _main() { int looping; ULONG sig,mclass; LONG GadPos; struct Gadget *maddress; struct MsgPort *inputDevPort; struct IOStdReq *inputRequestBlock; struct IntuiMessage *mesg; struct RastPort *ThisRastPort; PopUpTask = FindTask(0); sig = Output(); Write(sig, SIGNON, sizeof(SIGNON)); SetTaskPri( PopUpTask, 20); if ((inputDevPort = CreatePort(0,0)) == NULL) /* for input device */ goto abort0; if ((inputRequestBlock = CreateStdIO(inputDevPort)) == 0) goto abort; if ((sig = AllocSignal(-1)) == -1) goto abort; popupsig = 1 << sig; if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 33)) == NULL) goto abort; if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 33)) == NULL) goto abort; handlerStuff.is_Data = (APTR)&me[0]; /* address of handler data area */ handlerStuff.is_Code = HandlerInterface;/* addr of handler entry point */ handlerStuff.is_Node.ln_Pri = 51; /* set the priority 1 step higher than Intuition so that handler enters chain ahead of Intuition*/ if (OpenDevice("input.device",0,inputRequestBlock,0)) goto abort; inputRequestBlock->io_Command = IND_ADDHANDLER; inputRequestBlock->io_Data = (APTR)&handlerStuff; DoIO(inputRequestBlock); for(;;) /* FOREVER */ { sig = Wait( popupsig ); if (sig & popupsig) { /*=========================================================================*/ WBenchToFront(); if((PopWin=(struct Window *) make_window()) == NULL) /* Open window */ goto CleanUp; /* Draw Borders and Intuitexts in window */ ThisRastPort = PopWin -> RPort; DrawBorder(ThisRastPort,&QualityBorder,0,0); /* Draw boxes around gadgets */ PrintIText(ThisRastPort,&QualityText,0,0); /* Write titles above gadgets */ /* Convert values of margins into strings for IntuiTexts */ LeftOffset = IntToText(LeftMargData,LeftMargBuf); RightOffset = IntToText(RightMargData,RightMargBuf); LeftMargText.IText = &LeftMargBuf[0]; RightMargText.IText = &RightMargBuf[0]; PrintIText(ThisRastPort,&LeftMargText,LeftOffset,0); /* Print left marg value */ PrintIText(ThisRastPort,&RightMargText,RightOffset,0);/* Print rgt marg value */ /* Set up IDCMP read loop and handle events */ looping = TRUE; while (looping) { WaitPort(PopWin->UserPort); while((mesg=(struct IntuiMessage *) GetMsg(PopWin->UserPort))!=NULL) { mclass = mesg->Class; maddress = (struct Gadget *)mesg->IAddress; ReplyMsg(mesg); if(mclass == CLOSEWINDOW) looping = FALSE; if(mclass == GADGETDOWN) { switch (maddress->GadgetID) { case DRAFTBUTTON: MXGads(PopWin,&DraftGadget,&NLQGadget, &NULLGadget1,&NULLGadget2); break; case NLQBUTTON: MXGads(PopWin,&NLQGadget,&DraftGadget, &NULLGadget1,&NULLGadget2); break; case SETTABBUTTON: MXGads(PopWin,&SetTabGadget,&ClearTabGadget, &NULLGadget1,&NULLGadget2); break; case CLEARTABBUTTON: MXGads(PopWin,&ClearTabGadget,&SetTabGadget, &NULLGadget1,&NULLGadget2); break; case RESETBUTTON: /* "Ghost" all gadgets on Reset */ GadPos = RemoveGList(PopWin,&RightUpGadget,14L); ClearTabGadget.Flags ^= GADGDISABLED; SetTabGadget.Flags ^= GADGDISABLED; NLQGadget.Flags ^= GADGDISABLED; DraftGadget.Flags ^= GADGDISABLED; RightUpGadget.Flags ^= GADGDISABLED; RightDownGadget.Flags ^= GADGDISABLED; LeftUpGadget.Flags ^= GADGDISABLED; LeftDownGadget.Flags ^= GADGDISABLED; EnlargedGadget.Flags ^= GADGDISABLED; if((EnlargedGadget.Flags & SELECTED) != SELECTED) PSGadget.Flags ^= GADGDISABLED; FifteenGadget.Flags ^= GADGDISABLED; TwelveGadget.Flags ^= GADGDISABLED; TenGadget.Flags ^= GADGDISABLED; AddGList(PopWin,&RightUpGadget,GadPos,14L,(LONG)NULL); RefreshGList(&RightUpGadget,PopWin,(LONG)NULL,14L); break; case TENBUTTON: MXGads(PopWin,&TenGadget,&TwelveGadget, &FifteenGadget,&PSGadget); break; case TWELVEBUTTON: MXGads(PopWin,&TwelveGadget,&TenGadget, &FifteenGadget,&PSGadget); break; case FIFTEENBUTTON: MXGads(PopWin,&FifteenGadget,&TwelveGadget, &TenGadget,&PSGadget); break; case PSBUTTON: MXGads(PopWin,&PSGadget,&TwelveGadget, &FifteenGadget,&TenGadget); break; case ENLARGEDBUTTON: /* "Ghost" PS pitch gadget on Enlarged */ /* If PS selected, force to 10 pitch selection*/ if ((PSGadget.Flags & SELECTED) == SELECTED) MXGads(PopWin,&TenGadget,&TwelveGadget, &FifteenGadget,&PSGadget); GadPos = RemoveGList(PopWin,&PSGadget,1L); PSGadget.Flags ^= GADGDISABLED; AddGList(PopWin,&PSGadget,GadPos,1L,(LONG)NULL); RefreshGList(&PSGadget,PopWin,(LONG)NULL,1L); break; case LMDOWNBUTTON: /* Decrement value of left margin */ if(LeftMargData > 1) { LeftMargData--; LeftOffset = IntToText(LeftMargData,LeftMargBuf); LeftMargText.IText = &LeftMargBuf[0]; PrintIText(ThisRastPort,&BlankText,238,68); PrintIText(ThisRastPort,&LeftMargText,LeftOffset,0); } break; case LMUPBUTTON: /* Increment value of left margin */ if(LeftMargData < 998) { LeftMargData++; LeftOffset = IntToText(LeftMargData,LeftMargBuf); LeftMargText.IText = &LeftMargBuf[0]; PrintIText(ThisRastPort,&BlankText,238,68); PrintIText(ThisRastPort,&LeftMargText,LeftOffset,0); } break; case RMDOWNBUTTON: /* Decrement value of right margin */ if(RightMargData > 1) { RightMargData--; RightOffset = IntToText(RightMargData,RightMargBuf); RightMargText.IText = &RightMargBuf[0]; PrintIText(ThisRastPort,&BlankText,322,68); PrintIText(ThisRastPort,&RightMargText,RightOffset,0); } break; case RMUPBUTTON: /* Increment value of right margin */ if(RightMargData < 998) { RightMargData++; RightOffset = IntToText(RightMargData,RightMargBuf); RightMargText.IText = &RightMargBuf[0]; PrintIText(ThisRastPort,&BlankText,322,68); PrintIText(ThisRastPort,&RightMargText,RightOffset,0); } break; } } } } CloseWindow(PopWin); /* Close window on way out */ success = FALSE; printerPort = (struct MsgPort *)CreatePort("HelloPrinter",0); if(printerPort == NULL) goto ForgetIt; request = (union printerIO *)CreateExtIO(printerPort,sizeof(union printerIO)); if(request == NULL) goto ForgetIt; openError = OpenPrinter(request); if(openError) goto ForgetIt; success = TRUE; /* Now execute appropriate printer commands */ if((ResetGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b#1"); /* aRIN command */ else { if((NLQGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b[2\x22z"); /* aDEN2 command */ else PrintString(request,"\x1b[1\x22z"); /* aDEN1 command */ /* First "reset" the printer to normal (10) pich */ PrintString(request,"\x1b[0w"); /* aSHORP0 command */ if((FifteenGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b[4w"); /* aSHORP4 command */ if((TwelveGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b[2w"); /*aSHORP2 command */ if((PSGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b[2p"); /* aPROP2 command */ else PrintString(request,"\x1b[1p"); /* aPROP1 command */ if((EnlargedGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b[6w"); /* aSHORP6 command */ else PrintString(request,"\x1b[5w"); /* aSHORP5 command */ /* Set left & right margins using ESC [ n1 ; n2 s */ strcpy(SetMarginsBuffer,"\x1b["); strcat(SetMarginsBuffer,LeftMargBuf); strcat(SetMarginsBuffer,";"); strcat(SetMarginsBuffer,RightMargBuf); strcat(SetMarginsBuffer,"s"); PrintString(request,SetMarginsBuffer); if((SetTabGadget.Flags & SELECTED) == SELECTED) PrintString(request,"\x1b#5"); /* aTBSALL command */ else PrintString(request,"\x1b#4");/* aTBCALL command */ } PrintString(request,"\x0d"); /* Terminating C/R required by some printers */ goto CleanUp; /* Exit gracefully */ ForgetIt: Apologise("Sorry, but unable to send the", "control codes that you requested", "to the printer. Maybe in use?"); CleanUp: if(success) ClosePrinter(request); if(printerPort) DeletePort(printerPort); if(request) DeleteExtIO(request); /*=========================================================================*/ } } /* END OF FOREVER LOOP */ abort: if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); if (GfxBase != NULL) CloseLibrary(GfxBase); DeletePort(inputDevPort); abort0: XCEXIT(-1); } /************************************************************************ * Function to open window *************************************************************************/ make_window() { struct NewWindow NewWindow; NewWindow.LeftEdge=0; NewWindow.TopEdge=0; NewWindow.Width=402; NewWindow.Height=103; NewWindow.DetailPen=0; NewWindow.BlockPen=1; NewWindow.IDCMPFlags= CLOSEWINDOW | GADGETDOWN; NewWindow.Flags= ACTIVATE | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | NOCAREREFRESH | GIMMEZEROZERO; NewWindow.FirstGadget=&RightUpGadget; NewWindow.CheckMark=NULL; NewWindow.Title="PRINTPOP - Printer Setup Utility"; NewWindow.Screen=NULL; NewWindow.BitMap=NULL; NewWindow.MinWidth=0; NewWindow.MinHeight=0; NewWindow.MaxWidth=0; NewWindow.MaxHeight=0; NewWindow.Type=WBENCHSCREEN; return(OpenWindow(&NewWindow)); } /******************************************************************** * This routine fakes mutual-exclude of four gadgets ********************************************************************/ MXGads(win,gad1,gad2,gad3,gad4) struct Window *win; struct Gadget *gad1,*gad2,*gad3,*gad4; { LONG GadNumber1,GadNumber2,GadNumber3,GadNumber4; GadNumber1 = RemoveGList(win,gad1,1L); GadNumber2 = RemoveGList(win,gad2,1L); GadNumber3 = RemoveGList(win,gad3,1L); GadNumber4 = RemoveGList(win,gad4,1L); gad1->Flags |= SELECTED; /* FORCE TO BE SELECTED! */ if((gad2->Flags & SELECTED) == SELECTED) (gad2->Flags ^= SELECTED); if((gad3->Flags & SELECTED) == SELECTED) (gad3->Flags ^= SELECTED); if((gad4->Flags & SELECTED) == SELECTED) (gad4->Flags ^= SELECTED); AddGList(win,gad4,GadNumber4,1L,(LONG)NULL); RefreshGList(gad4,win,(LONG)NULL,1L); AddGList(win,gad3,GadNumber3,1L,(LONG)NULL); RefreshGList(gad3,win,(LONG)NULL,1L); AddGList(win,gad2,GadNumber2,1L,(LONG)NULL); RefreshGList(gad2,win,(LONG)NULL,1L); AddGList(win,gad1,GadNumber1,1L,(LONG)NULL); RefreshGList(gad1,win,(LONG)NULL,1L); } /************************************************************************ * Printersupport routines from 1.1 Rom Kernel manual *************************************************************************/ /* OPEN THE PRINTER */ int OpenPrinter(request) union printerIO *request; { return(OpenDevice("printer.device",0,request,0)); } /* CLOSE THE PRINTER */ int ClosePrinter(request) union printerIO *request; { CloseDevice(request); return(0); } /* SEND NULL TERMINATED STRING TO PRINTER */ int PrintString(request,string) union printerIO *request; char *string; { request->ios.io_Command = CMD_WRITE; request->ios.io_Data = (APTR)string; request->ios.io_Length = -1; return(DoIO(request)); } /************************************************************************ * Raise an autorequester with (up to) three lines of text *************************************************************************/ Apologise (line1, line2, line3) UBYTE *line1, *line2, *line3; { Sorry[0].IText = line1; Sorry[1].IText = line2; Sorry[2].IText = line3; AutoRequest (NULL, &Sorry, NULL, &Proceed, 0, 0, 300, 66); } /************************************************************************ * Convert margin value into text for IntuiText * (returns value to displace text string by for "good" appearance) *************************************************************************/ IntToText(n,string) int n; UBYTE *string; { int displace; /* Amount to displace display of text by */ string[0] = n/100 +'0'; if (string[0] == '0') { string[0] = (n%100)/10 + '0'; if (string[0] == '0') { string[0] = (n%100)%10 + '0'; string[1] = '\0'; displace = 8; } else { string[1] = (n%100)%10 + '0'; string[2] = '\0'; displace = 4; } } else { string[1] = (n%100)/10 + '0'; string[2] = (n%100)%10 + '0'; string[3] = '\0'; displace = 0; } return(displace); }