Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Notes > Scripting & Automation > Carbon >

The Enhanced Print Apple Event

CONTENTS

The printing system in the initial versions of Mac OS X supported a limited print Apple event but there was no way to specify any options or settings to the printing application. As of Mac OS X 10.3 (Panther), the printing system supports an enhanced print Apple event that provides scripters with control over settings such as number of copies, collation, page range, etc. This document describes the enhanced print event and the changes applications must make to support the new scriptable printing features. Printer Modules and CUPS filters will not need to change.

[Dec 09, 2003]






The Enhanced Print Apple event

As of Mac OS X 10.3, the print Apple event has been extended to include an optional print settings parameter that defines the settings for the print job or jobs, and an optional print dialog parameter that specifies whether the application should display the Print dialog. By default, the application should not show the Print dialog if the caller doesn't specify a print dialog parameter.

print: Print the specified object(s)

print reference -- Objects to print. Can be a list of files or an object specifier.

[with properties print settings] -- The print settings
[print dialog boolean] -- Should the application show the Print dialog?

The print settings parameter allows a scripter to specify the following information.

Class print settings:

Properties:

copies integer [r/o] -- The number of copies of a document to be printed
collating boolean [r/o] -- Should printed copies be collated?
starting page integer [r/o] -- The first page of the document to be printed
ending page integer [r/o] -- The last page of the document to be printed
pages across integer [r/o] -- Number of logical pages laid across a physical page
pages down integer [r/o] -- Number of logical pages laid out down a physical page
requested print time date [r/o] -- The time at which the desktop printer should print the document
error handling standard/summarized/detailed [r/o] -- How errors are handled
fax number text [r/o] -- The number to which to fax the document
target printer text [r/o] -- The name of the destination print queue


For example, the following script prints three copies of the second page of a document to the printer "Prints Charming" after showing the Print dialog.



set theDoc to alias "Macintosh HD:ReadMe"
set printConfig to {copies:3, starting page:2, ending page:2,
    target printer:"Prints Charming"}
print theDoc with properties printConfig with print dialog


These optional parameters to the print event provide much finer control than was previously possible.

Back to top


Application Changes Required

Applications will need to be revised to support the optional print settings parameter for the print event. While every effort has been made to minimize the number of changes you will need to make to your application, the actual amount of work is dependent upon the current state of the application's printing code. This section describes the changes needed to support the extended print event. In addition, there is sample code accompanying this Technote which shows how to add scriptable printing support to an application.

Download Sample code

There are 4 steps required to update your application to support scriptable printing and the optional parameters.

  1. Update your application's 'aete' resource to indicate support for the new, optional print parameter and for the print settings class. An example 'aete' is included with the sample code for this Technote in the file "AESupport.r"
  2. Revise the application's print event handler to respond to the optional print settings parameter. The optional print settings parameter for the print event uses the key keyAEPropData. An application's print handler retrieves the keyAEPropData parameter and coerces it into a PMPrintSettings object in one step using AEGetParamPtr. If the optional parameter was successfully coerced into a PMPrintSettings object, use those print settings for the current print job. The PMPageFormat information for the document to be printed comes from the page format stored with the document or from a newly defaulted page format.
  3. Check to see if the optional print settings parameter also contains a target printer object by calling AEGetParamPtr with a key of keyAEPropData and a type of kPMPrinterAEType. If the resulting PMPrinter is non-NULL, then it should be used as the target printer for the print session by calling PMSessionSetCurrentPrinter.
  4. Finally, check for the presence of the optional print dialog parameter that specifies whether or not your application should display the Print dialog to the user. If this parameter is missing, you should not display the Print dialog. In the case of multiple documents being printed with the same print event, the Print dialog should only be shown once and those settings should be used for each document.

The following code shows how to retrieve, coerce, and apply the PMPrintSettings object found in the optional print settings parameter.



