1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/printing/nsPrintEngine.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3977 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsPrintEngine.h" 1.10 + 1.11 +#include "nsIStringBundle.h" 1.12 +#include "nsReadableUtils.h" 1.13 +#include "nsCRT.h" 1.14 + 1.15 +#include "mozilla/AsyncEventDispatcher.h" 1.16 +#include "mozilla/dom/Selection.h" 1.17 +#include "nsIScriptGlobalObject.h" 1.18 +#include "nsPIDOMWindow.h" 1.19 +#include "nsIDocShell.h" 1.20 +#include "nsIFrame.h" 1.21 +#include "nsIURI.h" 1.22 +#include "nsITextToSubURI.h" 1.23 +#include "nsError.h" 1.24 + 1.25 +#include "nsView.h" 1.26 +#include <algorithm> 1.27 + 1.28 +// Print Options 1.29 +#include "nsIPrintSettings.h" 1.30 +#include "nsIPrintSettingsService.h" 1.31 +#include "nsIPrintOptions.h" 1.32 +#include "nsIPrintSession.h" 1.33 +#include "nsGfxCIID.h" 1.34 +#include "nsIServiceManager.h" 1.35 +#include "nsGkAtoms.h" 1.36 +#include "nsXPCOM.h" 1.37 +#include "nsISupportsPrimitives.h" 1.38 + 1.39 +static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1"; 1.40 + 1.41 +// Printing Events 1.42 +#include "nsPrintPreviewListener.h" 1.43 +#include "nsThreadUtils.h" 1.44 + 1.45 +// Printing 1.46 +#include "nsIWebBrowserPrint.h" 1.47 +#include "nsIDOMHTMLFrameElement.h" 1.48 +#include "nsIDOMHTMLFrameSetElement.h" 1.49 +#include "nsIDOMHTMLIFrameElement.h" 1.50 +#include "nsIDOMHTMLObjectElement.h" 1.51 +#include "nsIDOMHTMLEmbedElement.h" 1.52 + 1.53 +// Print Preview 1.54 +#include "imgIContainer.h" // image animation mode constants 1.55 +#include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants 1.56 + 1.57 +// Print Progress 1.58 +#include "nsIPrintProgress.h" 1.59 +#include "nsIPrintProgressParams.h" 1.60 +#include "nsIObserver.h" 1.61 + 1.62 +// Print error dialog 1.63 +#include "nsIPrompt.h" 1.64 +#include "nsIWindowWatcher.h" 1.65 + 1.66 +// Printing Prompts 1.67 +#include "nsIPrintingPromptService.h" 1.68 +static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingprompt-service;1"; 1.69 + 1.70 +// Printing Timer 1.71 +#include "nsPagePrintTimer.h" 1.72 + 1.73 +// FrameSet 1.74 +#include "nsIDocument.h" 1.75 + 1.76 +// Focus 1.77 +#include "nsISelectionController.h" 1.78 + 1.79 +// Misc 1.80 +#include "nsISupportsUtils.h" 1.81 +#include "nsIScriptContext.h" 1.82 +#include "nsIDOMDocument.h" 1.83 +#include "nsISelectionListener.h" 1.84 +#include "nsISelectionPrivate.h" 1.85 +#include "nsIDOMRange.h" 1.86 +#include "nsContentCID.h" 1.87 +#include "nsLayoutCID.h" 1.88 +#include "nsContentUtils.h" 1.89 +#include "nsIPresShell.h" 1.90 +#include "nsLayoutUtils.h" 1.91 +#include "mozilla/Preferences.h" 1.92 + 1.93 +#include "nsWidgetsCID.h" 1.94 +#include "nsIDeviceContextSpec.h" 1.95 +#include "nsViewManager.h" 1.96 +#include "nsView.h" 1.97 +#include "nsRenderingContext.h" 1.98 + 1.99 +#include "nsIPageSequenceFrame.h" 1.100 +#include "nsIURL.h" 1.101 +#include "nsIContentViewerEdit.h" 1.102 +#include "nsIContentViewerFile.h" 1.103 +#include "nsIMarkupDocumentViewer.h" 1.104 +#include "nsIInterfaceRequestor.h" 1.105 +#include "nsIInterfaceRequestorUtils.h" 1.106 +#include "nsIDocShellTreeOwner.h" 1.107 +#include "nsIWebBrowserChrome.h" 1.108 +#include "nsIBaseWindow.h" 1.109 +#include "nsILayoutHistoryState.h" 1.110 +#include "nsFrameManager.h" 1.111 +#include "nsHTMLReflowState.h" 1.112 +#include "nsIDOMHTMLAnchorElement.h" 1.113 +#include "nsIDOMHTMLAreaElement.h" 1.114 +#include "nsIDOMHTMLLinkElement.h" 1.115 +#include "nsIDOMHTMLImageElement.h" 1.116 +#include "nsIContentViewerContainer.h" 1.117 +#include "nsIContentViewer.h" 1.118 +#include "nsIDocumentViewerPrint.h" 1.119 + 1.120 +#include "nsFocusManager.h" 1.121 +#include "nsRange.h" 1.122 +#include "nsCDefaultURIFixup.h" 1.123 +#include "nsIURIFixup.h" 1.124 +#include "mozilla/dom/Element.h" 1.125 +#include "nsContentList.h" 1.126 +#include "nsIChannel.h" 1.127 +#include "xpcpublic.h" 1.128 + 1.129 +using namespace mozilla; 1.130 +using namespace mozilla::dom; 1.131 + 1.132 +//----------------------------------------------------- 1.133 +// PR LOGGING 1.134 +#ifdef MOZ_LOGGING 1.135 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.136 +#endif 1.137 + 1.138 +#include "prlog.h" 1.139 + 1.140 +#ifdef PR_LOGGING 1.141 + 1.142 +#ifdef DEBUG 1.143 +// PR_LOGGING is force to always be on (even in release builds) 1.144 +// but we only want some of it on, 1.145 +//#define EXTENDED_DEBUG_PRINTING 1.146 +#endif 1.147 + 1.148 +#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info 1.149 + 1.150 +#ifndef PR_PL 1.151 +static PRLogModuleInfo * 1.152 +GetPrintingLog() 1.153 +{ 1.154 + static PRLogModuleInfo *sLog; 1.155 + if (!sLog) 1.156 + sLog = PR_NewLogModule("printing"); 1.157 + return sLog; 1.158 +} 1.159 +#define PR_PL(_p1) PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1); 1.160 +#endif 1.161 + 1.162 +#ifdef EXTENDED_DEBUG_PRINTING 1.163 +static uint32_t gDumpFileNameCnt = 0; 1.164 +static uint32_t gDumpLOFileNameCnt = 0; 1.165 +#endif 1.166 + 1.167 +#define PRT_YESNO(_p) ((_p)?"YES":"NO") 1.168 +static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"}; 1.169 +static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"}; 1.170 +static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; 1.171 +static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"}; 1.172 +#else 1.173 +#define PRT_YESNO(_p) 1.174 +#define PR_PL(_p1) 1.175 +#endif 1.176 + 1.177 +#ifdef EXTENDED_DEBUG_PRINTING 1.178 +// Forward Declarations 1.179 +static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList); 1.180 +static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nullptr); 1.181 +static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsDeviceContext * aDC, int aLevel= 0, FILE * aFD = nullptr); 1.182 + 1.183 +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); 1.184 +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); 1.185 +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); 1.186 +#else 1.187 +#define DUMP_DOC_LIST(_title) 1.188 +#define DUMP_DOC_TREE 1.189 +#define DUMP_DOC_TREELAYOUT 1.190 +#endif 1.191 + 1.192 +class nsScriptSuppressor 1.193 +{ 1.194 +public: 1.195 + nsScriptSuppressor(nsPrintEngine* aPrintEngine) 1.196 + : mPrintEngine(aPrintEngine), mSuppressed(false) {} 1.197 + 1.198 + ~nsScriptSuppressor() { Unsuppress(); } 1.199 + 1.200 + void Suppress() 1.201 + { 1.202 + if (mPrintEngine) { 1.203 + mSuppressed = true; 1.204 + mPrintEngine->TurnScriptingOn(false); 1.205 + } 1.206 + } 1.207 + 1.208 + void Unsuppress() 1.209 + { 1.210 + if (mPrintEngine && mSuppressed) { 1.211 + mPrintEngine->TurnScriptingOn(true); 1.212 + } 1.213 + mSuppressed = false; 1.214 + } 1.215 + 1.216 + void Disconnect() { mPrintEngine = nullptr; } 1.217 +protected: 1.218 + nsRefPtr<nsPrintEngine> mPrintEngine; 1.219 + bool mSuppressed; 1.220 +}; 1.221 + 1.222 +NS_IMPL_ISUPPORTS(nsPrintEngine, nsIWebProgressListener, 1.223 + nsISupportsWeakReference, nsIObserver) 1.224 + 1.225 +//--------------------------------------------------- 1.226 +//-- nsPrintEngine Class Impl 1.227 +//--------------------------------------------------- 1.228 +nsPrintEngine::nsPrintEngine() : 1.229 + mIsCreatingPrintPreview(false), 1.230 + mIsDoingPrinting(false), 1.231 + mIsDoingPrintPreview(false), 1.232 + mProgressDialogIsShown(false), 1.233 + mScreenDPI(115.0f), 1.234 + mPrt(nullptr), 1.235 + mPagePrintTimer(nullptr), 1.236 + mPageSeqFrame(nullptr), 1.237 + mPrtPreview(nullptr), 1.238 + mOldPrtPreview(nullptr), 1.239 + mDebugFile(nullptr), 1.240 + mLoadCounter(0), 1.241 + mDidLoadDataForPrinting(false), 1.242 + mIsDestroying(false), 1.243 + mDisallowSelectionPrint(false), 1.244 + mNoMarginBoxes(false) 1.245 +{ 1.246 +} 1.247 + 1.248 +//------------------------------------------------------- 1.249 +nsPrintEngine::~nsPrintEngine() 1.250 +{ 1.251 + Destroy(); // for insurance 1.252 +} 1.253 + 1.254 +//------------------------------------------------------- 1.255 +void nsPrintEngine::Destroy() 1.256 +{ 1.257 + if (mIsDestroying) { 1.258 + return; 1.259 + } 1.260 + mIsDestroying = true; 1.261 + 1.262 + if (mPrt) { 1.263 + delete mPrt; 1.264 + mPrt = nullptr; 1.265 + } 1.266 + 1.267 +#ifdef NS_PRINT_PREVIEW 1.268 + if (mPrtPreview) { 1.269 + delete mPrtPreview; 1.270 + mPrtPreview = nullptr; 1.271 + } 1.272 + 1.273 + // This is insruance 1.274 + if (mOldPrtPreview) { 1.275 + delete mOldPrtPreview; 1.276 + mOldPrtPreview = nullptr; 1.277 + } 1.278 + 1.279 +#endif 1.280 + mDocViewerPrint = nullptr; 1.281 +} 1.282 + 1.283 +//------------------------------------------------------- 1.284 +void nsPrintEngine::DestroyPrintingData() 1.285 +{ 1.286 + if (mPrt) { 1.287 + nsPrintData* data = mPrt; 1.288 + mPrt = nullptr; 1.289 + delete data; 1.290 + } 1.291 +} 1.292 + 1.293 +//--------------------------------------------------------------------------------- 1.294 +//-- Section: Methods needed by the DocViewer 1.295 +//--------------------------------------------------------------------------------- 1.296 + 1.297 +//-------------------------------------------------------- 1.298 +nsresult nsPrintEngine::Initialize(nsIDocumentViewerPrint* aDocViewerPrint, 1.299 + nsIDocShell* aContainer, 1.300 + nsIDocument* aDocument, 1.301 + float aScreenDPI, 1.302 + FILE* aDebugFile) 1.303 +{ 1.304 + NS_ENSURE_ARG_POINTER(aDocViewerPrint); 1.305 + NS_ENSURE_ARG_POINTER(aContainer); 1.306 + NS_ENSURE_ARG_POINTER(aDocument); 1.307 + 1.308 + mDocViewerPrint = aDocViewerPrint; 1.309 + mContainer = do_GetWeakReference(aContainer); 1.310 + mDocument = aDocument; 1.311 + mScreenDPI = aScreenDPI; 1.312 + 1.313 + mDebugFile = aDebugFile; // ok to be nullptr 1.314 + 1.315 + return NS_OK; 1.316 +} 1.317 + 1.318 +//------------------------------------------------------- 1.319 +bool 1.320 +nsPrintEngine::CheckBeforeDestroy() 1.321 +{ 1.322 + if (mPrt && mPrt->mPreparingForPrint) { 1.323 + mPrt->mDocWasToBeDestroyed = true; 1.324 + return true; 1.325 + } 1.326 + return false; 1.327 +} 1.328 + 1.329 +//------------------------------------------------------- 1.330 +nsresult 1.331 +nsPrintEngine::Cancelled() 1.332 +{ 1.333 + if (mPrt && mPrt->mPrintSettings) { 1.334 + return mPrt->mPrintSettings->SetIsCancelled(true); 1.335 + } 1.336 + return NS_ERROR_FAILURE; 1.337 +} 1.338 + 1.339 +//------------------------------------------------------- 1.340 +// Install our event listeners on the document to prevent 1.341 +// some events from being processed while in PrintPreview 1.342 +// 1.343 +// No return code - if this fails, there isn't much we can do 1.344 +void 1.345 +nsPrintEngine::InstallPrintPreviewListener() 1.346 +{ 1.347 + if (!mPrt->mPPEventListeners) { 1.348 + nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mContainer); 1.349 + nsCOMPtr<nsPIDOMWindow> win(do_GetInterface(docShell)); 1.350 + if (win) { 1.351 + nsCOMPtr<EventTarget> target = do_QueryInterface(win->GetFrameElementInternal()); 1.352 + mPrt->mPPEventListeners = new nsPrintPreviewListener(target); 1.353 + mPrt->mPPEventListeners->AddListeners(); 1.354 + } 1.355 + } 1.356 +} 1.357 + 1.358 +//---------------------------------------------------------------------- 1.359 +nsresult 1.360 +nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO, 1.361 + nsIFrame*& aSeqFrame, 1.362 + int32_t& aCount) 1.363 +{ 1.364 + NS_ENSURE_ARG_POINTER(aPO); 1.365 + 1.366 + // Finds the SimplePageSequencer frame 1.367 + nsIPageSequenceFrame* seqFrame = aPO->mPresShell->GetPageSequenceFrame(); 1.368 + aSeqFrame = do_QueryFrame(seqFrame); 1.369 + if (!aSeqFrame) { 1.370 + return NS_ERROR_FAILURE; 1.371 + } 1.372 + 1.373 + // first count the total number of pages 1.374 + aCount = 0; 1.375 + nsIFrame* pageFrame = aSeqFrame->GetFirstPrincipalChild(); 1.376 + while (pageFrame != nullptr) { 1.377 + aCount++; 1.378 + pageFrame = pageFrame->GetNextSibling(); 1.379 + } 1.380 + 1.381 + return NS_OK; 1.382 + 1.383 +} 1.384 + 1.385 +//----------------------------------------------------------------- 1.386 +nsresult nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, int32_t& aCount) 1.387 +{ 1.388 + NS_ASSERTION(mPrtPreview, "mPrtPreview can't be null!"); 1.389 + return GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, aSeqFrame, aCount); 1.390 +} 1.391 +//--------------------------------------------------------------------------------- 1.392 +//-- Done: Methods needed by the DocViewer 1.393 +//--------------------------------------------------------------------------------- 1.394 + 1.395 + 1.396 +//--------------------------------------------------------------------------------- 1.397 +//-- Section: nsIWebBrowserPrint 1.398 +//--------------------------------------------------------------------------------- 1.399 + 1.400 +// Foward decl for Debug Helper Functions 1.401 +#ifdef EXTENDED_DEBUG_PRINTING 1.402 +static int RemoveFilesInDir(const char * aDir); 1.403 +static void GetDocTitleAndURL(nsPrintObject* aPO, char *& aDocStr, char *& aURLStr); 1.404 +static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD); 1.405 +static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList); 1.406 +static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent); 1.407 +static void DumpViews(nsIDocShell* aDocShell, FILE* out); 1.408 +static void DumpLayoutData(char* aTitleStr, char* aURLStr, 1.409 + nsPresContext* aPresContext, 1.410 + nsDeviceContext * aDC, nsIFrame * aRootFrame, 1.411 + nsIDocShell * aDocShell, FILE* aFD); 1.412 +#endif 1.413 + 1.414 +//-------------------------------------------------------------------------------- 1.415 + 1.416 +nsresult 1.417 +nsPrintEngine::CommonPrint(bool aIsPrintPreview, 1.418 + nsIPrintSettings* aPrintSettings, 1.419 + nsIWebProgressListener* aWebProgressListener, 1.420 + nsIDOMDocument* aDoc) { 1.421 + nsRefPtr<nsPrintEngine> kungfuDeathGrip = this; 1.422 + nsresult rv = DoCommonPrint(aIsPrintPreview, aPrintSettings, 1.423 + aWebProgressListener, aDoc); 1.424 + if (NS_FAILED(rv)) { 1.425 + if (aIsPrintPreview) { 1.426 + SetIsCreatingPrintPreview(false); 1.427 + SetIsPrintPreview(false); 1.428 + } else { 1.429 + SetIsPrinting(false); 1.430 + } 1.431 + if (mProgressDialogIsShown) 1.432 + CloseProgressDialog(aWebProgressListener); 1.433 + if (rv != NS_ERROR_ABORT && rv != NS_ERROR_OUT_OF_MEMORY) 1.434 + ShowPrintErrorDialog(rv, !aIsPrintPreview); 1.435 + delete mPrt; 1.436 + mPrt = nullptr; 1.437 + } 1.438 + 1.439 + return rv; 1.440 +} 1.441 + 1.442 +nsresult 1.443 +nsPrintEngine::DoCommonPrint(bool aIsPrintPreview, 1.444 + nsIPrintSettings* aPrintSettings, 1.445 + nsIWebProgressListener* aWebProgressListener, 1.446 + nsIDOMDocument* aDoc) 1.447 +{ 1.448 + nsresult rv; 1.449 + 1.450 + if (aIsPrintPreview) { 1.451 + // The WebProgressListener can be QI'ed to nsIPrintingPromptService 1.452 + // then that means the progress dialog is already being shown. 1.453 + nsCOMPtr<nsIPrintingPromptService> pps(do_QueryInterface(aWebProgressListener)); 1.454 + mProgressDialogIsShown = pps != nullptr; 1.455 + 1.456 + if (mIsDoingPrintPreview) { 1.457 + mOldPrtPreview = mPrtPreview; 1.458 + mPrtPreview = nullptr; 1.459 + } 1.460 + } else { 1.461 + mProgressDialogIsShown = false; 1.462 + } 1.463 + 1.464 + mPrt = new nsPrintData(aIsPrintPreview ? nsPrintData::eIsPrintPreview : 1.465 + nsPrintData::eIsPrinting); 1.466 + NS_ENSURE_TRUE(mPrt, NS_ERROR_OUT_OF_MEMORY); 1.467 + 1.468 + // if they don't pass in a PrintSettings, then get the Global PS 1.469 + mPrt->mPrintSettings = aPrintSettings; 1.470 + if (!mPrt->mPrintSettings) { 1.471 + rv = GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); 1.472 + NS_ENSURE_SUCCESS(rv, rv); 1.473 + } 1.474 + 1.475 + rv = CheckForPrinters(mPrt->mPrintSettings); 1.476 + NS_ENSURE_SUCCESS(rv, rv); 1.477 + 1.478 + mPrt->mPrintSettings->SetIsCancelled(false); 1.479 + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); 1.480 + 1.481 + // In the case the margin boxes are not printed store the print settings for 1.482 + // the footer/header to be used as default print setting for follow up prints. 1.483 + mPrt->mPrintSettings->SetPersistMarginBoxSettings(!mNoMarginBoxes); 1.484 + 1.485 + if (mNoMarginBoxes) { 1.486 + // Set the footer/header to blank. 1.487 + const char16_t* emptyString = EmptyString().get(); 1.488 + mPrt->mPrintSettings->SetHeaderStrLeft(emptyString); 1.489 + mPrt->mPrintSettings->SetHeaderStrCenter(emptyString); 1.490 + mPrt->mPrintSettings->SetHeaderStrRight(emptyString); 1.491 + mPrt->mPrintSettings->SetFooterStrLeft(emptyString); 1.492 + mPrt->mPrintSettings->SetFooterStrCenter(emptyString); 1.493 + mPrt->mPrintSettings->SetFooterStrRight(emptyString); 1.494 + } 1.495 + 1.496 + if (aIsPrintPreview) { 1.497 + SetIsCreatingPrintPreview(true); 1.498 + SetIsPrintPreview(true); 1.499 + nsCOMPtr<nsIMarkupDocumentViewer> viewer = 1.500 + do_QueryInterface(mDocViewerPrint); 1.501 + if (viewer) { 1.502 + viewer->SetTextZoom(1.0f); 1.503 + viewer->SetFullZoom(1.0f); 1.504 + viewer->SetMinFontSize(0); 1.505 + } 1.506 + } 1.507 + 1.508 + // Create a print session and let the print settings know about it. 1.509 + // The print settings hold an nsWeakPtr to the session so it does not 1.510 + // need to be cleared from the settings at the end of the job. 1.511 + // XXX What lifetime does the printSession need to have? 1.512 + nsCOMPtr<nsIPrintSession> printSession; 1.513 + if (!aIsPrintPreview) { 1.514 + printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv); 1.515 + NS_ENSURE_SUCCESS(rv, rv); 1.516 + mPrt->mPrintSettings->SetPrintSession(printSession); 1.517 + } 1.518 + 1.519 + if (aWebProgressListener != nullptr) { 1.520 + mPrt->mPrintProgressListeners.AppendObject(aWebProgressListener); 1.521 + } 1.522 + 1.523 + // Get the currently focused window and cache it 1.524 + // because the Print Dialog will "steal" focus and later when you try 1.525 + // to get the currently focused windows it will be nullptr 1.526 + mPrt->mCurrentFocusWin = FindFocusedDOMWindow(); 1.527 + 1.528 + // Check to see if there is a "regular" selection 1.529 + bool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); 1.530 + 1.531 + // Get the docshell for this documentviewer 1.532 + nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer, &rv)); 1.533 + NS_ENSURE_SUCCESS(rv, rv); 1.534 + 1.535 + { 1.536 + if (aIsPrintPreview) { 1.537 + nsCOMPtr<nsIContentViewer> viewer; 1.538 + webContainer->GetContentViewer(getter_AddRefs(viewer)); 1.539 + if (viewer && viewer->GetDocument() && viewer->GetDocument()->IsShowing()) { 1.540 + viewer->GetDocument()->OnPageHide(false, nullptr); 1.541 + } 1.542 + } 1.543 + 1.544 + nsAutoScriptBlocker scriptBlocker; 1.545 + mPrt->mPrintObject = new nsPrintObject(); 1.546 + NS_ENSURE_TRUE(mPrt->mPrintObject, NS_ERROR_OUT_OF_MEMORY); 1.547 + rv = mPrt->mPrintObject->Init(webContainer, aDoc, aIsPrintPreview); 1.548 + NS_ENSURE_SUCCESS(rv, rv); 1.549 + 1.550 + NS_ENSURE_TRUE(mPrt->mPrintDocList.AppendElement(mPrt->mPrintObject), 1.551 + NS_ERROR_OUT_OF_MEMORY); 1.552 + 1.553 + mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); 1.554 + mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc; 1.555 + 1.556 + // Build the "tree" of PrintObjects 1.557 + BuildDocTree(mPrt->mPrintObject->mDocShell, &mPrt->mPrintDocList, 1.558 + mPrt->mPrintObject); 1.559 + } 1.560 + 1.561 + if (!aIsPrintPreview) { 1.562 + SetIsPrinting(true); 1.563 + } 1.564 + 1.565 + // XXX This isn't really correct... 1.566 + if (!mPrt->mPrintObject->mDocument || 1.567 + !mPrt->mPrintObject->mDocument->GetRootElement()) 1.568 + return NS_ERROR_GFX_PRINTER_STARTDOC; 1.569 + 1.570 + // Create the linkage from the sub-docs back to the content element 1.571 + // in the parent document 1.572 + MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); 1.573 + 1.574 + mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); 1.575 + 1.576 + // Setup print options for UI 1.577 + if (mPrt->mIsParentAFrameSet) { 1.578 + if (mPrt->mCurrentFocusWin) { 1.579 + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); 1.580 + } else { 1.581 + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); 1.582 + } 1.583 + } else { 1.584 + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); 1.585 + } 1.586 + // Now determine how to set up the Frame print UI 1.587 + mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, 1.588 + isSelection || mPrt->mIsIFrameSelected); 1.589 + 1.590 + nsCOMPtr<nsIDeviceContextSpec> devspec 1.591 + (do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv)); 1.592 + NS_ENSURE_SUCCESS(rv, rv); 1.593 + 1.594 + nsScriptSuppressor scriptSuppressor(this); 1.595 + if (!aIsPrintPreview) { 1.596 +#ifdef DEBUG 1.597 + mPrt->mDebugFilePtr = mDebugFile; 1.598 +#endif 1.599 + 1.600 + scriptSuppressor.Suppress(); 1.601 + bool printSilently; 1.602 + mPrt->mPrintSettings->GetPrintSilent(&printSilently); 1.603 + 1.604 + // Check prefs for a default setting as to whether we should print silently 1.605 + printSilently = 1.606 + Preferences::GetBool("print.always_print_silent", printSilently); 1.607 + 1.608 + // Ask dialog to be Print Shown via the Plugable Printing Dialog Service 1.609 + // This service is for the Print Dialog and the Print Progress Dialog 1.610 + // If printing silently or you can't get the service continue on 1.611 + if (!printSilently) { 1.612 + nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService)); 1.613 + if (printPromptService) { 1.614 + nsIDOMWindow *domWin = mDocument->GetWindow(); 1.615 + NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE); 1.616 + 1.617 + // Platforms not implementing a given dialog for the service may 1.618 + // return NS_ERROR_NOT_IMPLEMENTED or an error code. 1.619 + // 1.620 + // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior 1.621 + // Any other error code means we must bail out 1.622 + // 1.623 + nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint)); 1.624 + rv = printPromptService->ShowPrintDialog(domWin, wbp, 1.625 + mPrt->mPrintSettings); 1.626 + // 1.627 + // ShowPrintDialog triggers an event loop which means we can't assume 1.628 + // that the state of this->{anything} matches the state we've checked 1.629 + // above. Including that a given {thing} is non null. 1.630 + if (!mPrt) { 1.631 + return NS_ERROR_FAILURE; 1.632 + } 1.633 + 1.634 + if (NS_SUCCEEDED(rv)) { 1.635 + // since we got the dialog and it worked then make sure we 1.636 + // are telling GFX we want to print silent 1.637 + printSilently = true; 1.638 + 1.639 + if (mPrt->mPrintSettings) { 1.640 + // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state 1.641 + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); 1.642 + } 1.643 + } else if (rv == NS_ERROR_NOT_IMPLEMENTED) { 1.644 + // This means the Dialog service was there, 1.645 + // but they choose not to implement this dialog and 1.646 + // are looking for default behavior from the toolkit 1.647 + rv = NS_OK; 1.648 + } 1.649 + } else { 1.650 + // No dialog service available 1.651 + rv = NS_ERROR_NOT_IMPLEMENTED; 1.652 + } 1.653 + } else { 1.654 + // Call any code that requires a run of the event loop. 1.655 + rv = mPrt->mPrintSettings->SetupSilentPrinting(); 1.656 + } 1.657 + // Check explicitly for abort because it's expected 1.658 + if (rv == NS_ERROR_ABORT) 1.659 + return rv; 1.660 + NS_ENSURE_SUCCESS(rv, rv); 1.661 + } 1.662 + 1.663 + rv = devspec->Init(nullptr, mPrt->mPrintSettings, aIsPrintPreview); 1.664 + NS_ENSURE_SUCCESS(rv, rv); 1.665 + 1.666 + mPrt->mPrintDC = new nsDeviceContext(); 1.667 + rv = mPrt->mPrintDC->InitForPrinting(devspec); 1.668 + NS_ENSURE_SUCCESS(rv, rv); 1.669 + 1.670 + if (aIsPrintPreview) { 1.671 + mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); 1.672 + 1.673 + // override any UI that wants to PrintPreview any selection or page range 1.674 + // we want to view every page in PrintPreview each time 1.675 + mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); 1.676 + } else { 1.677 + // Always check and set the print settings first and then fall back 1.678 + // onto the PrintService if there isn't a PrintSettings 1.679 + // 1.680 + // Posiible Usage values: 1.681 + // nsIPrintSettings::kUseInternalDefault 1.682 + // nsIPrintSettings::kUseSettingWhenPossible 1.683 + // 1.684 + // NOTE: The consts are the same for PrintSettings and PrintSettings 1.685 + int16_t printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible; 1.686 + mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage); 1.687 + 1.688 + // Ok, see if we are going to use our value and override the default 1.689 + if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) { 1.690 + // Get the Print Options/Settings PrintFrameType to see what is preferred 1.691 + int16_t printFrameType = nsIPrintSettings::kEachFrameSep; 1.692 + mPrt->mPrintSettings->GetPrintFrameType(&printFrameType); 1.693 + 1.694 + // Don't let anybody do something stupid like try to set it to 1.695 + // kNoFrames when we are printing a FrameSet 1.696 + if (printFrameType == nsIPrintSettings::kNoFrames) { 1.697 + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; 1.698 + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); 1.699 + } else { 1.700 + // First find out from the PrinService what options are available 1.701 + // to us for Printing FrameSets 1.702 + int16_t howToEnableFrameUI; 1.703 + mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); 1.704 + if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) { 1.705 + switch (howToEnableFrameUI) { 1.706 + case nsIPrintSettings::kFrameEnableAll: 1.707 + mPrt->mPrintFrameType = printFrameType; 1.708 + break; 1.709 + 1.710 + case nsIPrintSettings::kFrameEnableAsIsAndEach: 1.711 + if (printFrameType != nsIPrintSettings::kSelectedFrame) { 1.712 + mPrt->mPrintFrameType = printFrameType; 1.713 + } else { // revert back to a good value 1.714 + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; 1.715 + } 1.716 + break; 1.717 + } // switch 1.718 + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); 1.719 + } 1.720 + } 1.721 + } else { 1.722 + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); 1.723 + } 1.724 + } 1.725 + 1.726 + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { 1.727 + CheckForChildFrameSets(mPrt->mPrintObject); 1.728 + } 1.729 + 1.730 + if (NS_FAILED(EnablePOsForPrinting())) { 1.731 + return NS_ERROR_FAILURE; 1.732 + } 1.733 + 1.734 + // Attach progressListener to catch network requests. 1.735 + nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell); 1.736 + webProgress->AddProgressListener( 1.737 + static_cast<nsIWebProgressListener*>(this), 1.738 + nsIWebProgress::NOTIFY_STATE_REQUEST); 1.739 + 1.740 + mLoadCounter = 0; 1.741 + mDidLoadDataForPrinting = false; 1.742 + 1.743 + if (aIsPrintPreview) { 1.744 + bool notifyOnInit = false; 1.745 + ShowPrintProgress(false, notifyOnInit); 1.746 + 1.747 + // Very important! Turn Off scripting 1.748 + TurnScriptingOn(false); 1.749 + 1.750 + if (!notifyOnInit) { 1.751 + InstallPrintPreviewListener(); 1.752 + rv = InitPrintDocConstruction(false); 1.753 + } else { 1.754 + rv = NS_OK; 1.755 + } 1.756 + } else { 1.757 + bool doNotify; 1.758 + ShowPrintProgress(true, doNotify); 1.759 + if (!doNotify) { 1.760 + // Print listener setup... 1.761 + mPrt->OnStartPrinting(); 1.762 + 1.763 + rv = InitPrintDocConstruction(false); 1.764 + } 1.765 + } 1.766 + 1.767 + // We will enable scripting later after printing has finished. 1.768 + scriptSuppressor.Disconnect(); 1.769 + 1.770 + return NS_OK; 1.771 +} 1.772 + 1.773 +//--------------------------------------------------------------------------------- 1.774 +NS_IMETHODIMP 1.775 +nsPrintEngine::Print(nsIPrintSettings* aPrintSettings, 1.776 + nsIWebProgressListener* aWebProgressListener) 1.777 +{ 1.778 + // If we have a print preview document, use that instead of the original 1.779 + // mDocument. That way animated images etc. get printed using the same state 1.780 + // as in print preview. 1.781 + nsCOMPtr<nsIDOMDocument> doc = 1.782 + do_QueryInterface(mPrtPreview && mPrtPreview->mPrintObject ? 1.783 + mPrtPreview->mPrintObject->mDocument : mDocument); 1.784 + 1.785 + return CommonPrint(false, aPrintSettings, aWebProgressListener, doc); 1.786 +} 1.787 + 1.788 +NS_IMETHODIMP 1.789 +nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings, 1.790 + nsIDOMWindow *aChildDOMWin, 1.791 + nsIWebProgressListener* aWebProgressListener) 1.792 +{ 1.793 + // Get the DocShell and see if it is busy 1.794 + // (We can't Print Preview this document if it is still busy) 1.795 + nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer)); 1.796 + NS_ENSURE_STATE(docShell); 1.797 + 1.798 + uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE; 1.799 + if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || 1.800 + busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { 1.801 + CloseProgressDialog(aWebProgressListener); 1.802 + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY, false); 1.803 + return NS_ERROR_FAILURE; 1.804 + } 1.805 + 1.806 + NS_ENSURE_STATE(aChildDOMWin); 1.807 + nsCOMPtr<nsIDOMDocument> doc; 1.808 + aChildDOMWin->GetDocument(getter_AddRefs(doc)); 1.809 + NS_ENSURE_STATE(doc); 1.810 + 1.811 + // Document is not busy -- go ahead with the Print Preview 1.812 + return CommonPrint(true, aPrintSettings, aWebProgressListener, doc); 1.813 +} 1.814 + 1.815 +//---------------------------------------------------------------------------------- 1.816 +/* readonly attribute boolean isFramesetDocument; */ 1.817 +NS_IMETHODIMP 1.818 +nsPrintEngine::GetIsFramesetDocument(bool *aIsFramesetDocument) 1.819 +{ 1.820 + nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer)); 1.821 + *aIsFramesetDocument = IsParentAFrameSet(webContainer); 1.822 + return NS_OK; 1.823 +} 1.824 + 1.825 +//---------------------------------------------------------------------------------- 1.826 +/* readonly attribute boolean isIFrameSelected; */ 1.827 +NS_IMETHODIMP 1.828 +nsPrintEngine::GetIsIFrameSelected(bool *aIsIFrameSelected) 1.829 +{ 1.830 + *aIsIFrameSelected = false; 1.831 + 1.832 + // Get the docshell for this documentviewer 1.833 + nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer)); 1.834 + // Get the currently focused window 1.835 + nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow(); 1.836 + if (currentFocusWin && webContainer) { 1.837 + // Get whether the doc contains a frameset 1.838 + // Also, check to see if the currently focus docshell 1.839 + // is a child of this docshell 1.840 + bool isParentFrameSet; 1.841 + *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet); 1.842 + } 1.843 + return NS_OK; 1.844 +} 1.845 + 1.846 +//---------------------------------------------------------------------------------- 1.847 +/* readonly attribute boolean isRangeSelection; */ 1.848 +NS_IMETHODIMP 1.849 +nsPrintEngine::GetIsRangeSelection(bool *aIsRangeSelection) 1.850 +{ 1.851 + // Get the currently focused window 1.852 + nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow(); 1.853 + *aIsRangeSelection = IsThereARangeSelection(currentFocusWin); 1.854 + return NS_OK; 1.855 +} 1.856 + 1.857 +//---------------------------------------------------------------------------------- 1.858 +/* readonly attribute boolean isFramesetFrameSelected; */ 1.859 +NS_IMETHODIMP 1.860 +nsPrintEngine::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected) 1.861 +{ 1.862 + // Get the currently focused window 1.863 + nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow(); 1.864 + *aIsFramesetFrameSelected = currentFocusWin != nullptr; 1.865 + return NS_OK; 1.866 +} 1.867 + 1.868 +//---------------------------------------------------------------------------------- 1.869 +/* readonly attribute long printPreviewNumPages; */ 1.870 +NS_IMETHODIMP 1.871 +nsPrintEngine::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages) 1.872 +{ 1.873 + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); 1.874 + 1.875 + nsPrintData* prt = nullptr; 1.876 + nsIFrame* seqFrame = nullptr; 1.877 + *aPrintPreviewNumPages = 0; 1.878 + 1.879 + // When calling this function, the FinishPrintPreview() function might not 1.880 + // been called as there are still some 1.881 + if (mPrtPreview) { 1.882 + prt = mPrtPreview; 1.883 + } else { 1.884 + prt = mPrt; 1.885 + } 1.886 + if ((!prt) || 1.887 + NS_FAILED(GetSeqFrameAndCountPagesInternal(prt->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { 1.888 + return NS_ERROR_FAILURE; 1.889 + } 1.890 + return NS_OK; 1.891 +} 1.892 + 1.893 +//---------------------------------------------------------------------------------- 1.894 +// Enumerate all the documents for their titles 1.895 +NS_IMETHODIMP 1.896 +nsPrintEngine::EnumerateDocumentNames(uint32_t* aCount, 1.897 + char16_t*** aResult) 1.898 +{ 1.899 + NS_ENSURE_ARG(aCount); 1.900 + NS_ENSURE_ARG_POINTER(aResult); 1.901 + 1.902 + *aCount = 0; 1.903 + *aResult = nullptr; 1.904 + 1.905 + int32_t numDocs = mPrt->mPrintDocList.Length(); 1.906 + char16_t** array = (char16_t**) nsMemory::Alloc(numDocs * sizeof(char16_t*)); 1.907 + if (!array) 1.908 + return NS_ERROR_OUT_OF_MEMORY; 1.909 + 1.910 + for (int32_t i=0;i<numDocs;i++) { 1.911 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.912 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.913 + nsAutoString docTitleStr; 1.914 + nsAutoString docURLStr; 1.915 + GetDocumentTitleAndURL(po->mDocument, docTitleStr, docURLStr); 1.916 + 1.917 + // Use the URL if the doc is empty 1.918 + if (docTitleStr.IsEmpty() && !docURLStr.IsEmpty()) { 1.919 + docTitleStr = docURLStr; 1.920 + } 1.921 + array[i] = ToNewUnicode(docTitleStr); 1.922 + } 1.923 + *aCount = numDocs; 1.924 + *aResult = array; 1.925 + 1.926 + return NS_OK; 1.927 + 1.928 +} 1.929 + 1.930 +//---------------------------------------------------------------------------------- 1.931 +/* readonly attribute nsIPrintSettings globalPrintSettings; */ 1.932 +nsresult 1.933 +nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings) 1.934 +{ 1.935 + NS_ENSURE_ARG_POINTER(aGlobalPrintSettings); 1.936 + 1.937 + nsresult rv = NS_ERROR_FAILURE; 1.938 + nsCOMPtr<nsIPrintSettingsService> printSettingsService = 1.939 + do_GetService(sPrintSettingsServiceContractID, &rv); 1.940 + if (NS_SUCCEEDED(rv)) { 1.941 + rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings); 1.942 + } 1.943 + return rv; 1.944 +} 1.945 + 1.946 +//---------------------------------------------------------------------------------- 1.947 +/* readonly attribute boolean doingPrint; */ 1.948 +NS_IMETHODIMP 1.949 +nsPrintEngine::GetDoingPrint(bool *aDoingPrint) 1.950 +{ 1.951 + NS_ENSURE_ARG_POINTER(aDoingPrint); 1.952 + *aDoingPrint = mIsDoingPrinting; 1.953 + return NS_OK; 1.954 +} 1.955 + 1.956 +//---------------------------------------------------------------------------------- 1.957 +/* readonly attribute boolean doingPrintPreview; */ 1.958 +NS_IMETHODIMP 1.959 +nsPrintEngine::GetDoingPrintPreview(bool *aDoingPrintPreview) 1.960 +{ 1.961 + NS_ENSURE_ARG_POINTER(aDoingPrintPreview); 1.962 + *aDoingPrintPreview = mIsDoingPrintPreview; 1.963 + return NS_OK; 1.964 +} 1.965 + 1.966 +//---------------------------------------------------------------------------------- 1.967 +/* readonly attribute nsIPrintSettings currentPrintSettings; */ 1.968 +NS_IMETHODIMP 1.969 +nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) 1.970 +{ 1.971 + NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); 1.972 + 1.973 + if (mPrt) { 1.974 + *aCurrentPrintSettings = mPrt->mPrintSettings; 1.975 + 1.976 + } else if (mPrtPreview) { 1.977 + *aCurrentPrintSettings = mPrtPreview->mPrintSettings; 1.978 + 1.979 + } else { 1.980 + *aCurrentPrintSettings = nullptr; 1.981 + } 1.982 + NS_IF_ADDREF(*aCurrentPrintSettings); 1.983 + return NS_OK; 1.984 +} 1.985 + 1.986 +//----------------------------------------------------------------- 1.987 +//-- Section: Pre-Reflow Methods 1.988 +//----------------------------------------------------------------- 1.989 + 1.990 +//--------------------------------------------------------------------- 1.991 +// This method checks to see if there is at least one printer defined 1.992 +// and if so, it sets the first printer in the list as the default name 1.993 +// in the PrintSettings which is then used for Printer Preview 1.994 +nsresult 1.995 +nsPrintEngine::CheckForPrinters(nsIPrintSettings* aPrintSettings) 1.996 +{ 1.997 +#if defined(XP_MACOSX) || defined(ANDROID) 1.998 + // Mac doesn't support retrieving a printer list. 1.999 + return NS_OK; 1.1000 +#else 1.1001 + NS_ENSURE_ARG_POINTER(aPrintSettings); 1.1002 + 1.1003 + // See if aPrintSettings already has a printer 1.1004 + nsXPIDLString printerName; 1.1005 + nsresult rv = aPrintSettings->GetPrinterName(getter_Copies(printerName)); 1.1006 + if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) { 1.1007 + return NS_OK; 1.1008 + } 1.1009 + 1.1010 + // aPrintSettings doesn't have a printer set. Try to fetch the default. 1.1011 + nsCOMPtr<nsIPrintSettingsService> printSettingsService = 1.1012 + do_GetService(sPrintSettingsServiceContractID, &rv); 1.1013 + NS_ENSURE_SUCCESS(rv, rv); 1.1014 + 1.1015 + rv = printSettingsService->GetDefaultPrinterName(getter_Copies(printerName)); 1.1016 + if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) { 1.1017 + rv = aPrintSettings->SetPrinterName(printerName.get()); 1.1018 + } 1.1019 + return rv; 1.1020 +#endif 1.1021 +} 1.1022 + 1.1023 +//---------------------------------------------------------------------- 1.1024 +// Set up to use the "pluggable" Print Progress Dialog 1.1025 +void 1.1026 +nsPrintEngine::ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify) 1.1027 +{ 1.1028 + // default to not notifying, that if something here goes wrong 1.1029 + // or we aren't going to show the progress dialog we can straight into 1.1030 + // reflowing the doc for printing. 1.1031 + aDoNotify = false; 1.1032 + 1.1033 + // Assume we can't do progress and then see if we can 1.1034 + bool showProgresssDialog = false; 1.1035 + 1.1036 + // if it is already being shown then don't bother to find out if it should be 1.1037 + // so skip this and leave mShowProgressDialog set to FALSE 1.1038 + if (!mProgressDialogIsShown) { 1.1039 + showProgresssDialog = Preferences::GetBool("print.show_print_progress"); 1.1040 + } 1.1041 + 1.1042 + // Turning off the showing of Print Progress in Prefs overrides 1.1043 + // whether the calling PS desire to have it on or off, so only check PS if 1.1044 + // prefs says it's ok to be on. 1.1045 + if (showProgresssDialog) { 1.1046 + mPrt->mPrintSettings->GetShowPrintProgress(&showProgresssDialog); 1.1047 + } 1.1048 + 1.1049 + // Now open the service to get the progress dialog 1.1050 + // If we don't get a service, that's ok, then just don't show progress 1.1051 + if (showProgresssDialog) { 1.1052 + nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService)); 1.1053 + if (printPromptService) { 1.1054 + nsPIDOMWindow *domWin = mDocument->GetWindow(); 1.1055 + if (!domWin) return; 1.1056 + 1.1057 + nsCOMPtr<nsIDocShell> docShell = domWin->GetDocShell(); 1.1058 + if (!docShell) return; 1.1059 + nsCOMPtr<nsIDocShellTreeOwner> owner; 1.1060 + docShell->GetTreeOwner(getter_AddRefs(owner)); 1.1061 + nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(owner); 1.1062 + if (!browserChrome) return; 1.1063 + bool isModal = true; 1.1064 + browserChrome->IsWindowModal(&isModal); 1.1065 + if (isModal) { 1.1066 + // Showing a print progress dialog when printing a modal window 1.1067 + // isn't supported. See bug 301560. 1.1068 + return; 1.1069 + } 1.1070 + 1.1071 + nsCOMPtr<nsIWebProgressListener> printProgressListener; 1.1072 + 1.1073 + nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint)); 1.1074 + nsresult rv = printPromptService->ShowProgress(domWin, wbp, mPrt->mPrintSettings, this, aIsForPrinting, 1.1075 + getter_AddRefs(printProgressListener), 1.1076 + getter_AddRefs(mPrt->mPrintProgressParams), 1.1077 + &aDoNotify); 1.1078 + if (NS_SUCCEEDED(rv)) { 1.1079 + if (printProgressListener && mPrt->mPrintProgressParams) { 1.1080 + mPrt->mPrintProgressListeners.AppendObject(printProgressListener); 1.1081 + SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams); 1.1082 + } 1.1083 + } 1.1084 + } 1.1085 + } 1.1086 +} 1.1087 + 1.1088 +//--------------------------------------------------------------------- 1.1089 +bool 1.1090 +nsPrintEngine::IsThereARangeSelection(nsIDOMWindow* aDOMWin) 1.1091 +{ 1.1092 + if (mDisallowSelectionPrint) 1.1093 + return false; 1.1094 + 1.1095 + nsCOMPtr<nsIPresShell> presShell; 1.1096 + if (aDOMWin) { 1.1097 + nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aDOMWin)); 1.1098 + presShell = window->GetDocShell()->GetPresShell(); 1.1099 + } 1.1100 + 1.1101 + if (!presShell) 1.1102 + return false; 1.1103 + 1.1104 + // check here to see if there is a range selection 1.1105 + // so we know whether to turn on the "Selection" radio button 1.1106 + Selection* selection = 1.1107 + presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.1108 + if (!selection) { 1.1109 + return false; 1.1110 + } 1.1111 + 1.1112 + int32_t rangeCount = selection->GetRangeCount(); 1.1113 + if (!rangeCount) { 1.1114 + return false; 1.1115 + } 1.1116 + 1.1117 + if (rangeCount > 1) { 1.1118 + return true; 1.1119 + } 1.1120 + 1.1121 + // check to make sure it isn't an insertion selection 1.1122 + return selection->GetRangeAt(0) && !selection->IsCollapsed(); 1.1123 +} 1.1124 + 1.1125 +//--------------------------------------------------------------------- 1.1126 +bool 1.1127 +nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent) 1.1128 +{ 1.1129 + // See if the incoming doc is the root document 1.1130 + if (!aParent) return false; 1.1131 + 1.1132 + // When it is the top level document we need to check 1.1133 + // to see if it contains a frameset. If it does, then 1.1134 + // we only want to print the doc's children and not the document itself 1.1135 + // For anything else we always print all the children and the document 1.1136 + // for example, if the doc contains an IFRAME we eant to print the child 1.1137 + // document (the IFRAME) and then the rest of the document. 1.1138 + // 1.1139 + // XXX we really need to search the frame tree, and not the content 1.1140 + // but there is no way to distinguish between IFRAMEs and FRAMEs 1.1141 + // with the GetFrameType call. 1.1142 + // Bug 53459 has been files so we can eventually distinguish 1.1143 + // between IFRAME frames and FRAME frames 1.1144 + bool isFrameSet = false; 1.1145 + // only check to see if there is a frameset if there is 1.1146 + // NO parent doc for this doc. meaning this parent is the root doc 1.1147 + nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(aParent); 1.1148 + nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); 1.1149 + if (doc) { 1.1150 + nsIContent *rootElement = doc->GetRootElement(); 1.1151 + if (rootElement) { 1.1152 + isFrameSet = HasFramesetChild(rootElement); 1.1153 + } 1.1154 + } 1.1155 + return isFrameSet; 1.1156 +} 1.1157 + 1.1158 + 1.1159 +//--------------------------------------------------------------------- 1.1160 +// Recursively build a list of sub documents to be printed 1.1161 +// that mirrors the document tree 1.1162 +void 1.1163 +nsPrintEngine::BuildDocTree(nsIDocShell * aParentNode, 1.1164 + nsTArray<nsPrintObject*> * aDocList, 1.1165 + nsPrintObject * aPO) 1.1166 +{ 1.1167 + NS_ASSERTION(aParentNode, "Pointer is null!"); 1.1168 + NS_ASSERTION(aDocList, "Pointer is null!"); 1.1169 + NS_ASSERTION(aPO, "Pointer is null!"); 1.1170 + 1.1171 + int32_t childWebshellCount; 1.1172 + aParentNode->GetChildCount(&childWebshellCount); 1.1173 + if (childWebshellCount > 0) { 1.1174 + for (int32_t i=0;i<childWebshellCount;i++) { 1.1175 + nsCOMPtr<nsIDocShellTreeItem> child; 1.1176 + aParentNode->GetChildAt(i, getter_AddRefs(child)); 1.1177 + nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child)); 1.1178 + 1.1179 + nsCOMPtr<nsIContentViewer> viewer; 1.1180 + childAsShell->GetContentViewer(getter_AddRefs(viewer)); 1.1181 + if (viewer) { 1.1182 + nsCOMPtr<nsIContentViewerFile> viewerFile(do_QueryInterface(viewer)); 1.1183 + if (viewerFile) { 1.1184 + nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(childAsShell); 1.1185 + nsPrintObject * po = new nsPrintObject(); 1.1186 + po->mParent = aPO; 1.1187 + nsresult rv = po->Init(childAsShell, doc, aPO->mPrintPreview); 1.1188 + if (NS_FAILED(rv)) 1.1189 + NS_NOTREACHED("Init failed?"); 1.1190 + aPO->mKids.AppendElement(po); 1.1191 + aDocList->AppendElement(po); 1.1192 + BuildDocTree(childAsShell, aDocList, po); 1.1193 + } 1.1194 + } 1.1195 + } 1.1196 + } 1.1197 +} 1.1198 + 1.1199 +//--------------------------------------------------------------------- 1.1200 +void 1.1201 +nsPrintEngine::GetDocumentTitleAndURL(nsIDocument* aDoc, 1.1202 + nsAString& aTitle, 1.1203 + nsAString& aURLStr) 1.1204 +{ 1.1205 + NS_ASSERTION(aDoc, "Pointer is null!"); 1.1206 + 1.1207 + aTitle.Truncate(); 1.1208 + aURLStr.Truncate(); 1.1209 + 1.1210 + nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDoc); 1.1211 + doc->GetTitle(aTitle); 1.1212 + 1.1213 + nsIURI* url = aDoc->GetDocumentURI(); 1.1214 + if (!url) return; 1.1215 + 1.1216 + nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID)); 1.1217 + if (!urifixup) return; 1.1218 + 1.1219 + nsCOMPtr<nsIURI> exposableURI; 1.1220 + urifixup->CreateExposableURI(url, getter_AddRefs(exposableURI)); 1.1221 + 1.1222 + if (!exposableURI) return; 1.1223 + 1.1224 + nsAutoCString urlCStr; 1.1225 + exposableURI->GetSpec(urlCStr); 1.1226 + 1.1227 + nsresult rv; 1.1228 + nsCOMPtr<nsITextToSubURI> textToSubURI = 1.1229 + do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv); 1.1230 + if (NS_FAILED(rv)) return; 1.1231 + 1.1232 + textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"), 1.1233 + urlCStr, aURLStr); 1.1234 +} 1.1235 + 1.1236 +//--------------------------------------------------------------------- 1.1237 +// The walks the PO tree and for each document it walks the content 1.1238 +// tree looking for any content that are sub-shells 1.1239 +// 1.1240 +// It then sets the mContent pointer in the "found" PO object back to the 1.1241 +// the document that contained it. 1.1242 +void 1.1243 +nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO, 1.1244 + nsPrintObject* aPO) 1.1245 +{ 1.1246 + NS_ASSERTION(aRootPO, "Pointer is null!"); 1.1247 + NS_ASSERTION(aPO, "Pointer is null!"); 1.1248 + 1.1249 + // Recursively walk the content from the root item 1.1250 + // XXX Would be faster to enumerate the subdocuments, although right now 1.1251 + // nsIDocument doesn't expose quite what would be needed. 1.1252 + nsCOMPtr<nsIContentViewer> viewer; 1.1253 + aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer)); 1.1254 + if (!viewer) return; 1.1255 + 1.1256 + nsCOMPtr<nsIDOMDocument> domDoc; 1.1257 + viewer->GetDOMDocument(getter_AddRefs(domDoc)); 1.1258 + nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); 1.1259 + if (!doc) return; 1.1260 + 1.1261 + Element* rootElement = doc->GetRootElement(); 1.1262 + if (rootElement) { 1.1263 + MapContentForPO(aPO, rootElement); 1.1264 + } else { 1.1265 + NS_WARNING("Null root content on (sub)document."); 1.1266 + } 1.1267 + 1.1268 + // Continue recursively walking the chilren of this PO 1.1269 + for (uint32_t i=0;i<aPO->mKids.Length();i++) { 1.1270 + MapContentToWebShells(aRootPO, aPO->mKids[i]); 1.1271 + } 1.1272 + 1.1273 +} 1.1274 + 1.1275 +//------------------------------------------------------- 1.1276 +// A Frame's sub-doc may contain content or a FrameSet 1.1277 +// When it contains a FrameSet the mFrameType for the PrintObject 1.1278 +// is always set to an eFrame. Which is fine when printing "AsIs" 1.1279 +// but is incorrect when when printing "Each Frame Separately". 1.1280 +// When printing "Each Frame Separately" the Frame really acts like 1.1281 +// a frameset. 1.1282 +// 1.1283 +// This method walks the PO tree and checks to see if the PrintObject is 1.1284 +// an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet) 1.1285 +// If so, then the mFrameType need to be changed to eFrameSet 1.1286 +// 1.1287 +// Also note: We only want to call this we are printing "Each Frame Separately" 1.1288 +// when printing "As Is" leave it as an eFrame 1.1289 +void 1.1290 +nsPrintEngine::CheckForChildFrameSets(nsPrintObject* aPO) 1.1291 +{ 1.1292 + NS_ASSERTION(aPO, "Pointer is null!"); 1.1293 + 1.1294 + // Continue recursively walking the chilren of this PO 1.1295 + bool hasChildFrames = false; 1.1296 + for (uint32_t i=0;i<aPO->mKids.Length();i++) { 1.1297 + nsPrintObject* po = aPO->mKids[i]; 1.1298 + if (po->mFrameType == eFrame) { 1.1299 + hasChildFrames = true; 1.1300 + CheckForChildFrameSets(po); 1.1301 + } 1.1302 + } 1.1303 + 1.1304 + if (hasChildFrames && aPO->mFrameType == eFrame) { 1.1305 + aPO->mFrameType = eFrameSet; 1.1306 + } 1.1307 +} 1.1308 + 1.1309 +//--------------------------------------------------------------------- 1.1310 +// This method is key to the entire print mechanism. 1.1311 +// 1.1312 +// This "maps" or figures out which sub-doc represents a 1.1313 +// given Frame or IFrame in its parent sub-doc. 1.1314 +// 1.1315 +// So the Mcontent pointer in the child sub-doc points to the 1.1316 +// content in the its parent document, that caused it to be printed. 1.1317 +// This is used later to (after reflow) to find the absolute location 1.1318 +// of the sub-doc on its parent's page frame so it can be 1.1319 +// printed in the correct location. 1.1320 +// 1.1321 +// This method recursvely "walks" the content for a document finding 1.1322 +// all the Frames and IFrames, then sets the "mFrameType" data member 1.1323 +// which tells us what type of PO we have 1.1324 +void 1.1325 +nsPrintEngine::MapContentForPO(nsPrintObject* aPO, 1.1326 + nsIContent* aContent) 1.1327 +{ 1.1328 + NS_PRECONDITION(aPO && aContent, "Null argument"); 1.1329 + 1.1330 + nsIDocument* doc = aContent->GetDocument(); 1.1331 + 1.1332 + NS_ASSERTION(doc, "Content without a document from a document tree?"); 1.1333 + 1.1334 + nsIDocument* subDoc = doc->GetSubDocumentFor(aContent); 1.1335 + 1.1336 + if (subDoc) { 1.1337 + nsCOMPtr<nsIDocShell> docShell(subDoc->GetDocShell()); 1.1338 + 1.1339 + if (docShell) { 1.1340 + nsPrintObject * po = nullptr; 1.1341 + int32_t cnt = aPO->mKids.Length(); 1.1342 + for (int32_t i=0;i<cnt;i++) { 1.1343 + nsPrintObject* kid = aPO->mKids.ElementAt(i); 1.1344 + if (kid->mDocument == subDoc) { 1.1345 + po = kid; 1.1346 + break; 1.1347 + } 1.1348 + } 1.1349 + 1.1350 + // XXX If a subdocument has no onscreen presentation, there will be no PO 1.1351 + // This is even if there should be a print presentation 1.1352 + if (po) { 1.1353 + 1.1354 + nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent)); 1.1355 + // "frame" elements not in a frameset context should be treated 1.1356 + // as iframes 1.1357 + if (frame && po->mParent->mFrameType == eFrameSet) { 1.1358 + po->mFrameType = eFrame; 1.1359 + } else { 1.1360 + // Assume something iframe-like, i.e. iframe, object, or embed 1.1361 + po->mFrameType = eIFrame; 1.1362 + SetPrintAsIs(po, true); 1.1363 + NS_ASSERTION(po->mParent, "The root must be a parent"); 1.1364 + po->mParent->mPrintAsIs = true; 1.1365 + } 1.1366 + } 1.1367 + } 1.1368 + } 1.1369 + 1.1370 + // walk children content 1.1371 + for (nsIContent* child = aContent->GetFirstChild(); 1.1372 + child; 1.1373 + child = child->GetNextSibling()) { 1.1374 + MapContentForPO(aPO, child); 1.1375 + } 1.1376 +} 1.1377 + 1.1378 +//--------------------------------------------------------------------- 1.1379 +bool 1.1380 +nsPrintEngine::IsThereAnIFrameSelected(nsIDocShell* aDocShell, 1.1381 + nsIDOMWindow* aDOMWin, 1.1382 + bool& aIsParentFrameSet) 1.1383 +{ 1.1384 + aIsParentFrameSet = IsParentAFrameSet(aDocShell); 1.1385 + bool iFrameIsSelected = false; 1.1386 + if (mPrt && mPrt->mPrintObject) { 1.1387 + nsPrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin); 1.1388 + iFrameIsSelected = po && po->mFrameType == eIFrame; 1.1389 + } else { 1.1390 + // First, check to see if we are a frameset 1.1391 + if (!aIsParentFrameSet) { 1.1392 + // Check to see if there is a currenlt focused frame 1.1393 + // if so, it means the selected frame is either the main docshell 1.1394 + // or an IFRAME 1.1395 + if (aDOMWin) { 1.1396 + // Get the main docshell's DOMWin to see if it matches 1.1397 + // the frame that is selected 1.1398 + nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(aDocShell); 1.1399 + if (domWin != aDOMWin) { 1.1400 + iFrameIsSelected = true; // we have a selected IFRAME 1.1401 + } 1.1402 + } 1.1403 + } 1.1404 + } 1.1405 + 1.1406 + return iFrameIsSelected; 1.1407 +} 1.1408 + 1.1409 +//--------------------------------------------------------------------- 1.1410 +// Recursively sets all the PO items to be printed 1.1411 +// from the given item down into the tree 1.1412 +void 1.1413 +nsPrintEngine::SetPrintPO(nsPrintObject* aPO, bool aPrint) 1.1414 +{ 1.1415 + NS_ASSERTION(aPO, "Pointer is null!"); 1.1416 + 1.1417 + // Set whether to print flag 1.1418 + aPO->mDontPrint = !aPrint; 1.1419 + 1.1420 + for (uint32_t i=0;i<aPO->mKids.Length();i++) { 1.1421 + SetPrintPO(aPO->mKids[i], aPrint); 1.1422 + } 1.1423 +} 1.1424 + 1.1425 +//--------------------------------------------------------------------- 1.1426 +// This will first use a Title and/or URL from the PrintSettings 1.1427 +// if one isn't set then it uses the one from the document 1.1428 +// then if not title is there we will make sure we send something back 1.1429 +// depending on the situation. 1.1430 +void 1.1431 +nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject* aPO, 1.1432 + nsAString& aTitle, 1.1433 + nsAString& aURLStr, 1.1434 + eDocTitleDefault aDefType) 1.1435 +{ 1.1436 + NS_ASSERTION(aPO, "Pointer is null!"); 1.1437 + 1.1438 + if (!mPrt) 1.1439 + return; 1.1440 + 1.1441 + aTitle.Truncate(); 1.1442 + aURLStr.Truncate(); 1.1443 + 1.1444 + // First check to see if the PrintSettings has defined an alternate title 1.1445 + // and use that if it did 1.1446 + if (mPrt->mPrintSettings) { 1.1447 + char16_t * docTitleStrPS = nullptr; 1.1448 + char16_t * docURLStrPS = nullptr; 1.1449 + mPrt->mPrintSettings->GetTitle(&docTitleStrPS); 1.1450 + mPrt->mPrintSettings->GetDocURL(&docURLStrPS); 1.1451 + 1.1452 + if (docTitleStrPS) { 1.1453 + aTitle = docTitleStrPS; 1.1454 + } 1.1455 + 1.1456 + if (docURLStrPS) { 1.1457 + aURLStr = docURLStrPS; 1.1458 + } 1.1459 + 1.1460 + nsMemory::Free(docTitleStrPS); 1.1461 + nsMemory::Free(docURLStrPS); 1.1462 + } 1.1463 + 1.1464 + nsAutoString docTitle; 1.1465 + nsAutoString docUrl; 1.1466 + GetDocumentTitleAndURL(aPO->mDocument, docTitle, docUrl); 1.1467 + 1.1468 + if (aURLStr.IsEmpty() && !docUrl.IsEmpty()) { 1.1469 + aURLStr = docUrl; 1.1470 + } 1.1471 + 1.1472 + if (aTitle.IsEmpty()) { 1.1473 + if (!docTitle.IsEmpty()) { 1.1474 + aTitle = docTitle; 1.1475 + } else { 1.1476 + if (aDefType == eDocTitleDefURLDoc) { 1.1477 + if (!aURLStr.IsEmpty()) { 1.1478 + aTitle = aURLStr; 1.1479 + } else if (mPrt->mBrandName) { 1.1480 + aTitle = mPrt->mBrandName; 1.1481 + } 1.1482 + } 1.1483 + } 1.1484 + } 1.1485 +} 1.1486 + 1.1487 +//--------------------------------------------------------------------- 1.1488 +nsresult nsPrintEngine::DocumentReadyForPrinting() 1.1489 +{ 1.1490 + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { 1.1491 + CheckForChildFrameSets(mPrt->mPrintObject); 1.1492 + } 1.1493 + 1.1494 + // 1.1495 + // Send the document to the printer... 1.1496 + // 1.1497 + nsresult rv = SetupToPrintContent(); 1.1498 + if (NS_FAILED(rv)) { 1.1499 + // The print job was canceled or there was a problem 1.1500 + // So remove all other documents from the print list 1.1501 + DonePrintingPages(nullptr, rv); 1.1502 + } 1.1503 + return rv; 1.1504 +} 1.1505 + 1.1506 +/** --------------------------------------------------- 1.1507 + * Cleans up when an error occurred 1.1508 + */ 1.1509 +nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, bool aIsPrinting) 1.1510 +{ 1.1511 + PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting?"Printing":"Print Preview", aResult)); 1.1512 + 1.1513 + /* cleanup... */ 1.1514 + if (mPagePrintTimer) { 1.1515 + mPagePrintTimer->Stop(); 1.1516 + NS_RELEASE(mPagePrintTimer); 1.1517 + } 1.1518 + 1.1519 + if (aIsPrinting) { 1.1520 + SetIsPrinting(false); 1.1521 + } else { 1.1522 + SetIsPrintPreview(false); 1.1523 + SetIsCreatingPrintPreview(false); 1.1524 + } 1.1525 + 1.1526 + /* cleanup done, let's fire-up an error dialog to notify the user 1.1527 + * what went wrong... 1.1528 + * 1.1529 + * When rv == NS_ERROR_ABORT, it means we want out of the 1.1530 + * print job without displaying any error messages 1.1531 + */ 1.1532 + if (aResult != NS_ERROR_ABORT) { 1.1533 + ShowPrintErrorDialog(aResult, aIsPrinting); 1.1534 + } 1.1535 + 1.1536 + FirePrintCompletionEvent(); 1.1537 + 1.1538 + return aResult; 1.1539 + 1.1540 +} 1.1541 + 1.1542 +//--------------------------------------------------------------------- 1.1543 +void 1.1544 +nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, bool aIsPrinting) 1.1545 +{ 1.1546 + nsAutoCString stringName; 1.1547 + nsXPIDLString msg, title; 1.1548 + nsresult rv = NS_OK; 1.1549 + 1.1550 + switch(aPrintError) 1.1551 + { 1.1552 +#define ENTITY_FOR_ERROR(label) \ 1.1553 + case NS_ERROR_##label: stringName.AssignLiteral("PERR_" #label); break 1.1554 + 1.1555 + ENTITY_FOR_ERROR(GFX_PRINTER_NO_PRINTER_AVAILABLE); 1.1556 + ENTITY_FOR_ERROR(GFX_PRINTER_NAME_NOT_FOUND); 1.1557 + ENTITY_FOR_ERROR(GFX_PRINTER_COULD_NOT_OPEN_FILE); 1.1558 + ENTITY_FOR_ERROR(GFX_PRINTER_STARTDOC); 1.1559 + ENTITY_FOR_ERROR(GFX_PRINTER_ENDDOC); 1.1560 + ENTITY_FOR_ERROR(GFX_PRINTER_STARTPAGE); 1.1561 + ENTITY_FOR_ERROR(GFX_PRINTER_DOC_IS_BUSY); 1.1562 + 1.1563 + ENTITY_FOR_ERROR(ABORT); 1.1564 + ENTITY_FOR_ERROR(NOT_AVAILABLE); 1.1565 + ENTITY_FOR_ERROR(NOT_IMPLEMENTED); 1.1566 + ENTITY_FOR_ERROR(OUT_OF_MEMORY); 1.1567 + ENTITY_FOR_ERROR(UNEXPECTED); 1.1568 + 1.1569 + default: 1.1570 + ENTITY_FOR_ERROR(FAILURE); 1.1571 + 1.1572 +#undef ENTITY_FOR_ERROR 1.1573 + } 1.1574 + 1.1575 + if (!aIsPrinting) { 1.1576 + // Try first with _PP suffix. 1.1577 + stringName.AppendLiteral("_PP"); 1.1578 + rv = nsContentUtils::GetLocalizedString( 1.1579 + nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg); 1.1580 + if (NS_FAILED(rv)) { 1.1581 + stringName.Truncate(stringName.Length() - 3); 1.1582 + } 1.1583 + } 1.1584 + if (aIsPrinting || NS_FAILED(rv)) { 1.1585 + rv = nsContentUtils::GetLocalizedString( 1.1586 + nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg); 1.1587 + } 1.1588 + if (NS_FAILED(rv)) { 1.1589 + return; 1.1590 + } 1.1591 + 1.1592 + rv = nsContentUtils::GetLocalizedString( 1.1593 + nsContentUtils::ePRINTING_PROPERTIES, 1.1594 + aIsPrinting ? "print_error_dialog_title" 1.1595 + : "printpreview_error_dialog_title", 1.1596 + title); 1.1597 + if (NS_FAILED(rv)) { 1.1598 + return; 1.1599 + } 1.1600 + 1.1601 + nsCOMPtr<nsIWindowWatcher> wwatch = 1.1602 + do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); 1.1603 + if (NS_FAILED(rv)) { 1.1604 + return; 1.1605 + } 1.1606 + 1.1607 + nsCOMPtr<nsIDOMWindow> active; 1.1608 + wwatch->GetActiveWindow(getter_AddRefs(active)); 1.1609 + 1.1610 + nsCOMPtr<nsIPrompt> dialog; 1.1611 + /* |GetNewPrompter| allows that |active| is |nullptr| 1.1612 + * (see bug 234982 ("nsPrintEngine::ShowPrintErrorDialog() fails in many cases")) */ 1.1613 + wwatch->GetNewPrompter(active, getter_AddRefs(dialog)); 1.1614 + if (!dialog) { 1.1615 + return; 1.1616 + } 1.1617 + 1.1618 + dialog->Alert(title.get(), msg.get()); 1.1619 +} 1.1620 + 1.1621 +//----------------------------------------------------------------- 1.1622 +//-- Section: Reflow Methods 1.1623 +//----------------------------------------------------------------- 1.1624 + 1.1625 +nsresult 1.1626 +nsPrintEngine::ReconstructAndReflow(bool doSetPixelScale) 1.1627 +{ 1.1628 +#if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING) 1.1629 + // We need to clear all the output files here 1.1630 + // because they will be re-created with second reflow of the docs 1.1631 + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { 1.1632 + RemoveFilesInDir(".\\"); 1.1633 + gDumpFileNameCnt = 0; 1.1634 + gDumpLOFileNameCnt = 0; 1.1635 + } 1.1636 +#endif 1.1637 + 1.1638 + for (uint32_t i = 0; i < mPrt->mPrintDocList.Length(); ++i) { 1.1639 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.1640 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.1641 + 1.1642 + if (po->mDontPrint || po->mInvisible) { 1.1643 + continue; 1.1644 + } 1.1645 + 1.1646 + UpdateZoomRatio(po, doSetPixelScale); 1.1647 + 1.1648 + po->mPresContext->SetPageScale(po->mZoomRatio); 1.1649 + 1.1650 + // Calculate scale factor from printer to screen 1.1651 + float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) / 1.1652 + float(mPrt->mPrintDC->AppUnitsPerDevPixel()); 1.1653 + po->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI); 1.1654 + 1.1655 + po->mPresShell->ReconstructFrames(); 1.1656 + 1.1657 + // For all views except the first one, setup the root view. 1.1658 + // ??? Can there be multiple po for the top-level-document? 1.1659 + bool documentIsTopLevel = true; 1.1660 + if (i != 0) { 1.1661 + nsSize adjSize; 1.1662 + bool doReturn; 1.1663 + nsresult rv = SetRootView(po, doReturn, documentIsTopLevel, adjSize); 1.1664 + 1.1665 + MOZ_ASSERT(!documentIsTopLevel, "How could this happen?"); 1.1666 + 1.1667 + if (NS_FAILED(rv) || doReturn) { 1.1668 + return rv; 1.1669 + } 1.1670 + } 1.1671 + 1.1672 + po->mPresShell->FlushPendingNotifications(Flush_Layout); 1.1673 + 1.1674 + nsresult rv = UpdateSelectionAndShrinkPrintObject(po, documentIsTopLevel); 1.1675 + NS_ENSURE_SUCCESS(rv, rv); 1.1676 + } 1.1677 + return NS_OK; 1.1678 +} 1.1679 + 1.1680 +//------------------------------------------------------- 1.1681 +nsresult 1.1682 +nsPrintEngine::SetupToPrintContent() 1.1683 +{ 1.1684 + nsresult rv; 1.1685 + 1.1686 + bool didReconstruction = false; 1.1687 + 1.1688 + // If some new content got loaded since the initial reflow rebuild 1.1689 + // everything. 1.1690 + if (mDidLoadDataForPrinting) { 1.1691 + rv = ReconstructAndReflow(DoSetPixelScale()); 1.1692 + didReconstruction = true; 1.1693 + NS_ENSURE_SUCCESS(rv, rv); 1.1694 + } 1.1695 + 1.1696 + // Here is where we figure out if extra reflow for shrinking the content 1.1697 + // is required. 1.1698 + // But skip this step if we are in PrintPreview 1.1699 + bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; 1.1700 + if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { 1.1701 + // Now look for the PO that has the smallest percent for shrink to fit 1.1702 + if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { 1.1703 + nsPrintObject* smallestPO = FindSmallestSTF(); 1.1704 + NS_ASSERTION(smallestPO, "There must always be an XMost PO!"); 1.1705 + if (smallestPO) { 1.1706 + // Calc the shrinkage based on the entire content area 1.1707 + mPrt->mShrinkRatio = smallestPO->mShrinkRatio; 1.1708 + } 1.1709 + } else { 1.1710 + // Single document so use the Shrink as calculated for the PO 1.1711 + mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; 1.1712 + } 1.1713 + 1.1714 + if (mPrt->mShrinkRatio < 0.998f) { 1.1715 + rv = ReconstructAndReflow(true); 1.1716 + didReconstruction = true; 1.1717 + NS_ENSURE_SUCCESS(rv, rv); 1.1718 + } 1.1719 + 1.1720 +#ifdef PR_LOGGING 1.1721 + float calcRatio = 0.0f; 1.1722 + if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { 1.1723 + nsPrintObject* smallestPO = FindSmallestSTF(); 1.1724 + NS_ASSERTION(smallestPO, "There must always be an XMost PO!"); 1.1725 + if (smallestPO) { 1.1726 + // Calc the shrinkage based on the entire content area 1.1727 + calcRatio = smallestPO->mShrinkRatio; 1.1728 + } 1.1729 + } else { 1.1730 + // Single document so use the Shrink as calculated for the PO 1.1731 + calcRatio = mPrt->mPrintObject->mShrinkRatio; 1.1732 + } 1.1733 + PR_PL(("**************************************************************************\n")); 1.1734 + PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); 1.1735 + PR_PL(("**************************************************************************\n")); 1.1736 +#endif 1.1737 + } 1.1738 + 1.1739 + // If the frames got reconstructed and reflowed the number of pages might 1.1740 + // has changed. 1.1741 + if (didReconstruction) { 1.1742 + FirePrintPreviewUpdateEvent(); 1.1743 + } 1.1744 + 1.1745 + DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); 1.1746 + PR_PL(("\n")); 1.1747 + PR_PL(("-------------------------------------------------------\n")); 1.1748 + PR_PL(("\n")); 1.1749 + 1.1750 + CalcNumPrintablePages(mPrt->mNumPrintablePages); 1.1751 + 1.1752 + PR_PL(("--- Printing %d pages\n", mPrt->mNumPrintablePages)); 1.1753 + DUMP_DOC_TREELAYOUT; 1.1754 + 1.1755 + // Print listener setup... 1.1756 + if (mPrt != nullptr) { 1.1757 + mPrt->OnStartPrinting(); 1.1758 + } 1.1759 + 1.1760 + char16_t* fileName = nullptr; 1.1761 + // check to see if we are printing to a file 1.1762 + bool isPrintToFile = false; 1.1763 + mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); 1.1764 + if (isPrintToFile) { 1.1765 + // On some platforms The BeginDocument needs to know the name of the file 1.1766 + // and it uses the PrintService to get it, so we need to set it into the PrintService here 1.1767 + mPrt->mPrintSettings->GetToFileName(&fileName); 1.1768 + } 1.1769 + 1.1770 + nsAutoString docTitleStr; 1.1771 + nsAutoString docURLStr; 1.1772 + GetDisplayTitleAndURL(mPrt->mPrintObject, docTitleStr, docURLStr, eDocTitleDefURLDoc); 1.1773 + 1.1774 + int32_t startPage = 1; 1.1775 + int32_t endPage = mPrt->mNumPrintablePages; 1.1776 + 1.1777 + int16_t printRangeType = nsIPrintSettings::kRangeAllPages; 1.1778 + mPrt->mPrintSettings->GetPrintRange(&printRangeType); 1.1779 + if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { 1.1780 + mPrt->mPrintSettings->GetStartPageRange(&startPage); 1.1781 + mPrt->mPrintSettings->GetEndPageRange(&endPage); 1.1782 + if (endPage > mPrt->mNumPrintablePages) { 1.1783 + endPage = mPrt->mNumPrintablePages; 1.1784 + } 1.1785 + } 1.1786 + 1.1787 + rv = NS_OK; 1.1788 + // BeginDocument may pass back a FAILURE code 1.1789 + // i.e. On Windows, if you are printing to a file and hit "Cancel" 1.1790 + // to the "File Name" dialog, this comes back as an error 1.1791 + // Don't start printing when regression test are executed 1.1792 + if (!mPrt->mDebugFilePtr && mIsDoingPrinting) { 1.1793 + rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage); 1.1794 + } 1.1795 + 1.1796 + if (mIsCreatingPrintPreview) { 1.1797 + // Copy docTitleStr and docURLStr to the pageSequenceFrame, to be displayed 1.1798 + // in the header 1.1799 + nsIPageSequenceFrame *seqFrame = mPrt->mPrintObject->mPresShell->GetPageSequenceFrame(); 1.1800 + if (seqFrame) { 1.1801 + seqFrame->StartPrint(mPrt->mPrintObject->mPresContext, 1.1802 + mPrt->mPrintSettings, docTitleStr, docURLStr); 1.1803 + } 1.1804 + } 1.1805 + 1.1806 + PR_PL(("****************** Begin Document ************************\n")); 1.1807 + 1.1808 + NS_ENSURE_SUCCESS(rv, rv); 1.1809 + 1.1810 + // This will print the docshell document 1.1811 + // when it completes asynchronously in the DonePrintingPages method 1.1812 + // it will check to see if there are more docshells to be printed and 1.1813 + // then PrintDocContent will be called again. 1.1814 + 1.1815 + if (mIsDoingPrinting) { 1.1816 + PrintDocContent(mPrt->mPrintObject, rv); // ignore return value 1.1817 + } 1.1818 + 1.1819 + return rv; 1.1820 +} 1.1821 + 1.1822 +//------------------------------------------------------- 1.1823 +// Recursively reflow each sub-doc and then calc 1.1824 +// all the frame locations of the sub-docs 1.1825 +nsresult 1.1826 +nsPrintEngine::ReflowDocList(nsPrintObject* aPO, bool aSetPixelScale) 1.1827 +{ 1.1828 + NS_ENSURE_ARG_POINTER(aPO); 1.1829 + 1.1830 + // Check to see if the subdocument's element has been hidden by the parent document 1.1831 + if (aPO->mParent && aPO->mParent->mPresShell) { 1.1832 + nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr; 1.1833 + if (!frame || !frame->StyleVisibility()->IsVisible()) { 1.1834 + SetPrintPO(aPO, false); 1.1835 + aPO->mInvisible = true; 1.1836 + return NS_OK; 1.1837 + } 1.1838 + } 1.1839 + 1.1840 + UpdateZoomRatio(aPO, aSetPixelScale); 1.1841 + 1.1842 + nsresult rv; 1.1843 + // Reflow the PO 1.1844 + rv = ReflowPrintObject(aPO); 1.1845 + NS_ENSURE_SUCCESS(rv, rv); 1.1846 + 1.1847 + int32_t cnt = aPO->mKids.Length(); 1.1848 + for (int32_t i=0;i<cnt;i++) { 1.1849 + rv = ReflowDocList(aPO->mKids[i], aSetPixelScale); 1.1850 + NS_ENSURE_SUCCESS(rv, rv); 1.1851 + } 1.1852 + return NS_OK; 1.1853 +} 1.1854 + 1.1855 +void 1.1856 +nsPrintEngine::FirePrintPreviewUpdateEvent() 1.1857 +{ 1.1858 + // Dispatch the event only while in PrintPreview. When printing, there is no 1.1859 + // listener bound to this event and therefore no need to dispatch it. 1.1860 + if (mIsDoingPrintPreview && !mIsDoingPrinting) { 1.1861 + nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint); 1.1862 + (new AsyncEventDispatcher( 1.1863 + cv->GetDocument(), NS_LITERAL_STRING("printPreviewUpdate"), true, true) 1.1864 + )->RunDOMEventWhenSafe(); 1.1865 + } 1.1866 +} 1.1867 + 1.1868 +nsresult 1.1869 +nsPrintEngine::InitPrintDocConstruction(bool aHandleError) 1.1870 +{ 1.1871 + nsresult rv; 1.1872 + rv = ReflowDocList(mPrt->mPrintObject, DoSetPixelScale()); 1.1873 + NS_ENSURE_SUCCESS(rv, rv); 1.1874 + 1.1875 + FirePrintPreviewUpdateEvent(); 1.1876 + 1.1877 + if (mLoadCounter == 0) { 1.1878 + AfterNetworkPrint(aHandleError); 1.1879 + } 1.1880 + return rv; 1.1881 +} 1.1882 + 1.1883 +nsresult 1.1884 +nsPrintEngine::AfterNetworkPrint(bool aHandleError) 1.1885 +{ 1.1886 + nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell); 1.1887 + 1.1888 + webProgress->RemoveProgressListener( 1.1889 + static_cast<nsIWebProgressListener*>(this)); 1.1890 + 1.1891 + nsresult rv; 1.1892 + if (mIsDoingPrinting) { 1.1893 + rv = DocumentReadyForPrinting(); 1.1894 + } else { 1.1895 + rv = FinishPrintPreview(); 1.1896 + } 1.1897 + 1.1898 + /* cleaup on failure + notify user */ 1.1899 + if (aHandleError && NS_FAILED(rv)) { 1.1900 + CleanupOnFailure(rv, !mIsDoingPrinting); 1.1901 + } 1.1902 + 1.1903 + return rv; 1.1904 +} 1.1905 + 1.1906 +//////////////////////////////////////////////////////////////////////////////// 1.1907 +// nsIWebProgressListener 1.1908 + 1.1909 +NS_IMETHODIMP 1.1910 +nsPrintEngine::OnStateChange(nsIWebProgress* aWebProgress, 1.1911 + nsIRequest* aRequest, 1.1912 + uint32_t aStateFlags, 1.1913 + nsresult aStatus) 1.1914 +{ 1.1915 + nsAutoCString name; 1.1916 + aRequest->GetName(name); 1.1917 + if (name.Equals("about:document-onload-blocker")) { 1.1918 + return NS_OK; 1.1919 + } 1.1920 + if (aStateFlags & STATE_START) { 1.1921 + nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); 1.1922 + 1.1923 + ++mLoadCounter; 1.1924 + } else if (aStateFlags & STATE_STOP) { 1.1925 + mDidLoadDataForPrinting = true; 1.1926 + --mLoadCounter; 1.1927 + 1.1928 + // If all resources are loaded, then do a small timeout and if there 1.1929 + // are still no new requests, then another reflow. 1.1930 + if (mLoadCounter == 0) { 1.1931 + AfterNetworkPrint(true); 1.1932 + } 1.1933 + } 1.1934 + return NS_OK; 1.1935 +} 1.1936 + 1.1937 + 1.1938 + 1.1939 +NS_IMETHODIMP 1.1940 +nsPrintEngine::OnProgressChange(nsIWebProgress* aWebProgress, 1.1941 + nsIRequest* aRequest, 1.1942 + int32_t aCurSelfProgress, 1.1943 + int32_t aMaxSelfProgress, 1.1944 + int32_t aCurTotalProgress, 1.1945 + int32_t aMaxTotalProgress) 1.1946 +{ 1.1947 + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); 1.1948 + return NS_OK; 1.1949 +} 1.1950 + 1.1951 +NS_IMETHODIMP 1.1952 +nsPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress, 1.1953 + nsIRequest* aRequest, 1.1954 + nsIURI* aLocation, 1.1955 + uint32_t aFlags) 1.1956 +{ 1.1957 + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); 1.1958 + return NS_OK; 1.1959 +} 1.1960 + 1.1961 +NS_IMETHODIMP 1.1962 +nsPrintEngine::OnStatusChange(nsIWebProgress *aWebProgress, 1.1963 + nsIRequest *aRequest, 1.1964 + nsresult aStatus, 1.1965 + const char16_t *aMessage) 1.1966 +{ 1.1967 + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); 1.1968 + return NS_OK; 1.1969 +} 1.1970 + 1.1971 +NS_IMETHODIMP 1.1972 +nsPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress, 1.1973 + nsIRequest *aRequest, 1.1974 + uint32_t aState) 1.1975 +{ 1.1976 + NS_NOTREACHED("notification excluded in AddProgressListener(...)"); 1.1977 + return NS_OK; 1.1978 +} 1.1979 + 1.1980 +//------------------------------------------------------- 1.1981 + 1.1982 +void 1.1983 +nsPrintEngine::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale) 1.1984 +{ 1.1985 + // Here is where we set the shrinkage value into the DC 1.1986 + // and this is what actually makes it shrink 1.1987 + if (aSetPixelScale && aPO->mFrameType != eIFrame) { 1.1988 + float ratio; 1.1989 + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { 1.1990 + ratio = mPrt->mShrinkRatio - 0.005f; // round down 1.1991 + } else { 1.1992 + ratio = aPO->mShrinkRatio - 0.005f; // round down 1.1993 + } 1.1994 + aPO->mZoomRatio = ratio; 1.1995 + } else if (!mPrt->mShrinkToFit) { 1.1996 + double scaling; 1.1997 + mPrt->mPrintSettings->GetScaling(&scaling); 1.1998 + aPO->mZoomRatio = float(scaling); 1.1999 + } 1.2000 +} 1.2001 + 1.2002 +nsresult 1.2003 +nsPrintEngine::UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO, 1.2004 + bool aDocumentIsTopLevel) 1.2005 +{ 1.2006 + nsCOMPtr<nsIPresShell> displayShell = aPO->mDocShell->GetPresShell(); 1.2007 + // Transfer Selection Ranges to the new Print PresShell 1.2008 + nsRefPtr<Selection> selection, selectionPS; 1.2009 + // It's okay if there is no display shell, just skip copying the selection 1.2010 + if (displayShell) { 1.2011 + selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.2012 + } 1.2013 + selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.2014 + 1.2015 + // Reset all existing selection ranges that might have been added by calling 1.2016 + // this function before. 1.2017 + if (selectionPS) { 1.2018 + selectionPS->RemoveAllRanges(); 1.2019 + } 1.2020 + if (selection && selectionPS) { 1.2021 + int32_t cnt = selection->GetRangeCount(); 1.2022 + int32_t inx; 1.2023 + for (inx = 0; inx < cnt; ++inx) { 1.2024 + selectionPS->AddRange(selection->GetRangeAt(inx)); 1.2025 + } 1.2026 + } 1.2027 + 1.2028 + // If we are trying to shrink the contents to fit on the page 1.2029 + // we must first locate the "pageContent" frame 1.2030 + // Then we walk the frame tree and look for the "xmost" frame 1.2031 + // this is the frame where the right-hand side of the frame extends 1.2032 + // the furthest 1.2033 + if (mPrt->mShrinkToFit && aDocumentIsTopLevel) { 1.2034 + nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame(); 1.2035 + NS_ENSURE_STATE(pageSequence); 1.2036 + pageSequence->GetSTFPercent(aPO->mShrinkRatio); 1.2037 + // Limit the shrink-to-fit scaling for some text-ish type of documents. 1.2038 + nsAutoString contentType; 1.2039 + aPO->mPresShell->GetDocument()->GetContentType(contentType); 1.2040 + if (contentType.EqualsLiteral("application/xhtml+xml") || 1.2041 + StringBeginsWith(contentType, NS_LITERAL_STRING("text/"))) { 1.2042 + int32_t limitPercent = 1.2043 + Preferences::GetInt("print.shrink-to-fit.scale-limit-percent", 20); 1.2044 + limitPercent = std::max(0, limitPercent); 1.2045 + limitPercent = std::min(100, limitPercent); 1.2046 + float minShrinkRatio = float(limitPercent) / 100; 1.2047 + aPO->mShrinkRatio = std::max(aPO->mShrinkRatio, minShrinkRatio); 1.2048 + } 1.2049 + } 1.2050 + return NS_OK; 1.2051 +} 1.2052 + 1.2053 +bool 1.2054 +nsPrintEngine::DoSetPixelScale() 1.2055 +{ 1.2056 + // This is an Optimization 1.2057 + // If we are in PP then we already know all the shrinkage information 1.2058 + // so just transfer it to the PrintData and we will skip the extra shrinkage reflow 1.2059 + // 1.2060 + // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC 1.2061 + // The first time we do not want to do this, the second time through we do 1.2062 + bool doSetPixelScale = false; 1.2063 + bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; 1.2064 + if (ppIsShrinkToFit) { 1.2065 + mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; 1.2066 + doSetPixelScale = true; 1.2067 + } 1.2068 + return doSetPixelScale; 1.2069 +} 1.2070 + 1.2071 +nsView* 1.2072 +nsPrintEngine::GetParentViewForRoot() 1.2073 +{ 1.2074 + if (mIsCreatingPrintPreview) { 1.2075 + nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint); 1.2076 + if (cv) { 1.2077 + return cv->FindContainerView(); 1.2078 + } 1.2079 + } 1.2080 + return nullptr; 1.2081 +} 1.2082 + 1.2083 +nsresult 1.2084 +nsPrintEngine::SetRootView( 1.2085 + nsPrintObject* aPO, 1.2086 + bool& doReturn, 1.2087 + bool& documentIsTopLevel, 1.2088 + nsSize& adjSize 1.2089 +) 1.2090 +{ 1.2091 + bool canCreateScrollbars = true; 1.2092 + 1.2093 + nsView* rootView; 1.2094 + nsView* parentView = nullptr; 1.2095 + 1.2096 + doReturn = false; 1.2097 + 1.2098 + if (aPO->mParent && aPO->mParent->IsPrintable()) { 1.2099 + nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr; 1.2100 + // Without a frame, this document can't be displayed; therefore, there is no 1.2101 + // point to reflowing it 1.2102 + if (!frame) { 1.2103 + SetPrintPO(aPO, false); 1.2104 + doReturn = true; 1.2105 + return NS_OK; 1.2106 + } 1.2107 + 1.2108 + //XXX If printing supported printing document hierarchies with non-constant 1.2109 + // zoom this would be wrong as we use the same mPrt->mPrintDC for all 1.2110 + // subdocuments. 1.2111 + adjSize = frame->GetContentRect().Size(); 1.2112 + documentIsTopLevel = false; 1.2113 + // presshell exists because parent is printable 1.2114 + 1.2115 + // the top nsPrintObject's widget will always have scrollbars 1.2116 + if (frame && frame->GetType() == nsGkAtoms::subDocumentFrame) { 1.2117 + nsView* view = frame->GetView(); 1.2118 + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); 1.2119 + view = view->GetFirstChild(); 1.2120 + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); 1.2121 + parentView = view; 1.2122 + canCreateScrollbars = false; 1.2123 + } 1.2124 + } else { 1.2125 + nscoord pageWidth, pageHeight; 1.2126 + mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); 1.2127 + adjSize = nsSize(pageWidth, pageHeight); 1.2128 + documentIsTopLevel = true; 1.2129 + parentView = GetParentViewForRoot(); 1.2130 + } 1.2131 + 1.2132 + if (aPO->mViewManager->GetRootView()) { 1.2133 + // Reuse the root view that is already on the root frame. 1.2134 + rootView = aPO->mViewManager->GetRootView(); 1.2135 + // Remove it from its existing parent if necessary 1.2136 + aPO->mViewManager->RemoveChild(rootView); 1.2137 + rootView->SetParent(parentView); 1.2138 + } else { 1.2139 + // Create a child window of the parent that is our "root view/window" 1.2140 + nsRect tbounds = nsRect(nsPoint(0, 0), adjSize); 1.2141 + rootView = aPO->mViewManager->CreateView(tbounds, parentView); 1.2142 + NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY); 1.2143 + } 1.2144 + 1.2145 + if (mIsCreatingPrintPreview && documentIsTopLevel) { 1.2146 + aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); 1.2147 + } 1.2148 + 1.2149 + // Setup hierarchical relationship in view manager 1.2150 + aPO->mViewManager->SetRootView(rootView); 1.2151 + 1.2152 + return NS_OK; 1.2153 +} 1.2154 + 1.2155 +// Reflow a nsPrintObject 1.2156 +nsresult 1.2157 +nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO) 1.2158 +{ 1.2159 + NS_ENSURE_STATE(aPO); 1.2160 + 1.2161 + if (!aPO->IsPrintable()) { 1.2162 + return NS_OK; 1.2163 + } 1.2164 + 1.2165 + NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext"); 1.2166 + 1.2167 + // create the PresContext 1.2168 + nsPresContext::nsPresContextType type = 1.2169 + mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview: 1.2170 + nsPresContext::eContext_Print; 1.2171 + nsView* parentView = 1.2172 + aPO->mParent && aPO->mParent->IsPrintable() ? nullptr : GetParentViewForRoot(); 1.2173 + aPO->mPresContext = parentView ? 1.2174 + new nsPresContext(aPO->mDocument, type) : 1.2175 + new nsRootPresContext(aPO->mDocument, type); 1.2176 + NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY); 1.2177 + aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings); 1.2178 + 1.2179 + // set the presentation context to the value in the print settings 1.2180 + bool printBGColors; 1.2181 + mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); 1.2182 + aPO->mPresContext->SetBackgroundColorDraw(printBGColors); 1.2183 + mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); 1.2184 + aPO->mPresContext->SetBackgroundImageDraw(printBGColors); 1.2185 + 1.2186 + // init it with the DC 1.2187 + nsresult rv = aPO->mPresContext->Init(mPrt->mPrintDC); 1.2188 + NS_ENSURE_SUCCESS(rv, rv); 1.2189 + 1.2190 + aPO->mViewManager = new nsViewManager(); 1.2191 + 1.2192 + rv = aPO->mViewManager->Init(mPrt->mPrintDC); 1.2193 + NS_ENSURE_SUCCESS(rv,rv); 1.2194 + 1.2195 + nsStyleSet* styleSet; 1.2196 + rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, &styleSet); 1.2197 + NS_ENSURE_SUCCESS(rv, rv); 1.2198 + 1.2199 + aPO->mPresShell = aPO->mDocument->CreateShell(aPO->mPresContext, 1.2200 + aPO->mViewManager, styleSet); 1.2201 + if (!aPO->mPresShell) { 1.2202 + delete styleSet; 1.2203 + return NS_ERROR_FAILURE; 1.2204 + } 1.2205 + 1.2206 + styleSet->EndUpdate(); 1.2207 + 1.2208 + // The pres shell now owns the style set object. 1.2209 + 1.2210 + 1.2211 + bool doReturn = false;; 1.2212 + bool documentIsTopLevel = false; 1.2213 + nsSize adjSize; 1.2214 + 1.2215 + rv = SetRootView(aPO, doReturn, documentIsTopLevel, adjSize); 1.2216 + 1.2217 + if (NS_FAILED(rv) || doReturn) { 1.2218 + return rv; 1.2219 + } 1.2220 + 1.2221 + PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n", aPO, aPO->mPresShell.get(), 1.2222 + gFrameTypesStr[aPO->mFrameType], adjSize.width, adjSize.height)); 1.2223 + 1.2224 + 1.2225 + // This docshell stuff is weird; will go away when we stop having multiple 1.2226 + // presentations per document 1.2227 + aPO->mPresContext->SetContainer(aPO->mDocShell); 1.2228 + 1.2229 + aPO->mPresShell->BeginObservingDocument(); 1.2230 + 1.2231 + aPO->mPresContext->SetPageSize(adjSize); 1.2232 + aPO->mPresContext->SetIsRootPaginatedDocument(documentIsTopLevel); 1.2233 + aPO->mPresContext->SetPageScale(aPO->mZoomRatio); 1.2234 + // Calculate scale factor from printer to screen 1.2235 + float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) / 1.2236 + float(mPrt->mPrintDC->AppUnitsPerDevPixel()); 1.2237 + aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI); 1.2238 + 1.2239 + if (mIsCreatingPrintPreview && documentIsTopLevel) { 1.2240 + mDocViewerPrint->SetPrintPreviewPresentation(aPO->mViewManager, 1.2241 + aPO->mPresContext, 1.2242 + aPO->mPresShell); 1.2243 + } 1.2244 + 1.2245 + rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height); 1.2246 + 1.2247 + NS_ENSURE_SUCCESS(rv, rv); 1.2248 + NS_ASSERTION(aPO->mPresShell, "Presshell should still be here"); 1.2249 + 1.2250 + // Process the reflow event Initialize posted 1.2251 + aPO->mPresShell->FlushPendingNotifications(Flush_Layout); 1.2252 + 1.2253 + rv = UpdateSelectionAndShrinkPrintObject(aPO, documentIsTopLevel); 1.2254 + NS_ENSURE_SUCCESS(rv, rv); 1.2255 + 1.2256 +#ifdef EXTENDED_DEBUG_PRINTING 1.2257 + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { 1.2258 + nsAutoCString docStr; 1.2259 + nsAutoCString urlStr; 1.2260 + GetDocTitleAndURL(aPO, docStr, urlStr); 1.2261 + char filename[256]; 1.2262 + sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); 1.2263 + // Dump all the frames and view to a a file 1.2264 + FILE * fd = fopen(filename, "w"); 1.2265 + if (fd) { 1.2266 + nsIFrame *theRootFrame = 1.2267 + aPO->mPresShell->FrameManager()->GetRootFrame(); 1.2268 + fprintf(fd, "Title: %s\n", docStr.get()); 1.2269 + fprintf(fd, "URL: %s\n", urlStr.get()); 1.2270 + fprintf(fd, "--------------- Frames ----------------\n"); 1.2271 + nsRefPtr<nsRenderingContext> renderingContext = 1.2272 + mPrt->mPrintDocDC->CreateRenderingContext(); 1.2273 + RootFrameList(aPO->mPresContext, fd, 0); 1.2274 + //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0); 1.2275 + fprintf(fd, "---------------------------------------\n\n"); 1.2276 + fprintf(fd, "--------------- Views From Root Frame----------------\n"); 1.2277 + nsView* v = theRootFrame->GetView(); 1.2278 + if (v) { 1.2279 + v->List(fd); 1.2280 + } else { 1.2281 + printf("View is null!\n"); 1.2282 + } 1.2283 + if (docShell) { 1.2284 + fprintf(fd, "--------------- All Views ----------------\n"); 1.2285 + DumpViews(docShell, fd); 1.2286 + fprintf(fd, "---------------------------------------\n\n"); 1.2287 + } 1.2288 + fclose(fd); 1.2289 + } 1.2290 + } 1.2291 +#endif 1.2292 + 1.2293 + return NS_OK; 1.2294 +} 1.2295 + 1.2296 +//------------------------------------------------------- 1.2297 +// Figure out how many documents and how many total pages we are printing 1.2298 +void 1.2299 +nsPrintEngine::CalcNumPrintablePages(int32_t& aNumPages) 1.2300 +{ 1.2301 + aNumPages = 0; 1.2302 + // Count the number of printable documents 1.2303 + // and printable pages 1.2304 + for (uint32_t i=0; i<mPrt->mPrintDocList.Length(); i++) { 1.2305 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.2306 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.2307 + if (po->mPresContext && po->mPresContext->IsRootPaginatedDocument()) { 1.2308 + nsIPageSequenceFrame* pageSequence = po->mPresShell->GetPageSequenceFrame(); 1.2309 + nsIFrame * seqFrame = do_QueryFrame(pageSequence); 1.2310 + if (seqFrame) { 1.2311 + nsIFrame* frame = seqFrame->GetFirstPrincipalChild(); 1.2312 + while (frame) { 1.2313 + aNumPages++; 1.2314 + frame = frame->GetNextSibling(); 1.2315 + } 1.2316 + } 1.2317 + } 1.2318 + } 1.2319 +} 1.2320 + 1.2321 +//----------------------------------------------------------------- 1.2322 +//-- Done: Reflow Methods 1.2323 +//----------------------------------------------------------------- 1.2324 + 1.2325 +//----------------------------------------------------------------- 1.2326 +//-- Section: Printing Methods 1.2327 +//----------------------------------------------------------------- 1.2328 + 1.2329 +//------------------------------------------------------- 1.2330 +// Called for each DocShell that needs to be printed 1.2331 +bool 1.2332 +nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus) 1.2333 +{ 1.2334 + NS_ASSERTION(aPO, "Pointer is null!"); 1.2335 + aStatus = NS_OK; 1.2336 + 1.2337 + if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) { 1.2338 + aStatus = DoPrint(aPO); 1.2339 + return true; 1.2340 + } 1.2341 + 1.2342 + // If |aPO->mPrintAsIs| and |aPO->mHasBeenPrinted| are true, 1.2343 + // the kids frames are already processed in |PrintPage|. 1.2344 + if (!aPO->mInvisible && !(aPO->mPrintAsIs && aPO->mHasBeenPrinted)) { 1.2345 + for (uint32_t i=0;i<aPO->mKids.Length();i++) { 1.2346 + nsPrintObject* po = aPO->mKids[i]; 1.2347 + bool printed = PrintDocContent(po, aStatus); 1.2348 + if (printed || NS_FAILED(aStatus)) { 1.2349 + return true; 1.2350 + } 1.2351 + } 1.2352 + } 1.2353 + return false; 1.2354 +} 1.2355 + 1.2356 +static already_AddRefed<nsIDOMNode> 1.2357 +GetEqualNodeInCloneTree(nsIDOMNode* aNode, nsIDocument* aDoc) 1.2358 +{ 1.2359 + nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); 1.2360 + // Selections in anonymous subtrees aren't supported. 1.2361 + if (content && content->IsInAnonymousSubtree()) { 1.2362 + return nullptr; 1.2363 + } 1.2364 + 1.2365 + nsCOMPtr<nsINode> node = do_QueryInterface(aNode); 1.2366 + NS_ENSURE_TRUE(node, nullptr); 1.2367 + 1.2368 + nsTArray<int32_t> indexArray; 1.2369 + nsINode* current = node; 1.2370 + NS_ENSURE_TRUE(current, nullptr); 1.2371 + while (current) { 1.2372 + nsINode* parent = current->GetParentNode(); 1.2373 + if (!parent) { 1.2374 + break; 1.2375 + } 1.2376 + int32_t index = parent->IndexOf(current); 1.2377 + NS_ENSURE_TRUE(index >= 0, nullptr); 1.2378 + indexArray.AppendElement(index); 1.2379 + current = parent; 1.2380 + } 1.2381 + NS_ENSURE_TRUE(current->IsNodeOfType(nsINode::eDOCUMENT), nullptr); 1.2382 + 1.2383 + current = aDoc; 1.2384 + for (int32_t i = indexArray.Length() - 1; i >= 0; --i) { 1.2385 + current = current->GetChildAt(indexArray[i]); 1.2386 + NS_ENSURE_TRUE(current, nullptr); 1.2387 + } 1.2388 + nsCOMPtr<nsIDOMNode> result = do_QueryInterface(current); 1.2389 + return result.forget(); 1.2390 +} 1.2391 + 1.2392 +static void 1.2393 +CloneRangeToSelection(nsRange* aRange, nsIDocument* aDoc, 1.2394 + Selection* aSelection) 1.2395 +{ 1.2396 + if (aRange->Collapsed()) { 1.2397 + return; 1.2398 + } 1.2399 + 1.2400 + nsCOMPtr<nsIDOMNode> startContainer, endContainer; 1.2401 + aRange->GetStartContainer(getter_AddRefs(startContainer)); 1.2402 + int32_t startOffset = aRange->StartOffset(); 1.2403 + aRange->GetEndContainer(getter_AddRefs(endContainer)); 1.2404 + int32_t endOffset = aRange->EndOffset(); 1.2405 + NS_ENSURE_TRUE_VOID(startContainer && endContainer); 1.2406 + 1.2407 + nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc); 1.2408 + nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc); 1.2409 + NS_ENSURE_TRUE_VOID(newStart && newEnd); 1.2410 + 1.2411 + nsCOMPtr<nsINode> newStartNode = do_QueryInterface(newStart); 1.2412 + NS_ENSURE_TRUE_VOID(newStartNode); 1.2413 + 1.2414 + nsRefPtr<nsRange> range = new nsRange(newStartNode); 1.2415 + nsresult rv = range->SetStart(newStartNode, startOffset); 1.2416 + NS_ENSURE_SUCCESS_VOID(rv); 1.2417 + rv = range->SetEnd(newEnd, endOffset); 1.2418 + NS_ENSURE_SUCCESS_VOID(rv); 1.2419 + 1.2420 + aSelection->AddRange(range); 1.2421 +} 1.2422 + 1.2423 +static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc) 1.2424 +{ 1.2425 + nsIPresShell* origShell = aOrigDoc->GetShell(); 1.2426 + nsIPresShell* shell = aDoc->GetShell(); 1.2427 + NS_ENSURE_STATE(origShell && shell); 1.2428 + 1.2429 + nsRefPtr<Selection> origSelection = 1.2430 + origShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.2431 + nsRefPtr<Selection> selection = 1.2432 + shell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.2433 + NS_ENSURE_STATE(origSelection && selection); 1.2434 + 1.2435 + int32_t rangeCount = origSelection->GetRangeCount(); 1.2436 + for (int32_t i = 0; i < rangeCount; ++i) { 1.2437 + CloneRangeToSelection(origSelection->GetRangeAt(i), aDoc, selection); 1.2438 + } 1.2439 + return NS_OK; 1.2440 +} 1.2441 + 1.2442 +//------------------------------------------------------- 1.2443 +nsresult 1.2444 +nsPrintEngine::DoPrint(nsPrintObject * aPO) 1.2445 +{ 1.2446 + PR_PL(("\n")); 1.2447 + PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType])); 1.2448 + PR_PL(("****** In DV::DoPrint PO: %p \n", aPO)); 1.2449 + 1.2450 + nsIPresShell* poPresShell = aPO->mPresShell; 1.2451 + nsPresContext* poPresContext = aPO->mPresContext; 1.2452 + 1.2453 + NS_ASSERTION(poPresContext, "PrintObject has not been reflowed"); 1.2454 + NS_ASSERTION(poPresContext->Type() != nsPresContext::eContext_PrintPreview, 1.2455 + "How did this context end up here?"); 1.2456 + 1.2457 + if (mPrt->mPrintProgressParams) { 1.2458 + SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams); 1.2459 + } 1.2460 + 1.2461 + { 1.2462 + int16_t printRangeType = nsIPrintSettings::kRangeAllPages; 1.2463 + nsresult rv; 1.2464 + if (mPrt->mPrintSettings != nullptr) { 1.2465 + mPrt->mPrintSettings->GetPrintRange(&printRangeType); 1.2466 + } 1.2467 + 1.2468 + // Ask the page sequence frame to print all the pages 1.2469 + nsIPageSequenceFrame* pageSequence = poPresShell->GetPageSequenceFrame(); 1.2470 + NS_ASSERTION(nullptr != pageSequence, "no page sequence frame"); 1.2471 + 1.2472 + // We are done preparing for printing, so we can turn this off 1.2473 + mPrt->mPreparingForPrint = false; 1.2474 + 1.2475 + // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging 1.2476 + if (nullptr != mPrt->mDebugFilePtr) { 1.2477 +#ifdef DEBUG 1.2478 + // output the regression test 1.2479 + nsIFrame* root = poPresShell->FrameManager()->GetRootFrame(); 1.2480 + root->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0); 1.2481 + fclose(mPrt->mDebugFilePtr); 1.2482 + SetIsPrinting(false); 1.2483 +#endif 1.2484 + } else { 1.2485 +#ifdef EXTENDED_DEBUG_PRINTING 1.2486 + nsIFrame* rootFrame = poPresShell->FrameManager()->GetRootFrame(); 1.2487 + if (aPO->IsPrintable()) { 1.2488 + nsAutoCString docStr; 1.2489 + nsAutoCString urlStr; 1.2490 + GetDocTitleAndURL(aPO, docStr, urlStr); 1.2491 + DumpLayoutData(docStr.get(), urlStr.get(), poPresContext, mPrt->mPrintDocDC, rootFrame, docShell, nullptr); 1.2492 + } 1.2493 +#endif 1.2494 + 1.2495 + if (!mPrt->mPrintSettings) { 1.2496 + // not sure what to do here! 1.2497 + SetIsPrinting(false); 1.2498 + return NS_ERROR_FAILURE; 1.2499 + } 1.2500 + 1.2501 + nsAutoString docTitleStr; 1.2502 + nsAutoString docURLStr; 1.2503 + GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefBlank); 1.2504 + 1.2505 + if (nsIPrintSettings::kRangeSelection == printRangeType) { 1.2506 + CloneSelection(aPO->mDocument->GetOriginalDocument(), aPO->mDocument); 1.2507 + 1.2508 + poPresContext->SetIsRenderingOnlySelection(true); 1.2509 + // temporarily creating rendering context 1.2510 + // which is needed to find the selection frames 1.2511 + nsRefPtr<nsRenderingContext> rc = 1.2512 + mPrt->mPrintDC->CreateRenderingContext(); 1.2513 + 1.2514 + // find the starting and ending page numbers 1.2515 + // via the selection 1.2516 + nsIFrame* startFrame; 1.2517 + nsIFrame* endFrame; 1.2518 + int32_t startPageNum; 1.2519 + int32_t endPageNum; 1.2520 + nsRect startRect; 1.2521 + nsRect endRect; 1.2522 + 1.2523 + nsRefPtr<Selection> selectionPS = 1.2524 + poPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL); 1.2525 + 1.2526 + rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence, 1.2527 + &startFrame, startPageNum, startRect, 1.2528 + &endFrame, endPageNum, endRect); 1.2529 + if (NS_SUCCEEDED(rv)) { 1.2530 + mPrt->mPrintSettings->SetStartPageRange(startPageNum); 1.2531 + mPrt->mPrintSettings->SetEndPageRange(endPageNum); 1.2532 + nsIntMargin marginTwips(0,0,0,0); 1.2533 + nsIntMargin unwrtMarginTwips(0,0,0,0); 1.2534 + mPrt->mPrintSettings->GetMarginInTwips(marginTwips); 1.2535 + mPrt->mPrintSettings->GetUnwriteableMarginInTwips(unwrtMarginTwips); 1.2536 + nsMargin totalMargin = poPresContext->CSSTwipsToAppUnits(marginTwips + 1.2537 + unwrtMarginTwips); 1.2538 + if (startPageNum == endPageNum) { 1.2539 + startRect.y -= totalMargin.top; 1.2540 + endRect.y -= totalMargin.top; 1.2541 + 1.2542 + // Clip out selection regions above the top of the first page 1.2543 + if (startRect.y < 0) { 1.2544 + // Reduce height to be the height of the positive-territory 1.2545 + // region of original rect 1.2546 + startRect.height = std::max(0, startRect.YMost()); 1.2547 + startRect.y = 0; 1.2548 + } 1.2549 + if (endRect.y < 0) { 1.2550 + // Reduce height to be the height of the positive-territory 1.2551 + // region of original rect 1.2552 + endRect.height = std::max(0, endRect.YMost()); 1.2553 + endRect.y = 0; 1.2554 + } 1.2555 + NS_ASSERTION(endRect.y >= startRect.y, 1.2556 + "Selection end point should be after start point"); 1.2557 + NS_ASSERTION(startRect.height >= 0, 1.2558 + "rect should have non-negative height."); 1.2559 + NS_ASSERTION(endRect.height >= 0, 1.2560 + "rect should have non-negative height."); 1.2561 + 1.2562 + nscoord selectionHgt = endRect.y + endRect.height - startRect.y; 1.2563 + // XXX This is temporary fix for printing more than one page of a selection 1.2564 + pageSequence->SetSelectionHeight(startRect.y * aPO->mZoomRatio, 1.2565 + selectionHgt * aPO->mZoomRatio); 1.2566 + 1.2567 + // calc total pages by getting calculating the selection's height 1.2568 + // and then dividing it by how page content frames will fit. 1.2569 + nscoord pageWidth, pageHeight; 1.2570 + mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); 1.2571 + pageHeight -= totalMargin.top + totalMargin.bottom; 1.2572 + int32_t totalPages = NSToIntCeil(float(selectionHgt) * aPO->mZoomRatio / float(pageHeight)); 1.2573 + pageSequence->SetTotalNumPages(totalPages); 1.2574 + } 1.2575 + } 1.2576 + } 1.2577 + 1.2578 + nsIFrame * seqFrame = do_QueryFrame(pageSequence); 1.2579 + if (!seqFrame) { 1.2580 + SetIsPrinting(false); 1.2581 + return NS_ERROR_FAILURE; 1.2582 + } 1.2583 + 1.2584 + mPageSeqFrame = pageSequence; 1.2585 + mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); 1.2586 + 1.2587 + // Schedule Page to Print 1.2588 + PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); 1.2589 + StartPagePrintTimer(aPO); 1.2590 + } 1.2591 + } 1.2592 + 1.2593 + return NS_OK; 1.2594 +} 1.2595 + 1.2596 +//--------------------------------------------------------------------- 1.2597 +void 1.2598 +nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO, 1.2599 + nsIPrintProgressParams* aParams) 1.2600 +{ 1.2601 + NS_ASSERTION(aPO, "Must have valid nsPrintObject"); 1.2602 + NS_ASSERTION(aParams, "Must have valid nsIPrintProgressParams"); 1.2603 + 1.2604 + if (!aPO || !aPO->mDocShell || !aParams) { 1.2605 + return; 1.2606 + } 1.2607 + const uint32_t kTitleLength = 64; 1.2608 + 1.2609 + nsAutoString docTitleStr; 1.2610 + nsAutoString docURLStr; 1.2611 + GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefURLDoc); 1.2612 + 1.2613 + // Make sure the Titles & URLS don't get too long for the progress dialog 1.2614 + EllipseLongString(docTitleStr, kTitleLength, false); 1.2615 + EllipseLongString(docURLStr, kTitleLength, true); 1.2616 + 1.2617 + aParams->SetDocTitle(docTitleStr.get()); 1.2618 + aParams->SetDocURL(docURLStr.get()); 1.2619 +} 1.2620 + 1.2621 +//--------------------------------------------------------------------- 1.2622 +void 1.2623 +nsPrintEngine::EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront) 1.2624 +{ 1.2625 + // Make sure the URLS don't get too long for the progress dialog 1.2626 + if (aLen >= 3 && aStr.Length() > aLen) { 1.2627 + if (aDoFront) { 1.2628 + nsAutoString newStr; 1.2629 + newStr.AppendLiteral("..."); 1.2630 + newStr += Substring(aStr, aStr.Length() - (aLen - 3), aLen - 3); 1.2631 + aStr = newStr; 1.2632 + } else { 1.2633 + aStr.SetLength(aLen - 3); 1.2634 + aStr.AppendLiteral("..."); 1.2635 + } 1.2636 + } 1.2637 +} 1.2638 + 1.2639 +static bool 1.2640 +DocHasPrintCallbackCanvas(nsIDocument* aDoc, void* aData) 1.2641 +{ 1.2642 + if (!aDoc) { 1.2643 + return true; 1.2644 + } 1.2645 + Element* root = aDoc->GetRootElement(); 1.2646 + if (!root) { 1.2647 + return true; 1.2648 + } 1.2649 + nsRefPtr<nsContentList> canvases = NS_GetContentList(root, 1.2650 + kNameSpaceID_XHTML, 1.2651 + NS_LITERAL_STRING("canvas")); 1.2652 + uint32_t canvasCount = canvases->Length(true); 1.2653 + for (uint32_t i = 0; i < canvasCount; ++i) { 1.2654 + HTMLCanvasElement* canvas = HTMLCanvasElement::FromContentOrNull(canvases->Item(i, false)); 1.2655 + if (canvas && canvas->GetMozPrintCallback()) { 1.2656 + // This subdocument has a print callback. Set result and return false to 1.2657 + // stop iteration. 1.2658 + *static_cast<bool*>(aData) = true; 1.2659 + return false; 1.2660 + } 1.2661 + } 1.2662 + return true; 1.2663 +} 1.2664 + 1.2665 +static bool 1.2666 +DocHasPrintCallbackCanvas(nsIDocument* aDoc) 1.2667 +{ 1.2668 + bool result = false; 1.2669 + aDoc->EnumerateSubDocuments(&DocHasPrintCallbackCanvas, static_cast<void*>(&result)); 1.2670 + return result; 1.2671 +} 1.2672 + 1.2673 +/** 1.2674 + * Checks to see if the document this print engine is associated with has any 1.2675 + * canvases that have a mozPrintCallback. 1.2676 + */ 1.2677 +bool 1.2678 +nsPrintEngine::HasPrintCallbackCanvas() 1.2679 +{ 1.2680 + if (!mDocument) { 1.2681 + return false; 1.2682 + } 1.2683 + // First check this mDocument. 1.2684 + bool result = false; 1.2685 + DocHasPrintCallbackCanvas(mDocument, static_cast<void*>(&result)); 1.2686 + // Also check the sub documents. 1.2687 + return result || DocHasPrintCallbackCanvas(mDocument); 1.2688 +} 1.2689 + 1.2690 +//------------------------------------------------------- 1.2691 +bool 1.2692 +nsPrintEngine::PrePrintPage() 1.2693 +{ 1.2694 + NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); 1.2695 + NS_ASSERTION(mPrt, "mPrt is null!"); 1.2696 + 1.2697 + // Although these should NEVER be nullptr 1.2698 + // This is added insurance, to make sure we don't crash in optimized builds 1.2699 + if (!mPrt || !mPageSeqFrame) { 1.2700 + return true; // means we are done preparing the page. 1.2701 + } 1.2702 + 1.2703 + // Check setting to see if someone request it be cancelled 1.2704 + bool isCancelled = false; 1.2705 + mPrt->mPrintSettings->GetIsCancelled(&isCancelled); 1.2706 + if (isCancelled) 1.2707 + return true; 1.2708 + 1.2709 + // Ask mPageSeqFrame if the page is ready to be printed. 1.2710 + // If the page doesn't get printed at all, the |done| will be |true|. 1.2711 + bool done = false; 1.2712 + nsresult rv = mPageSeqFrame->PrePrintNextPage(mPagePrintTimer, &done); 1.2713 + if (NS_FAILED(rv)) { 1.2714 + // ??? ::PrintPage doesn't set |mPrt->mIsAborted = true| if rv != NS_ERROR_ABORT, 1.2715 + // but I don't really understand why this should be the right thing to do? 1.2716 + // Shouldn't |mPrt->mIsAborted| set to true all the time if something 1.2717 + // wents wrong? 1.2718 + if (rv != NS_ERROR_ABORT) { 1.2719 + ShowPrintErrorDialog(rv); 1.2720 + mPrt->mIsAborted = true; 1.2721 + } 1.2722 + done = true; 1.2723 + } 1.2724 + return done; 1.2725 +} 1.2726 + 1.2727 +bool 1.2728 +nsPrintEngine::PrintPage(nsPrintObject* aPO, 1.2729 + bool& aInRange) 1.2730 +{ 1.2731 + NS_ASSERTION(aPO, "aPO is null!"); 1.2732 + NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); 1.2733 + NS_ASSERTION(mPrt, "mPrt is null!"); 1.2734 + 1.2735 + // Although these should NEVER be nullptr 1.2736 + // This is added insurance, to make sure we don't crash in optimized builds 1.2737 + if (!mPrt || !aPO || !mPageSeqFrame) { 1.2738 + ShowPrintErrorDialog(NS_ERROR_FAILURE); 1.2739 + return true; // means we are done printing 1.2740 + } 1.2741 + 1.2742 + PR_PL(("-----------------------------------\n")); 1.2743 + PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType])); 1.2744 + 1.2745 + // Check setting to see if someone request it be cancelled 1.2746 + bool isCancelled = false; 1.2747 + mPrt->mPrintSettings->GetIsCancelled(&isCancelled); 1.2748 + if (isCancelled || mPrt->mIsAborted) 1.2749 + return true; 1.2750 + 1.2751 + int32_t pageNum, numPages, endPage; 1.2752 + mPageSeqFrame->GetCurrentPageNum(&pageNum); 1.2753 + mPageSeqFrame->GetNumPages(&numPages); 1.2754 + 1.2755 + bool donePrinting; 1.2756 + bool isDoingPrintRange; 1.2757 + mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); 1.2758 + if (isDoingPrintRange) { 1.2759 + int32_t fromPage; 1.2760 + int32_t toPage; 1.2761 + mPageSeqFrame->GetPrintRange(&fromPage, &toPage); 1.2762 + 1.2763 + if (fromPage > numPages) { 1.2764 + return true; 1.2765 + } 1.2766 + if (toPage > numPages) { 1.2767 + toPage = numPages; 1.2768 + } 1.2769 + 1.2770 + PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage)); 1.2771 + 1.2772 + donePrinting = pageNum >= toPage; 1.2773 + aInRange = pageNum >= fromPage && pageNum <= toPage; 1.2774 + endPage = (toPage - fromPage)+1; 1.2775 + } else { 1.2776 + PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages)); 1.2777 + 1.2778 + donePrinting = pageNum >= numPages; 1.2779 + endPage = numPages; 1.2780 + aInRange = true; 1.2781 + } 1.2782 + 1.2783 + // XXX This is wrong, but the actual behavior in the presence of a print 1.2784 + // range sucks. 1.2785 + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) 1.2786 + endPage = mPrt->mNumPrintablePages; 1.2787 + 1.2788 + mPrt->DoOnProgressChange(++mPrt->mNumPagesPrinted, endPage, false, 0); 1.2789 + 1.2790 + // Print the Page 1.2791 + // if a print job was cancelled externally, an EndPage or BeginPage may 1.2792 + // fail and the failure is passed back here. 1.2793 + // Returning true means we are done printing. 1.2794 + // 1.2795 + // When rv == NS_ERROR_ABORT, it means we want out of the 1.2796 + // print job without displaying any error messages 1.2797 + nsresult rv = mPageSeqFrame->PrintNextPage(); 1.2798 + if (NS_FAILED(rv)) { 1.2799 + if (rv != NS_ERROR_ABORT) { 1.2800 + ShowPrintErrorDialog(rv); 1.2801 + mPrt->mIsAborted = true; 1.2802 + } 1.2803 + return true; 1.2804 + } 1.2805 + 1.2806 + mPageSeqFrame->DoPageEnd(); 1.2807 + 1.2808 + return donePrinting; 1.2809 +} 1.2810 + 1.2811 +/** --------------------------------------------------- 1.2812 + * Find by checking frames type 1.2813 + */ 1.2814 +nsresult 1.2815 +nsPrintEngine::FindSelectionBoundsWithList(nsPresContext* aPresContext, 1.2816 + nsRenderingContext& aRC, 1.2817 + nsFrameList::Enumerator& aChildFrames, 1.2818 + nsIFrame * aParentFrame, 1.2819 + nsRect& aRect, 1.2820 + nsIFrame *& aStartFrame, 1.2821 + nsRect& aStartRect, 1.2822 + nsIFrame *& aEndFrame, 1.2823 + nsRect& aEndRect) 1.2824 +{ 1.2825 + NS_ASSERTION(aPresContext, "Pointer is null!"); 1.2826 + NS_ASSERTION(aParentFrame, "Pointer is null!"); 1.2827 + 1.2828 + aRect += aParentFrame->GetPosition(); 1.2829 + for (; !aChildFrames.AtEnd(); aChildFrames.Next()) { 1.2830 + nsIFrame* child = aChildFrames.get(); 1.2831 + if (child->IsSelected() && child->IsVisibleForPainting()) { 1.2832 + nsRect r = child->GetRect(); 1.2833 + if (aStartFrame == nullptr) { 1.2834 + aStartFrame = child; 1.2835 + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); 1.2836 + } else { 1.2837 + aEndFrame = child; 1.2838 + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); 1.2839 + } 1.2840 + } 1.2841 + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); 1.2842 + child = child->GetNextSibling(); 1.2843 + } 1.2844 + aRect -= aParentFrame->GetPosition(); 1.2845 + return NS_OK; 1.2846 +} 1.2847 + 1.2848 +//------------------------------------------------------- 1.2849 +// Find the Frame that is XMost 1.2850 +nsresult 1.2851 +nsPrintEngine::FindSelectionBounds(nsPresContext* aPresContext, 1.2852 + nsRenderingContext& aRC, 1.2853 + nsIFrame * aParentFrame, 1.2854 + nsRect& aRect, 1.2855 + nsIFrame *& aStartFrame, 1.2856 + nsRect& aStartRect, 1.2857 + nsIFrame *& aEndFrame, 1.2858 + nsRect& aEndRect) 1.2859 +{ 1.2860 + NS_ASSERTION(aPresContext, "Pointer is null!"); 1.2861 + NS_ASSERTION(aParentFrame, "Pointer is null!"); 1.2862 + 1.2863 + // loop through named child lists 1.2864 + nsIFrame::ChildListIterator lists(aParentFrame); 1.2865 + for (; !lists.IsDone(); lists.Next()) { 1.2866 + nsFrameList::Enumerator childFrames(lists.CurrentList()); 1.2867 + nsresult rv = FindSelectionBoundsWithList(aPresContext, aRC, childFrames, aParentFrame, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); 1.2868 + NS_ENSURE_SUCCESS(rv, rv); 1.2869 + } 1.2870 + return NS_OK; 1.2871 +} 1.2872 + 1.2873 +/** --------------------------------------------------- 1.2874 + * This method finds the starting and ending page numbers 1.2875 + * of the selection and also returns rect for each where 1.2876 + * the x,y of the rect is relative to the very top of the 1.2877 + * frame tree (absolutely positioned) 1.2878 + */ 1.2879 +nsresult 1.2880 +nsPrintEngine::GetPageRangeForSelection(nsIPresShell * aPresShell, 1.2881 + nsPresContext* aPresContext, 1.2882 + nsRenderingContext& aRC, 1.2883 + nsISelection* aSelection, 1.2884 + nsIPageSequenceFrame* aPageSeqFrame, 1.2885 + nsIFrame** aStartFrame, 1.2886 + int32_t& aStartPageNum, 1.2887 + nsRect& aStartRect, 1.2888 + nsIFrame** aEndFrame, 1.2889 + int32_t& aEndPageNum, 1.2890 + nsRect& aEndRect) 1.2891 +{ 1.2892 + NS_ASSERTION(aPresShell, "Pointer is null!"); 1.2893 + NS_ASSERTION(aPresContext, "Pointer is null!"); 1.2894 + NS_ASSERTION(aSelection, "Pointer is null!"); 1.2895 + NS_ASSERTION(aPageSeqFrame, "Pointer is null!"); 1.2896 + NS_ASSERTION(aStartFrame, "Pointer is null!"); 1.2897 + NS_ASSERTION(aEndFrame, "Pointer is null!"); 1.2898 + 1.2899 + nsIFrame * seqFrame = do_QueryFrame(aPageSeqFrame); 1.2900 + if (!seqFrame) { 1.2901 + return NS_ERROR_FAILURE; 1.2902 + } 1.2903 + 1.2904 + nsIFrame * startFrame = nullptr; 1.2905 + nsIFrame * endFrame = nullptr; 1.2906 + 1.2907 + // start out with the sequence frame and search the entire frame tree 1.2908 + // capturing the starting and ending child frames of the selection 1.2909 + // and their rects 1.2910 + nsRect r = seqFrame->GetRect(); 1.2911 + FindSelectionBounds(aPresContext, aRC, seqFrame, r, 1.2912 + startFrame, aStartRect, endFrame, aEndRect); 1.2913 + 1.2914 +#ifdef DEBUG_rodsX 1.2915 + printf("Start Frame: %p\n", startFrame); 1.2916 + printf("End Frame: %p\n", endFrame); 1.2917 +#endif 1.2918 + 1.2919 + // initial the page numbers here 1.2920 + // in case we don't find and frames 1.2921 + aStartPageNum = -1; 1.2922 + aEndPageNum = -1; 1.2923 + 1.2924 + nsIFrame * startPageFrame; 1.2925 + nsIFrame * endPageFrame; 1.2926 + 1.2927 + // check to make sure we found a starting frame 1.2928 + if (startFrame != nullptr) { 1.2929 + // Now search up the tree to find what page the 1.2930 + // start/ending selections frames are on 1.2931 + // 1.2932 + // Check to see if start should be same as end if 1.2933 + // the end frame comes back null 1.2934 + if (endFrame == nullptr) { 1.2935 + // XXX the "GetPageFrame" step could be integrated into 1.2936 + // the FindSelectionBounds step, but walking up to find 1.2937 + // the parent of a child frame isn't expensive and it makes 1.2938 + // FindSelectionBounds a little easier to understand 1.2939 + startPageFrame = nsLayoutUtils::GetPageFrame(startFrame); 1.2940 + endPageFrame = startPageFrame; 1.2941 + aEndRect = aStartRect; 1.2942 + } else { 1.2943 + startPageFrame = nsLayoutUtils::GetPageFrame(startFrame); 1.2944 + endPageFrame = nsLayoutUtils::GetPageFrame(endFrame); 1.2945 + } 1.2946 + } else { 1.2947 + return NS_ERROR_FAILURE; 1.2948 + } 1.2949 + 1.2950 +#ifdef DEBUG_rodsX 1.2951 + printf("Start Page: %p\n", startPageFrame); 1.2952 + printf("End Page: %p\n", endPageFrame); 1.2953 + 1.2954 + // dump all the pages and their pointers 1.2955 + { 1.2956 + int32_t pageNum = 1; 1.2957 + nsIFrame* child = seqFrame->GetFirstPrincipalChild(); 1.2958 + while (child != nullptr) { 1.2959 + printf("Page: %d - %p\n", pageNum, child); 1.2960 + pageNum++; 1.2961 + child = child->GetNextSibling(); 1.2962 + } 1.2963 + } 1.2964 +#endif 1.2965 + 1.2966 + // Now that we have the page frames 1.2967 + // find out what the page numbers are for each frame 1.2968 + int32_t pageNum = 1; 1.2969 + nsIFrame* page = seqFrame->GetFirstPrincipalChild(); 1.2970 + while (page != nullptr) { 1.2971 + if (page == startPageFrame) { 1.2972 + aStartPageNum = pageNum; 1.2973 + } 1.2974 + if (page == endPageFrame) { 1.2975 + aEndPageNum = pageNum; 1.2976 + } 1.2977 + pageNum++; 1.2978 + page = page->GetNextSibling(); 1.2979 + } 1.2980 + 1.2981 +#ifdef DEBUG_rodsX 1.2982 + printf("Start Page No: %d\n", aStartPageNum); 1.2983 + printf("End Page No: %d\n", aEndPageNum); 1.2984 +#endif 1.2985 + 1.2986 + *aStartFrame = startPageFrame; 1.2987 + *aEndFrame = endPageFrame; 1.2988 + 1.2989 + return NS_OK; 1.2990 +} 1.2991 + 1.2992 +//----------------------------------------------------------------- 1.2993 +//-- Done: Printing Methods 1.2994 +//----------------------------------------------------------------- 1.2995 + 1.2996 + 1.2997 +//----------------------------------------------------------------- 1.2998 +//-- Section: Misc Support Methods 1.2999 +//----------------------------------------------------------------- 1.3000 + 1.3001 +//--------------------------------------------------------------------- 1.3002 +void nsPrintEngine::SetIsPrinting(bool aIsPrinting) 1.3003 +{ 1.3004 + mIsDoingPrinting = aIsPrinting; 1.3005 + // Calling SetIsPrinting while in print preview confuses the document viewer 1.3006 + // This is safe because we prevent exiting print preview while printing 1.3007 + if (!mIsDoingPrintPreview && mDocViewerPrint) { 1.3008 + mDocViewerPrint->SetIsPrinting(aIsPrinting); 1.3009 + } 1.3010 + if (mPrt && aIsPrinting) { 1.3011 + mPrt->mPreparingForPrint = true; 1.3012 + } 1.3013 +} 1.3014 + 1.3015 +//--------------------------------------------------------------------- 1.3016 +void nsPrintEngine::SetIsPrintPreview(bool aIsPrintPreview) 1.3017 +{ 1.3018 + mIsDoingPrintPreview = aIsPrintPreview; 1.3019 + 1.3020 + if (mDocViewerPrint) { 1.3021 + mDocViewerPrint->SetIsPrintPreview(aIsPrintPreview); 1.3022 + } 1.3023 +} 1.3024 + 1.3025 +//--------------------------------------------------------------------- 1.3026 +void 1.3027 +nsPrintEngine::CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount) 1.3028 +{ 1.3029 + for (int32_t i = aCount - 1; i >= 0; i--) { 1.3030 + nsMemory::Free(aArray[i]); 1.3031 + } 1.3032 + nsMemory::Free(aArray); 1.3033 + aArray = nullptr; 1.3034 + aCount = 0; 1.3035 +} 1.3036 + 1.3037 +//--------------------------------------------------------------------- 1.3038 +// static 1.3039 +bool nsPrintEngine::HasFramesetChild(nsIContent* aContent) 1.3040 +{ 1.3041 + if (!aContent) { 1.3042 + return false; 1.3043 + } 1.3044 + 1.3045 + // do a breadth search across all siblings 1.3046 + for (nsIContent* child = aContent->GetFirstChild(); 1.3047 + child; 1.3048 + child = child->GetNextSibling()) { 1.3049 + if (child->IsHTML(nsGkAtoms::frameset)) { 1.3050 + return true; 1.3051 + } 1.3052 + } 1.3053 + 1.3054 + return false; 1.3055 +} 1.3056 + 1.3057 + 1.3058 + 1.3059 +/** --------------------------------------------------- 1.3060 + * Get the Focused Frame for a documentviewer 1.3061 + */ 1.3062 +already_AddRefed<nsIDOMWindow> 1.3063 +nsPrintEngine::FindFocusedDOMWindow() 1.3064 +{ 1.3065 + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); 1.3066 + NS_ENSURE_TRUE(fm, nullptr); 1.3067 + 1.3068 + nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow()); 1.3069 + NS_ENSURE_TRUE(window, nullptr); 1.3070 + 1.3071 + nsCOMPtr<nsPIDOMWindow> rootWindow = window->GetPrivateRoot(); 1.3072 + NS_ENSURE_TRUE(rootWindow, nullptr); 1.3073 + 1.3074 + nsCOMPtr<nsPIDOMWindow> focusedWindow; 1.3075 + nsFocusManager::GetFocusedDescendant(rootWindow, true, 1.3076 + getter_AddRefs(focusedWindow)); 1.3077 + NS_ENSURE_TRUE(focusedWindow, nullptr); 1.3078 + 1.3079 + if (IsWindowsInOurSubTree(focusedWindow)) { 1.3080 + return focusedWindow.forget(); 1.3081 + } 1.3082 + 1.3083 + return nullptr; 1.3084 +} 1.3085 + 1.3086 +//--------------------------------------------------------------------- 1.3087 +bool 1.3088 +nsPrintEngine::IsWindowsInOurSubTree(nsPIDOMWindow * window) 1.3089 +{ 1.3090 + bool found = false; 1.3091 + 1.3092 + // now check to make sure it is in "our" tree of docshells 1.3093 + if (window) { 1.3094 + nsCOMPtr<nsIDocShell> docShell = window->GetDocShell(); 1.3095 + 1.3096 + if (docShell) { 1.3097 + // get this DocViewer docshell 1.3098 + nsCOMPtr<nsIDocShell> thisDVDocShell(do_QueryReferent(mContainer)); 1.3099 + while (!found) { 1.3100 + if (docShell) { 1.3101 + if (docShell == thisDVDocShell) { 1.3102 + found = true; 1.3103 + break; 1.3104 + } 1.3105 + } else { 1.3106 + break; // at top of tree 1.3107 + } 1.3108 + nsCOMPtr<nsIDocShellTreeItem> docShellItemParent; 1.3109 + docShell->GetSameTypeParent(getter_AddRefs(docShellItemParent)); 1.3110 + docShell = do_QueryInterface(docShellItemParent); 1.3111 + } // while 1.3112 + } 1.3113 + } // scriptobj 1.3114 + 1.3115 + return found; 1.3116 +} 1.3117 + 1.3118 +//------------------------------------------------------- 1.3119 +bool 1.3120 +nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult) 1.3121 +{ 1.3122 + //NS_ASSERTION(aPO, "Pointer is null!"); 1.3123 + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:"")); 1.3124 + 1.3125 + // If there is a pageSeqFrame, make sure there are no more printCanvas active 1.3126 + // that might call |Notify| on the pagePrintTimer after things are cleaned up 1.3127 + // and printing was marked as being done. 1.3128 + if (mPageSeqFrame) { 1.3129 + mPageSeqFrame->ResetPrintCanvasList(); 1.3130 + } 1.3131 + 1.3132 + if (aPO && !mPrt->mIsAborted) { 1.3133 + aPO->mHasBeenPrinted = true; 1.3134 + nsresult rv; 1.3135 + bool didPrint = PrintDocContent(mPrt->mPrintObject, rv); 1.3136 + if (NS_SUCCEEDED(rv) && didPrint) { 1.3137 + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint))); 1.3138 + return false; 1.3139 + } 1.3140 + } 1.3141 + 1.3142 + if (NS_SUCCEEDED(aResult)) { 1.3143 + FirePrintCompletionEvent(); 1.3144 + } 1.3145 + 1.3146 + TurnScriptingOn(true); 1.3147 + SetIsPrinting(false); 1.3148 + 1.3149 + // Release reference to mPagePrintTimer; the timer object destroys itself 1.3150 + // after this returns true 1.3151 + NS_IF_RELEASE(mPagePrintTimer); 1.3152 + 1.3153 + return true; 1.3154 +} 1.3155 + 1.3156 +//------------------------------------------------------- 1.3157 +// Recursively sets the PO items to be printed "As Is" 1.3158 +// from the given item down into the tree 1.3159 +void 1.3160 +nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, bool aAsIs) 1.3161 +{ 1.3162 + NS_ASSERTION(aPO, "Pointer is null!"); 1.3163 + 1.3164 + aPO->mPrintAsIs = aAsIs; 1.3165 + for (uint32_t i=0;i<aPO->mKids.Length();i++) { 1.3166 + SetPrintAsIs(aPO->mKids[i], aAsIs); 1.3167 + } 1.3168 +} 1.3169 + 1.3170 +//------------------------------------------------------- 1.3171 +// Given a DOMWindow it recursively finds the PO object that matches 1.3172 +nsPrintObject* 1.3173 +nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO, 1.3174 + nsIDOMWindow* aDOMWin) 1.3175 +{ 1.3176 + NS_ASSERTION(aPO, "Pointer is null!"); 1.3177 + 1.3178 + // Often the CurFocused DOMWindow is passed in 1.3179 + // andit is valid for it to be null, so short circut 1.3180 + if (!aDOMWin) { 1.3181 + return nullptr; 1.3182 + } 1.3183 + 1.3184 + nsCOMPtr<nsIDOMDocument> domDoc; 1.3185 + aDOMWin->GetDocument(getter_AddRefs(domDoc)); 1.3186 + nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); 1.3187 + if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) { 1.3188 + return aPO; 1.3189 + } 1.3190 + 1.3191 + int32_t cnt = aPO->mKids.Length(); 1.3192 + for (int32_t i = 0; i < cnt; ++i) { 1.3193 + nsPrintObject* po = FindPrintObjectByDOMWin(aPO->mKids[i], aDOMWin); 1.3194 + if (po) { 1.3195 + return po; 1.3196 + } 1.3197 + } 1.3198 + 1.3199 + return nullptr; 1.3200 +} 1.3201 + 1.3202 +//------------------------------------------------------- 1.3203 +nsresult 1.3204 +nsPrintEngine::EnablePOsForPrinting() 1.3205 +{ 1.3206 + // NOTE: All POs have been "turned off" for printing 1.3207 + // this is where we decided which POs get printed. 1.3208 + mPrt->mSelectedPO = nullptr; 1.3209 + 1.3210 + if (mPrt->mPrintSettings == nullptr) { 1.3211 + return NS_ERROR_FAILURE; 1.3212 + } 1.3213 + 1.3214 + mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames; 1.3215 + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); 1.3216 + 1.3217 + int16_t printHowEnable = nsIPrintSettings::kFrameEnableNone; 1.3218 + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); 1.3219 + 1.3220 + int16_t printRangeType = nsIPrintSettings::kRangeAllPages; 1.3221 + mPrt->mPrintSettings->GetPrintRange(&printRangeType); 1.3222 + 1.3223 + PR_PL(("\n")); 1.3224 + PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n")); 1.3225 + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); 1.3226 + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); 1.3227 + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); 1.3228 + PR_PL(("----\n")); 1.3229 + 1.3230 + // ***** This is the ultimate override ***** 1.3231 + // if we are printing the selection (either an IFrame or selection range) 1.3232 + // then set the mPrintFrameType as if it were the selected frame 1.3233 + if (printRangeType == nsIPrintSettings::kRangeSelection) { 1.3234 + mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame; 1.3235 + printHowEnable = nsIPrintSettings::kFrameEnableNone; 1.3236 + } 1.3237 + 1.3238 + // This tells us that the "Frame" UI has turned off, 1.3239 + // so therefore there are no FrameSets/Frames/IFrames to be printed 1.3240 + // 1.3241 + // This means there are not FrameSets, 1.3242 + // but the document could contain an IFrame 1.3243 + if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { 1.3244 + 1.3245 + // Print all the pages or a sub range of pages 1.3246 + if (printRangeType == nsIPrintSettings::kRangeAllPages || 1.3247 + printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { 1.3248 + SetPrintPO(mPrt->mPrintObject, true); 1.3249 + 1.3250 + // Set the children so they are PrinAsIs 1.3251 + // In this case, the children are probably IFrames 1.3252 + if (mPrt->mPrintObject->mKids.Length() > 0) { 1.3253 + for (uint32_t i=0;i<mPrt->mPrintObject->mKids.Length();i++) { 1.3254 + nsPrintObject* po = mPrt->mPrintObject->mKids[i]; 1.3255 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3256 + SetPrintAsIs(po); 1.3257 + } 1.3258 + 1.3259 + // ***** Another override ***** 1.3260 + mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs; 1.3261 + } 1.3262 + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); 1.3263 + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); 1.3264 + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); 1.3265 + return NS_OK; 1.3266 + } 1.3267 + 1.3268 + // This means we are either printed a selected IFrame or 1.3269 + // we are printing the current selection 1.3270 + if (printRangeType == nsIPrintSettings::kRangeSelection) { 1.3271 + 1.3272 + // If the currentFocusDOMWin can'r be null if something is selected 1.3273 + if (mPrt->mCurrentFocusWin) { 1.3274 + // Find the selected IFrame 1.3275 + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); 1.3276 + if (po != nullptr) { 1.3277 + mPrt->mSelectedPO = po; 1.3278 + // Makes sure all of its children are be printed "AsIs" 1.3279 + SetPrintAsIs(po); 1.3280 + 1.3281 + // Now, only enable this POs (the selected PO) and all of its children 1.3282 + SetPrintPO(po, true); 1.3283 + 1.3284 + // check to see if we have a range selection, 1.3285 + // as oppose to a insert selection 1.3286 + // this means if the user just clicked on the IFrame then 1.3287 + // there will not be a selection so we want the entire page to print 1.3288 + // 1.3289 + // XXX this is sort of a hack right here to make the page 1.3290 + // not try to reposition itself when printing selection 1.3291 + nsCOMPtr<nsIDOMWindow> domWin = 1.3292 + do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow()); 1.3293 + if (!IsThereARangeSelection(domWin)) { 1.3294 + printRangeType = nsIPrintSettings::kRangeAllPages; 1.3295 + mPrt->mPrintSettings->SetPrintRange(printRangeType); 1.3296 + } 1.3297 + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); 1.3298 + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); 1.3299 + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); 1.3300 + return NS_OK; 1.3301 + } 1.3302 + } else { 1.3303 + for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) { 1.3304 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.3305 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3306 + nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell); 1.3307 + if (IsThereARangeSelection(domWin)) { 1.3308 + mPrt->mCurrentFocusWin = domWin; 1.3309 + SetPrintPO(po, true); 1.3310 + break; 1.3311 + } 1.3312 + } 1.3313 + return NS_OK; 1.3314 + } 1.3315 + } 1.3316 + } 1.3317 + 1.3318 + // check to see if there is a selection when a FrameSet is present 1.3319 + if (printRangeType == nsIPrintSettings::kRangeSelection) { 1.3320 + // If the currentFocusDOMWin can'r be null if something is selected 1.3321 + if (mPrt->mCurrentFocusWin) { 1.3322 + // Find the selected IFrame 1.3323 + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); 1.3324 + if (po != nullptr) { 1.3325 + mPrt->mSelectedPO = po; 1.3326 + // Makes sure all of its children are be printed "AsIs" 1.3327 + SetPrintAsIs(po); 1.3328 + 1.3329 + // Now, only enable this POs (the selected PO) and all of its children 1.3330 + SetPrintPO(po, true); 1.3331 + 1.3332 + // check to see if we have a range selection, 1.3333 + // as oppose to a insert selection 1.3334 + // this means if the user just clicked on the IFrame then 1.3335 + // there will not be a selection so we want the entire page to print 1.3336 + // 1.3337 + // XXX this is sort of a hack right here to make the page 1.3338 + // not try to reposition itself when printing selection 1.3339 + nsCOMPtr<nsIDOMWindow> domWin = 1.3340 + do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow()); 1.3341 + if (!IsThereARangeSelection(domWin)) { 1.3342 + printRangeType = nsIPrintSettings::kRangeAllPages; 1.3343 + mPrt->mPrintSettings->SetPrintRange(printRangeType); 1.3344 + } 1.3345 + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); 1.3346 + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); 1.3347 + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); 1.3348 + return NS_OK; 1.3349 + } 1.3350 + } 1.3351 + } 1.3352 + 1.3353 + // If we are printing "AsIs" then sets all the POs to be printed as is 1.3354 + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { 1.3355 + SetPrintAsIs(mPrt->mPrintObject); 1.3356 + SetPrintPO(mPrt->mPrintObject, true); 1.3357 + return NS_OK; 1.3358 + } 1.3359 + 1.3360 + // If we are printing the selected Frame then 1.3361 + // find that PO for that selected DOMWin and set it all of its 1.3362 + // children to be printed 1.3363 + if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { 1.3364 + 1.3365 + if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) { 1.3366 + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); 1.3367 + if (po != nullptr) { 1.3368 + mPrt->mSelectedPO = po; 1.3369 + // NOTE: Calling this sets the "po" and 1.3370 + // we don't want to do this for documents that have no children, 1.3371 + // because then the "DoEndPage" gets called and it shouldn't 1.3372 + if (po->mKids.Length() > 0) { 1.3373 + // Makes sure that itself, and all of its children are printed "AsIs" 1.3374 + SetPrintAsIs(po); 1.3375 + } 1.3376 + 1.3377 + // Now, only enable this POs (the selected PO) and all of its children 1.3378 + SetPrintPO(po, true); 1.3379 + } 1.3380 + } 1.3381 + return NS_OK; 1.3382 + } 1.3383 + 1.3384 + // If we are print each subdoc separately, 1.3385 + // then don't print any of the FraneSet Docs 1.3386 + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { 1.3387 + SetPrintPO(mPrt->mPrintObject, true); 1.3388 + int32_t cnt = mPrt->mPrintDocList.Length(); 1.3389 + for (int32_t i=0;i<cnt;i++) { 1.3390 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.3391 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3392 + if (po->mFrameType == eFrameSet) { 1.3393 + po->mDontPrint = true; 1.3394 + } 1.3395 + } 1.3396 + } 1.3397 + 1.3398 + return NS_OK; 1.3399 +} 1.3400 + 1.3401 +//------------------------------------------------------- 1.3402 +// Return the nsPrintObject with that is XMost (The widest frameset frame) AND 1.3403 +// contains the XMost (widest) layout frame 1.3404 +nsPrintObject* 1.3405 +nsPrintEngine::FindSmallestSTF() 1.3406 +{ 1.3407 + float smallestRatio = 1.0f; 1.3408 + nsPrintObject* smallestPO = nullptr; 1.3409 + 1.3410 + for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) { 1.3411 + nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i); 1.3412 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3413 + if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) { 1.3414 + if (po->mShrinkRatio < smallestRatio) { 1.3415 + smallestRatio = po->mShrinkRatio; 1.3416 + smallestPO = po; 1.3417 + } 1.3418 + } 1.3419 + } 1.3420 + 1.3421 +#ifdef EXTENDED_DEBUG_PRINTING 1.3422 + if (smallestPO) printf("*PO: %p Type: %d %10.3f\n", smallestPO, smallestPO->mFrameType, smallestPO->mShrinkRatio); 1.3423 +#endif 1.3424 + return smallestPO; 1.3425 +} 1.3426 + 1.3427 +//------------------------------------------------------- 1.3428 +void 1.3429 +nsPrintEngine::TurnScriptingOn(bool aDoTurnOn) 1.3430 +{ 1.3431 + if (mIsDoingPrinting && aDoTurnOn && mDocViewerPrint && 1.3432 + mDocViewerPrint->GetIsPrintPreview()) { 1.3433 + // We don't want to turn scripting on if print preview is shown still after 1.3434 + // printing. 1.3435 + return; 1.3436 + } 1.3437 + 1.3438 + nsPrintData* prt = mPrt; 1.3439 +#ifdef NS_PRINT_PREVIEW 1.3440 + if (!prt) { 1.3441 + prt = mPrtPreview; 1.3442 + } 1.3443 +#endif 1.3444 + if (!prt) { 1.3445 + return; 1.3446 + } 1.3447 + 1.3448 + NS_ASSERTION(mDocument, "We MUST have a document."); 1.3449 + // First, get the script global object from the document... 1.3450 + 1.3451 + for (uint32_t i=0;i<prt->mPrintDocList.Length();i++) { 1.3452 + nsPrintObject* po = prt->mPrintDocList.ElementAt(i); 1.3453 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3454 + 1.3455 + nsIDocument* doc = po->mDocument; 1.3456 + if (!doc) { 1.3457 + continue; 1.3458 + } 1.3459 + 1.3460 + if (nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow()) { 1.3461 + nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window); 1.3462 + NS_WARN_IF_FALSE(go && go->GetGlobalJSObject(), "Can't get global"); 1.3463 + nsresult propThere = NS_PROPTABLE_PROP_NOT_THERE; 1.3464 + doc->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview, 1.3465 + &propThere); 1.3466 + if (aDoTurnOn) { 1.3467 + if (propThere != NS_PROPTABLE_PROP_NOT_THERE) { 1.3468 + doc->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview); 1.3469 + if (go && go->GetGlobalJSObject()) { 1.3470 + xpc::Scriptability::Get(go->GetGlobalJSObject()).Unblock(); 1.3471 + } 1.3472 + window->ResumeTimeouts(false); 1.3473 + } 1.3474 + } else { 1.3475 + // Have to be careful, because people call us over and over again with 1.3476 + // aDoTurnOn == false. So don't set the property if it's already 1.3477 + // set, since in that case we'd set it to the wrong value. 1.3478 + if (propThere == NS_PROPTABLE_PROP_NOT_THERE) { 1.3479 + // Stash the current value of IsScriptEnabled on the document, so 1.3480 + // that layout code running in print preview doesn't get confused. 1.3481 + doc->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview, 1.3482 + NS_INT32_TO_PTR(doc->IsScriptEnabled())); 1.3483 + if (go && go->GetGlobalJSObject()) { 1.3484 + xpc::Scriptability::Get(go->GetGlobalJSObject()).Block(); 1.3485 + } 1.3486 + window->SuspendTimeouts(1, false); 1.3487 + } 1.3488 + } 1.3489 + } 1.3490 + } 1.3491 +} 1.3492 + 1.3493 +//----------------------------------------------------------------- 1.3494 +//-- Done: Misc Support Methods 1.3495 +//----------------------------------------------------------------- 1.3496 + 1.3497 + 1.3498 +//----------------------------------------------------------------- 1.3499 +//-- Section: Finishing up or Cleaning up 1.3500 +//----------------------------------------------------------------- 1.3501 + 1.3502 +//----------------------------------------------------------------- 1.3503 +void 1.3504 +nsPrintEngine::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener) 1.3505 +{ 1.3506 + if (aWebProgressListener) { 1.3507 + aWebProgressListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, NS_OK); 1.3508 + } 1.3509 +} 1.3510 + 1.3511 +//----------------------------------------------------------------- 1.3512 +nsresult 1.3513 +nsPrintEngine::FinishPrintPreview() 1.3514 +{ 1.3515 + nsresult rv = NS_OK; 1.3516 + 1.3517 +#ifdef NS_PRINT_PREVIEW 1.3518 + 1.3519 + if (!mPrt) { 1.3520 + /* we're already finished with print preview */ 1.3521 + return rv; 1.3522 + } 1.3523 + 1.3524 + rv = DocumentReadyForPrinting(); 1.3525 + 1.3526 + SetIsCreatingPrintPreview(false); 1.3527 + 1.3528 + /* cleaup on failure + notify user */ 1.3529 + if (NS_FAILED(rv)) { 1.3530 + /* cleanup done, let's fire-up an error dialog to notify the user 1.3531 + * what went wrong... 1.3532 + */ 1.3533 + mPrt->OnEndPrinting(); 1.3534 + TurnScriptingOn(true); 1.3535 + 1.3536 + return rv; 1.3537 + } 1.3538 + 1.3539 + // At this point we are done preparing everything 1.3540 + // before it is to be created 1.3541 + 1.3542 + 1.3543 + if (mIsDoingPrintPreview && mOldPrtPreview) { 1.3544 + delete mOldPrtPreview; 1.3545 + mOldPrtPreview = nullptr; 1.3546 + } 1.3547 + 1.3548 + 1.3549 + mPrt->OnEndPrinting(); 1.3550 + 1.3551 + // PrintPreview was built using the mPrt (code reuse) 1.3552 + // then we assign it over 1.3553 + mPrtPreview = mPrt; 1.3554 + mPrt = nullptr; 1.3555 + 1.3556 +#endif // NS_PRINT_PREVIEW 1.3557 + 1.3558 + return NS_OK; 1.3559 +} 1.3560 + 1.3561 +//----------------------------------------------------------------- 1.3562 +//-- Done: Finishing up or Cleaning up 1.3563 +//----------------------------------------------------------------- 1.3564 + 1.3565 + 1.3566 +/*=============== Timer Related Code ======================*/ 1.3567 +nsresult 1.3568 +nsPrintEngine::StartPagePrintTimer(nsPrintObject* aPO) 1.3569 +{ 1.3570 + if (!mPagePrintTimer) { 1.3571 + // Get the delay time in between the printing of each page 1.3572 + // this gives the user more time to press cancel 1.3573 + int32_t printPageDelay = 50; 1.3574 + mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay); 1.3575 + 1.3576 + nsRefPtr<nsPagePrintTimer> timer = 1.3577 + new nsPagePrintTimer(this, mDocViewerPrint, printPageDelay); 1.3578 + timer.forget(&mPagePrintTimer); 1.3579 + } 1.3580 + 1.3581 + return mPagePrintTimer->Start(aPO); 1.3582 +} 1.3583 + 1.3584 +/*=============== nsIObserver Interface ======================*/ 1.3585 +NS_IMETHODIMP 1.3586 +nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) 1.3587 +{ 1.3588 + nsresult rv = NS_ERROR_FAILURE; 1.3589 + 1.3590 + rv = InitPrintDocConstruction(true); 1.3591 + if (!mIsDoingPrinting && mPrtPreview) { 1.3592 + mPrtPreview->OnEndPrinting(); 1.3593 + } 1.3594 + 1.3595 + return rv; 1.3596 + 1.3597 +} 1.3598 + 1.3599 +//--------------------------------------------------------------- 1.3600 +//-- PLEvent Notification 1.3601 +//--------------------------------------------------------------- 1.3602 +class nsPrintCompletionEvent : public nsRunnable { 1.3603 +public: 1.3604 + nsPrintCompletionEvent(nsIDocumentViewerPrint *docViewerPrint) 1.3605 + : mDocViewerPrint(docViewerPrint) { 1.3606 + NS_ASSERTION(mDocViewerPrint, "mDocViewerPrint is null."); 1.3607 + } 1.3608 + 1.3609 + NS_IMETHOD Run() MOZ_OVERRIDE { 1.3610 + if (mDocViewerPrint) 1.3611 + mDocViewerPrint->OnDonePrinting(); 1.3612 + return NS_OK; 1.3613 + } 1.3614 + 1.3615 +private: 1.3616 + nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint; 1.3617 +}; 1.3618 + 1.3619 +//----------------------------------------------------------- 1.3620 +void 1.3621 +nsPrintEngine::FirePrintCompletionEvent() 1.3622 +{ 1.3623 + nsCOMPtr<nsIRunnable> event = new nsPrintCompletionEvent(mDocViewerPrint); 1.3624 + if (NS_FAILED(NS_DispatchToCurrentThread(event))) 1.3625 + NS_WARNING("failed to dispatch print completion event"); 1.3626 +} 1.3627 + 1.3628 +//--------------------------------------------------------------- 1.3629 +//--------------------------------------------------------------- 1.3630 +//-- Debug helper routines 1.3631 +//--------------------------------------------------------------- 1.3632 +//--------------------------------------------------------------- 1.3633 +#if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING) 1.3634 +#include "windows.h" 1.3635 +#include "process.h" 1.3636 +#include "direct.h" 1.3637 + 1.3638 +#define MY_FINDFIRST(a,b) FindFirstFile(a,b) 1.3639 +#define MY_FINDNEXT(a,b) FindNextFile(a,b) 1.3640 +#define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 1.3641 +#define MY_FINDCLOSE(a) FindClose(a) 1.3642 +#define MY_FILENAME(a) a.cFileName 1.3643 +#define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow 1.3644 + 1.3645 +int RemoveFilesInDir(const char * aDir) 1.3646 +{ 1.3647 + WIN32_FIND_DATA data_ptr; 1.3648 + HANDLE find_handle; 1.3649 + 1.3650 + char path[MAX_PATH]; 1.3651 + 1.3652 + strcpy(path, aDir); 1.3653 + 1.3654 + // Append slash to the end of the directory names if not there 1.3655 + if (path[strlen(path)-1] != '\\') 1.3656 + strcat(path, "\\"); 1.3657 + 1.3658 + char findPath[MAX_PATH]; 1.3659 + strcpy(findPath, path); 1.3660 + strcat(findPath, "*.*"); 1.3661 + 1.3662 + find_handle = MY_FINDFIRST(findPath, &data_ptr); 1.3663 + 1.3664 + if (find_handle != INVALID_HANDLE_VALUE) { 1.3665 + do { 1.3666 + if (ISDIR(data_ptr) 1.3667 + && (stricmp(MY_FILENAME(data_ptr),".")) 1.3668 + && (stricmp(MY_FILENAME(data_ptr),".."))) { 1.3669 + // skip 1.3670 + } 1.3671 + else if (!ISDIR(data_ptr)) { 1.3672 + if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) { 1.3673 + char fileName[MAX_PATH]; 1.3674 + strcpy(fileName, aDir); 1.3675 + strcat(fileName, "\\"); 1.3676 + strcat(fileName, MY_FILENAME(data_ptr)); 1.3677 + printf("Removing %s\n", fileName); 1.3678 + remove(fileName); 1.3679 + } 1.3680 + } 1.3681 + } while(MY_FINDNEXT(find_handle,&data_ptr)); 1.3682 + MY_FINDCLOSE(find_handle); 1.3683 + } 1.3684 + return TRUE; 1.3685 +} 1.3686 +#endif 1.3687 + 1.3688 +#ifdef EXTENDED_DEBUG_PRINTING 1.3689 + 1.3690 +/** --------------------------------------------------- 1.3691 + * Dumps Frames for Printing 1.3692 + */ 1.3693 +static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent) 1.3694 +{ 1.3695 + if (!aPresContext || !out) 1.3696 + return; 1.3697 + 1.3698 + nsIPresShell *shell = aPresContext->GetPresShell(); 1.3699 + if (shell) { 1.3700 + nsIFrame* frame = shell->FrameManager()->GetRootFrame(); 1.3701 + if (frame) { 1.3702 + frame->List(aPresContext, out, aIndent); 1.3703 + } 1.3704 + } 1.3705 +} 1.3706 + 1.3707 +/** --------------------------------------------------- 1.3708 + * Dumps Frames for Printing 1.3709 + */ 1.3710 +static void DumpFrames(FILE* out, 1.3711 + nsPresContext* aPresContext, 1.3712 + nsRenderingContext * aRendContext, 1.3713 + nsIFrame * aFrame, 1.3714 + int32_t aLevel) 1.3715 +{ 1.3716 + NS_ASSERTION(out, "Pointer is null!"); 1.3717 + NS_ASSERTION(aPresContext, "Pointer is null!"); 1.3718 + NS_ASSERTION(aRendContext, "Pointer is null!"); 1.3719 + NS_ASSERTION(aFrame, "Pointer is null!"); 1.3720 + 1.3721 + nsIFrame* child = aFrame->GetFirstPrincipalChild(); 1.3722 + while (child != nullptr) { 1.3723 + for (int32_t i=0;i<aLevel;i++) { 1.3724 + fprintf(out, " "); 1.3725 + } 1.3726 + nsAutoString tmp; 1.3727 + child->GetFrameName(tmp); 1.3728 + fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out); 1.3729 + bool isSelected; 1.3730 + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, true, &isSelected))) { 1.3731 + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); 1.3732 + nsRect rect = child->GetRect(); 1.3733 + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); 1.3734 + fprintf(out, "v: %p ", (void*)child->GetView()); 1.3735 + fprintf(out, "\n"); 1.3736 + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); 1.3737 + child = child->GetNextSibling(); 1.3738 + } 1.3739 + } 1.3740 +} 1.3741 + 1.3742 + 1.3743 +/** --------------------------------------------------- 1.3744 + * Dumps the Views from the DocShell 1.3745 + */ 1.3746 +static void 1.3747 +DumpViews(nsIDocShell* aDocShell, FILE* out) 1.3748 +{ 1.3749 + NS_ASSERTION(aDocShell, "Pointer is null!"); 1.3750 + NS_ASSERTION(out, "Pointer is null!"); 1.3751 + 1.3752 + if (nullptr != aDocShell) { 1.3753 + fprintf(out, "docshell=%p \n", aDocShell); 1.3754 + nsIPresShell* shell = nsPrintEngine::GetPresShellFor(aDocShell); 1.3755 + if (shell) { 1.3756 + nsViewManager* vm = shell->GetViewManager(); 1.3757 + if (vm) { 1.3758 + nsView* root = vm->GetRootView(); 1.3759 + if (root) { 1.3760 + root->List(out); 1.3761 + } 1.3762 + } 1.3763 + } 1.3764 + else { 1.3765 + fputs("null pres shell\n", out); 1.3766 + } 1.3767 + 1.3768 + // dump the views of the sub documents 1.3769 + int32_t i, n; 1.3770 + aDocShell->GetChildCount(&n); 1.3771 + for (i = 0; i < n; i++) { 1.3772 + nsCOMPtr<nsIDocShellTreeItem> child; 1.3773 + aDocShell->GetChildAt(i, getter_AddRefs(child)); 1.3774 + nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child)); 1.3775 + if (childAsShell) { 1.3776 + DumpViews(childAsShell, out); 1.3777 + } 1.3778 + } 1.3779 + } 1.3780 +} 1.3781 + 1.3782 +/** --------------------------------------------------- 1.3783 + * Dumps the Views and Frames 1.3784 + */ 1.3785 +void DumpLayoutData(char* aTitleStr, 1.3786 + char* aURLStr, 1.3787 + nsPresContext* aPresContext, 1.3788 + nsDeviceContext * aDC, 1.3789 + nsIFrame * aRootFrame, 1.3790 + nsIDocShekk * aDocShell, 1.3791 + FILE* aFD = nullptr) 1.3792 +{ 1.3793 + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; 1.3794 + 1.3795 + if (aPresContext == nullptr || aDC == nullptr) { 1.3796 + return; 1.3797 + } 1.3798 + 1.3799 +#ifdef NS_PRINT_PREVIEW 1.3800 + if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) { 1.3801 + return; 1.3802 + } 1.3803 +#endif 1.3804 + 1.3805 + NS_ASSERTION(aRootFrame, "Pointer is null!"); 1.3806 + NS_ASSERTION(aDocShell, "Pointer is null!"); 1.3807 + 1.3808 + // Dump all the frames and view to a a file 1.3809 + char filename[256]; 1.3810 + sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++); 1.3811 + FILE * fd = aFD?aFD:fopen(filename, "w"); 1.3812 + if (fd) { 1.3813 + fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:""); 1.3814 + fprintf(fd, "URL: %s\n", aURLStr?aURLStr:""); 1.3815 + fprintf(fd, "--------------- Frames ----------------\n"); 1.3816 + fprintf(fd, "--------------- Frames ----------------\n"); 1.3817 + nsRefPtr<nsRenderingContext> renderingContext = 1.3818 + aDC->CreateRenderingContext(); 1.3819 + RootFrameList(aPresContext, fd, 0); 1.3820 + //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); 1.3821 + fprintf(fd, "---------------------------------------\n\n"); 1.3822 + fprintf(fd, "--------------- Views From Root Frame----------------\n"); 1.3823 + nsView* v = aRootFrame->GetView(); 1.3824 + if (v) { 1.3825 + v->List(fd); 1.3826 + } else { 1.3827 + printf("View is null!\n"); 1.3828 + } 1.3829 + if (aDocShell) { 1.3830 + fprintf(fd, "--------------- All Views ----------------\n"); 1.3831 + DumpViews(aDocShell, fd); 1.3832 + fprintf(fd, "---------------------------------------\n\n"); 1.3833 + } 1.3834 + if (aFD == nullptr) { 1.3835 + fclose(fd); 1.3836 + } 1.3837 + } 1.3838 +} 1.3839 + 1.3840 +//------------------------------------------------------------- 1.3841 +static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList) 1.3842 +{ 1.3843 + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; 1.3844 + 1.3845 + NS_ASSERTION(aDocList, "Pointer is null!"); 1.3846 + 1.3847 + const char types[][3] = {"DC", "FR", "IF", "FS"}; 1.3848 + PR_PL(("Doc List\n***************************************************\n")); 1.3849 + PR_PL(("T P A H PO DocShell Seq Page Root Page# Rect\n")); 1.3850 + int32_t cnt = aDocList->Length(); 1.3851 + for (int32_t i=0;i<cnt;i++) { 1.3852 + nsPrintObject* po = aDocList->ElementAt(i); 1.3853 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3854 + nsIFrame* rootFrame = nullptr; 1.3855 + if (po->mPresShell) { 1.3856 + rootFrame = po->mPresShell->FrameManager()->GetRootFrame(); 1.3857 + while (rootFrame != nullptr) { 1.3858 + nsIPageSequenceFrame * sqf = do_QueryFrame(rootFrame); 1.3859 + if (sqf) { 1.3860 + break; 1.3861 + } 1.3862 + rootFrame = rootFrame->GetFirstPrincipalChild(); 1.3863 + } 1.3864 + } 1.3865 + 1.3866 + PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], 1.3867 + po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mDocShell.get(), po->mSeqFrame, 1.3868 + po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height)); 1.3869 + } 1.3870 +} 1.3871 + 1.3872 +//------------------------------------------------------------- 1.3873 +static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD) 1.3874 +{ 1.3875 + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; 1.3876 + 1.3877 + NS_ASSERTION(aPO, "Pointer is null!"); 1.3878 + 1.3879 + FILE * fd = aFD?aFD:stdout; 1.3880 + const char types[][3] = {"DC", "FR", "IF", "FS"}; 1.3881 + if (aLevel == 0) { 1.3882 + fprintf(fd, "DocTree\n***************************************************\n"); 1.3883 + fprintf(fd, "T PO DocShell Seq Page Page# Rect\n"); 1.3884 + } 1.3885 + int32_t cnt = aPO->mKids.Length(); 1.3886 + for (int32_t i=0;i<cnt;i++) { 1.3887 + nsPrintObject* po = aPO->mKids.ElementAt(i); 1.3888 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3889 + for (int32_t k=0;k<aLevel;k++) fprintf(fd, " "); 1.3890 + fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], po, po->mDocShell.get(), po->mSeqFrame, 1.3891 + po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height); 1.3892 + } 1.3893 +} 1.3894 + 1.3895 +//------------------------------------------------------------- 1.3896 +static void GetDocTitleAndURL(nsPrintObject* aPO, nsACString& aDocStr, nsACString& aURLStr) 1.3897 +{ 1.3898 + nsAutoString docTitleStr; 1.3899 + nsAutoString docURLStr; 1.3900 + nsPrintEngine::GetDisplayTitleAndURL(aPO, 1.3901 + docTitleStr, docURLStr, 1.3902 + nsPrintEngine::eDocTitleDefURLDoc); 1.3903 + aDocStr = NS_ConvertUTF16toUTF8(docTitleStr); 1.3904 + aURLStr = NS_ConvertUTF16toUTF8(docURLStr); 1.3905 +} 1.3906 + 1.3907 +//------------------------------------------------------------- 1.3908 +static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO, 1.3909 + nsDeviceContext * aDC, 1.3910 + int aLevel, FILE * aFD) 1.3911 +{ 1.3912 + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; 1.3913 + 1.3914 + NS_ASSERTION(aPO, "Pointer is null!"); 1.3915 + NS_ASSERTION(aDC, "Pointer is null!"); 1.3916 + 1.3917 + const char types[][3] = {"DC", "FR", "IF", "FS"}; 1.3918 + FILE * fd = nullptr; 1.3919 + if (aLevel == 0) { 1.3920 + fd = fopen("tree_layout.txt", "w"); 1.3921 + fprintf(fd, "DocTree\n***************************************************\n"); 1.3922 + fprintf(fd, "***************************************************\n"); 1.3923 + fprintf(fd, "T PO DocShell Seq Page Page# Rect\n"); 1.3924 + } else { 1.3925 + fd = aFD; 1.3926 + } 1.3927 + if (fd) { 1.3928 + nsIFrame* rootFrame = nullptr; 1.3929 + if (aPO->mPresShell) { 1.3930 + rootFrame = aPO->mPresShell->FrameManager()->GetRootFrame(); 1.3931 + } 1.3932 + for (int32_t k=0;k<aLevel;k++) fprintf(fd, " "); 1.3933 + fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[aPO->mFrameType], aPO, aPO->mDocShell.get(), aPO->mSeqFrame, 1.3934 + aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height); 1.3935 + if (aPO->IsPrintable()) { 1.3936 + nsAutoCString docStr; 1.3937 + nsAutoCString urlStr; 1.3938 + GetDocTitleAndURL(aPO, docStr, urlStr); 1.3939 + DumpLayoutData(docStr.get(), urlStr.get(), aPO->mPresContext, aDC, rootFrame, aPO->mDocShell, fd); 1.3940 + } 1.3941 + fprintf(fd, "<***************************************************>\n"); 1.3942 + 1.3943 + int32_t cnt = aPO->mKids.Length(); 1.3944 + for (int32_t i=0;i<cnt;i++) { 1.3945 + nsPrintObject* po = aPO->mKids.ElementAt(i); 1.3946 + NS_ASSERTION(po, "nsPrintObject can't be null!"); 1.3947 + DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd); 1.3948 + } 1.3949 + } 1.3950 + if (aLevel == 0 && fd) { 1.3951 + fclose(fd); 1.3952 + } 1.3953 +} 1.3954 + 1.3955 +//------------------------------------------------------------- 1.3956 +static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList) 1.3957 +{ 1.3958 + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; 1.3959 + 1.3960 + NS_ASSERTION(aStr, "Pointer is null!"); 1.3961 + NS_ASSERTION(aDocList, "Pointer is null!"); 1.3962 + 1.3963 + PR_PL(("%s\n", aStr)); 1.3964 + DumpPrintObjectsList(aDocList); 1.3965 +} 1.3966 + 1.3967 +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); 1.3968 +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); 1.3969 +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); 1.3970 + 1.3971 +#else 1.3972 +#define DUMP_DOC_LIST(_title) 1.3973 +#define DUMP_DOC_TREE 1.3974 +#define DUMP_DOC_TREELAYOUT 1.3975 +#endif 1.3976 + 1.3977 +//--------------------------------------------------------------- 1.3978 +//--------------------------------------------------------------- 1.3979 +//-- End of debug helper routines 1.3980 +//---------------------------------------------------------------