Back to index

lightning-sunbird  0.9+nobinonly
PDECore.c
Go to the documentation of this file.
00001 /*
00002 ********************************************************************************
00003 
00004     $Log: PDECore.c,v $
00005     Revision 1.2  2003/04/03 19:20:04  ccarlen%netscape.com
00006     Bug 188508 - Upgrade print dialog PDE. r=pinkerton/sr=sfraser
00007 
00008 
00009 
00010     (c) Copyright 2002 Apple Computer, Inc.  All rights reserved.
00011     
00012     IMPORTANT: This Apple software is supplied to you by Apple Computer,
00013     Inc. ("Apple") in consideration of your agreement to the following
00014     terms, and your use, installation, modification or redistribution of
00015     this Apple software constitutes acceptance of these terms.  If you do
00016     not agree with these terms, please do not use, install, modify or
00017     redistribute this Apple software.
00018     
00019     In consideration of your agreement to abide by the following terms, and
00020     subject to these terms, Apple grants you a personal, non-exclusive
00021     license, under Apple's copyrights in this original Apple software (the
00022     "Apple Software"), to use, reproduce, modify and redistribute the Apple
00023     Software, with or without modifications, in source and/or binary forms;
00024     provided that if you redistribute the Apple Software in its entirety and
00025     without modifications, you must retain this notice and the following
00026     text and disclaimers in all such redistributions of the Apple Software.
00027     Neither the name, trademarks, service marks or logos of Apple Computer,
00028     Inc. may be used to endorse or promote products derived from the Apple
00029     Software without specific prior written permission from Apple.  Except
00030     as expressly stated in this notice, no other rights or licenses, express
00031     or implied, are granted by Apple herein, including but not limited to
00032     any patent rights that may be infringed by your derivative works or by
00033     other works in which the Apple Software may be incorporated.
00034     
00035     The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
00036     NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
00037     IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
00038     A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
00039     OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
00040     
00041     IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
00042     OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00043     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00044     INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
00045     MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
00046     AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
00047     STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
00048     POSSIBILITY OF SUCH DAMAGE.
00049     
00050 ********************************************************************************
00051 */
00052 
00053 #include <Carbon/Carbon.h>
00054 #include <Print/PMPrintingDialogExtensions.h>
00055 
00056 #include "PDECustom.h"
00057 #include "PDEUtilities.h"
00058 
00059 
00060 enum SyncDirection {
00061     kSyncTicketFromPane = FALSE,
00062     kSyncPaneFromTicket = TRUE
00063 };
00064 
00065 
00066 /*
00067 --------------------------------------------------------------------------------
00068     Prototypes
00069 --------------------------------------------------------------------------------
00070 */
00071 
00072 // callbacks
00073 
00074 static HRESULT   MyQueryInterface   (void*, REFIID, LPVOID*);
00075 static ULONG     MyIUnknownRetain   (void*);
00076 static ULONG     MyIUnknownRelease  (void*);
00077 
00078 static OSStatus  MyPMRetain         (PMPlugInHeaderInterface*);
00079 static OSStatus  MyPMRelease        (PMPlugInHeaderInterface**);
00080 static OSStatus  MyPMGetAPIVersion  (PMPlugInHeaderInterface*, PMPlugInAPIVersion*);
00081 
00082 static OSStatus  MyPrologue   (PMPDEContext*, OSType*, CFStringRef*, CFStringRef*, UInt32*, UInt32*);
00083 static OSStatus  MyInitialize (PMPDEContext, PMPDEFlags*, PMPDERef, ControlRef, PMPrintSession);
00084 static OSStatus  MySync       (PMPDEContext, PMPrintSession, Boolean);
00085 static OSStatus  MyGetSummary (PMPDEContext, CFArrayRef*, CFArrayRef*);
00086 static OSStatus  MyOpen       (PMPDEContext);
00087 static OSStatus  MyClose      (PMPDEContext);
00088 static OSStatus  MyTerminate  (PMPDEContext, OSStatus);
00089 
00090 
00091 /*
00092 --------------------------------------------------------------------------------
00093     instance types for the two interfaces we support
00094 --------------------------------------------------------------------------------
00095 */
00096 
00097 typedef struct
00098 {
00099     const IUnknownVTbl *vtable;
00100     SInt32 refCount;
00101     CFUUIDRef factoryID;
00102 
00103 } MyIUnknownInstance;
00104 
00105 typedef struct
00106 {
00107     const PlugInIntfVTable *vtable;
00108     SInt32 refCount;
00109 
00110 } MyPDEInstance;
00111 
00112 
00113 #pragma mark -
00114 
00115 /*
00116 --------------------------------------------------------------------------------
00117 **  MyCFPlugInFactory
00118 **  
00119 **  Creates an instance of the IUnknown interface (see the COM
00120 **  specification for more information about IUnknown). The name of this
00121 **  factory function needs to be associated with the factory UUID in the
00122 **  CFPlugInFactories property list entry, so it can be loaded by the
00123 **  printing system for use in the dialog.
00124 **  
00125 --------------------------------------------------------------------------------
00126 */
00127 
00128 extern void* MyCFPlugInFactory (
00129     CFAllocatorRef allocator, 
00130     CFUUIDRef typeUUID
00131 )
00132 
00133 {
00134     // our IUnknown interface function table
00135     static const IUnknownVTbl sMyIUnknownVTable =
00136     {
00137         NULL, // required padding for COM
00138         MyQueryInterface,
00139         MyIUnknownRetain,
00140         MyIUnknownRelease
00141     };
00142     
00143     CFBundleRef         myBundle    = NULL;
00144     CFDictionaryRef     myTypes     = NULL;
00145     CFStringRef         requestType = NULL;
00146     CFArrayRef          factories   = NULL;
00147     CFStringRef         factory     = NULL;
00148     CFUUIDRef           factoryID   = NULL;
00149     MyIUnknownInstance  *instance   = NULL;
00150 
00151     myBundle = MyGetBundle();
00152 
00153     if (myBundle != NULL)
00154     {
00155         myTypes = CFBundleGetValueForInfoDictionaryKey (
00156             myBundle, CFSTR("CFPlugInTypes"));
00157     
00158         if (myTypes != NULL) 
00159         {
00160             // get a reference to the requested type 
00161             // verify that the requested type matches my type (it should!)
00162             requestType = CFUUIDCreateString (allocator, typeUUID);
00163             if (requestType != NULL)
00164             {
00165                 factories = CFDictionaryGetValue (myTypes, requestType);
00166                 CFRelease (requestType);
00167                 if (factories != NULL) 
00168                 {   // assume the factory we want is entry [0]
00169                     factory = CFArrayGetValueAtIndex (factories, 0);
00170                     if (factory != NULL) 
00171                     {
00172                        // get a reference to my factory ID
00173                         factoryID = CFUUIDCreateFromString (
00174                             allocator, factory);
00175                         if (factoryID != NULL)
00176                         {
00177                             // construct an instance of the IUnknown interface
00178                             instance = malloc (sizeof(MyIUnknownInstance));
00179                             if (instance != NULL)
00180                             {
00181                                 instance->vtable = &sMyIUnknownVTable;
00182                                 instance->refCount = 1;
00183                                 instance->factoryID = factoryID;
00184                                 CFPlugInAddInstanceForFactory (factoryID);
00185                             }
00186                             else {
00187                                 CFRelease (factoryID);
00188                             }
00189                         }
00190                     }
00191                 }
00192             }
00193         }
00194     }
00195 
00196     MyDebugMessage ("Factory", (SInt32) instance);
00197     return instance;
00198 }
00199 
00200 
00201 #pragma mark -
00202 
00203 /*
00204 --------------------------------------------------------------------------------
00205 **  MyQueryInterface
00206 **  
00207 **  Finds the requested interface and returns an instance to the caller.
00208 **  If the request is for the "base" IUnknown interface, we just bump
00209 **  the refcount.
00210 **  
00211 --------------------------------------------------------------------------------
00212 */
00213  
00214 static HRESULT MyQueryInterface (
00215     void *this, 
00216     REFIID iID, 
00217     LPVOID *ppv
00218 )
00219 
00220 {
00221 
00222     // PDE interface function table
00223 
00224     static const PlugInIntfVTable sMyPDEVTable = 
00225     { 
00226         {
00227             MyPMRetain,
00228             MyPMRelease, 
00229             MyPMGetAPIVersion 
00230         },
00231         MyPrologue,
00232         MyInitialize,
00233         MySync,
00234         MyGetSummary,
00235         MyOpen,
00236         MyClose,
00237         MyTerminate
00238     };
00239 
00240 
00241     CFUUIDRef requestID = NULL;
00242     CFUUIDRef actualID  = NULL;
00243     HRESULT   result = E_UNEXPECTED;
00244 
00245     
00246     // get a reference to the UUID for the requested interface
00247     requestID = CFUUIDCreateFromUUIDBytes (kCFAllocatorDefault, iID);
00248     if (requestID != NULL)
00249     {
00250         // get a reference to the UUID for all PDE interfaces
00251         actualID = CFUUIDCreateFromString (kCFAllocatorDefault, kDialogExtensionIntfIDStr);
00252         if (actualID != NULL)
00253         {
00254             if (CFEqual (requestID, actualID))
00255             {
00256                 // caller wants an instance of my PDE interface
00257         
00258                 MyPDEInstance *instance = malloc (sizeof(MyPDEInstance));
00259         
00260                 if (instance != NULL)
00261                 {
00262                     instance->vtable = &sMyPDEVTable;
00263                     instance->refCount = 1;
00264                     *ppv = instance;
00265                     result = S_OK;
00266                 }
00267             }
00268             else
00269             {
00270                 if (CFEqual (requestID, IUnknownUUID))
00271                 {
00272                     // caller wants an instance of my IUnknown interface
00273                     MyIUnknownRetain (this);
00274                     *ppv = this;
00275                     result = S_OK;
00276                 }
00277                 else
00278                 {
00279                     *ppv = NULL;
00280                     result = E_NOINTERFACE;
00281                 }
00282             }
00283             CFRelease (actualID);
00284         }
00285         CFRelease (requestID);
00286     }
00287 
00288     MyDebugMessage("MyQueryInterface", result);
00289     return result;
00290 }
00291 
00292 
00293 /*
00294 --------------------------------------------------------------------------------
00295 **  MyIUnknownRetain
00296 **  
00297 **  Increments the reference count for the calling interface on an
00298 **  object. It should be called for every new copy of a pointer to an
00299 **  interface on a given object.
00300 **  
00301 **  Returns an integer from 1 to n, the value of the new reference
00302 **  count. This information is meant to be used for diagnostic/testing
00303 **  purposes only, because, in certain situations, the value might be
00304 **  unstable.
00305 **  
00306 --------------------------------------------------------------------------------
00307 */
00308 
00309 static ULONG MyIUnknownRetain (void* this)
00310 {   
00311     MyIUnknownInstance* instance = (MyIUnknownInstance*) this;
00312     ULONG refCount = 1;
00313         
00314     if (instance != NULL) {
00315         refCount = ++instance->refCount;
00316     }
00317 
00318     MyDebugMessage("MyIUnknownRetain", refCount);
00319     return refCount;
00320 }
00321 
00322 
00323 /*
00324 --------------------------------------------------------------------------------
00325 **  MyIUnknownRelease
00326 **  
00327 **  Decrements the reference count for the calling interface on an
00328 **  object. If the reference count on the object reaches zero, the
00329 **  object is freed from memory.
00330 **  
00331 **  Returns the resulting value of the reference count, which is for 
00332 **  diagnostic/testing purposes only.
00333 **  
00334 --------------------------------------------------------------------------------
00335 */
00336 
00337 static ULONG MyIUnknownRelease (void* this)
00338 {
00339     MyIUnknownInstance* instance = (MyIUnknownInstance*) this;
00340     ULONG refCount = 0;
00341 
00342     if (instance != NULL)
00343     {
00344         refCount = --instance->refCount;
00345         if (refCount == 0)
00346         {
00347             CFPlugInRemoveInstanceForFactory (instance->factoryID);
00348             CFRelease (instance->factoryID);
00349             free (instance);
00350         }
00351     }
00352 
00353     MyDebugMessage("MyIUnknownRelease", refCount);
00354     return refCount;      
00355 }
00356 
00357 
00358 /*
00359 --------------------------------------------------------------------------------
00360     MyPMRetain
00361 --------------------------------------------------------------------------------
00362 */
00363 
00364 static OSStatus MyPMRetain (PMPlugInHeaderInterface* this)
00365 {
00366     MyPDEInstance* instance = (MyPDEInstance*) this;
00367     ULONG refCount = 1;
00368     OSStatus result = noErr;
00369     
00370     if (instance != NULL) {
00371         refCount = ++instance->refCount;
00372     }
00373 
00374     MyDebugMessage("MyPMRetain", refCount);
00375     return result;
00376 }
00377 
00378 
00379 /*
00380 --------------------------------------------------------------------------------
00381     MyPMRelease
00382 --------------------------------------------------------------------------------
00383 */
00384 
00385 static OSStatus MyPMRelease (
00386     PMPlugInHeaderInterface** this
00387 )
00388 
00389 {
00390     MyPDEInstance* instance = (MyPDEInstance*) *this;
00391     ULONG refCount = 0;
00392     OSStatus result = noErr;
00393 
00394     // clear caller's instance variable (don't ask)
00395     *this = NULL;
00396 
00397     if(instance != NULL)
00398     {
00399         // decrement instance reference count, and free if zero
00400         refCount = --instance->refCount;
00401     
00402         if (refCount == 0) 
00403         {
00404             free (instance);
00405             MyFreeTitle();
00406             MyFreeBundle();
00407         }
00408     }
00409 
00410     MyDebugMessage("MyPMRelease", refCount);
00411     return result;
00412 }
00413 
00414 
00415 /*
00416 --------------------------------------------------------------------------------
00417     MyPMGetAPIVersion
00418 --------------------------------------------------------------------------------
00419 */
00420 
00421 static OSStatus MyPMGetAPIVersion (
00422     PMPlugInHeaderInterface* this, 
00423     PMPlugInAPIVersion* versionPtr
00424 )
00425 
00426 {
00427     OSStatus result = noErr;
00428 
00429     // constants defined in PMPrintingDialogExtensions.h
00430     versionPtr->buildVersionMajor = kPDEBuildVersionMajor;
00431     versionPtr->buildVersionMinor = kPDEBuildVersionMinor;
00432     versionPtr->baseVersionMajor = kPDEBaseVersionMajor;
00433     versionPtr->baseVersionMinor = kPDEBaseVersionMinor;
00434     
00435     MyDebugMessage("MyPMGetAPIVersion", result);
00436     return result;
00437 }
00438 
00439 
00440 #pragma mark -
00441 
00442 /*
00443 --------------------------------------------------------------------------------
00444     MyPrologue
00445 --------------------------------------------------------------------------------
00446 */
00447 
00448 /*
00449     When the printing system displays a printing dialog, it calls the
00450     prologue function in each registered dialog extension. If the user
00451     chooses a different printer while the dialog is still open, each
00452     prologue function is called again.
00453 
00454     If a prologue function returns a non-zero result code, the printing
00455     system will call the plug-in's terminate function.
00456 */
00457 
00458 static OSStatus MyPrologue (
00459     PMPDEContext    *outContext,    // session-specific global data
00460     OSType          *creator,       // not used
00461     CFStringRef     *paneKind,      // kind ID string for this PDE
00462     CFStringRef     *title,         // localized title string
00463     UInt32          *maxH,          // maximum horizontal extent
00464     UInt32          *maxV           // maximum vertical extent
00465 )
00466 
00467 {
00468     MyContext context = NULL;
00469     OSStatus result = kPMInvalidPDEContext;
00470 
00471     context = malloc (sizeof (MyContextBlock));
00472 
00473     if (context != NULL)
00474     {
00475         context->customContext = MyCreateCustomContext();
00476         context->initialized = FALSE;
00477         context->userPane = NULL;
00478         context->helpHandler = NULL;
00479         context->helpHandlerUPP = NULL;
00480 
00481         // assign output parameters
00482         *outContext = (PMPDEContext) context;
00483         *creator    = kMozPDECreatorCode;
00484         *paneKind   = kMyPaneKindID;
00485         *title      = MyGetTitle();
00486         *maxH       = kMyMaxH;
00487         *maxV       = kMyMaxV;
00488 
00489         result = noErr;
00490     }
00491 
00492     MyDebugMessage("MyPrologue", result);
00493     return result;
00494 }
00495 
00496 
00497 /*
00498 --------------------------------------------------------------------------------
00499     MyInitialize
00500 --------------------------------------------------------------------------------
00501 */
00502 
00503 static OSStatus MyInitialize (   
00504     PMPDEContext inContext,
00505     PMPDEFlags* flags,
00506     PMPDERef ref,
00507     ControlRef userPane,
00508     PMPrintSession session
00509 )
00510 
00511 {
00512     MyContext context = (MyContext) inContext;
00513     OSStatus result = noErr;
00514 
00515     *flags = kPMPDENoFlags;
00516     context->userPane = userPane;
00517 
00518     result = MySync (
00519         inContext, session, kSyncPaneFromTicket);
00520 
00521     MyDebugMessage("MyInitialize", result);
00522     return result;
00523 }
00524 
00525 
00526 /*
00527 --------------------------------------------------------------------------------
00528     MySync
00529 --------------------------------------------------------------------------------
00530 */
00531 
00532 static OSStatus MySync (
00533     PMPDEContext inContext,
00534     PMPrintSession session,
00535     Boolean syncDirection
00536 )
00537 
00538 {
00539     MyContext context = (MyContext) inContext;
00540     OSStatus result = noErr;
00541 
00542     if (syncDirection == kSyncPaneFromTicket)
00543     {
00544         result = MySyncPaneFromTicket (context->customContext, session);
00545     }
00546     else
00547     {
00548         result = MySyncTicketFromPane (context->customContext, session);
00549     }
00550 
00551     return result;
00552 }
00553 
00554 
00555 /*
00556 --------------------------------------------------------------------------------
00557     MyGetSummary
00558 --------------------------------------------------------------------------------
00559 */
00560 
00561 /*
00562     For each control, gets a localized description of the title & current value
00563 */
00564 
00565 static OSStatus MyGetSummary (
00566     PMPDEContext inContext,
00567     CFArrayRef *titles,
00568     CFArrayRef *values
00569 )
00570 
00571 {
00572     MyContext context = (MyContext) inContext;
00573     CFMutableArrayRef titleArray = NULL;
00574     CFMutableArrayRef valueArray = NULL;
00575 
00576     // assume the worst
00577     OSStatus result = kPMInvalidPDEContext;
00578 
00579     // when the second argument to CFArrayCreateMutable is 0, 
00580     // the array size is not fixed
00581 
00582     titleArray = CFArrayCreateMutable (
00583         kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
00584 
00585     if (titleArray != NULL)
00586     {
00587         valueArray = CFArrayCreateMutable (
00588             kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
00589 
00590         if (valueArray != NULL)
00591         {
00592             result = MyGetSummaryText (
00593                 context->customContext, 
00594                 titleArray, 
00595                 valueArray
00596             );
00597         }
00598     }
00599 
00600     if (result != noErr)
00601     {
00602         if (titleArray != NULL)
00603         {
00604             CFRelease (titleArray);
00605             titleArray = NULL;
00606         }
00607         if (valueArray != NULL)
00608         {
00609             CFRelease (valueArray);
00610             valueArray = NULL;
00611         }
00612     }
00613 
00614     *titles = titleArray;
00615     *values = valueArray;
00616 
00617     MyDebugMessage("MyGetSummary", result);
00618     return result;
00619 }
00620 
00621 
00622 /*
00623 --------------------------------------------------------------------------------
00624     MyOpen
00625 --------------------------------------------------------------------------------
00626 */
00627 
00628 static OSStatus MyOpen (PMPDEContext inContext)
00629 {
00630     MyContext context = (MyContext) inContext;
00631     OSStatus result = noErr;
00632 
00633     if (!context->initialized)
00634     {
00635         // initialize pane
00636     
00637         IBNibRef nib = NULL;
00638     
00639         result = CreateNibReferenceWithCFBundle (
00640             MyGetBundle(), 
00641             kMyNibFile,
00642             &nib
00643         );
00644 
00645         if (result == noErr)
00646         {
00647             WindowRef nibWindow = NULL;
00648  
00649             result = CreateWindowFromNib (
00650                 nib, 
00651                 kMyNibWindow, 
00652                 &nibWindow
00653             );
00654 
00655             if (result == noErr)
00656             {
00657                 result = MyEmbedCustomControls (
00658                     context->customContext, 
00659                     nibWindow, 
00660                     context->userPane
00661                 );
00662 
00663                 if (result == noErr)
00664                 {
00665                     context->initialized = TRUE;
00666                 }
00667 
00668                 DisposeWindow (nibWindow);
00669             }
00670 
00671             DisposeNibReference (nib);
00672         }
00673     }
00674 
00675     if (context->initialized)
00676     {
00677         result = MyInstallHelpEventHandler (
00678             GetControlOwner (context->userPane), 
00679             &(context->helpHandler),
00680             &(context->helpHandlerUPP)
00681         );
00682     }
00683     
00684     MyDebugMessage("MyOpen", result);
00685     return result;
00686 }
00687 
00688 
00689 /*
00690 --------------------------------------------------------------------------------
00691     MyClose
00692 --------------------------------------------------------------------------------
00693 */
00694 
00695 static OSStatus MyClose (PMPDEContext inContext)
00696 {
00697     MyContext context = (MyContext) inContext;
00698     OSStatus result = noErr;
00699 
00700     result = MyRemoveHelpEventHandler (
00701         &(context->helpHandler),
00702         &(context->helpHandlerUPP)
00703     );
00704 
00705     MyDebugMessage("MyClose", result);
00706     return result;
00707 }
00708 
00709 
00710 /*
00711 --------------------------------------------------------------------------------
00712     MyTerminate
00713 --------------------------------------------------------------------------------
00714 */
00715 
00716 static OSStatus MyTerminate (
00717     PMPDEContext inContext, 
00718     OSStatus inStatus
00719 )
00720 
00721 {
00722     MyContext context = (MyContext) inContext;
00723     OSStatus result = noErr;
00724 
00725     if (context != NULL)
00726     {
00727         result = MyRemoveHelpEventHandler (
00728             &(context->helpHandler),
00729             &(context->helpHandlerUPP)
00730         );
00731 
00732         if (context->customContext != NULL) {
00733             MyReleaseCustomContext (context->customContext);
00734         }
00735 
00736         free (context);
00737     }
00738 
00739     MyDebugMessage("MyTerminate", result);
00740     return result;
00741 }
00742 
00743 
00744 // END OF SOURCE