OSErr AEPrintDocument ( const AppleEvent *inputEvent,
                             AppleEvent *outputEvent,
                             SInt32 handlerRefCon )
{
#pragma unused (outputEvent,handlerRefCon)

    assert( inputEvent != NULL );

    OSStatus        status = noErr;
    PMPrintSettings printSettings = kPMNoPrintSettings;
    PMPrinter       printer = NULL;
    Boolean         showPrintDialog = false;
    PMPrintSession  session = NULL;
    PMPageFormat    pageFormat = kPMNoPageFormat;
    Boolean         printIt = true;

    #define kDontCare NULL
    
    //  In this next section, grab the parameters from the incoming
    //  Apple event. Note that since everything is optional, we're
    //  ignoring status - if the data isn't present then move on.

    //  Grab the print settings
    //  They may not have requested any specific print settings.
    //  Later on, we'll use the default print settings in this case.
    status = AEGetParamPtr( inputEvent,
                            keyAEPropData, kPMPrintSettingsAEType,
                            kDontCare, &printSettings,
                            sizeof( void* ), kDontCare );
    
    //  Grab the requested printer, if any
    //  They may not have requested a target printer.
    status = AEGetParamPtr( inputEvent,
                            keyAEPropData, kPMPrinterAEType,
                            kDontCare, &printer, sizeof( void* ),
                            kDontCare );

    //  See if we need to show the print dialog - default is no.
    status = AEGetParamPtr( inputEvent,
                            kPMShowPrintDialogAEType, typeBoolean,
                            kDontCare, &showPrintDialog,
                            sizeof( Boolean ), kDontCare );

    //  Now that we've retrieved the PMPrintSettings, PMPrinter,
    //  and showPrintDialog items from the event, print the files.

    // Create the session we'll use to print.
    status = PMCreateSession( &session );
    
    if ( status == noErr )
    {
        // Set the output to the target printer.
        if ( printer != NULL )
        {
            status = PMSessionSetCurrentPMPrinter( session, printer);
        }
    
        //  If the scripter didn't request any specific print
        //  settings, load up the default set
        if ( printSettings == kPMNoPrintSettings )
        {
            status = PMCreatePrintSettings( &printSettings );
            if ( status == noErr )
            {
               status = PMSessionDefaultPrintSettings(session,
                                                      printSettings);
            }
        }
    
        //  Create a default PMPageFormat
        //  In a real application, unflatten the page format stored
        //  with the document and use that
        status = PMCreatePageFormat(&pageFormat);
        
        if ( (status == noErr) && (pageFormat != kPMNoPageFormat) )
        {
            PMSessionDefaultPageFormat(session, pageFormat);
        }
    
        //  Show the print dialog?
        //  Only show the print dialog once for a given pdoc event.
        //  Use the resulting settings for all files in the event.
        if ( showPrintDialog )
        {
            status = PMSessionPrintDialog( session, printSettings,
                                           pageFormat, &printIt );
        }

        if ( printIt )
        {
            AEDescList      docList;
            long            index, itemsInList;
            
            // Get the file list.
            status = AEGetParamDesc( inputEvent, keyDirectObject,
                                     typeAEList, &docList );
    
            if ( status == noErr )
            {
                //  How many files are we supposed to print?
                status = AECountItems( &docList, &itemsInList );
    
                //  Walk the list of files.
                for ( index = 1; index <= itemsInList; index++ )
                {
                    AEKeyword       keywd;
                    DescType        returnedType;
                    Size            actualSize;
                    HFSUniStr255    fileName;
                    CFStringRef     fileNameRef=NULL;
                    WindowRef       windowRef = NULL;
                    char            buffer[ kFileBufferSize ];
                    long            count = sizeof( buffer );
                    FSRef           fileRef;
    
                    // Get the file ref.
                    status = AEGetNthPtr( &docList, index, typeFSRef,
                                          &keywd, &returnedType,
                                          (Ptr)(&fileRef), 
                                          sizeof( fileRef ), 
                                          &actualSize );
    
                    // Get the file name to use in the window's title.
                    if ( status == noErr )
                    {
                        status = FSGetCatalogInfo( &fileRef, 0, NULL,
                                                   &fileName,
                                                   NULL, NULL );
                    }
                    
                    if ( status == noErr )
                    {
                        fileNameRef = CFStringCreateWithCharacters(
                                        kCFAllocatorDefault,
                                        &fileName.unicode[0], 
                                        fileName.length );
                    }
    
                    // Open the file for reading.
                    if ( status == noErr )
                    {
                        status = ReadFileData( fileRef, &count,
                                               &buffer[0] );
                        if ( status == noErr )
                        {
                            //  Show a sample document window
                            windowRef = ShowDocumentWindow(
                                          fileNameRef,buffer,count);
    
                            status = PrintDocument( session,
                                       printSettings, pageFormat,
                                       fileNameRef, buffer );
    
                            //  We're done with the filename string
                            CFRelease( fileNameRef );
    
                            //  We're done with the window
                            DisposeWindow( windowRef );
                        }
                    }
                }
            }
        }
        
        // Clean up.
        PMRelease( pageFormat );
        PMRelease( session );
    }

    // We're done so get rid of everything.
    PMRelease( printSettings );
    PMRelease( printer );

    return status;
}   //  AEPrintDocument


Back to top


Summary

The introduction of the enhanced print Apple event with Mac OS X 10.3 allows users to script the printing process with much finer control than before. Supporting this scriptability requires that applications change their print loops to make use of the optional parameters. The rewards for AppleScript users will be significant, since these changes will provide much more flexibility in printing.

Back to top


References

Mac OS X Printing developer page

Mac OS X Printing Technical Documentation

Mac OS X Printing Q&As

Mac OS X Printing Technotes

AppleScript developer page

AppleScript on Mac OS X

AppleScript documentation

Back to top


Downloadables

Binhexed

Sample Code.

Download


Back to top