ScriptablePrinting.c

/*
**  File:       ScriptablePrinting.c
**
**  Functions defined in Technote 11xx
**
** Copyright 1999 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 <Printing.h>
#include <AppleEvents.h>
#include "ScriptablePrinting.h"
#include "ExtendPrintRecord.h"
#include "CoercePrGeneral.h"
 
OSStatus getPrintRecordFromEvent(const AppleEvent *inAppleEvent,
                                THPrint     *hPrintP)
/*  Given a print event Apple Event descriptor inAppleEvent,
    look for the optional print setting parameter.
    If this parameter exists, then coerce it into a print
    record and place the handle to the print record into
    *hPrintP. If the optional parameter does not exist
    or it cannot be converted, then a non-zero error code
    is returned and *hPrintP is set to NULL
*/
{
    OSStatus    err = noErr;
    AEDesc      optionalDesc = {};
    AEDesc      printRecordDesc = {};
    
    AECoercionHandlerUPP handler = NULL;
    long refCon;
    Boolean typeIsDesc;
 
    PrOpen();
    err = PrError();
 
    if(err == noErr) {
        err = AEGetParamDesc(inAppleEvent, keyAEPropData, typeAERecord, &optionalDesc);
        if (err == noErr) {
            // if you want to call PrGeneral directly, comment out this call,
            // and set err to errAEHandlerNotFound. This will simulate the
            // case when Desktop Printing is not running, so the coercion
            // handler has not been loaded. See the Technote for more details.
            err = AEGetCoercionHandler(typeAERecord, kPrintRecordAEType, 
                                        &handler, &refCon, &typeIsDesc, true);
 
            if (err == noErr) {
                err = AECoerceDesc(&optionalDesc, kPrintRecordAEType, &printRecordDesc);
            } else if (err == errAEHandlerNotFound) {
                /*  If desktop printing is not enabled,
                    the handler won't be installed. This
                    is not fatal, since we can call the
                    driver's PrGeneral call directly.
                    It's better to use the coercion handler,
                    but if we can't find it, this is a
                    good fallback to use
                 */
                PrCoerceStruct  coerceData;
                
                coerceData.iOpCode = kPrCoerceOp;
                coerceData.iError = noErr;
                coerceData.lReserved = 0;
                coerceData.fromDesc = &optionalDesc;
                coerceData.toType = kPrintRecordAEType;
                coerceData.toDesc = &printRecordDesc;
 
                PrGeneral((Ptr)&coerceData);
 
                err = coerceData.iError;
            }
        }
    }
 
    if (err == noErr) {
        OSErr   tempErr;
 
        *hPrintP = (THPrint) printRecordDesc.dataHandle;
        err = HandToHand((Handle *)hPrintP);
        tempErr = AEDisposeDesc(&printRecordDesc);
        if (err == noErr) err = tempErr;
    } else {
        *hPrintP = NULL;
    }
    
    err = AEDisposeDesc(&optionalDesc);
    
    PrClose();
 
    return err;
}
 
OSStatus getPrintJobPrintRec(THPrint docPrintRec,
                            THPrint settingsPrintRec,
                            THPrint *jobPrintRecP)
/*  The caller passes in the print record stored with a
    document, docPrintRec, as well as the print record
    obtained from the print event, settingsPrintRec.
    This function creates a new print record that combines
    the formatting information from docPrintRec with
    the print time settings in settingsPrintRec and
    places the new print record into *jobPrintRecP.
    On entry, settingsPrintRec can be NULL in which
    case docPrintRec is duplicated and returned in
    *jobPrintRecP. In either case, if a new print
    record can not be created, this function sets
    *jobPrintRecP to NULL and returns a non-zero error
    code.
*/
{
    OSStatus    err = noErr;
    THPrint     jobPrintRec = docPrintRec;
    
    err = HandToHand((Handle *)&jobPrintRec);
    if ((err == noErr) && (settingsPrintRec != NULL)) {
        /*  Both print records must be extended when
            calling PrJobMerge in order to get a full
            merge. The scripted print settings print
            record is extended by the coercion so
            nothing need be done to it here.
        */
        err = extendPrValidate(docPrintRec);    // from TN 1161
        
        if (err == noErr) {
            PrJobMerge(settingsPrintRec, jobPrintRec);
            err = PrError();
        }
    } else {
        jobPrintRec = NULL;
    }
    
    if (err != noErr) {
        if (jobPrintRec != NULL) {
            DisposeHandle((Handle) jobPrintRec);
            jobPrintRec = NULL;
        }
    }
    
    *jobPrintRecP = jobPrintRec;
    
    return err;
}
 
OSStatus getPrintJobShowDialog(const AppleEvent *inAppleEvent,
                                Boolean *showDialog)
/*  Given a print Apple Event, look for the optional parameter
    saying whether or not the application should show the
    PrJobDialog. While an apple event with the "print settings"
    parameter COULD have most of the items that will be needed
    to print the job, it's possible that the user or scripter
    will    want to present the dialog to handle printer-specific
    settings. An application should not prevent the user from
    doing so, so this function is needed. The application should
    default to showing the dialog if the parameter is not
    specified.
*/
{
    OSStatus    err = noErr;
    AEDesc      showDesc = {};
    
    err = AEGetParamDesc(inAppleEvent, kPrintDialogAEType,
                        typeBoolean, &showDesc);
    if (err == noErr) {
        *showDialog = **(showDesc.dataHandle);
    }
    if (err == errAEDescNotFound) {
        /*  not having the descriptor is okay.
            It just means we default to showing.
        */
        *showDialog = true;
        err = noErr;
    }
    
    return err;
}