| 
     
|  | 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 settingsparameter that defines the settings for the print job or jobs, 
and an optionalprint dialogparameter 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 aprint dialogparameter. 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 settingsparameter 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 printedcollating  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 settingsparameter 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.
 
    Update your application's 'aete'resource to indicate support for the 
    new, optional print parameter and for theprint settingsclass. An example'aete'is included with the sample code for this Technote in the file "AESupport.r"Revise the application's print event handler to respond to the optional print settingsparameter.  The optionalprint settingsparameter for the print event uses the keykeyAEPropData. An application's print handler
	retrieves thekeyAEPropDataparameter and coerces it into aPMPrintSettingsobject in one step usingAEGetParamPtr. If the optional parameter was successfully coerced into aPMPrintSettingsobject, 
    use those print settings for the current print job. ThePMPageFormatinformation 
    for the document to be printed comes from the page format stored with the document or from a newly
    defaulted page format.Check to see if the optional print settingsparameter also contains atarget printerobject by callingAEGetParamPtrwith a key ofkeyAEPropDataand a type ofkPMPrinterAEType.  If the resultingPMPrinteris non-NULL, then it should be used as the target printer for the print session by callingPMSessionSetCurrentPrinter.Finally, check for the presence of the optional print dialogparameter 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 PMPrintSettingsobject 
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 
 ReferencesMac 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
 Back to top |