Source/MyPDEF_0_DraftMode.c

/*
** Copyright 1991-1996 Apple Computer. All rights reserved.
**
**  You may incorporate this sample code into your applications without
**  restriction, though the sample code has been provided "AS IS" and the
**  responsibility for its operation is 100% yours.  However, what you are
**  not permitted to do is to redistribute the source as "DSC Sample Code"
**  after having made changes. If you're going to re-distribute the source,
**  we require that you make it clear in the source that the code was
**  descended from Apple Sample Code, but that you've made changes.
*/
 
#include <stddef.h>
#include <types.h>
 
#include <Printing.h>
#include <Memory.h>
#include <Files.h>
#include <Resources.h>
#include <TextUtils.h>
#include <StandardFile.h>
#include <Events.h>
 
#include "driverTypes.h"
#include "StringUtils.h"
#include "FileUtils.h"
#include "SettingsUtils.h"
 
pascal TPPrPort DraftPrOpenDoc(THPrint hPrint, TPPrPort pPrPort, Ptr pIOBuf);
pascal void DraftPrCloseDoc(TPPrPort pPrPort);
pascal void DraftPrOpenPage(TPPrPort pPrPort, TPRect pPageFrame);
pascal void DraftPrClosePage(TPPrPort pPrPort);
 
#if defined(__MWERKS__)
asm void __Startup__ (void);
asm void __Startup__ (void)
{
    JMP DraftPrOpenDoc
    JMP DraftPrCloseDoc
    JMP DraftPrOpenPage
    JMP DraftPrClosePage
}
#endif
 
/*******************************************************************************
    Constants for the Command-period checker.
*******************************************************************************/
#define kModifiersMask      0xFF00 & ~cmdKey    /*  We need all modifiers
                                                    except the command key
                                                    for KeyTrans. */
#define kOtherCharCodeMask  0x00FF0000          /*  Get the key out of the
                                                    ASCII1 byte. */
 
static Boolean IsColorGrafPort(GrafPtr thePort)
{
    return(thePort->portBits.rowBytes < 0);
}
 
static void GetEventChars(EventRecord *theEvent, long *lowChar, long *highChar)
{
    unsigned    long    state = 0;
    long                keyInfo;
    long                virtualKey = (theEvent->message & keyCodeMask) >> 8;
    long                keyCID  = GetScript(GetEnvirons(smKeyScript), smScriptKeys);
    Handle              hKCHR   = GetResource('KCHR', keyCID);
    unsigned    short   keyCode = (theEvent->modifiers & kModifiersMask) | virtualKey;
 
    if (hKCHR != nil) {
        HLock(hKCHR);
        keyInfo = KeyTranslate((void *)(*hKCHR), keyCode, &state);
        HUnlock(hKCHR);
        ReleaseResource( hKCHR );
    } else {
        keyInfo = theEvent->message;
    }
 
    *lowChar =  keyInfo & charCodeMask;
    *highChar = (keyInfo & kOtherCharCodeMask) >> 16;
}
 
static Boolean CmdPeriod(EventRecord *theEvent)
{
    Boolean  result;
 
    if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
        long    lowChar, highChar;
        GetEventChars(theEvent, &lowChar, &highChar);
 
        if ((theEvent->modifiers & cmdKey) != 0 ) {
            result = ((lowChar == period) || (highChar == period));
        } else {
            result = ((lowChar == escape) || (highChar == escape));
        }
    } else result = false;  // it wasn't my kind of event
 
    return result;
}
 
static void MyIdleProc(void)
{
    const short mask = (keyDownMask | autoKeyMask);
    EventRecord theEvent;
    
    if (EventAvail(mask,&theEvent)) {
        if (CmdPeriod(&theEvent)) {
            (void)GetNextEvent(mask,&theEvent); // eat the event
            setPrintErr(iPrAbort);
        }
    }
}
 
static void CallIdleProc(PrIdleUPP idleProc)
{
    if (idleProc)
        CallPrIdleProc(idleProc);
    else
        MyIdleProc();
}
 
