/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Rod Spears * Don Cone * Conrad Carlen * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsPrintingPromptService.h" #include "nsCOMPtr.h" #include "nsIPrintingPromptService.h" #include "nsIFactory.h" #include "nsIDOMWindow.h" #include "nsReadableUtils.h" #include "nsIEmbeddingSiteWindow.h" #include "nsIServiceManager.h" #include "nsIWebBrowserChrome.h" #include "nsIWindowWatcher.h" #include "nsIPrintSettingsMac.h" #include "nsComponentResContext.h" #include "nsWatchTask.h" // Printing Progress Includes #include "nsPrintProgress.h" #include "nsPrintProgressParams.h" #include "nsIWebProgressListener.h" // OS Includes #include #include #include #include // Constants static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul"; //----------------------------------------------------------------------------- // Dialog Extension Code //----------------------------------------------------------------------------- // Types and Defines // items to support the additional items for the dialog #define DITL_ADDITIONS 128 enum { ePrintSelectionCheckboxID = 1, ePrintFrameAsIsCheckboxID, ePrintSelectedFrameCheckboxID, ePrintAllFramesCheckboxID, eDrawFrameID }; typedef struct dialog_item_struct { Handle handle; // handle or procedure pointer for this item */ Rect bounds; // display rectangle for this item */ char type; // item type - 1 */ char data[1]; // length byte of data */ } DialogItem, *DialogItemPtr, **DialogItemHandle; typedef struct append_item_list_struct { short max_index; // number of items - 1 DialogItem items[1]; // first item in the array } ItemList, *ItemListPtr, **ItemListHandle; // Static Variables - used by the dialog callbacks - no choice but globals //static pascal TPPrDlg MyJobDlgInit(THPrint); // Our extention to PrJobInit static TPPrDlg gPrtJobDialog; // pointer to job dialog static long prFirstItem; // our first item in the extended dialog static PItemUPP prPItemProc; // store the old item handler here static PRBool gPrintSelection; static PItemUPP gPrtJobDialogItemProc; static UserItemUPP gDrawListUPP = nsnull; static nsIPrintSettings *gPrintSettings = nsnull; // Routines /** ------------------------------------------------------- * this is a drawing procedure for the user item.. this draws a box around the frameset radio buttons * @update dc 12/02/98 */ static pascal void MyBBoxDraw(WindowPtr theWindow, short aItemNo) { short itemType; Rect itemBox; Handle itemH; ::GetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem + eDrawFrameID-1, &itemType, &itemH, &itemBox); // use appearance if possible if ((long)DrawThemeSecondaryGroup != kUnresolvedCFragSymbolAddress) ::DrawThemeSecondaryGroup(&itemBox, kThemeStateActive); else ::FrameRect(&itemBox); } /** ------------------------------------------------------- * this is the dialog hook, takes care of setting the dialog items * @update dc 12/02/98 */ static pascal void MyJobItems(DialogPtr aDialog, short aItemNo) { short myItem, firstItem, i, itemType; short value; Rect itemBox; Handle itemH; firstItem = prFirstItem; myItem = aItemNo-firstItem+1; if (myItem>0) { switch (myItem) { case ePrintSelectionCheckboxID: ::GetDialogItem(aDialog, firstItem, &itemType, &itemH, &itemBox); gPrintSelection = !gPrintSelection; ::SetControlValue((ControlHandle)itemH, gPrintSelection); break; case ePrintFrameAsIsCheckboxID: case ePrintSelectedFrameCheckboxID: case ePrintAllFramesCheckboxID: for (i=ePrintFrameAsIsCheckboxID; i<=ePrintAllFramesCheckboxID; i++){ ::GetDialogItem(aDialog, firstItem+i-1, &itemType, &itemH, &itemBox); ::SetControlValue((ControlHandle)itemH, i==myItem); } break; default: break; } } else { // chain to standard Item handler CallPItemProc(prPItemProc, aDialog, aItemNo); if (((TPPrDlg)aDialog)->fDone) { // cleanup and set the print options to what we want if (gPrintSettings) { // print selection ::GetDialogItem(aDialog, firstItem+ePrintSelectionCheckboxID-1, &itemType, &itemH, &itemBox); value = ::GetControlValue((ControlHandle)itemH); if (1==value){ gPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection); } else { gPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); } // print frames as is ::GetDialogItem(aDialog, firstItem+ePrintFrameAsIsCheckboxID-1, &itemType, &itemH, &itemBox); value = ::GetControlValue((ControlHandle)itemH); if (1==value){ gPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); } // selected frame ::GetDialogItem(aDialog, firstItem+ePrintSelectedFrameCheckboxID-1, &itemType, &itemH, &itemBox); value = ::GetControlValue((ControlHandle)itemH); if (1==value){ gPrintSettings->SetPrintFrameType(nsIPrintSettings::kSelectedFrame); } // print all frames ::GetDialogItem(aDialog, firstItem+ePrintAllFramesCheckboxID-1, &itemType, &itemH, &itemBox); value = ::GetControlValue((ControlHandle)itemH); if (1==value){ gPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep); } } } } } /** ------------------------------------------------------- * Append DITL items to the dialog * @update dc 05/04/2001 */ static PRInt32 AppendToDialog(TPPrDlg aDialog, PRInt32 aDITLID) { short firstItem; ItemListHandle myAppendDITLH; ItemListHandle dlg_Item_List; dlg_Item_List = (ItemListHandle)((DialogPeek)aDialog)->items; firstItem = (**dlg_Item_List).max_index+2; nsComponentResourceContext resContext; if (resContext.BecomeCurrent()) { // destructor restores myAppendDITLH = (ItemListHandle)::GetResource('DITL', aDITLID); NS_ASSERTION(myAppendDITLH, "Failed to get DITL items"); if (myAppendDITLH) { ::AppendDITL((DialogPtr)aDialog, (Handle)myAppendDITLH, appendDITLBottom); ::ReleaseResource((Handle) myAppendDITLH); } } return firstItem; } /** ------------------------------------------------------- * Initialize the print dialogs additional items * @update dc 05/04/2001 */ static pascal TPPrDlg MyJobDlgInit(THPrint aHPrint) { PRInt32 i; short itemType; Handle itemH; Rect itemBox; PRBool isOn; PRInt16 howToEnableFrameUI = nsIPrintSettings::kFrameEnableNone; prFirstItem = AppendToDialog(gPrtJobDialog, DITL_ADDITIONS); if (gPrintSettings) { gPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &isOn); gPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); } ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+ePrintSelectionCheckboxID-1, &itemType, &itemH, &itemBox); if ( isOn ) { ::HiliteControl((ControlHandle)itemH, 0); } else { ::HiliteControl((ControlHandle)itemH, 255); } gPrintSelection = PR_FALSE; ::SetControlValue((ControlHandle) itemH, gPrintSelection); if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableAll) { for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){ ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox); ::SetControlValue((ControlHandle) itemH, (i==4)); ::HiliteControl((ControlHandle)itemH, 0); } } else if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableAsIsAndEach) { for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){ ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox); ::SetControlValue((ControlHandle) itemH, (i==4)); if ( i == 3){ ::HiliteControl((ControlHandle)itemH, 255); } } } else { for (i = ePrintFrameAsIsCheckboxID; i <= ePrintAllFramesCheckboxID; i++){ ::GetDialogItem((DialogPtr) gPrtJobDialog, prFirstItem+i-1, &itemType, &itemH, &itemBox); ::SetControlValue((ControlHandle) itemH, FALSE); ::HiliteControl((ControlHandle)itemH, 255); } } // attach our handler prPItemProc = gPrtJobDialog->pItemProc; gPrtJobDialog->pItemProc = gPrtJobDialogItemProc = NewPItemUPP(MyJobItems); // attach a draw routine gDrawListUPP = NewUserItemProc(MyBBoxDraw); ::GetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem+eDrawFrameID-1, &itemType, &itemH, &itemBox); ::SetDialogItem((DialogPtr)gPrtJobDialog, prFirstItem+eDrawFrameID-1, itemType, (Handle)gDrawListUPP, &itemBox); return gPrtJobDialog; } //***************************************************************************** // nsPrintingPromptService //***************************************************************************** NS_IMPL_ISUPPORTS2(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener) nsPrintingPromptService::nsPrintingPromptService() : mWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID)) { } nsPrintingPromptService::~nsPrintingPromptService() { } nsresult nsPrintingPromptService::Init() { return NS_OK; } //***************************************************************************** // nsPrintingPromptService::nsIPrintingPromptService //***************************************************************************** NS_IMETHODIMP nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings) { THPrint printRecH = nsnull; // local copy of nsIPrintSettingsMac's data GrafPtr oldport; PDlgInitUPP theInitProcPtr; gPrintSettings = printSettings; ::GetPort(&oldport); nsresult rv; nsCOMPtr printSettingsMac(do_QueryInterface(printSettings)); if (!printSettingsMac) return NS_ERROR_NO_INTERFACE; theInitProcPtr = NewPDlgInitProc(MyJobDlgInit); if (!theInitProcPtr) return NS_ERROR_FAILURE; // Get the print record from the settings rv = printSettingsMac->GetTHPrint(&printRecH); if (NS_FAILED(rv)) return rv; // open the printing manager ::PrOpen(); if (::PrError() != noErr) { ::DisposeHandle((Handle)printRecH); return NS_ERROR_FAILURE; } // make sure the print record is valid ::PrValidate(printRecH); if (::PrError() != noErr) { ::DisposeHandle((Handle)printRecH); ::PrClose(); return NS_ERROR_FAILURE; } // get pointer to invisible job dialog box gPrtJobDialog = ::PrJobInit(printRecH); if (::PrError() != noErr) { ::DisposeHandle((Handle)printRecH); ::PrClose(); return NS_ERROR_FAILURE; } // create a UUP for the dialog init procedure theInitProcPtr = NewPDlgInitProc(MyJobDlgInit); if (!theInitProcPtr) return NS_ERROR_FAILURE; nsWatchTask::GetTask().Suspend(); ::InitCursor(); // put up the print dialog if (::PrDlgMain(printRecH, theInitProcPtr)) { // have the print record rv = NS_OK; printSettingsMac->SetTHPrint(printRecH); } else { // don't print ::SetPort(oldport); rv = NS_ERROR_ABORT; } ::DisposeHandle((Handle)printRecH); // clean up our dialog routines DisposePItemUPP(gPrtJobDialogItemProc); gPrtJobDialogItemProc = nsnull; DisposePItemUPP(theInitProcPtr); DisposePItemUPP(gDrawListUPP); gDrawListUPP = nsnull; nsWatchTask::GetTask().Resume(); return rv; } NS_IMETHODIMP nsPrintingPromptService::ShowProgress(nsIDOMWindow* parent, nsIWebBrowserPrint* webBrowserPrint, // ok to be null nsIPrintSettings* printSettings, // ok to be null nsIObserver* openDialogObserver, // ok to be null PRBool isForPrinting, nsIWebProgressListener** webProgressListener, nsIPrintProgressParams** printProgressParams, PRBool* notifyOnOpen) { NS_ENSURE_ARG(webProgressListener); NS_ENSURE_ARG(printProgressParams); NS_ENSURE_ARG(notifyOnOpen); *notifyOnOpen = PR_FALSE; nsPrintProgress* prtProgress = new nsPrintProgress(); nsresult rv = prtProgress->QueryInterface(NS_GET_IID(nsIPrintProgress), (void**)getter_AddRefs(mPrintProgress)); NS_ENSURE_SUCCESS(rv, rv); rv = prtProgress->QueryInterface(NS_GET_IID(nsIWebProgressListener), (void**)getter_AddRefs(mWebProgressListener)); NS_ENSURE_SUCCESS(rv, rv); nsPrintProgressParams* prtProgressParams = new nsPrintProgressParams(); rv = prtProgressParams->QueryInterface(NS_GET_IID(nsIPrintProgressParams), (void**)printProgressParams); NS_ENSURE_SUCCESS(rv, rv); if (printProgressParams) { if (mWatcher) { nsCOMPtr active; mWatcher->GetActiveWindow(getter_AddRefs(active)); nsCOMPtr parent(do_QueryInterface(active)); mPrintProgress->OpenProgressDialog(parent, kPrintProgressDialogURL, *printProgressParams, openDialogObserver, notifyOnOpen); } } *webProgressListener = NS_STATIC_CAST(nsIWebProgressListener*, this); NS_ADDREF(*webProgressListener); return rv; } NS_IMETHODIMP nsPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *printSettings, nsIObserver *aObs) { nsCOMPtr printSettingsMac(do_QueryInterface(printSettings)); if (!printSettingsMac) return NS_ERROR_NO_INTERFACE; // open the printing manager ::PrOpen(); if(::PrError() != noErr) return NS_ERROR_FAILURE; THPrint printRecH; nsresult rv; rv = printSettingsMac->GetTHPrint(&printRecH); if (NS_FAILED(rv)) return rv; ::PrValidate(printRecH); NS_ASSERTION(::PrError() == noErr, "PrValidate error"); nsWatchTask::GetTask().Suspend(); ::InitCursor(); Boolean dialogOK = ::PrStlDialog(printRecH); // open up and process the style record nsWatchTask::GetTask().Resume(); OSErr err = ::PrError(); ::PrClose(); if (dialogOK) rv = printSettingsMac->SetTHPrint(printRecH); if (err != noErr) return NS_ERROR_FAILURE; if (!dialogOK) return NS_ERROR_ABORT; return rv; } NS_IMETHODIMP nsPrintingPromptService::ShowPrinterProperties(nsIDOMWindow *parent, const PRUnichar *printerName, nsIPrintSettings *printSettings) { return NS_ERROR_NOT_IMPLEMENTED; } //***************************************************************************** // nsPrintingPromptService::nsIWebProgressListener //***************************************************************************** NS_IMETHODIMP nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) { if ((aStateFlags & STATE_STOP) && mWebProgressListener) { mWebProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus); if (mPrintProgress) { mPrintProgress->CloseProgressDialog(PR_TRUE); } mPrintProgress = nsnull; mWebProgressListener = nsnull; } return NS_OK; } /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ NS_IMETHODIMP nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { if (mWebProgressListener) { return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress); } return NS_OK; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ NS_IMETHODIMP nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) { if (mWebProgressListener) { return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location); } return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ NS_IMETHODIMP nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) { if (mWebProgressListener) { return mWebProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage); } return NS_OK; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */ NS_IMETHODIMP nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) { if (mWebProgressListener) { return mWebProgressListener->OnSecurityChange(aWebProgress, aRequest, state); } return NS_OK; }