Back to index

lightning-sunbird  0.9+nobinonly
nsPrintingPromptService.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Rod Spears <rods@netscape.com>
00024  *   Don Cone <dcone@netscape.com>
00025  *   Conrad Carlen <ccarlen@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsPrintingPromptService.h"
00042 
00043 #include "nsCOMPtr.h"
00044 
00045 #include "nsIPrintingPromptService.h"
00046 #include "nsIFactory.h"
00047 #include "nsIDOMWindow.h"
00048 #include "nsReadableUtils.h"
00049 #include "nsIEmbeddingSiteWindow.h"
00050 #include "nsIServiceManager.h"
00051 #include "nsIWebBrowserChrome.h"
00052 #include "nsIWindowWatcher.h"
00053 #include "nsIPrintSettingsMac.h"
00054 #include "nsComponentResContext.h"
00055 #include "nsWatchTask.h"
00056 
00057 // Printing Progress Includes
00058 #include "nsPrintProgress.h"
00059 #include "nsPrintProgressParams.h"
00060 #include "nsIWebProgressListener.h"
00061 
00062 // OS Includes
00063 #include <Printing.h>
00064 #include <Dialogs.h>
00065 #include <Appearance.h>
00066 #include <Resources.h>
00067 
00068 // Constants
00069 static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul";
00070 
00071 //-----------------------------------------------------------------------------
00072 // Dialog Extension Code
00073 //-----------------------------------------------------------------------------
00074 
00075 // Types and Defines
00076 
00077 // items to support the additional items for the dialog
00078 #define DITL_ADDITIONS  128
00079 
00080 enum {
00081   ePrintSelectionCheckboxID = 1,
00082   ePrintFrameAsIsCheckboxID,
00083   ePrintSelectedFrameCheckboxID,
00084   ePrintAllFramesCheckboxID,
00085   eDrawFrameID
00086 };
00087 
00088 typedef struct dialog_item_struct {
00089   Handle  handle;       // handle or procedure pointer for this item */
00090   Rect    bounds;         // display rectangle for this item */
00091   char    type;           // item type - 1 */
00092   char    data[1];        // length byte of data */
00093 } DialogItem, *DialogItemPtr, **DialogItemHandle;
00094  
00095 typedef struct append_item_list_struct {
00096   short max_index;      // number of items - 1 
00097   DialogItem  items[1]; // first item in the array
00098 } ItemList, *ItemListPtr, **ItemListHandle;
00099 
00100 // Static Variables - used by the dialog callbacks - no choice but globals
00101 
00102 //static pascal TPPrDlg   MyJobDlgInit(THPrint);        // Our extention to PrJobInit
00103 static TPPrDlg          gPrtJobDialog;                 // pointer to job dialog 
00104 static long             prFirstItem;                  // our first item in the extended dialog
00105 static PItemUPP         prPItemProc;                  // store the old item handler here
00106 static PRBool           gPrintSelection;
00107 static PItemUPP         gPrtJobDialogItemProc;
00108 static UserItemUPP      gDrawListUPP = nsnull;
00109 static nsIPrintSettings     *gPrintSettings = nsnull;
00110 
00111 // Routines
00112 
00117 static pascal void MyBBoxDraw(WindowPtr theWindow, short aItemNo)
00118 {
00119   short   itemType;
00120   Rect    itemBox;
00121   Handle  itemH;
00122 
00123   ::GetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem + eDrawFrameID-1, &itemType, &itemH, &itemBox);
00124   
00125   // use appearance if possible
00126   if ((long)DrawThemeSecondaryGroup != kUnresolvedCFragSymbolAddress)
00127     ::DrawThemeSecondaryGroup(&itemBox, kThemeStateActive);
00128   else
00129     ::FrameRect(&itemBox);
00130 }
00131 
00132 
00137 static pascal void MyJobItems(DialogPtr aDialog, short aItemNo)
00138 {
00139 short   myItem, firstItem, i, itemType;
00140 short   value;
00141 Rect    itemBox;
00142 Handle  itemH;
00143 
00144   firstItem = prFirstItem;
00145   
00146   myItem = aItemNo-firstItem+1;
00147   if (myItem>0) {
00148     switch (myItem) {
00149       case ePrintSelectionCheckboxID:
00150         ::GetDialogItem(aDialog, firstItem, &itemType, &itemH, &itemBox);
00151         gPrintSelection = !gPrintSelection;
00152         ::SetControlValue((ControlHandle)itemH, gPrintSelection);
00153         break;
00154 
00155       case ePrintFrameAsIsCheckboxID:
00156       case ePrintSelectedFrameCheckboxID:
00157       case ePrintAllFramesCheckboxID:
00158         for (i=ePrintFrameAsIsCheckboxID; i<=ePrintAllFramesCheckboxID; i++){
00159           ::GetDialogItem(aDialog, firstItem+i-1, &itemType, &itemH, &itemBox);
00160           ::SetControlValue((ControlHandle)itemH, i==myItem);
00161         }
00162         break;
00163         
00164       default:
00165         break;
00166     }
00167   } else {
00168     // chain to standard Item handler
00169     CallPItemProc(prPItemProc, aDialog, aItemNo);
00170     
00171     if (((TPPrDlg)aDialog)->fDone)
00172     {
00173       // cleanup and set the print options to what we want
00174       if (gPrintSettings)
00175       {
00176         // print selection
00177         ::GetDialogItem(aDialog, firstItem+ePrintSelectionCheckboxID-1, &itemType, &itemH, &itemBox);
00178         value = ::GetControlValue((ControlHandle)itemH);
00179         if (1==value){
00180           gPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection);
00181         } else {
00182           gPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
00183         }
00184         
00185         // print frames as is
00186         ::GetDialogItem(aDialog, firstItem+ePrintFrameAsIsCheckboxID-1, &itemType, &itemH, &itemBox);
00187         value = ::GetControlValue((ControlHandle)itemH);
00188         if (1==value){
00189           gPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
00190         }
00191         
00192         // selected frame
00193         ::GetDialogItem(aDialog, firstItem+ePrintSelectedFrameCheckboxID-1, &itemType, &itemH, &itemBox);
00194         value = ::GetControlValue((ControlHandle)itemH);
00195         if (1==value){
00196           gPrintSettings->SetPrintFrameType(nsIPrintSettings::kSelectedFrame);
00197         }
00198         
00199         // print all frames
00200         ::GetDialogItem(aDialog, firstItem+ePrintAllFramesCheckboxID-1, &itemType, &itemH, &itemBox);
00201         value = ::GetControlValue((ControlHandle)itemH);
00202         if (1==value){
00203           gPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
00204         }        
00205       }
00206     }
00207   }
00208 }
00209 
00214 static PRInt32  AppendToDialog(TPPrDlg  aDialog, PRInt32  aDITLID)
00215 {
00216   short           firstItem;
00217   ItemListHandle  myAppendDITLH;
00218   ItemListHandle  dlg_Item_List;
00219 
00220   dlg_Item_List = (ItemListHandle)((DialogPeek)aDialog)->items;
00221   firstItem = (**dlg_Item_List).max_index+2;
00222 
00223   nsComponentResourceContext resContext;
00224   if (resContext.BecomeCurrent()) { // destructor restores
00225     myAppendDITLH = (ItemListHandle)::GetResource('DITL', aDITLID);
00226     NS_ASSERTION(myAppendDITLH, "Failed to get DITL items");
00227     if (myAppendDITLH) {
00228       ::AppendDITL((DialogPtr)aDialog, (Handle)myAppendDITLH, appendDITLBottom);
00229       ::ReleaseResource((Handle) myAppendDITLH);
00230     }
00231   }
00232 
00233   return firstItem;
00234 }
00235 
00236 
00241 static pascal TPPrDlg MyJobDlgInit(THPrint aHPrint)
00242 {
00243   PRInt32 i;
00244   short   itemType;
00245   Handle  itemH;
00246   Rect    itemBox;
00247   PRBool  isOn;
00248   PRInt16 howToEnableFrameUI = nsIPrintSettings::kFrameEnableNone;
00249 
00250   prFirstItem = AppendToDialog(gPrtJobDialog, DITL_ADDITIONS);
00251 
00252   if (gPrintSettings) {
00253     gPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &isOn);
00254     gPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
00255   }
00256 
00257   ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+ePrintSelectionCheckboxID-1, &itemType, &itemH, &itemBox);
00258   if ( isOn ) {
00259     ::HiliteControl((ControlHandle)itemH, 0);
00260   } else {
00261     ::HiliteControl((ControlHandle)itemH, 255); 
00262   }
00263   
00264   gPrintSelection = PR_FALSE;
00265   ::SetControlValue((ControlHandle) itemH, gPrintSelection);
00266 
00267   if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableAll) {
00268     for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){
00269       ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox);
00270       ::SetControlValue((ControlHandle) itemH, (i==4));
00271       ::HiliteControl((ControlHandle)itemH, 0);
00272     }
00273   }
00274   else if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableAsIsAndEach) {
00275     for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){
00276       ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox);
00277       ::SetControlValue((ControlHandle) itemH, (i==4));
00278       if ( i == 3){
00279         ::HiliteControl((ControlHandle)itemH, 255);
00280       }
00281     }
00282   }
00283   else {
00284     for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){
00285       ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox);
00286       ::SetControlValue((ControlHandle) itemH, FALSE);
00287       ::HiliteControl((ControlHandle)itemH, 255); 
00288     }
00289   }
00290   
00291   // attach our handler
00292   prPItemProc = gPrtJobDialog->pItemProc;
00293   gPrtJobDialog->pItemProc = gPrtJobDialogItemProc = NewPItemUPP(MyJobItems);
00294 
00295 
00296   // attach a draw routine
00297   gDrawListUPP = NewUserItemProc(MyBBoxDraw);
00298   ::GetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem+eDrawFrameID-1, &itemType, &itemH, &itemBox);
00299   ::SetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem+eDrawFrameID-1, itemType, (Handle)gDrawListUPP, &itemBox);
00300 
00301   return gPrtJobDialog;
00302 }
00303 
00304 
00305 //*****************************************************************************
00306 // nsPrintingPromptService
00307 //*****************************************************************************   
00308 
00309 NS_IMPL_ISUPPORTS2(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
00310 
00311 nsPrintingPromptService::nsPrintingPromptService() :
00312     mWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID))
00313 {
00314 }
00315 
00316 nsPrintingPromptService::~nsPrintingPromptService()
00317 {
00318 }
00319 
00320 nsresult nsPrintingPromptService::Init()
00321 {
00322     return NS_OK;
00323 }
00324 
00325 //*****************************************************************************
00326 // nsPrintingPromptService::nsIPrintingPromptService
00327 //*****************************************************************************   
00328 
00329 NS_IMETHODIMP 
00330 nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
00331 {
00332   THPrint     printRecH = nsnull;    // local copy of nsIPrintSettingsMac's data
00333   GrafPtr     oldport;
00334   PDlgInitUPP theInitProcPtr;
00335 
00336        gPrintSettings = printSettings;
00337 
00338   ::GetPort(&oldport);
00339   
00340   nsresult rv;
00341   nsCOMPtr<nsIPrintSettingsMac> printSettingsMac(do_QueryInterface(printSettings));
00342   if (!printSettingsMac)
00343     return NS_ERROR_NO_INTERFACE;
00344 
00345   theInitProcPtr = NewPDlgInitProc(MyJobDlgInit);
00346   if (!theInitProcPtr)
00347     return NS_ERROR_FAILURE;
00348       
00349   // Get the print record from the settings
00350   rv = printSettingsMac->GetTHPrint(&printRecH);
00351   if (NS_FAILED(rv))
00352     return rv;
00353 
00354   // open the printing manager
00355   ::PrOpen();
00356   if (::PrError() != noErr) {
00357     ::DisposeHandle((Handle)printRecH);
00358     return NS_ERROR_FAILURE;
00359   }
00360   
00361   // make sure the print record is valid
00362   ::PrValidate(printRecH);
00363   if (::PrError() != noErr) {
00364     ::DisposeHandle((Handle)printRecH);
00365     ::PrClose();
00366     return NS_ERROR_FAILURE;
00367   }
00368   
00369   // get pointer to invisible job dialog box
00370   gPrtJobDialog = ::PrJobInit(printRecH);
00371   if (::PrError() != noErr) {
00372     ::DisposeHandle((Handle)printRecH);
00373     ::PrClose();
00374     return NS_ERROR_FAILURE;
00375   }
00376 
00377   // create a UUP  for the dialog init procedure
00378   theInitProcPtr = NewPDlgInitProc(MyJobDlgInit);
00379   if (!theInitProcPtr)
00380     return NS_ERROR_FAILURE;      
00381 
00382   nsWatchTask::GetTask().Suspend();
00383   ::InitCursor();
00384        
00385   // put up the print dialog
00386   if (::PrDlgMain(printRecH, theInitProcPtr))
00387   {
00388     // have the print record
00389     rv = NS_OK;
00390     printSettingsMac->SetTHPrint(printRecH);
00391   }
00392   else
00393   {
00394     // don't print
00395     ::SetPort(oldport); 
00396     rv = NS_ERROR_ABORT;
00397   }
00398   
00399   ::DisposeHandle((Handle)printRecH);
00400   
00401   // clean up our dialog routines
00402   DisposePItemUPP(gPrtJobDialogItemProc);
00403   gPrtJobDialogItemProc = nsnull;
00404   
00405   DisposePItemUPP(theInitProcPtr);
00406   DisposePItemUPP(gDrawListUPP);
00407   gDrawListUPP = nsnull;
00408       
00409   nsWatchTask::GetTask().Resume();
00410   return rv;
00411 }
00412 
00413 NS_IMETHODIMP 
00414 nsPrintingPromptService::ShowProgress(nsIDOMWindow*            parent, 
00415                                       nsIWebBrowserPrint*      webBrowserPrint,    // ok to be null
00416                                       nsIPrintSettings*        printSettings,      // ok to be null
00417                                       nsIObserver*             openDialogObserver, // ok to be null
00418                                       PRBool                   isForPrinting,
00419                                       nsIWebProgressListener** webProgressListener,
00420                                       nsIPrintProgressParams** printProgressParams,
00421                                       PRBool*                  notifyOnOpen)
00422 {
00423     NS_ENSURE_ARG(webProgressListener);
00424     NS_ENSURE_ARG(printProgressParams);
00425     NS_ENSURE_ARG(notifyOnOpen);
00426 
00427     *notifyOnOpen = PR_FALSE;
00428 
00429     nsPrintProgress* prtProgress = new nsPrintProgress();
00430     nsresult rv = prtProgress->QueryInterface(NS_GET_IID(nsIPrintProgress), (void**)getter_AddRefs(mPrintProgress));
00431     NS_ENSURE_SUCCESS(rv, rv);
00432 
00433     rv = prtProgress->QueryInterface(NS_GET_IID(nsIWebProgressListener), (void**)getter_AddRefs(mWebProgressListener));
00434     NS_ENSURE_SUCCESS(rv, rv);
00435 
00436     nsPrintProgressParams* prtProgressParams = new nsPrintProgressParams();
00437     rv = prtProgressParams->QueryInterface(NS_GET_IID(nsIPrintProgressParams), (void**)printProgressParams);
00438     NS_ENSURE_SUCCESS(rv, rv);
00439 
00440     if (printProgressParams) 
00441     {
00442         if (mWatcher) 
00443         {
00444             nsCOMPtr<nsIDOMWindow> active;
00445             mWatcher->GetActiveWindow(getter_AddRefs(active));
00446             nsCOMPtr<nsIDOMWindowInternal> parent(do_QueryInterface(active));
00447             mPrintProgress->OpenProgressDialog(parent, kPrintProgressDialogURL, *printProgressParams, openDialogObserver, notifyOnOpen);
00448         }
00449     }
00450 
00451     *webProgressListener = NS_STATIC_CAST(nsIWebProgressListener*, this);
00452     NS_ADDREF(*webProgressListener);
00453 
00454     return rv;
00455 }
00456 
00457 NS_IMETHODIMP 
00458 nsPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *printSettings, nsIObserver *aObs)
00459 {
00460   nsCOMPtr<nsIPrintSettingsMac> printSettingsMac(do_QueryInterface(printSettings));
00461   if (!printSettingsMac)
00462     return NS_ERROR_NO_INTERFACE;
00463 
00464   // open the printing manager
00465   ::PrOpen();
00466   if(::PrError() != noErr)
00467     return NS_ERROR_FAILURE;
00468   
00469   THPrint printRecH;
00470   nsresult rv;
00471   
00472   rv = printSettingsMac->GetTHPrint(&printRecH);
00473   if (NS_FAILED(rv))
00474     return rv;
00475     
00476   ::PrValidate(printRecH);
00477   NS_ASSERTION(::PrError() == noErr, "PrValidate error");
00478 
00479   nsWatchTask::GetTask().Suspend();
00480   ::InitCursor();
00481   Boolean   dialogOK = ::PrStlDialog(printRecH);        // open up and process the style record
00482   nsWatchTask::GetTask().Resume();
00483   
00484   OSErr err = ::PrError();
00485   ::PrClose();
00486 
00487   if (dialogOK)
00488     rv = printSettingsMac->SetTHPrint(printRecH);
00489       
00490   if (err != noErr)
00491     return NS_ERROR_FAILURE;
00492   if (!dialogOK)
00493     return NS_ERROR_ABORT;
00494     
00495   return rv;
00496 }
00497 
00498 NS_IMETHODIMP 
00499 nsPrintingPromptService::ShowPrinterProperties(nsIDOMWindow *parent, const PRUnichar *printerName, nsIPrintSettings *printSettings)
00500 {
00501     return NS_ERROR_NOT_IMPLEMENTED;
00502 }
00503 
00504 //*****************************************************************************
00505 // nsPrintingPromptService::nsIWebProgressListener
00506 //*****************************************************************************   
00507 
00508 NS_IMETHODIMP 
00509 nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
00510 {
00511     if ((aStateFlags & STATE_STOP) && mWebProgressListener) 
00512     {
00513         mWebProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
00514         if (mPrintProgress) 
00515         {
00516             mPrintProgress->CloseProgressDialog(PR_TRUE);
00517         }
00518         mPrintProgress       = nsnull;
00519         mWebProgressListener = nsnull;
00520     }
00521     return NS_OK;
00522 }
00523 
00524 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
00525 NS_IMETHODIMP 
00526 nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
00527 {
00528     if (mWebProgressListener) {
00529       return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
00530     }
00531     return NS_OK;
00532 }
00533 
00534 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
00535 NS_IMETHODIMP 
00536 nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
00537 {
00538     if (mWebProgressListener) {
00539         return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location);
00540     }
00541     return NS_OK;
00542 }
00543 
00544 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
00545 NS_IMETHODIMP 
00546 nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
00547 {
00548     if (mWebProgressListener) {
00549         return mWebProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
00550     }
00551     return NS_OK;
00552 }
00553 
00554 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
00555 NS_IMETHODIMP 
00556 nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
00557 {
00558     if (mWebProgressListener) {
00559         return mWebProgressListener->OnSecurityChange(aWebProgress, aRequest, state);
00560     }
00561     return NS_OK;
00562 }