pascal void DraftPrText(short byteCount, Ptr textBuf, Point numer, Point denom)
{
#pragma unused(numer)
#pragma unused(denom)
 
    GrafPtr pPrPort;
    MyPrintPtr myPrintRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrText;g");
#endif
 
    GetPort(&pPrPort);
 
    // don't need to worry about rgnSave or polySave for text
 
    myPrintRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    BlockMoveData(pPrPort, myPrintRecord->OtherPort, mostOfGrafPort);
    SetPort(myPrintRecord->OtherPort);
    // do scaling here
    DrawText(textBuf, 0, byteCount);
    CallIdleProc(myPrintRecord->idleProc);
    SetPort(pPrPort);
    // adjust the pen location for scaling
}
 
pascal void DraftPrLine(Point newPt)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrLine;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
        StdLine(newPt);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        LineTo(newPt.h, newPt.v);
        SetPort(pPrPort);
        pPrPort->pnLoc = newPt; // set the pen location correctly
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrRect(GrafVerb verb, RectPtr r)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrRect;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
        StdRect(verb,r);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FrameRect(r);
                break;
            case paint:
                PaintRect(r);
                break;
            case erase:
                EraseRect(r);
                break;
            case invert:
                InvertRect(r);
                break;
            case fill:
                FillRect(r, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown verb for rect");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrrRect(GrafVerb verb, Rect * r, short ovalWidth, short ovalHeight)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrrRect;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
        StdRRect(verb,r,ovalWidth,ovalHeight);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FrameRoundRect(r, ovalWidth, ovalHeight);
                break;
            case paint:
                PaintRoundRect(r, ovalWidth, ovalHeight);
                break;
            case erase:
                EraseRoundRect(r, ovalWidth, ovalHeight);
                break;
            case invert:
                InvertRoundRect(r, ovalWidth, ovalHeight);
                break;
            case fill:
                FillRoundRect(r, ovalWidth, ovalHeight, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown verb for RoundRect");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrOval(GrafVerb verb, Rect * r)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrOval;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
        StdOval(verb,r);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FrameOval(r);
                break;
            case paint:
                PaintOval(r);
                break;
            case erase:
                EraseOval(r);
                break;
            case invert:
                InvertOval(r);
                break;
            case fill:
                FillOval(r, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown verb for oval");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrArc(GrafVerb verb, Rect * r, short startAngle, short arcAngle)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrArc;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    if ((pPrPort->rgnSave) || (pPrPort->polySave)) {
        StdArc(verb,r,startAngle,arcAngle);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FrameArc(r, startAngle, arcAngle);
                break;
            case paint:
                PaintArc(r, startAngle, arcAngle);
                break;
            case erase:
                EraseArc(r, startAngle, arcAngle);
                break;
            case invert:
                InvertArc(r, startAngle, arcAngle);
                break;
            case fill:
                FillArc(r, startAngle, arcAngle, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown verb for arc");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrPoly(GrafVerb verb, PolyHandle Poly)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrPoly;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording
    // calling poly procs with poly recording on is bad, so we won't
    // even think about that possibility
    if (pPrPort->rgnSave) {
        StdPoly(verb,Poly);
    } else {
        BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FramePoly(Poly);
                break;
            case paint:
                PaintPoly(Poly);
                break;
            case erase:
                ErasePoly(Poly);
                break;
            case invert:
                InvertPoly(Poly);
                break;
            case fill:
                FillPoly(Poly, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown verb for poly");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrRgn(GrafVerb verb, RgnHandle Rgn)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrRgn;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    // if rgnSave field of grafPort is non-nil, don't change port,
    // since that screws up region recording, same goes for polySave
    // calling poly procs with poly recording on would be
    // bad enough that I'm just going to ignore it.
    if (pPrPort->polySave) {
        StdRgn(verb,Rgn);
    } else {
        BlockMoveData(pPrPort,printRecord->OtherPort, mostOfGrafPort);
        SetPort(printRecord->OtherPort);
        // do scaling here
        switch (verb) { 
            case frame:
                FrameRgn(Rgn);
                break;
            case paint:
                PaintRgn(Rgn);
                break;
            case erase:
                EraseRgn(Rgn);
                break;
            case invert:
                InvertRgn(Rgn);
                break;
            case fill:
                FillRgn(Rgn, &printRecord->OtherPort->fillPat);
                break;
            default:
                DebugStr("\pUnknown region verb");
                break;
        }
        SetPort(pPrPort);
    }
    CallIdleProc(printRecord->idleProc);
}
 
pascal void DraftPrBits(BitMapPtr srcBits, Rect * srcRect, Rect * dstRect, short mode, RgnHandle maskRgn)
{
    GrafPtr pPrPort;
    Rect aRect;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrBits;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
    SetPort(printRecord->OtherPort);
    aRect = *dstRect;
    // do scaling here
    CopyBits(srcBits, &printRecord->OtherPort->portBits, srcRect, &aRect, mode, maskRgn);
    CallIdleProc(printRecord->idleProc);
    SetPort(pPrPort);
}
 
pascal void DraftPrComment(short kind, short dataSize, Handle dataHandle)
{
    GrafPtr pPrPort;
    MyPrintPtr printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrComment;g");
#endif
 
    GetPort(&pPrPort);
 
    printRecord = (MyPrintPtr)(((TPPrPort)pPrPort)->lGParam4);
 
    BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
    SetPort(printRecord->OtherPort);
    PicComment(kind, dataSize, dataHandle);
    CallIdleProc(printRecord->idleProc);
    SetPort(pPrPort);
}
 
pascal short DraftPrTxMeas(short byteCount, Ptr textAddr,
    Point *numer, Point *denom, FontInfo *info)
{
    short   retval;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrTxMeas;g");
#endif
 
    // If the port is scaled, you'll need to modify the values
    // passed to and returned by StdTxMeas() to take the
    // scaling into account
    retval = StdTxMeas(byteCount,textAddr,numer,denom,info);
    return retval;
}
 
#ifdef COMPRESSED_DATA
pascal void DraftPrPix(PixMapPtr src, const Rect *srcRect, MatrixRecordPtr matrix,
    short mode, RgnHandle mask, PixMapPtr matte, Rect *matteRect, short flags)
{
#pragma unused(src)
#pragma unused(srcRect)
#pragma unused(matrix)
#pragma unused(mode)
#pragma unused(mask)
#pragma unused(matte)
#pragma unused(matteRect)
#pragma unused(flags)
    // If we want to support sending compressed data, this is the
    // place to hook in the support. See Develop 24, pp 72-83 for
    // details. Also see IM:QuickTime pg 3-137 and IM:Imaging for
    // more details. As an added benefit, CopyDeepMask comes through
    // this proc, which is why the setIsPrintingFlag and
    // clearIsPrintingFlag macros are commented out in the header
    // file and point you to here for more explanation.
    DebugStr("\pTsk. COMPRESSED_DATA flag set, but no code written.");
}
#endif
 
void SetPrgProcs(TPPrPort myPPrPort)
{
    // Using UPPs, since this hopes to be native some day
    myPPrPort->gProcs.textProc = NewQDTextProc(DraftPrText);
    myPPrPort->gProcs.lineProc = NewQDLineProc(DraftPrLine);
    myPPrPort->gProcs.rectProc = NewQDRectProc(DraftPrRect);
    myPPrPort->gProcs.rRectProc = NewQDRRectProc(DraftPrrRect);
    myPPrPort->gProcs.ovalProc = NewQDOvalProc(DraftPrOval);
    myPPrPort->gProcs.arcProc = NewQDArcProc(DraftPrArc);
    myPPrPort->gProcs.polyProc = NewQDPolyProc(DraftPrPoly);
    myPPrPort->gProcs.rgnProc = NewQDRgnProc(DraftPrRgn);
    myPPrPort->gProcs.bitsProc = NewQDBitsProc(DraftPrBits);
    myPPrPort->gProcs.commentProc = NewQDCommentProc(DraftPrComment);
    myPPrPort->gProcs.txMeasProc = NewQDTxMeasProc(DraftPrTxMeas);
 
    // note: no bottleneck replacement for getPicProc or putPicProc
    
    // Note: also no pixProc bottleneck, since it ain't there unless
    // it's a CGrafPort, which this ain't.
}
 
pascal void ChangeBottleNeck(Boolean withColor, TPPrPort myPPrPort, MyPrintPtr thePrintPtr)
{
    if (withColor) {
        OpenCPort((CGrafPtr)myPPrPort);
        SetStdCProcs(&thePrintPtr->cProcs);
        
        // even with a Color PICT saving, we set the gProcs field of the Printing port 
        // just in case some weird application wants to use them directly 
        // to my knowledge, no application do such an absurd thing as that but Murphy Lives ! 
        SetPrgProcs(myPPrPort);
        
        thePrintPtr->cProcs.textProc = NewQDTextProc(DraftPrText);
        thePrintPtr->cProcs.lineProc = NewQDLineProc(DraftPrLine);
        thePrintPtr->cProcs.rectProc = NewQDRectProc(DraftPrRect);
        thePrintPtr->cProcs.rRectProc = NewQDRRectProc(DraftPrrRect);
        thePrintPtr->cProcs.ovalProc = NewQDOvalProc(DraftPrOval);
        thePrintPtr->cProcs.arcProc = NewQDArcProc(DraftPrArc);
        thePrintPtr->cProcs.polyProc = NewQDPolyProc(DraftPrPoly);
        thePrintPtr->cProcs.rgnProc = NewQDRgnProc(DraftPrRgn);
        thePrintPtr->cProcs.bitsProc = NewQDBitsProc(DraftPrBits);
        thePrintPtr->cProcs.commentProc = NewQDCommentProc(DraftPrComment);
        thePrintPtr->cProcs.txMeasProc = NewQDTxMeasProc(DraftPrTxMeas);
#ifdef COMPRESSED_DATA
        // If we want to handle compressed data, we put in our stdPix replacement
        ///// Hmm. There doesn't seem to be a declaration for a NewQDPixProc in QuickDraw.h
        ///// Bummer. Radar ID#1341027. -DaveP 4/15/96
        ((CGrafPort)(myPPrPort->gPort)).grafProcs->newProc1 = DraftPrPix;
#endif
        ((CGrafPtr)myPPrPort)->grafProcs = &(thePrintPtr->cProcs);
    } else {
        OpenPort((GrafPtr)myPPrPort);
        SetStdProcs(&myPPrPort->gProcs);
        SetPrgProcs(myPPrPort);
        myPPrPort->gPort.grafProcs = &myPPrPort->gProcs;
    }
}
 
pascal TPPrPort DraftPrOpenDoc(THPrint hPrint, TPPrPort pPrPort, Ptr pIOBuf)
{
#pragma unused(pIOBuf)
 
    SysEnvRec   theWorld;
    OSErr       bugOutError;
    TPPrPort    myPPrPort;
    THPrint     *myHPrint;
    MyPrintPtr  printRecord;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrOpenDoc;g");
#endif
 
    myHPrint = &hPrint;
    if (pPrPort == NULL) {  // does the caller give us a Printing Port or do we allocate it ? 
        myPPrPort = (TPPrPort)NewPtrClear(sizeof(TPrPort));
        if (myPPrPort == NULL) {
            bugOutError = iMemFullErr;
            goto BUGOUT;
        }
        myPPrPort->fOurPtr = true;
    } else {
        myPPrPort = pPrPort;
        myPPrPort->fOurPtr = false;
    }
    myPPrPort->lGParam1 = 0xDEADBEEF;   // a flag value showing badness
    myPPrPort->lGParam2 = 0xDEADBEEF;   // a flag value showing badness
    myPPrPort->lGParam3 = 0xDEADBEEF;   // a flag value showing badness
    myPPrPort->lGParam4 = (long) NewPtrClear(sizeof(MyPrintRec));   // we need this space to work
    if (myPPrPort->lGParam4 == 0) {
        bugOutError = iMemFullErr;
        goto BUGOUT;
    }
    
    SysEnvirons(1, &theWorld);
    
    // the real job is here, changing the QuickDraw Bottleneck to install our printing routines 
    ChangeBottleNeck(((theWorld.hasColorQD) && ((**hPrint).printX[8] == 0)),
         myPPrPort, (MyPrintPtr)myPPrPort->lGParam4);
    
    // to prevent any real drawing, set the bounds to EmptyRect
    if (IsColorGrafPort(&(myPPrPort->gPort))) {
        CGrafPtr    thePort = (CGrafPtr)(&(myPPrPort->gPort));
        Rect        *theRect = &((**(thePort->portPixMap)).bounds);
        SetRect(theRect, 0, 0, 0, 0);
    } else {
        SetRect(&(myPPrPort->gPort.portBits.bounds), 0, 0, 0, 0);
    }
    myPPrPort->gPort.portRect = (**hPrint).prInfo.rPage;
    
    printRecord = (MyPrintPtr)(myPPrPort->lGParam4);
    
    if ((**hPrint).printX[6]) {
        // just print specified range
        printRecord->firstPage = (**hPrint).prJob.iFstPage;
        printRecord->lastPage = (**hPrint).prJob.iLstPage;
    } else {
        // print all pages
        printRecord->firstPage = iPrPgFst;
        printRecord->lastPage = iPrPgMax;
    }
 
    printRecord->idleProc = (**hPrint).prJob.pIdleProc;
 
    printRecord->OtherPort = (GrafPtr)(NewPtrClear(sizeof(GrafPort)));
    if (printRecord->OtherPort == NULL) {
        bugOutError = iMemFullErr;
        goto BUGOUT;
    }
    BlockMoveData(myPPrPort, printRecord->OtherPort, mostOfGrafPort);
    
    bugOutError = SelectOutputFile(&(printRecord->fileSpec));
    if (bugOutError != noErr) {
        DebugStr("\pFailed to select");
        goto BUGOUT;
    }
 
    bugOutError = OpenOutputFile(&(printRecord->fileSpec),
                                &(printRecord->fileRef),
                                GetSavedRadioOption());
    if (bugOutError != noErr) {
        DebugStr("\pFailed to open");
        goto BUGOUT;
    }
 
// normal return
    return myPPrPort;
 
 
// error conditions make us come here
BUGOUT:
    if (myPPrPort != NULL) {
        if (myPPrPort->lGParam4 != 0) {
            if (!((*(*myHPrint))->printX[7] == 0)) {
                DisposePtr((Ptr)(printRecord->OtherPort));
            }
            DisposePtr((Ptr)printRecord);
            if (IsColorGrafPort(&(myPPrPort->gPort)))
                CloseCPort((CGrafPtr)(myPPrPort));
            else 
                ClosePort((GrafPtr)(myPPrPort));
        }
        if (myPPrPort->fOurPtr) 
            DisposePtr((Ptr)(myPPrPort));
    }
    setPrintErr(bugOutError);
    return 0L;
}
 
static void DisposeQDBottleNeckProcs(QDProcs theOldProcs)
{
    DisposeRoutineDescriptor(theOldProcs.textProc);
    DisposeRoutineDescriptor(theOldProcs.lineProc);
    DisposeRoutineDescriptor(theOldProcs.rectProc);
    DisposeRoutineDescriptor(theOldProcs.rRectProc);
    DisposeRoutineDescriptor(theOldProcs.ovalProc);
    DisposeRoutineDescriptor(theOldProcs.arcProc);
    DisposeRoutineDescriptor(theOldProcs.polyProc);
    DisposeRoutineDescriptor(theOldProcs.rgnProc);
    DisposeRoutineDescriptor(theOldProcs.bitsProc);
    DisposeRoutineDescriptor(theOldProcs.commentProc);
    DisposeRoutineDescriptor(theOldProcs.txMeasProc);
}
 
static void DisposeCQDBottleNeckProcs(CQDProcs theColorProcs)
{
    DisposeRoutineDescriptor(theColorProcs.textProc);
    DisposeRoutineDescriptor(theColorProcs.lineProc);
    DisposeRoutineDescriptor(theColorProcs.rectProc);
    DisposeRoutineDescriptor(theColorProcs.rRectProc);
    DisposeRoutineDescriptor(theColorProcs.ovalProc);
    DisposeRoutineDescriptor(theColorProcs.arcProc);
    DisposeRoutineDescriptor(theColorProcs.polyProc);
    DisposeRoutineDescriptor(theColorProcs.rgnProc);
    DisposeRoutineDescriptor(theColorProcs.bitsProc);
    DisposeRoutineDescriptor(theColorProcs.commentProc);
    DisposeRoutineDescriptor(theColorProcs.txMeasProc);
    ///// The following gets commented in when the NewxxxxxProc macro is used
#ifdef COMPRESSED_DATA
    // If we want to handle compressed data, we put in our stdPix replacement
    ///// Hmm. There doesn't seem to be a declaration for a NewQDPixProc in QuickDraw.h
    ///// Bummer. Radar ID#1341027. -DaveP 4/15/96
/////   DisposeRoutineDescriptor(grafProcs->newProc1);
#endif
}
 
pascal void DraftPrCloseDoc(TPPrPort pPrPort)
{
#ifdef TRACKING
    DebugStr("\pin DraftPrCloseDoc;g");
#endif
 
    if (pPrPort != NULL) {
        if (pPrPort->lGParam4 != 0) {
            MyPrintPtr  printRecord = (MyPrintPtr)(pPrPort->lGParam4);
 
            (void) CloseOutputFile(printRecord->fileRef, GetSavedRadioOption());
 
            // Clean up the routineDescriptors in the procs
            // This is needed for PPC native drivers, which this
            // isn't yet, but I put it in now so I didn't space it.
            // -DaveP 4/15/96
            DisposeQDBottleNeckProcs(pPrPort->gProcs);
            DisposeCQDBottleNeckProcs(printRecord->cProcs);
            DisposePtr((Ptr)printRecord->OtherPort);
            DisposePtr((Ptr)printRecord);
        } else {
            DebugStr("\pThis doesn't seem to be my Print Record that I've been asked to close!");
        }
 
        if (IsColorGrafPort((GrafPtr)pPrPort))
            CloseCPort((CGrafPtr)pPrPort);
        else 
            ClosePort((GrafPtr)pPrPort);
 
        // only nuke the grafport if we made it
        if (pPrPort->fOurPtr) DisposePtr((Ptr)pPrPort);
    } else {
        DebugStr("\pTsk. Naughty application calls PrCloseDoc with a bad port");
    }
}
 
pascal void DraftPrOpenPage(TPPrPort pPrPort, TPRect pPageFrame)
{
#pragma unused(pPageFrame)
    // in case of PICT saving, we create a new PICT file for each page 
    // the name of the PICT file is the name chosen by the user + the
    // number of the page and we store that file in the folder with the
    // same name that we created in DraftPrOpenDoc 
 
    MyPrintPtr printRecord = (MyPrintPtr)pPrPort->lGParam4;
 
#ifdef TRACKING
    DebugStr("\pin DraftPrOpenPage;g");
#endif
 
    printRecord->CurPage++;
 
    setIsPrintingFlag();
 
    // we reinitialize this every page, even though I'm not sure I need to
    BlockMoveData(pPrPort, printRecord->OtherPort, mostOfGrafPort);
    printRecord->OtherPort->picSave = NULL;
    printRecord->OtherPort->rgnSave = NULL;
    printRecord->OtherPort->polySave = NULL;
    printRecord->OtherPort->grafProcs = NULL;
    SetPort(printRecord->OtherPort);
    // do scaling here
    printRecord->thePict = OpenPicture(&printRecord->OtherPort->portRect);
    if (printRecord->thePict == NULL) {
        setPrintErr(iMemFullErr);
        return;
    }
    ClipRect(&(printRecord->OtherPort->portRect));
    SetPort((GrafPtr)pPrPort);
}
 
static CTabHandle GetPmTable(CGrafPtr thePort)
{
    PixMapHandle thePixMap = thePort->portPixMap;
    return((**thePixMap).pmTable);
}
 
static Boolean IsInRange(short num, short min, short max)
{
    return ((num >= min) && (num <= max));
}
 
pascal void DraftPrClosePage(TPPrPort pPrPort)
{
    long        theCount;
    MyPrintPtr  printRecord = (MyPrintPtr)(pPrPort->lGParam4);
 
#ifdef TRACKING
    DebugStr("\pin DraftPrClosePage;g");
#endif
 
    SetPort(printRecord->OtherPort);
    ClosePicture();
 
    clearIsPrintingFlag();
 
    SetPort((GrafPtr)pPrPort);
    if (IsInRange(printRecord->CurPage,printRecord->firstPage,printRecord->lastPage)) {
        // the following disposes of the handle correctly, too
        OSErr   writeError = WritePictData(printRecord->fileRef,
                            (Handle) printRecord->thePict,
                            printRecord->CurPage,
                            GetSavedRadioOption());
        if (writeError) {
            setPrintErr(writeError);
            return;
        }
        
        // we also save the current color table as a 'clut' resource
        // in the same file since a lot of Color Paint or Draw software
        // use that kind of information to get the colors right
        writeError = WriteCLUTData(printRecord->fileRef);
        if (writeError) {
            setPrintErr(writeError);
            return;
        }
    } else {
        DisposeHandle((Handle)(printRecord->thePict));
    }
}