shebanow@ernie.BERKELEY.EDU (Mike Shebanow) (11/25/85)
References: (Beware the line eater) This posting contains the source for a full fledged printing loop program. The program provides hooks to do just about any kind of printing on the Macintosh. Although all of the code for doing more sophisticated page printing is present, the application just prints out a simple page of graphics/text. The program requires my library of glue routines, "IMLib.REL", to compile. In addition, you cannot use "Standard Library.REL" as the startup code, since it has name conflicts with the File Manager routines in IMLib. Instead, you have to create a new library using the .REL files distributed with your Toolkit disk. This is the link file for that library: /Library MacCLib.REL /Create QStartLib CommonLib FloatLib SaneLib MathLib FloatConv /End These are the only Consulair REL files needed to create Macish applications. Of course, you cannot use printf or any of the other UNIX/Mac C Toolkit routines. IMLib.REL is being posted in .hqx format seperately. Source for IMLib is coming, in small chunks. Hope everyone finds this useful... Andrew Shebanow shebanow@ernie ======================PrEx1.Job (MDSMake Version)=========================== PrExMain.c : PrExample.h PrEx1.c : PrExample.h PrEx1.link : PrEx1Res.RSRC ===============================PrEx1.Link=================================== /Start QUICKSTART /Bundle /NoAnimate /Type 'APPL' 'PRPR' MacCLib PrExMain PrEx1 IMLib /Include PrEx1Res.RSRC /End ==============================Print.h=================================== /****************************************************************/ /* */ /* print.h */ /* Mac C Printing defs. */ /* */ /* Copyright (C) 1985 Consulair Corporation. */ /* All Rights Reserved */ /* */ /* ***Jan 14, 1985 9:50 AM*** */ /* Sept 24, 1985: Added constants, changed to match Print */ /* Manager Document dated 3/27/85 */ /****************************************************************/ // Requires QuickDraw.h #ifndef PrintLoaded #ifndef QuickdrawLoaded #include "QuickDraw.h" #endif #define PrintLoaded /* constants */ #define bDraftLoop 0 #define bSpoolLoop 1 #define bDevCItoh 1 #define bDevLaser 3 #define iPFMaxPgs 128 /* result codes */ #define noErr 0 #define iPrSavPFil -1 #define controlErr -17 #define iIObortErr -27 #define iMemFullErr -108 #define iPrAbort 128 typedef struct TStr80 { char count; char contents[80]; } TStr80; #define TPStr80 TStr80 * #define TPRect Rect * typedef struct TPrPort { GrafPort gPort; QDProcs gProcs; // more internal info } TPrPort; #define TPPrPort TPrPort * typedef struct TPrInfo { short iDev; short iVRes; short iHRes; Rect rPage; } TPrInfo; #define TFeed char typedef struct TPrStl { short wDev; short iPageV; short iPageH; char bPort; /* 0 for B, 1 for A */ TFeed feed; } TPrStl; typedef struct TPrJob { short iFstPage; short iLstPage; short iCopies; char bJDocLoop; char fFromUsr; ProcPtr pIdleProc; TPStr80 pFileName; short iFileVol; char bFileVers; char bJobX; } TPrJob; #define TScan char typedef struct TPrXinfo { short iRowBytes; short iBandV; short iBandH; short iDevBytes; short iBands; char bPatScale; char bULThick; char bULOffset; char bULShadow; TScan scan; char bXinfoX; } TPrXinfo; typedef struct TPrint { short iPrVersion; TPrInfo prInfo; Rect rPaper; TPrStl prStl; TPrInfo prInfoPT; TPrXinfo prXInfo; TPrJob prJob; short printX[19]; } TPrint; #define TPPrint TPrint * #define THPrint TPPrint * #define iPrintSize 120 typedef struct TPrStatus { short iToPages; short iCurPage; short iTotCopies; short iCurCopy; short iTotBands; short iCurBand; char fPgDirty; char fImaging; THPrint hPrint; TPPrPort pPrPort; PicHandle hPic; } TPrStatus; #endif ==============================Corrections.h=================================== /*************************************************************************/ /* Corrections to Consulair Mac C Header files */ /* corrections & omissions */ /* */ /* created Oct 15, 1985 DJB (Dave Burnard) */ /*************************************************************************/ /* always include this file after Consulair's header files, but before any custom header files, like IMLib.h */ /* Events.h */ #ifdef EventLoaded /* add masks for message field of events */ #define charCodeMask 0x000000FFL #define keyCodeMask 0x0000FF00L /* add constants for special chars */ #define commandMark '\021' #define checkMark '\022' #define diamondMark '\023' #define appleMark '\024' #endif /* Font.h */ #ifdef FontLoaded /* add constants for new fonts */ #define cairo 11 #define losAngeles 12 #define times 20 #define helvetica 21 #define courier 22 #define symbol 23 #define taliesin 24 #define kanji 25 /* add Style for normal text...or use NIL */ #define normalStyle 0 #endif /* MacDefs.h */ #ifdef MacdefsLoaded /* add OSType definition (4 char literal) */ typedef long OSType; /* add OSErr type definition and the null error */ typedef short OSErr; #define noErr 0 #endif /* Memory.h */ #ifdef MemoryLoaded /* spelling error...was MaxSize */ #define maxSize 0x800000 #endif /* OsIO.h */ #ifdef OSioLoaded /* spelling error...was rFNumErr */ #define rfNumErr -51 /* add Finder attributes flags */ #define cfInited 0x0100 #define cfHasChanged 0x0200 #define cfIsBusy 0x0400 #define cfNoCopy 0x0800 #define cfSystemFile 0x1000 #define cfHasBundle 0x2000 #define cfInvisible 0x4000 #define cfLocked 0x8000 /* add Finder fdFlag values */ #define fTrash -3 #define fDeskTop -2 #define fDisk 0 /* add File System attribute flags */ #define fsLocked 0x01 #define fsNoCopy 0x40 #define fsBusy 0x80 /* add read/write permissions */ #define fsCurPerm 0 #define fsRdPerm 1 #define fsWrPerm 2 #define fsRdWrPerm 3 /* add ioPosMode settings */ #define fsAtMark 0 /* at current position of mark - ignore ioPosOffset */ #define fsFromStart 1 /* offset relative to beginning of file */ #define fsFromLEOF 2 /* offset relative to logical end-of-file */ #define fsFromMark 3 /* offset relative to current mark */ /* add an equivalent to ioParam... */ typedef struct __IO IOParam; #endif /* Osmisc.h */ #ifdef OSmiscLoaded /* don't use these constants - use those above (OSio.h)... */ #undef fHasBundle 32 #undef fInvisible 64 /* Pointer to a Queue Header */ typedef QHdr *QHdrPtr; #endif /* Packages.h */ #ifdef PackagesLoaded /* redefine SFReply to use fName as in IM */ #undef SFReply typedef struct { char good; char copy; OSType ftype; short vRefNum; short version; char fName; char Name[63]; } SFReply; /* constant for IUDateString() */ #define abbrevDate 512 #endif /* pbDefs.h */ #ifdef pbDefsLoaded /* spelling error...was PBGetVInfo() */ #define PBGetVolInfo(pbBlock, asynchFlag) (short)pbCall(pbBlock, asynchFlag, 0xA007) #endif /* QuickDraw.h */ #ifdef QuickdrawLoaded /* add constants for cursors in system file */ #define iBeamCursor 1 #define crossCursor 2 #define plusCursor 3 #define watchCursor 4 #endif /* TextEdit.h */ #ifdef TextEditLoaded /* add constants for justification */ #define teJustLeft 0 #define teJustCenter 1 #define teJustRight -1 /* change two fields of the TERec data structure: */ #define teLength telength #define fontAscent firstBL #endif ==============================PrExample.h=================================== /* * PrExample.h Andrew G. Shebanow 10/27/85 * * local defintions for the print example program. */ /* error message numbers */ #define PRMGRERR 1 /* dialog id numbers */ #define NOTEERRDLOG 128 #define SAVEDLOG 256 #define PRINTDLOG 257 /* string# id numbers */ #define ERRMSGSTRS 128 /* miscellaneous definitions */ #define VOID void #define BYTE char #define WORD short #define LONG int #define UBYTE unsigned char #define UWORD unsigned short #define ULONG unsigned int #define REG register #define LOCAL static #define GLOBAL /* */ #define EXTERN extern /* pascal boolean definitions */ #define TRUE 1 #define FALSE 0 #define NULL 0 /**************************** end of Pr.h ***************************/ ==============================PrExMain.c=================================== /* * PrExMain.c Andrew G. Shebanow 10/27/85 * * Main portion of printing program. More or less useable for * any printing application, it assumes that these three routines * have been provided: * * CalcDocPrint() Prepares the current document for printing, * and calculates number of pages in document. * PrintPage(page) Does the quickdraw calls for each page, * which the print manager uses to image the * page. Note that random access to the pages * of the document is assumed. * DoPrSegSwap() Swaps out any unneeded code segments and/or * other resources to free up memory for the * print manager. * PrDocCleanup() Allow cleanup of document related data * structures. */ #include "QuickDraw.h" #include "Font.h" #include "Events.h" #include "Window.h" #include "Dialog.h" #include "Memory.h" #include "Print.h" /* fix things up */ #include "Corrections.h" /* program specific definitions */ #include "PrExample.h" /* external print manager routines */ EXTERN WORD CPrError(); EXTERN BYTE CPrJobDialog(); EXTERN BYTE CPrStlDialog(); EXTERN TPrPort *CPrOpenDoc(); /* print manager related variables */ GLOBAL THPrint prHandle; /* the print record handle */ GLOBAL TPrPort *prPort; /* the printing GrafPort */ GLOBAL TPrStatus status; /* used in PrPicFile call */ GLOBAL GrafPort *oldPort; /* saved grafport */ /* dialogs for printing: Lets Be User Friendly Out There */ GLOBAL DialogPtr saveDialog; /* Saving to disk dialog */ GLOBAL DialogPtr printDialog; /* now printing dialog */ /* variables used by printing loop */ GLOBAL UBYTE curPrinter; /* current printing device */ GLOBAL WORD curLoop; /* print loop type */ GLOBAL WORD frontFirst; /* print front to back? */ GLOBAL WORD numCopies; /* number of times to print doc */ /* * pageCount is the number of pages in the document. It MUST be set * by the CalcDocPrint() routine! */ GLOBAL WORD pageCount; /* * DoPrError: * * handle abnormal termination of printing. If the termination * was not user generated (via Command-.), put up an alert box. */ GLOBAL VOID DoPrError() { WORD theError; LOCAL Str255 errStr; LOCAL Str255 numStr; theError = CPrError(); CPrSetError(iPrAbort); CPrClose(); SetPort(oldPort); if ((theError == noErr) || (theError == iPrAbort)) return; GetIndString(ERRMSGSTRS,PRMGRERR,&errStr); NumToString((LONG) theError,&numStr); ParamText(&errStr,&numStr,NULL,NULL); NoteAlert(NOTEERRDLOG,NULL); ParamText(NULL,NULL,NULL,NULL); } /* * PageSetup: * * handle a page setup command. This function, while simple, actually * causes a large amount of disk and memory manager activitity. There must * be sufficient memory to load the Print Driver into memory. */ GLOBAL VOID PageSetup(hPrint) THPrint hPrint; { CPrOpen(); if (CPrError() != noErr) { /* handle the error */ return; } CPrStlDialog(hPrint); CPrClose(); } /* * PrintPages: * * print the pages of the document, in the desired order. */ GLOBAL VOID PrintPages(hPrint) THPrint hPrint; { WORD start, end, incr; WORD curPage; if (frontFirst == TRUE) { start = 1; end = pageCount + 1; incr = 1; } else { start = pageCount; end = 0; incr = -1; } for (curPage = start; (CPrError() == noErr) && (curPage != end); curPage += incr) { CPrOpenPage(prPort,NULL); /* if the page is within range, print it */ if ((CPrError() == noErr) && (curPage >= (*hPrint)->prJob.iFstPage) && (curPage <= (*hPrint)->prJob.iLstPage)) PrintPage(curPage); CPrClosePage(prPort); } } /* * PrintDoc: * * This is the actual loop for printing a single document. Is * pretty general, except that it does NOT support printing multiple * documents from the finder. */ GLOBAL VOID PrintDoc(hPrint) THPrint hPrint; { WORD curCopy; /* save current grafport for later */ GetPort(&oldPort); /* get the print and save dialogs */ saveDialog = GetNewDialog(SAVEDLOG,NULL,-1L); printDialog = GetNewDialog(PRINTDLOG,NULL,-1L); /* make sure they aren't visible */ HideWindow(saveDialog); HideWindow(printDialog); CPrOpen(); if (CPrError() != noErr) { /* we couldn't open the print driver */ DoPrError(); DisposeDialog(saveDialog); DisposeDialog(printDialog); return; } /* put up the print dialog box for the user, & check for cancel */ if (CPrJobDialog(hPrint) == FALSE) { /* cancel button selected */ CPrClose(); DisposeDialog(saveDialog); DisposeDialog(printDialog); /* restore saved grafport */ SetPort(oldPort); return; } /* set up the printer device id for reference */ curPrinter = (UBYTE) (((*hPrint)->prStl.wDev >> 8) & 0x0ff); /* set up the print loop type for future reference */ curLoop = (*hPrint)->prJob.bJDocLoop; /* if we are a laserwriter, print back to front */ if (curPrinter == bDevLaser) frontFirst = FALSE; else frontFirst = TRUE; /* call the document specific print init routine */ CalcDocPrint(); /* * determine number of copies to print. Print once if in spool * mode, or if in draft mode on a laserwriter, since the multiple * copies are handled automatically. Otherwise, we have to print * the document repeatedly. */ if ((curLoop == bDraftLoop) && (curPrinter != bDevLaser)) { numCopies = (*hPrint)->prJob.iCopies; /* should we set prJob.iCopies to 1 here? */ /* since it works, we won't mess with it */ } else numCopies = 1; for (curCopy = 1; (curCopy <= numCopies) && (CPrError() == noErr); curCopy++) { /* get a printing GrafPort */ prPort = CPrOpenDoc(hPrint,NULL,NULL); /* put up the first dialog box */ if (curLoop == bSpoolLoop) { ShowWindow(saveDialog); DrawDialog(saveDialog); } else { ShowWindow(printDialog); DrawDialog(printDialog); } /* print the pages */ PrintPages(hPrint); /* close the document */ CPrCloseDoc(prPort); /* if spooling, display print dialog & print spool file */ if (curLoop == bSpoolLoop) { HideWindow(saveDialog); ShowWindow(printDialog); DrawDialog(printDialog); if (CPrError() == noErr) CPrPicFile(hPrint,NULL,NULL,NULL,&status); if (CPrError() != noErr) DoPrError(); } HideWindow(printDialog); } if (CPrError() != noErr) DoPrError(); /* close the print driver */ CPrClose(); /* delete the dialogs */ DisposeDialog(printDialog); DisposeDialog(saveDialog); /* restore the old grafport */ SetPort(oldPort); } /* * main: * * This is a do nothing main program. It just calls the PageSetup * and PrintDoc routines to handle the print job. */ GLOBAL VOID main() { InitMenus(); TEInit(); InitDialogs(NULL); prHandle = (THPrint) NewHandle(iPrintSize); FlushEvents(0x0ffffL); InitCursor(); PageSetup(prHandle); PrintDoc(prHandle); ExitToShell(); } /************************* end of PrExMain.c *************************/ ==============================PrEx1.c=================================== /* * PrEx1.c Andrew G. Shebanow 10/27/85 * * The simplest type of printing routine. Always prints the same * page, regardless of desired pagecount. Does not attempt to scale * document in any way. */ #include "QuickDraw.h" #include "Memory.h" #include "Font.h" #include "Print.h" /* fix things up */ #include "Corrections.h" /* program specific definitions */ #include "PrExample.h" GLOBAL StringHandle theStr; /* a string to print */ EXTERN THPrint prHandle; /* the print record handle */ EXTERN TPrPort *prPort; /* the printing GrafPort */ EXTERN UBYTE curPrinter; /* current printing device */ EXTERN WORD pageCount; /* # of pages in "document" */ /* * CalcDocPrint: * * Prepare the current document for printing. The document size * in pages must be set up here. */ GLOBAL VOID CalcDocPrint() { pageCount = 1; /* only one page */ } /* * DoPrSegSwap: * * this function would normally be used to unload as many code * segments & other resources from memory as possible. It suffices to mark * the resources as purgeable, since the memory manager will delete them * from memory when the Print Manager tries to allocate a large chunk of * memory for its own use. */ GLOBAL VOID DoPrSegSwap() { } /* * PrDocCleanup: * * clean up after printing a document. Deallocate data structures, etc. */ GLOBAL VOID PrDocCleanup() { } /* * PrintPage: * * prints a specific page from the current document. */ GLOBAL VOID PrintPage(pageNum) WORD pageNum; { Rect tRect; PolyHandle tPoly; theStr = (StringHandle) GetString(128); HLock(theStr); /* set up the text font based on printer type */ if (curPrinter != bDevLaser) TextFont(geneva); else TextFont(helvetica); /* draw a rectangle */ SetRect(&tRect,240,90,350,300); PenSize(1,1); FillRect(&tRect,&(QD->ltGray)); FrameRect(&tRect); /* draw a circle */ SetRect(&tRect,120,120,280,280); PenSize(3,3); FrameOval(&tRect); /* draw some text */ TextFace(0); TextSize(12); MoveTo(100,100); DrawString(*theStr); /* draw some more text, only bigger */ TextFace(boldStyle); TextSize(24); MoveTo(50,50); DrawString(*theStr); /* define a polygon */ tPoly = OpenPoly(); MoveTo(200,250); LineTo(320,270); LineTo(320,150); LineTo(290,210); LineTo(200,250); ClosePoly(); /* draw the polygon */ PenSize(2,2); FillPoly(tPoly,&(QD->white)); FramePoly(tPoly); KillPoly(tPoly); } /*************************** end of PrEx1.c ****************************/ ========================PrEx1Res.RSRC (in hqx format)====================== (This file must be converted with BinHex 4.0) :$9"b4AJa8Q9c,P*68N-!N"%'h3ek!*!%!3#3!`@Y!!!%V3!!!6!"rrl`!*!$#J( rr[)!N!--!Irqp!#3!`i"rrlf!*!$%J(rr[J!N!-8!IrqqJ#3!aJ$rrUN9%9B9!2 rqVC"8&"-5!!h!*!%&JPD"&"dFJ#l&JPD@J4)B@jNE'8!ZaB,U&S%8(*[Be"dFJ# TU+Ql&K6l$3N%BfpeER3!Z`d*"(-!fccrhE[p"&0dFM)e03#l&J46G()b068!@J4 6G(*TEQG3G()!ZaB%8h4bD@jR8(4b!&S%8h4bD@jR5'&ZC'aP!,X@&!43EfPZG!$ l#J4f!,X+"'J!Zrd%8'pTER3!ZaB8"&*PBh3!q`43EfPZG!!%G!#3!``!C!!S!,i "iJ#!998!N!-F8&*38J#3!`&*3diM!*!&J%C548B!N!@!!*!$9!#3"`S!#J!Y!B' )3dj[Gb"`FQPZG'PZCbiJ9'mJBf&ZBf9X,#"SEfaN)'4[GfiJG'KP)"%JDf9j)'& ZC#"dHA"P)'%JF'9bD@pN)#JZ+5kJ!*!$-!#3"`S!#J!Y!B'))%j[Gb"cBACTEQF JF(*TER4PC#"MEh"j)(4[)'4TFfXZ!*!$*J!"!*!&2!$"!&!"!J3#6dX!N!8+!%J !+!'NL!9H-#"H-HB!N!05!!-!N!9B!+!!E!$F"!*25`#3"9J!-!"X!'`%"N0KEQ0 PE!#3"4J!b!!X!333!6M)!*!&'!!3!#J!U)J18f9d)&4KBL"AD@4dD$S!!!'8!!N !N!@S!5!!Z`&V"!*25`#3"3J!%!!B!2Z)'&"b)'*j)%&ZC(*PGb"(,L"6D'9LB@j [G`#3"6J!%!"*!2b)(PCPFR0TEfiJ-5i`-b!J6f0dEf*PFL!a0b`J-6Ni03#3"5! !%!!`!2Q)(N%J8fpeFQ0P)%CTE'8J8(*TER4TEQFJ9A4TE'PdH3#3"9!!%!"K!A# )-9GbDA4dC@iJGA0TEQFJ3fpZFh9XB@Pb*h-J6@&M3b"%CACPE'p`E@9ZG#"6HA0 dC@eP!*!&D!!3!(N"2iJQ9'KTFb"cEfCdGf&bC5"TFb"TEL"dD'8J8(9LE'PM)%4 [E@&TELi!N!@B!#J!U!$SL!P)HA"PFP0[CR4Q!*!&U!!S!,J!k)JE-M%b0#",DA4 dFQ9NCf8J8h4bC@9d,#!M-6Fd0`#3"EJ!+!$)!1L)%N*PFQYPE'9j,#"$35!j0$F `0!#3"B!!%!#4!6q)(e4SDA-JF(*[Ch*KE5"LFQpeCfKd)(4[)(P[G5"LH6S`!*! $&J"N!$)!PJ(#!!%!N!J"N!0i!*!$&J"N!$)!PJ(#!!%!N!J"!!&i!*!$)!"m!&i "!!&k!!%"!*!)JJY8B@*c)%4TB@a[C`#3!b%!4J!m!48"`J!"!3#3#(i-3@*[GA3 J4'PKE'pR!*!$"d&38%`!N!8"!!!"!*!$!S!!!!4!!!!))!!!%"!!!#3)!!"-"!! !NN)!!5hK!!*&X)!%UfK!#5E8)",YTK!LQd`)36Er")$Y`)*!fi"")E8`)K$Vb"3 )ARq2"#B`"`)G!!F"#)!(!)"J"`"!(qF!)!)I!"!%"`!)#!!!""!!!!)J!!!"3!# 3!i!!!!%!N!-$J!!!"m!!!!rJ!!!Im!!!2rJ!!(rm!!$rrJ!"rrm!!rrrJ!Irrm! 2rrrJ(rrrm$rrrrKrrrrmrj!$rRrrN!-rrrrq(rrrr!rrN!-(rj!$!rq3!`(rN!- !rj!$!(rrr`!rrKm!(r`(!!ri!!!(m!!!!q!!!!(!!*!$J!#3""F@8(*&H'&YF'a P)&CPFR0TEfiJ-5i`-!#3!a-58h9bFQ9ZC'9b)%4[FQpdD(NK!*!$&`!"&&"bD@j d)%eKEQ&RCA)J4A*bEh)k!!!"!*!$"Dd!!!5Y!!!"-!!")K3!A!#3!a`"*J!)38a 59!#3!dT#6N4-!*!$9N4*9%`!"!"L4%a24`!$!*j'8N9'!*!$cNP$6L-!N!2D8&* 38J#3!qC69&)J!*!$mP088L-!N!2q!)$rr`#3"3%Kf!#!rrm!N!-3!!%Kh!"qrrm !!!%m!!%S$!##rrm!N!2Q!!%S"!#!rrm!N!1m!!%Rp!%!rrm!N!1)!!%Ri!%"rrm !N!-`!!%Rd!"qrrm!!!-X!!%TS!##rrm!!!-)!!%TN!!"!2rr!!!#lJ!"+A`"!Ir r!!!#e!!"+@`!J2rr!!!$83!"+3!!J!#3"!0F!!%Sl!!!rrm!!!4J!!%Sh!#!rrm !!!4l!!%UV!#!rrm!!!55!!%UR!P0B@YP)%PMEfi$4`: