layout/printing/nsPrintEngine.cpp

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsPrintEngine.h"
michael@0 7
michael@0 8 #include "nsIStringBundle.h"
michael@0 9 #include "nsReadableUtils.h"
michael@0 10 #include "nsCRT.h"
michael@0 11
michael@0 12 #include "mozilla/AsyncEventDispatcher.h"
michael@0 13 #include "mozilla/dom/Selection.h"
michael@0 14 #include "nsIScriptGlobalObject.h"
michael@0 15 #include "nsPIDOMWindow.h"
michael@0 16 #include "nsIDocShell.h"
michael@0 17 #include "nsIFrame.h"
michael@0 18 #include "nsIURI.h"
michael@0 19 #include "nsITextToSubURI.h"
michael@0 20 #include "nsError.h"
michael@0 21
michael@0 22 #include "nsView.h"
michael@0 23 #include <algorithm>
michael@0 24
michael@0 25 // Print Options
michael@0 26 #include "nsIPrintSettings.h"
michael@0 27 #include "nsIPrintSettingsService.h"
michael@0 28 #include "nsIPrintOptions.h"
michael@0 29 #include "nsIPrintSession.h"
michael@0 30 #include "nsGfxCIID.h"
michael@0 31 #include "nsIServiceManager.h"
michael@0 32 #include "nsGkAtoms.h"
michael@0 33 #include "nsXPCOM.h"
michael@0 34 #include "nsISupportsPrimitives.h"
michael@0 35
michael@0 36 static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1";
michael@0 37
michael@0 38 // Printing Events
michael@0 39 #include "nsPrintPreviewListener.h"
michael@0 40 #include "nsThreadUtils.h"
michael@0 41
michael@0 42 // Printing
michael@0 43 #include "nsIWebBrowserPrint.h"
michael@0 44 #include "nsIDOMHTMLFrameElement.h"
michael@0 45 #include "nsIDOMHTMLFrameSetElement.h"
michael@0 46 #include "nsIDOMHTMLIFrameElement.h"
michael@0 47 #include "nsIDOMHTMLObjectElement.h"
michael@0 48 #include "nsIDOMHTMLEmbedElement.h"
michael@0 49
michael@0 50 // Print Preview
michael@0 51 #include "imgIContainer.h" // image animation mode constants
michael@0 52 #include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants
michael@0 53
michael@0 54 // Print Progress
michael@0 55 #include "nsIPrintProgress.h"
michael@0 56 #include "nsIPrintProgressParams.h"
michael@0 57 #include "nsIObserver.h"
michael@0 58
michael@0 59 // Print error dialog
michael@0 60 #include "nsIPrompt.h"
michael@0 61 #include "nsIWindowWatcher.h"
michael@0 62
michael@0 63 // Printing Prompts
michael@0 64 #include "nsIPrintingPromptService.h"
michael@0 65 static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingprompt-service;1";
michael@0 66
michael@0 67 // Printing Timer
michael@0 68 #include "nsPagePrintTimer.h"
michael@0 69
michael@0 70 // FrameSet
michael@0 71 #include "nsIDocument.h"
michael@0 72
michael@0 73 // Focus
michael@0 74 #include "nsISelectionController.h"
michael@0 75
michael@0 76 // Misc
michael@0 77 #include "nsISupportsUtils.h"
michael@0 78 #include "nsIScriptContext.h"
michael@0 79 #include "nsIDOMDocument.h"
michael@0 80 #include "nsISelectionListener.h"
michael@0 81 #include "nsISelectionPrivate.h"
michael@0 82 #include "nsIDOMRange.h"
michael@0 83 #include "nsContentCID.h"
michael@0 84 #include "nsLayoutCID.h"
michael@0 85 #include "nsContentUtils.h"
michael@0 86 #include "nsIPresShell.h"
michael@0 87 #include "nsLayoutUtils.h"
michael@0 88 #include "mozilla/Preferences.h"
michael@0 89
michael@0 90 #include "nsWidgetsCID.h"
michael@0 91 #include "nsIDeviceContextSpec.h"
michael@0 92 #include "nsViewManager.h"
michael@0 93 #include "nsView.h"
michael@0 94 #include "nsRenderingContext.h"
michael@0 95
michael@0 96 #include "nsIPageSequenceFrame.h"
michael@0 97 #include "nsIURL.h"
michael@0 98 #include "nsIContentViewerEdit.h"
michael@0 99 #include "nsIContentViewerFile.h"
michael@0 100 #include "nsIMarkupDocumentViewer.h"
michael@0 101 #include "nsIInterfaceRequestor.h"
michael@0 102 #include "nsIInterfaceRequestorUtils.h"
michael@0 103 #include "nsIDocShellTreeOwner.h"
michael@0 104 #include "nsIWebBrowserChrome.h"
michael@0 105 #include "nsIBaseWindow.h"
michael@0 106 #include "nsILayoutHistoryState.h"
michael@0 107 #include "nsFrameManager.h"
michael@0 108 #include "nsHTMLReflowState.h"
michael@0 109 #include "nsIDOMHTMLAnchorElement.h"
michael@0 110 #include "nsIDOMHTMLAreaElement.h"
michael@0 111 #include "nsIDOMHTMLLinkElement.h"
michael@0 112 #include "nsIDOMHTMLImageElement.h"
michael@0 113 #include "nsIContentViewerContainer.h"
michael@0 114 #include "nsIContentViewer.h"
michael@0 115 #include "nsIDocumentViewerPrint.h"
michael@0 116
michael@0 117 #include "nsFocusManager.h"
michael@0 118 #include "nsRange.h"
michael@0 119 #include "nsCDefaultURIFixup.h"
michael@0 120 #include "nsIURIFixup.h"
michael@0 121 #include "mozilla/dom/Element.h"
michael@0 122 #include "nsContentList.h"
michael@0 123 #include "nsIChannel.h"
michael@0 124 #include "xpcpublic.h"
michael@0 125
michael@0 126 using namespace mozilla;
michael@0 127 using namespace mozilla::dom;
michael@0 128
michael@0 129 //-----------------------------------------------------
michael@0 130 // PR LOGGING
michael@0 131 #ifdef MOZ_LOGGING
michael@0 132 #define FORCE_PR_LOG /* Allow logging in the release build */
michael@0 133 #endif
michael@0 134
michael@0 135 #include "prlog.h"
michael@0 136
michael@0 137 #ifdef PR_LOGGING
michael@0 138
michael@0 139 #ifdef DEBUG
michael@0 140 // PR_LOGGING is force to always be on (even in release builds)
michael@0 141 // but we only want some of it on,
michael@0 142 //#define EXTENDED_DEBUG_PRINTING
michael@0 143 #endif
michael@0 144
michael@0 145 #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
michael@0 146
michael@0 147 #ifndef PR_PL
michael@0 148 static PRLogModuleInfo *
michael@0 149 GetPrintingLog()
michael@0 150 {
michael@0 151 static PRLogModuleInfo *sLog;
michael@0 152 if (!sLog)
michael@0 153 sLog = PR_NewLogModule("printing");
michael@0 154 return sLog;
michael@0 155 }
michael@0 156 #define PR_PL(_p1) PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1);
michael@0 157 #endif
michael@0 158
michael@0 159 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 160 static uint32_t gDumpFileNameCnt = 0;
michael@0 161 static uint32_t gDumpLOFileNameCnt = 0;
michael@0 162 #endif
michael@0 163
michael@0 164 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
michael@0 165 static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"};
michael@0 166 static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"};
michael@0 167 static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"};
michael@0 168 static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"};
michael@0 169 #else
michael@0 170 #define PRT_YESNO(_p)
michael@0 171 #define PR_PL(_p1)
michael@0 172 #endif
michael@0 173
michael@0 174 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 175 // Forward Declarations
michael@0 176 static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList);
michael@0 177 static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nullptr);
michael@0 178 static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsDeviceContext * aDC, int aLevel= 0, FILE * aFD = nullptr);
michael@0 179
michael@0 180 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
michael@0 181 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
michael@0 182 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
michael@0 183 #else
michael@0 184 #define DUMP_DOC_LIST(_title)
michael@0 185 #define DUMP_DOC_TREE
michael@0 186 #define DUMP_DOC_TREELAYOUT
michael@0 187 #endif
michael@0 188
michael@0 189 class nsScriptSuppressor
michael@0 190 {
michael@0 191 public:
michael@0 192 nsScriptSuppressor(nsPrintEngine* aPrintEngine)
michael@0 193 : mPrintEngine(aPrintEngine), mSuppressed(false) {}
michael@0 194
michael@0 195 ~nsScriptSuppressor() { Unsuppress(); }
michael@0 196
michael@0 197 void Suppress()
michael@0 198 {
michael@0 199 if (mPrintEngine) {
michael@0 200 mSuppressed = true;
michael@0 201 mPrintEngine->TurnScriptingOn(false);
michael@0 202 }
michael@0 203 }
michael@0 204
michael@0 205 void Unsuppress()
michael@0 206 {
michael@0 207 if (mPrintEngine && mSuppressed) {
michael@0 208 mPrintEngine->TurnScriptingOn(true);
michael@0 209 }
michael@0 210 mSuppressed = false;
michael@0 211 }
michael@0 212
michael@0 213 void Disconnect() { mPrintEngine = nullptr; }
michael@0 214 protected:
michael@0 215 nsRefPtr<nsPrintEngine> mPrintEngine;
michael@0 216 bool mSuppressed;
michael@0 217 };
michael@0 218
michael@0 219 NS_IMPL_ISUPPORTS(nsPrintEngine, nsIWebProgressListener,
michael@0 220 nsISupportsWeakReference, nsIObserver)
michael@0 221
michael@0 222 //---------------------------------------------------
michael@0 223 //-- nsPrintEngine Class Impl
michael@0 224 //---------------------------------------------------
michael@0 225 nsPrintEngine::nsPrintEngine() :
michael@0 226 mIsCreatingPrintPreview(false),
michael@0 227 mIsDoingPrinting(false),
michael@0 228 mIsDoingPrintPreview(false),
michael@0 229 mProgressDialogIsShown(false),
michael@0 230 mScreenDPI(115.0f),
michael@0 231 mPrt(nullptr),
michael@0 232 mPagePrintTimer(nullptr),
michael@0 233 mPageSeqFrame(nullptr),
michael@0 234 mPrtPreview(nullptr),
michael@0 235 mOldPrtPreview(nullptr),
michael@0 236 mDebugFile(nullptr),
michael@0 237 mLoadCounter(0),
michael@0 238 mDidLoadDataForPrinting(false),
michael@0 239 mIsDestroying(false),
michael@0 240 mDisallowSelectionPrint(false),
michael@0 241 mNoMarginBoxes(false)
michael@0 242 {
michael@0 243 }
michael@0 244
michael@0 245 //-------------------------------------------------------
michael@0 246 nsPrintEngine::~nsPrintEngine()
michael@0 247 {
michael@0 248 Destroy(); // for insurance
michael@0 249 }
michael@0 250
michael@0 251 //-------------------------------------------------------
michael@0 252 void nsPrintEngine::Destroy()
michael@0 253 {
michael@0 254 if (mIsDestroying) {
michael@0 255 return;
michael@0 256 }
michael@0 257 mIsDestroying = true;
michael@0 258
michael@0 259 if (mPrt) {
michael@0 260 delete mPrt;
michael@0 261 mPrt = nullptr;
michael@0 262 }
michael@0 263
michael@0 264 #ifdef NS_PRINT_PREVIEW
michael@0 265 if (mPrtPreview) {
michael@0 266 delete mPrtPreview;
michael@0 267 mPrtPreview = nullptr;
michael@0 268 }
michael@0 269
michael@0 270 // This is insruance
michael@0 271 if (mOldPrtPreview) {
michael@0 272 delete mOldPrtPreview;
michael@0 273 mOldPrtPreview = nullptr;
michael@0 274 }
michael@0 275
michael@0 276 #endif
michael@0 277 mDocViewerPrint = nullptr;
michael@0 278 }
michael@0 279
michael@0 280 //-------------------------------------------------------
michael@0 281 void nsPrintEngine::DestroyPrintingData()
michael@0 282 {
michael@0 283 if (mPrt) {
michael@0 284 nsPrintData* data = mPrt;
michael@0 285 mPrt = nullptr;
michael@0 286 delete data;
michael@0 287 }
michael@0 288 }
michael@0 289
michael@0 290 //---------------------------------------------------------------------------------
michael@0 291 //-- Section: Methods needed by the DocViewer
michael@0 292 //---------------------------------------------------------------------------------
michael@0 293
michael@0 294 //--------------------------------------------------------
michael@0 295 nsresult nsPrintEngine::Initialize(nsIDocumentViewerPrint* aDocViewerPrint,
michael@0 296 nsIDocShell* aContainer,
michael@0 297 nsIDocument* aDocument,
michael@0 298 float aScreenDPI,
michael@0 299 FILE* aDebugFile)
michael@0 300 {
michael@0 301 NS_ENSURE_ARG_POINTER(aDocViewerPrint);
michael@0 302 NS_ENSURE_ARG_POINTER(aContainer);
michael@0 303 NS_ENSURE_ARG_POINTER(aDocument);
michael@0 304
michael@0 305 mDocViewerPrint = aDocViewerPrint;
michael@0 306 mContainer = do_GetWeakReference(aContainer);
michael@0 307 mDocument = aDocument;
michael@0 308 mScreenDPI = aScreenDPI;
michael@0 309
michael@0 310 mDebugFile = aDebugFile; // ok to be nullptr
michael@0 311
michael@0 312 return NS_OK;
michael@0 313 }
michael@0 314
michael@0 315 //-------------------------------------------------------
michael@0 316 bool
michael@0 317 nsPrintEngine::CheckBeforeDestroy()
michael@0 318 {
michael@0 319 if (mPrt && mPrt->mPreparingForPrint) {
michael@0 320 mPrt->mDocWasToBeDestroyed = true;
michael@0 321 return true;
michael@0 322 }
michael@0 323 return false;
michael@0 324 }
michael@0 325
michael@0 326 //-------------------------------------------------------
michael@0 327 nsresult
michael@0 328 nsPrintEngine::Cancelled()
michael@0 329 {
michael@0 330 if (mPrt && mPrt->mPrintSettings) {
michael@0 331 return mPrt->mPrintSettings->SetIsCancelled(true);
michael@0 332 }
michael@0 333 return NS_ERROR_FAILURE;
michael@0 334 }
michael@0 335
michael@0 336 //-------------------------------------------------------
michael@0 337 // Install our event listeners on the document to prevent
michael@0 338 // some events from being processed while in PrintPreview
michael@0 339 //
michael@0 340 // No return code - if this fails, there isn't much we can do
michael@0 341 void
michael@0 342 nsPrintEngine::InstallPrintPreviewListener()
michael@0 343 {
michael@0 344 if (!mPrt->mPPEventListeners) {
michael@0 345 nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mContainer);
michael@0 346 nsCOMPtr<nsPIDOMWindow> win(do_GetInterface(docShell));
michael@0 347 if (win) {
michael@0 348 nsCOMPtr<EventTarget> target = do_QueryInterface(win->GetFrameElementInternal());
michael@0 349 mPrt->mPPEventListeners = new nsPrintPreviewListener(target);
michael@0 350 mPrt->mPPEventListeners->AddListeners();
michael@0 351 }
michael@0 352 }
michael@0 353 }
michael@0 354
michael@0 355 //----------------------------------------------------------------------
michael@0 356 nsresult
michael@0 357 nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO,
michael@0 358 nsIFrame*& aSeqFrame,
michael@0 359 int32_t& aCount)
michael@0 360 {
michael@0 361 NS_ENSURE_ARG_POINTER(aPO);
michael@0 362
michael@0 363 // Finds the SimplePageSequencer frame
michael@0 364 nsIPageSequenceFrame* seqFrame = aPO->mPresShell->GetPageSequenceFrame();
michael@0 365 aSeqFrame = do_QueryFrame(seqFrame);
michael@0 366 if (!aSeqFrame) {
michael@0 367 return NS_ERROR_FAILURE;
michael@0 368 }
michael@0 369
michael@0 370 // first count the total number of pages
michael@0 371 aCount = 0;
michael@0 372 nsIFrame* pageFrame = aSeqFrame->GetFirstPrincipalChild();
michael@0 373 while (pageFrame != nullptr) {
michael@0 374 aCount++;
michael@0 375 pageFrame = pageFrame->GetNextSibling();
michael@0 376 }
michael@0 377
michael@0 378 return NS_OK;
michael@0 379
michael@0 380 }
michael@0 381
michael@0 382 //-----------------------------------------------------------------
michael@0 383 nsresult nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, int32_t& aCount)
michael@0 384 {
michael@0 385 NS_ASSERTION(mPrtPreview, "mPrtPreview can't be null!");
michael@0 386 return GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, aSeqFrame, aCount);
michael@0 387 }
michael@0 388 //---------------------------------------------------------------------------------
michael@0 389 //-- Done: Methods needed by the DocViewer
michael@0 390 //---------------------------------------------------------------------------------
michael@0 391
michael@0 392
michael@0 393 //---------------------------------------------------------------------------------
michael@0 394 //-- Section: nsIWebBrowserPrint
michael@0 395 //---------------------------------------------------------------------------------
michael@0 396
michael@0 397 // Foward decl for Debug Helper Functions
michael@0 398 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 399 static int RemoveFilesInDir(const char * aDir);
michael@0 400 static void GetDocTitleAndURL(nsPrintObject* aPO, char *& aDocStr, char *& aURLStr);
michael@0 401 static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD);
michael@0 402 static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList);
michael@0 403 static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent);
michael@0 404 static void DumpViews(nsIDocShell* aDocShell, FILE* out);
michael@0 405 static void DumpLayoutData(char* aTitleStr, char* aURLStr,
michael@0 406 nsPresContext* aPresContext,
michael@0 407 nsDeviceContext * aDC, nsIFrame * aRootFrame,
michael@0 408 nsIDocShell * aDocShell, FILE* aFD);
michael@0 409 #endif
michael@0 410
michael@0 411 //--------------------------------------------------------------------------------
michael@0 412
michael@0 413 nsresult
michael@0 414 nsPrintEngine::CommonPrint(bool aIsPrintPreview,
michael@0 415 nsIPrintSettings* aPrintSettings,
michael@0 416 nsIWebProgressListener* aWebProgressListener,
michael@0 417 nsIDOMDocument* aDoc) {
michael@0 418 nsRefPtr<nsPrintEngine> kungfuDeathGrip = this;
michael@0 419 nsresult rv = DoCommonPrint(aIsPrintPreview, aPrintSettings,
michael@0 420 aWebProgressListener, aDoc);
michael@0 421 if (NS_FAILED(rv)) {
michael@0 422 if (aIsPrintPreview) {
michael@0 423 SetIsCreatingPrintPreview(false);
michael@0 424 SetIsPrintPreview(false);
michael@0 425 } else {
michael@0 426 SetIsPrinting(false);
michael@0 427 }
michael@0 428 if (mProgressDialogIsShown)
michael@0 429 CloseProgressDialog(aWebProgressListener);
michael@0 430 if (rv != NS_ERROR_ABORT && rv != NS_ERROR_OUT_OF_MEMORY)
michael@0 431 ShowPrintErrorDialog(rv, !aIsPrintPreview);
michael@0 432 delete mPrt;
michael@0 433 mPrt = nullptr;
michael@0 434 }
michael@0 435
michael@0 436 return rv;
michael@0 437 }
michael@0 438
michael@0 439 nsresult
michael@0 440 nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
michael@0 441 nsIPrintSettings* aPrintSettings,
michael@0 442 nsIWebProgressListener* aWebProgressListener,
michael@0 443 nsIDOMDocument* aDoc)
michael@0 444 {
michael@0 445 nsresult rv;
michael@0 446
michael@0 447 if (aIsPrintPreview) {
michael@0 448 // The WebProgressListener can be QI'ed to nsIPrintingPromptService
michael@0 449 // then that means the progress dialog is already being shown.
michael@0 450 nsCOMPtr<nsIPrintingPromptService> pps(do_QueryInterface(aWebProgressListener));
michael@0 451 mProgressDialogIsShown = pps != nullptr;
michael@0 452
michael@0 453 if (mIsDoingPrintPreview) {
michael@0 454 mOldPrtPreview = mPrtPreview;
michael@0 455 mPrtPreview = nullptr;
michael@0 456 }
michael@0 457 } else {
michael@0 458 mProgressDialogIsShown = false;
michael@0 459 }
michael@0 460
michael@0 461 mPrt = new nsPrintData(aIsPrintPreview ? nsPrintData::eIsPrintPreview :
michael@0 462 nsPrintData::eIsPrinting);
michael@0 463 NS_ENSURE_TRUE(mPrt, NS_ERROR_OUT_OF_MEMORY);
michael@0 464
michael@0 465 // if they don't pass in a PrintSettings, then get the Global PS
michael@0 466 mPrt->mPrintSettings = aPrintSettings;
michael@0 467 if (!mPrt->mPrintSettings) {
michael@0 468 rv = GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings));
michael@0 469 NS_ENSURE_SUCCESS(rv, rv);
michael@0 470 }
michael@0 471
michael@0 472 rv = CheckForPrinters(mPrt->mPrintSettings);
michael@0 473 NS_ENSURE_SUCCESS(rv, rv);
michael@0 474
michael@0 475 mPrt->mPrintSettings->SetIsCancelled(false);
michael@0 476 mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit);
michael@0 477
michael@0 478 // In the case the margin boxes are not printed store the print settings for
michael@0 479 // the footer/header to be used as default print setting for follow up prints.
michael@0 480 mPrt->mPrintSettings->SetPersistMarginBoxSettings(!mNoMarginBoxes);
michael@0 481
michael@0 482 if (mNoMarginBoxes) {
michael@0 483 // Set the footer/header to blank.
michael@0 484 const char16_t* emptyString = EmptyString().get();
michael@0 485 mPrt->mPrintSettings->SetHeaderStrLeft(emptyString);
michael@0 486 mPrt->mPrintSettings->SetHeaderStrCenter(emptyString);
michael@0 487 mPrt->mPrintSettings->SetHeaderStrRight(emptyString);
michael@0 488 mPrt->mPrintSettings->SetFooterStrLeft(emptyString);
michael@0 489 mPrt->mPrintSettings->SetFooterStrCenter(emptyString);
michael@0 490 mPrt->mPrintSettings->SetFooterStrRight(emptyString);
michael@0 491 }
michael@0 492
michael@0 493 if (aIsPrintPreview) {
michael@0 494 SetIsCreatingPrintPreview(true);
michael@0 495 SetIsPrintPreview(true);
michael@0 496 nsCOMPtr<nsIMarkupDocumentViewer> viewer =
michael@0 497 do_QueryInterface(mDocViewerPrint);
michael@0 498 if (viewer) {
michael@0 499 viewer->SetTextZoom(1.0f);
michael@0 500 viewer->SetFullZoom(1.0f);
michael@0 501 viewer->SetMinFontSize(0);
michael@0 502 }
michael@0 503 }
michael@0 504
michael@0 505 // Create a print session and let the print settings know about it.
michael@0 506 // The print settings hold an nsWeakPtr to the session so it does not
michael@0 507 // need to be cleared from the settings at the end of the job.
michael@0 508 // XXX What lifetime does the printSession need to have?
michael@0 509 nsCOMPtr<nsIPrintSession> printSession;
michael@0 510 if (!aIsPrintPreview) {
michael@0 511 printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
michael@0 512 NS_ENSURE_SUCCESS(rv, rv);
michael@0 513 mPrt->mPrintSettings->SetPrintSession(printSession);
michael@0 514 }
michael@0 515
michael@0 516 if (aWebProgressListener != nullptr) {
michael@0 517 mPrt->mPrintProgressListeners.AppendObject(aWebProgressListener);
michael@0 518 }
michael@0 519
michael@0 520 // Get the currently focused window and cache it
michael@0 521 // because the Print Dialog will "steal" focus and later when you try
michael@0 522 // to get the currently focused windows it will be nullptr
michael@0 523 mPrt->mCurrentFocusWin = FindFocusedDOMWindow();
michael@0 524
michael@0 525 // Check to see if there is a "regular" selection
michael@0 526 bool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin);
michael@0 527
michael@0 528 // Get the docshell for this documentviewer
michael@0 529 nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer, &rv));
michael@0 530 NS_ENSURE_SUCCESS(rv, rv);
michael@0 531
michael@0 532 {
michael@0 533 if (aIsPrintPreview) {
michael@0 534 nsCOMPtr<nsIContentViewer> viewer;
michael@0 535 webContainer->GetContentViewer(getter_AddRefs(viewer));
michael@0 536 if (viewer && viewer->GetDocument() && viewer->GetDocument()->IsShowing()) {
michael@0 537 viewer->GetDocument()->OnPageHide(false, nullptr);
michael@0 538 }
michael@0 539 }
michael@0 540
michael@0 541 nsAutoScriptBlocker scriptBlocker;
michael@0 542 mPrt->mPrintObject = new nsPrintObject();
michael@0 543 NS_ENSURE_TRUE(mPrt->mPrintObject, NS_ERROR_OUT_OF_MEMORY);
michael@0 544 rv = mPrt->mPrintObject->Init(webContainer, aDoc, aIsPrintPreview);
michael@0 545 NS_ENSURE_SUCCESS(rv, rv);
michael@0 546
michael@0 547 NS_ENSURE_TRUE(mPrt->mPrintDocList.AppendElement(mPrt->mPrintObject),
michael@0 548 NS_ERROR_OUT_OF_MEMORY);
michael@0 549
michael@0 550 mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer);
michael@0 551 mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc;
michael@0 552
michael@0 553 // Build the "tree" of PrintObjects
michael@0 554 BuildDocTree(mPrt->mPrintObject->mDocShell, &mPrt->mPrintDocList,
michael@0 555 mPrt->mPrintObject);
michael@0 556 }
michael@0 557
michael@0 558 if (!aIsPrintPreview) {
michael@0 559 SetIsPrinting(true);
michael@0 560 }
michael@0 561
michael@0 562 // XXX This isn't really correct...
michael@0 563 if (!mPrt->mPrintObject->mDocument ||
michael@0 564 !mPrt->mPrintObject->mDocument->GetRootElement())
michael@0 565 return NS_ERROR_GFX_PRINTER_STARTDOC;
michael@0 566
michael@0 567 // Create the linkage from the sub-docs back to the content element
michael@0 568 // in the parent document
michael@0 569 MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject);
michael@0 570
michael@0 571 mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet);
michael@0 572
michael@0 573 // Setup print options for UI
michael@0 574 if (mPrt->mIsParentAFrameSet) {
michael@0 575 if (mPrt->mCurrentFocusWin) {
michael@0 576 mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll);
michael@0 577 } else {
michael@0 578 mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach);
michael@0 579 }
michael@0 580 } else {
michael@0 581 mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone);
michael@0 582 }
michael@0 583 // Now determine how to set up the Frame print UI
michael@0 584 mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB,
michael@0 585 isSelection || mPrt->mIsIFrameSelected);
michael@0 586
michael@0 587 nsCOMPtr<nsIDeviceContextSpec> devspec
michael@0 588 (do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv));
michael@0 589 NS_ENSURE_SUCCESS(rv, rv);
michael@0 590
michael@0 591 nsScriptSuppressor scriptSuppressor(this);
michael@0 592 if (!aIsPrintPreview) {
michael@0 593 #ifdef DEBUG
michael@0 594 mPrt->mDebugFilePtr = mDebugFile;
michael@0 595 #endif
michael@0 596
michael@0 597 scriptSuppressor.Suppress();
michael@0 598 bool printSilently;
michael@0 599 mPrt->mPrintSettings->GetPrintSilent(&printSilently);
michael@0 600
michael@0 601 // Check prefs for a default setting as to whether we should print silently
michael@0 602 printSilently =
michael@0 603 Preferences::GetBool("print.always_print_silent", printSilently);
michael@0 604
michael@0 605 // Ask dialog to be Print Shown via the Plugable Printing Dialog Service
michael@0 606 // This service is for the Print Dialog and the Print Progress Dialog
michael@0 607 // If printing silently or you can't get the service continue on
michael@0 608 if (!printSilently) {
michael@0 609 nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService));
michael@0 610 if (printPromptService) {
michael@0 611 nsIDOMWindow *domWin = mDocument->GetWindow();
michael@0 612 NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE);
michael@0 613
michael@0 614 // Platforms not implementing a given dialog for the service may
michael@0 615 // return NS_ERROR_NOT_IMPLEMENTED or an error code.
michael@0 616 //
michael@0 617 // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior
michael@0 618 // Any other error code means we must bail out
michael@0 619 //
michael@0 620 nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
michael@0 621 rv = printPromptService->ShowPrintDialog(domWin, wbp,
michael@0 622 mPrt->mPrintSettings);
michael@0 623 //
michael@0 624 // ShowPrintDialog triggers an event loop which means we can't assume
michael@0 625 // that the state of this->{anything} matches the state we've checked
michael@0 626 // above. Including that a given {thing} is non null.
michael@0 627 if (!mPrt) {
michael@0 628 return NS_ERROR_FAILURE;
michael@0 629 }
michael@0 630
michael@0 631 if (NS_SUCCEEDED(rv)) {
michael@0 632 // since we got the dialog and it worked then make sure we
michael@0 633 // are telling GFX we want to print silent
michael@0 634 printSilently = true;
michael@0 635
michael@0 636 if (mPrt->mPrintSettings) {
michael@0 637 // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
michael@0 638 mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit);
michael@0 639 }
michael@0 640 } else if (rv == NS_ERROR_NOT_IMPLEMENTED) {
michael@0 641 // This means the Dialog service was there,
michael@0 642 // but they choose not to implement this dialog and
michael@0 643 // are looking for default behavior from the toolkit
michael@0 644 rv = NS_OK;
michael@0 645 }
michael@0 646 } else {
michael@0 647 // No dialog service available
michael@0 648 rv = NS_ERROR_NOT_IMPLEMENTED;
michael@0 649 }
michael@0 650 } else {
michael@0 651 // Call any code that requires a run of the event loop.
michael@0 652 rv = mPrt->mPrintSettings->SetupSilentPrinting();
michael@0 653 }
michael@0 654 // Check explicitly for abort because it's expected
michael@0 655 if (rv == NS_ERROR_ABORT)
michael@0 656 return rv;
michael@0 657 NS_ENSURE_SUCCESS(rv, rv);
michael@0 658 }
michael@0 659
michael@0 660 rv = devspec->Init(nullptr, mPrt->mPrintSettings, aIsPrintPreview);
michael@0 661 NS_ENSURE_SUCCESS(rv, rv);
michael@0 662
michael@0 663 mPrt->mPrintDC = new nsDeviceContext();
michael@0 664 rv = mPrt->mPrintDC->InitForPrinting(devspec);
michael@0 665 NS_ENSURE_SUCCESS(rv, rv);
michael@0 666
michael@0 667 if (aIsPrintPreview) {
michael@0 668 mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
michael@0 669
michael@0 670 // override any UI that wants to PrintPreview any selection or page range
michael@0 671 // we want to view every page in PrintPreview each time
michael@0 672 mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
michael@0 673 } else {
michael@0 674 // Always check and set the print settings first and then fall back
michael@0 675 // onto the PrintService if there isn't a PrintSettings
michael@0 676 //
michael@0 677 // Posiible Usage values:
michael@0 678 // nsIPrintSettings::kUseInternalDefault
michael@0 679 // nsIPrintSettings::kUseSettingWhenPossible
michael@0 680 //
michael@0 681 // NOTE: The consts are the same for PrintSettings and PrintSettings
michael@0 682 int16_t printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible;
michael@0 683 mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage);
michael@0 684
michael@0 685 // Ok, see if we are going to use our value and override the default
michael@0 686 if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) {
michael@0 687 // Get the Print Options/Settings PrintFrameType to see what is preferred
michael@0 688 int16_t printFrameType = nsIPrintSettings::kEachFrameSep;
michael@0 689 mPrt->mPrintSettings->GetPrintFrameType(&printFrameType);
michael@0 690
michael@0 691 // Don't let anybody do something stupid like try to set it to
michael@0 692 // kNoFrames when we are printing a FrameSet
michael@0 693 if (printFrameType == nsIPrintSettings::kNoFrames) {
michael@0 694 mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep;
michael@0 695 mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType);
michael@0 696 } else {
michael@0 697 // First find out from the PrinService what options are available
michael@0 698 // to us for Printing FrameSets
michael@0 699 int16_t howToEnableFrameUI;
michael@0 700 mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
michael@0 701 if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) {
michael@0 702 switch (howToEnableFrameUI) {
michael@0 703 case nsIPrintSettings::kFrameEnableAll:
michael@0 704 mPrt->mPrintFrameType = printFrameType;
michael@0 705 break;
michael@0 706
michael@0 707 case nsIPrintSettings::kFrameEnableAsIsAndEach:
michael@0 708 if (printFrameType != nsIPrintSettings::kSelectedFrame) {
michael@0 709 mPrt->mPrintFrameType = printFrameType;
michael@0 710 } else { // revert back to a good value
michael@0 711 mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep;
michael@0 712 }
michael@0 713 break;
michael@0 714 } // switch
michael@0 715 mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType);
michael@0 716 }
michael@0 717 }
michael@0 718 } else {
michael@0 719 mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType);
michael@0 720 }
michael@0 721 }
michael@0 722
michael@0 723 if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
michael@0 724 CheckForChildFrameSets(mPrt->mPrintObject);
michael@0 725 }
michael@0 726
michael@0 727 if (NS_FAILED(EnablePOsForPrinting())) {
michael@0 728 return NS_ERROR_FAILURE;
michael@0 729 }
michael@0 730
michael@0 731 // Attach progressListener to catch network requests.
michael@0 732 nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell);
michael@0 733 webProgress->AddProgressListener(
michael@0 734 static_cast<nsIWebProgressListener*>(this),
michael@0 735 nsIWebProgress::NOTIFY_STATE_REQUEST);
michael@0 736
michael@0 737 mLoadCounter = 0;
michael@0 738 mDidLoadDataForPrinting = false;
michael@0 739
michael@0 740 if (aIsPrintPreview) {
michael@0 741 bool notifyOnInit = false;
michael@0 742 ShowPrintProgress(false, notifyOnInit);
michael@0 743
michael@0 744 // Very important! Turn Off scripting
michael@0 745 TurnScriptingOn(false);
michael@0 746
michael@0 747 if (!notifyOnInit) {
michael@0 748 InstallPrintPreviewListener();
michael@0 749 rv = InitPrintDocConstruction(false);
michael@0 750 } else {
michael@0 751 rv = NS_OK;
michael@0 752 }
michael@0 753 } else {
michael@0 754 bool doNotify;
michael@0 755 ShowPrintProgress(true, doNotify);
michael@0 756 if (!doNotify) {
michael@0 757 // Print listener setup...
michael@0 758 mPrt->OnStartPrinting();
michael@0 759
michael@0 760 rv = InitPrintDocConstruction(false);
michael@0 761 }
michael@0 762 }
michael@0 763
michael@0 764 // We will enable scripting later after printing has finished.
michael@0 765 scriptSuppressor.Disconnect();
michael@0 766
michael@0 767 return NS_OK;
michael@0 768 }
michael@0 769
michael@0 770 //---------------------------------------------------------------------------------
michael@0 771 NS_IMETHODIMP
michael@0 772 nsPrintEngine::Print(nsIPrintSettings* aPrintSettings,
michael@0 773 nsIWebProgressListener* aWebProgressListener)
michael@0 774 {
michael@0 775 // If we have a print preview document, use that instead of the original
michael@0 776 // mDocument. That way animated images etc. get printed using the same state
michael@0 777 // as in print preview.
michael@0 778 nsCOMPtr<nsIDOMDocument> doc =
michael@0 779 do_QueryInterface(mPrtPreview && mPrtPreview->mPrintObject ?
michael@0 780 mPrtPreview->mPrintObject->mDocument : mDocument);
michael@0 781
michael@0 782 return CommonPrint(false, aPrintSettings, aWebProgressListener, doc);
michael@0 783 }
michael@0 784
michael@0 785 NS_IMETHODIMP
michael@0 786 nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings,
michael@0 787 nsIDOMWindow *aChildDOMWin,
michael@0 788 nsIWebProgressListener* aWebProgressListener)
michael@0 789 {
michael@0 790 // Get the DocShell and see if it is busy
michael@0 791 // (We can't Print Preview this document if it is still busy)
michael@0 792 nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
michael@0 793 NS_ENSURE_STATE(docShell);
michael@0 794
michael@0 795 uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
michael@0 796 if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
michael@0 797 busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
michael@0 798 CloseProgressDialog(aWebProgressListener);
michael@0 799 ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY, false);
michael@0 800 return NS_ERROR_FAILURE;
michael@0 801 }
michael@0 802
michael@0 803 NS_ENSURE_STATE(aChildDOMWin);
michael@0 804 nsCOMPtr<nsIDOMDocument> doc;
michael@0 805 aChildDOMWin->GetDocument(getter_AddRefs(doc));
michael@0 806 NS_ENSURE_STATE(doc);
michael@0 807
michael@0 808 // Document is not busy -- go ahead with the Print Preview
michael@0 809 return CommonPrint(true, aPrintSettings, aWebProgressListener, doc);
michael@0 810 }
michael@0 811
michael@0 812 //----------------------------------------------------------------------------------
michael@0 813 /* readonly attribute boolean isFramesetDocument; */
michael@0 814 NS_IMETHODIMP
michael@0 815 nsPrintEngine::GetIsFramesetDocument(bool *aIsFramesetDocument)
michael@0 816 {
michael@0 817 nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer));
michael@0 818 *aIsFramesetDocument = IsParentAFrameSet(webContainer);
michael@0 819 return NS_OK;
michael@0 820 }
michael@0 821
michael@0 822 //----------------------------------------------------------------------------------
michael@0 823 /* readonly attribute boolean isIFrameSelected; */
michael@0 824 NS_IMETHODIMP
michael@0 825 nsPrintEngine::GetIsIFrameSelected(bool *aIsIFrameSelected)
michael@0 826 {
michael@0 827 *aIsIFrameSelected = false;
michael@0 828
michael@0 829 // Get the docshell for this documentviewer
michael@0 830 nsCOMPtr<nsIDocShell> webContainer(do_QueryReferent(mContainer));
michael@0 831 // Get the currently focused window
michael@0 832 nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow();
michael@0 833 if (currentFocusWin && webContainer) {
michael@0 834 // Get whether the doc contains a frameset
michael@0 835 // Also, check to see if the currently focus docshell
michael@0 836 // is a child of this docshell
michael@0 837 bool isParentFrameSet;
michael@0 838 *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet);
michael@0 839 }
michael@0 840 return NS_OK;
michael@0 841 }
michael@0 842
michael@0 843 //----------------------------------------------------------------------------------
michael@0 844 /* readonly attribute boolean isRangeSelection; */
michael@0 845 NS_IMETHODIMP
michael@0 846 nsPrintEngine::GetIsRangeSelection(bool *aIsRangeSelection)
michael@0 847 {
michael@0 848 // Get the currently focused window
michael@0 849 nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow();
michael@0 850 *aIsRangeSelection = IsThereARangeSelection(currentFocusWin);
michael@0 851 return NS_OK;
michael@0 852 }
michael@0 853
michael@0 854 //----------------------------------------------------------------------------------
michael@0 855 /* readonly attribute boolean isFramesetFrameSelected; */
michael@0 856 NS_IMETHODIMP
michael@0 857 nsPrintEngine::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected)
michael@0 858 {
michael@0 859 // Get the currently focused window
michael@0 860 nsCOMPtr<nsIDOMWindow> currentFocusWin = FindFocusedDOMWindow();
michael@0 861 *aIsFramesetFrameSelected = currentFocusWin != nullptr;
michael@0 862 return NS_OK;
michael@0 863 }
michael@0 864
michael@0 865 //----------------------------------------------------------------------------------
michael@0 866 /* readonly attribute long printPreviewNumPages; */
michael@0 867 NS_IMETHODIMP
michael@0 868 nsPrintEngine::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
michael@0 869 {
michael@0 870 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages);
michael@0 871
michael@0 872 nsPrintData* prt = nullptr;
michael@0 873 nsIFrame* seqFrame = nullptr;
michael@0 874 *aPrintPreviewNumPages = 0;
michael@0 875
michael@0 876 // When calling this function, the FinishPrintPreview() function might not
michael@0 877 // been called as there are still some
michael@0 878 if (mPrtPreview) {
michael@0 879 prt = mPrtPreview;
michael@0 880 } else {
michael@0 881 prt = mPrt;
michael@0 882 }
michael@0 883 if ((!prt) ||
michael@0 884 NS_FAILED(GetSeqFrameAndCountPagesInternal(prt->mPrintObject, seqFrame, *aPrintPreviewNumPages))) {
michael@0 885 return NS_ERROR_FAILURE;
michael@0 886 }
michael@0 887 return NS_OK;
michael@0 888 }
michael@0 889
michael@0 890 //----------------------------------------------------------------------------------
michael@0 891 // Enumerate all the documents for their titles
michael@0 892 NS_IMETHODIMP
michael@0 893 nsPrintEngine::EnumerateDocumentNames(uint32_t* aCount,
michael@0 894 char16_t*** aResult)
michael@0 895 {
michael@0 896 NS_ENSURE_ARG(aCount);
michael@0 897 NS_ENSURE_ARG_POINTER(aResult);
michael@0 898
michael@0 899 *aCount = 0;
michael@0 900 *aResult = nullptr;
michael@0 901
michael@0 902 int32_t numDocs = mPrt->mPrintDocList.Length();
michael@0 903 char16_t** array = (char16_t**) nsMemory::Alloc(numDocs * sizeof(char16_t*));
michael@0 904 if (!array)
michael@0 905 return NS_ERROR_OUT_OF_MEMORY;
michael@0 906
michael@0 907 for (int32_t i=0;i<numDocs;i++) {
michael@0 908 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 909 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 910 nsAutoString docTitleStr;
michael@0 911 nsAutoString docURLStr;
michael@0 912 GetDocumentTitleAndURL(po->mDocument, docTitleStr, docURLStr);
michael@0 913
michael@0 914 // Use the URL if the doc is empty
michael@0 915 if (docTitleStr.IsEmpty() && !docURLStr.IsEmpty()) {
michael@0 916 docTitleStr = docURLStr;
michael@0 917 }
michael@0 918 array[i] = ToNewUnicode(docTitleStr);
michael@0 919 }
michael@0 920 *aCount = numDocs;
michael@0 921 *aResult = array;
michael@0 922
michael@0 923 return NS_OK;
michael@0 924
michael@0 925 }
michael@0 926
michael@0 927 //----------------------------------------------------------------------------------
michael@0 928 /* readonly attribute nsIPrintSettings globalPrintSettings; */
michael@0 929 nsresult
michael@0 930 nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
michael@0 931 {
michael@0 932 NS_ENSURE_ARG_POINTER(aGlobalPrintSettings);
michael@0 933
michael@0 934 nsresult rv = NS_ERROR_FAILURE;
michael@0 935 nsCOMPtr<nsIPrintSettingsService> printSettingsService =
michael@0 936 do_GetService(sPrintSettingsServiceContractID, &rv);
michael@0 937 if (NS_SUCCEEDED(rv)) {
michael@0 938 rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings);
michael@0 939 }
michael@0 940 return rv;
michael@0 941 }
michael@0 942
michael@0 943 //----------------------------------------------------------------------------------
michael@0 944 /* readonly attribute boolean doingPrint; */
michael@0 945 NS_IMETHODIMP
michael@0 946 nsPrintEngine::GetDoingPrint(bool *aDoingPrint)
michael@0 947 {
michael@0 948 NS_ENSURE_ARG_POINTER(aDoingPrint);
michael@0 949 *aDoingPrint = mIsDoingPrinting;
michael@0 950 return NS_OK;
michael@0 951 }
michael@0 952
michael@0 953 //----------------------------------------------------------------------------------
michael@0 954 /* readonly attribute boolean doingPrintPreview; */
michael@0 955 NS_IMETHODIMP
michael@0 956 nsPrintEngine::GetDoingPrintPreview(bool *aDoingPrintPreview)
michael@0 957 {
michael@0 958 NS_ENSURE_ARG_POINTER(aDoingPrintPreview);
michael@0 959 *aDoingPrintPreview = mIsDoingPrintPreview;
michael@0 960 return NS_OK;
michael@0 961 }
michael@0 962
michael@0 963 //----------------------------------------------------------------------------------
michael@0 964 /* readonly attribute nsIPrintSettings currentPrintSettings; */
michael@0 965 NS_IMETHODIMP
michael@0 966 nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings)
michael@0 967 {
michael@0 968 NS_ENSURE_ARG_POINTER(aCurrentPrintSettings);
michael@0 969
michael@0 970 if (mPrt) {
michael@0 971 *aCurrentPrintSettings = mPrt->mPrintSettings;
michael@0 972
michael@0 973 } else if (mPrtPreview) {
michael@0 974 *aCurrentPrintSettings = mPrtPreview->mPrintSettings;
michael@0 975
michael@0 976 } else {
michael@0 977 *aCurrentPrintSettings = nullptr;
michael@0 978 }
michael@0 979 NS_IF_ADDREF(*aCurrentPrintSettings);
michael@0 980 return NS_OK;
michael@0 981 }
michael@0 982
michael@0 983 //-----------------------------------------------------------------
michael@0 984 //-- Section: Pre-Reflow Methods
michael@0 985 //-----------------------------------------------------------------
michael@0 986
michael@0 987 //---------------------------------------------------------------------
michael@0 988 // This method checks to see if there is at least one printer defined
michael@0 989 // and if so, it sets the first printer in the list as the default name
michael@0 990 // in the PrintSettings which is then used for Printer Preview
michael@0 991 nsresult
michael@0 992 nsPrintEngine::CheckForPrinters(nsIPrintSettings* aPrintSettings)
michael@0 993 {
michael@0 994 #if defined(XP_MACOSX) || defined(ANDROID)
michael@0 995 // Mac doesn't support retrieving a printer list.
michael@0 996 return NS_OK;
michael@0 997 #else
michael@0 998 NS_ENSURE_ARG_POINTER(aPrintSettings);
michael@0 999
michael@0 1000 // See if aPrintSettings already has a printer
michael@0 1001 nsXPIDLString printerName;
michael@0 1002 nsresult rv = aPrintSettings->GetPrinterName(getter_Copies(printerName));
michael@0 1003 if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) {
michael@0 1004 return NS_OK;
michael@0 1005 }
michael@0 1006
michael@0 1007 // aPrintSettings doesn't have a printer set. Try to fetch the default.
michael@0 1008 nsCOMPtr<nsIPrintSettingsService> printSettingsService =
michael@0 1009 do_GetService(sPrintSettingsServiceContractID, &rv);
michael@0 1010 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1011
michael@0 1012 rv = printSettingsService->GetDefaultPrinterName(getter_Copies(printerName));
michael@0 1013 if (NS_SUCCEEDED(rv) && !printerName.IsEmpty()) {
michael@0 1014 rv = aPrintSettings->SetPrinterName(printerName.get());
michael@0 1015 }
michael@0 1016 return rv;
michael@0 1017 #endif
michael@0 1018 }
michael@0 1019
michael@0 1020 //----------------------------------------------------------------------
michael@0 1021 // Set up to use the "pluggable" Print Progress Dialog
michael@0 1022 void
michael@0 1023 nsPrintEngine::ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify)
michael@0 1024 {
michael@0 1025 // default to not notifying, that if something here goes wrong
michael@0 1026 // or we aren't going to show the progress dialog we can straight into
michael@0 1027 // reflowing the doc for printing.
michael@0 1028 aDoNotify = false;
michael@0 1029
michael@0 1030 // Assume we can't do progress and then see if we can
michael@0 1031 bool showProgresssDialog = false;
michael@0 1032
michael@0 1033 // if it is already being shown then don't bother to find out if it should be
michael@0 1034 // so skip this and leave mShowProgressDialog set to FALSE
michael@0 1035 if (!mProgressDialogIsShown) {
michael@0 1036 showProgresssDialog = Preferences::GetBool("print.show_print_progress");
michael@0 1037 }
michael@0 1038
michael@0 1039 // Turning off the showing of Print Progress in Prefs overrides
michael@0 1040 // whether the calling PS desire to have it on or off, so only check PS if
michael@0 1041 // prefs says it's ok to be on.
michael@0 1042 if (showProgresssDialog) {
michael@0 1043 mPrt->mPrintSettings->GetShowPrintProgress(&showProgresssDialog);
michael@0 1044 }
michael@0 1045
michael@0 1046 // Now open the service to get the progress dialog
michael@0 1047 // If we don't get a service, that's ok, then just don't show progress
michael@0 1048 if (showProgresssDialog) {
michael@0 1049 nsCOMPtr<nsIPrintingPromptService> printPromptService(do_GetService(kPrintingPromptService));
michael@0 1050 if (printPromptService) {
michael@0 1051 nsPIDOMWindow *domWin = mDocument->GetWindow();
michael@0 1052 if (!domWin) return;
michael@0 1053
michael@0 1054 nsCOMPtr<nsIDocShell> docShell = domWin->GetDocShell();
michael@0 1055 if (!docShell) return;
michael@0 1056 nsCOMPtr<nsIDocShellTreeOwner> owner;
michael@0 1057 docShell->GetTreeOwner(getter_AddRefs(owner));
michael@0 1058 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(owner);
michael@0 1059 if (!browserChrome) return;
michael@0 1060 bool isModal = true;
michael@0 1061 browserChrome->IsWindowModal(&isModal);
michael@0 1062 if (isModal) {
michael@0 1063 // Showing a print progress dialog when printing a modal window
michael@0 1064 // isn't supported. See bug 301560.
michael@0 1065 return;
michael@0 1066 }
michael@0 1067
michael@0 1068 nsCOMPtr<nsIWebProgressListener> printProgressListener;
michael@0 1069
michael@0 1070 nsCOMPtr<nsIWebBrowserPrint> wbp(do_QueryInterface(mDocViewerPrint));
michael@0 1071 nsresult rv = printPromptService->ShowProgress(domWin, wbp, mPrt->mPrintSettings, this, aIsForPrinting,
michael@0 1072 getter_AddRefs(printProgressListener),
michael@0 1073 getter_AddRefs(mPrt->mPrintProgressParams),
michael@0 1074 &aDoNotify);
michael@0 1075 if (NS_SUCCEEDED(rv)) {
michael@0 1076 if (printProgressListener && mPrt->mPrintProgressParams) {
michael@0 1077 mPrt->mPrintProgressListeners.AppendObject(printProgressListener);
michael@0 1078 SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams);
michael@0 1079 }
michael@0 1080 }
michael@0 1081 }
michael@0 1082 }
michael@0 1083 }
michael@0 1084
michael@0 1085 //---------------------------------------------------------------------
michael@0 1086 bool
michael@0 1087 nsPrintEngine::IsThereARangeSelection(nsIDOMWindow* aDOMWin)
michael@0 1088 {
michael@0 1089 if (mDisallowSelectionPrint)
michael@0 1090 return false;
michael@0 1091
michael@0 1092 nsCOMPtr<nsIPresShell> presShell;
michael@0 1093 if (aDOMWin) {
michael@0 1094 nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aDOMWin));
michael@0 1095 presShell = window->GetDocShell()->GetPresShell();
michael@0 1096 }
michael@0 1097
michael@0 1098 if (!presShell)
michael@0 1099 return false;
michael@0 1100
michael@0 1101 // check here to see if there is a range selection
michael@0 1102 // so we know whether to turn on the "Selection" radio button
michael@0 1103 Selection* selection =
michael@0 1104 presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 1105 if (!selection) {
michael@0 1106 return false;
michael@0 1107 }
michael@0 1108
michael@0 1109 int32_t rangeCount = selection->GetRangeCount();
michael@0 1110 if (!rangeCount) {
michael@0 1111 return false;
michael@0 1112 }
michael@0 1113
michael@0 1114 if (rangeCount > 1) {
michael@0 1115 return true;
michael@0 1116 }
michael@0 1117
michael@0 1118 // check to make sure it isn't an insertion selection
michael@0 1119 return selection->GetRangeAt(0) && !selection->IsCollapsed();
michael@0 1120 }
michael@0 1121
michael@0 1122 //---------------------------------------------------------------------
michael@0 1123 bool
michael@0 1124 nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent)
michael@0 1125 {
michael@0 1126 // See if the incoming doc is the root document
michael@0 1127 if (!aParent) return false;
michael@0 1128
michael@0 1129 // When it is the top level document we need to check
michael@0 1130 // to see if it contains a frameset. If it does, then
michael@0 1131 // we only want to print the doc's children and not the document itself
michael@0 1132 // For anything else we always print all the children and the document
michael@0 1133 // for example, if the doc contains an IFRAME we eant to print the child
michael@0 1134 // document (the IFRAME) and then the rest of the document.
michael@0 1135 //
michael@0 1136 // XXX we really need to search the frame tree, and not the content
michael@0 1137 // but there is no way to distinguish between IFRAMEs and FRAMEs
michael@0 1138 // with the GetFrameType call.
michael@0 1139 // Bug 53459 has been files so we can eventually distinguish
michael@0 1140 // between IFRAME frames and FRAME frames
michael@0 1141 bool isFrameSet = false;
michael@0 1142 // only check to see if there is a frameset if there is
michael@0 1143 // NO parent doc for this doc. meaning this parent is the root doc
michael@0 1144 nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(aParent);
michael@0 1145 nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
michael@0 1146 if (doc) {
michael@0 1147 nsIContent *rootElement = doc->GetRootElement();
michael@0 1148 if (rootElement) {
michael@0 1149 isFrameSet = HasFramesetChild(rootElement);
michael@0 1150 }
michael@0 1151 }
michael@0 1152 return isFrameSet;
michael@0 1153 }
michael@0 1154
michael@0 1155
michael@0 1156 //---------------------------------------------------------------------
michael@0 1157 // Recursively build a list of sub documents to be printed
michael@0 1158 // that mirrors the document tree
michael@0 1159 void
michael@0 1160 nsPrintEngine::BuildDocTree(nsIDocShell * aParentNode,
michael@0 1161 nsTArray<nsPrintObject*> * aDocList,
michael@0 1162 nsPrintObject * aPO)
michael@0 1163 {
michael@0 1164 NS_ASSERTION(aParentNode, "Pointer is null!");
michael@0 1165 NS_ASSERTION(aDocList, "Pointer is null!");
michael@0 1166 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 1167
michael@0 1168 int32_t childWebshellCount;
michael@0 1169 aParentNode->GetChildCount(&childWebshellCount);
michael@0 1170 if (childWebshellCount > 0) {
michael@0 1171 for (int32_t i=0;i<childWebshellCount;i++) {
michael@0 1172 nsCOMPtr<nsIDocShellTreeItem> child;
michael@0 1173 aParentNode->GetChildAt(i, getter_AddRefs(child));
michael@0 1174 nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
michael@0 1175
michael@0 1176 nsCOMPtr<nsIContentViewer> viewer;
michael@0 1177 childAsShell->GetContentViewer(getter_AddRefs(viewer));
michael@0 1178 if (viewer) {
michael@0 1179 nsCOMPtr<nsIContentViewerFile> viewerFile(do_QueryInterface(viewer));
michael@0 1180 if (viewerFile) {
michael@0 1181 nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(childAsShell);
michael@0 1182 nsPrintObject * po = new nsPrintObject();
michael@0 1183 po->mParent = aPO;
michael@0 1184 nsresult rv = po->Init(childAsShell, doc, aPO->mPrintPreview);
michael@0 1185 if (NS_FAILED(rv))
michael@0 1186 NS_NOTREACHED("Init failed?");
michael@0 1187 aPO->mKids.AppendElement(po);
michael@0 1188 aDocList->AppendElement(po);
michael@0 1189 BuildDocTree(childAsShell, aDocList, po);
michael@0 1190 }
michael@0 1191 }
michael@0 1192 }
michael@0 1193 }
michael@0 1194 }
michael@0 1195
michael@0 1196 //---------------------------------------------------------------------
michael@0 1197 void
michael@0 1198 nsPrintEngine::GetDocumentTitleAndURL(nsIDocument* aDoc,
michael@0 1199 nsAString& aTitle,
michael@0 1200 nsAString& aURLStr)
michael@0 1201 {
michael@0 1202 NS_ASSERTION(aDoc, "Pointer is null!");
michael@0 1203
michael@0 1204 aTitle.Truncate();
michael@0 1205 aURLStr.Truncate();
michael@0 1206
michael@0 1207 nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDoc);
michael@0 1208 doc->GetTitle(aTitle);
michael@0 1209
michael@0 1210 nsIURI* url = aDoc->GetDocumentURI();
michael@0 1211 if (!url) return;
michael@0 1212
michael@0 1213 nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
michael@0 1214 if (!urifixup) return;
michael@0 1215
michael@0 1216 nsCOMPtr<nsIURI> exposableURI;
michael@0 1217 urifixup->CreateExposableURI(url, getter_AddRefs(exposableURI));
michael@0 1218
michael@0 1219 if (!exposableURI) return;
michael@0 1220
michael@0 1221 nsAutoCString urlCStr;
michael@0 1222 exposableURI->GetSpec(urlCStr);
michael@0 1223
michael@0 1224 nsresult rv;
michael@0 1225 nsCOMPtr<nsITextToSubURI> textToSubURI =
michael@0 1226 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
michael@0 1227 if (NS_FAILED(rv)) return;
michael@0 1228
michael@0 1229 textToSubURI->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
michael@0 1230 urlCStr, aURLStr);
michael@0 1231 }
michael@0 1232
michael@0 1233 //---------------------------------------------------------------------
michael@0 1234 // The walks the PO tree and for each document it walks the content
michael@0 1235 // tree looking for any content that are sub-shells
michael@0 1236 //
michael@0 1237 // It then sets the mContent pointer in the "found" PO object back to the
michael@0 1238 // the document that contained it.
michael@0 1239 void
michael@0 1240 nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO,
michael@0 1241 nsPrintObject* aPO)
michael@0 1242 {
michael@0 1243 NS_ASSERTION(aRootPO, "Pointer is null!");
michael@0 1244 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 1245
michael@0 1246 // Recursively walk the content from the root item
michael@0 1247 // XXX Would be faster to enumerate the subdocuments, although right now
michael@0 1248 // nsIDocument doesn't expose quite what would be needed.
michael@0 1249 nsCOMPtr<nsIContentViewer> viewer;
michael@0 1250 aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer));
michael@0 1251 if (!viewer) return;
michael@0 1252
michael@0 1253 nsCOMPtr<nsIDOMDocument> domDoc;
michael@0 1254 viewer->GetDOMDocument(getter_AddRefs(domDoc));
michael@0 1255 nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
michael@0 1256 if (!doc) return;
michael@0 1257
michael@0 1258 Element* rootElement = doc->GetRootElement();
michael@0 1259 if (rootElement) {
michael@0 1260 MapContentForPO(aPO, rootElement);
michael@0 1261 } else {
michael@0 1262 NS_WARNING("Null root content on (sub)document.");
michael@0 1263 }
michael@0 1264
michael@0 1265 // Continue recursively walking the chilren of this PO
michael@0 1266 for (uint32_t i=0;i<aPO->mKids.Length();i++) {
michael@0 1267 MapContentToWebShells(aRootPO, aPO->mKids[i]);
michael@0 1268 }
michael@0 1269
michael@0 1270 }
michael@0 1271
michael@0 1272 //-------------------------------------------------------
michael@0 1273 // A Frame's sub-doc may contain content or a FrameSet
michael@0 1274 // When it contains a FrameSet the mFrameType for the PrintObject
michael@0 1275 // is always set to an eFrame. Which is fine when printing "AsIs"
michael@0 1276 // but is incorrect when when printing "Each Frame Separately".
michael@0 1277 // When printing "Each Frame Separately" the Frame really acts like
michael@0 1278 // a frameset.
michael@0 1279 //
michael@0 1280 // This method walks the PO tree and checks to see if the PrintObject is
michael@0 1281 // an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet)
michael@0 1282 // If so, then the mFrameType need to be changed to eFrameSet
michael@0 1283 //
michael@0 1284 // Also note: We only want to call this we are printing "Each Frame Separately"
michael@0 1285 // when printing "As Is" leave it as an eFrame
michael@0 1286 void
michael@0 1287 nsPrintEngine::CheckForChildFrameSets(nsPrintObject* aPO)
michael@0 1288 {
michael@0 1289 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 1290
michael@0 1291 // Continue recursively walking the chilren of this PO
michael@0 1292 bool hasChildFrames = false;
michael@0 1293 for (uint32_t i=0;i<aPO->mKids.Length();i++) {
michael@0 1294 nsPrintObject* po = aPO->mKids[i];
michael@0 1295 if (po->mFrameType == eFrame) {
michael@0 1296 hasChildFrames = true;
michael@0 1297 CheckForChildFrameSets(po);
michael@0 1298 }
michael@0 1299 }
michael@0 1300
michael@0 1301 if (hasChildFrames && aPO->mFrameType == eFrame) {
michael@0 1302 aPO->mFrameType = eFrameSet;
michael@0 1303 }
michael@0 1304 }
michael@0 1305
michael@0 1306 //---------------------------------------------------------------------
michael@0 1307 // This method is key to the entire print mechanism.
michael@0 1308 //
michael@0 1309 // This "maps" or figures out which sub-doc represents a
michael@0 1310 // given Frame or IFrame in its parent sub-doc.
michael@0 1311 //
michael@0 1312 // So the Mcontent pointer in the child sub-doc points to the
michael@0 1313 // content in the its parent document, that caused it to be printed.
michael@0 1314 // This is used later to (after reflow) to find the absolute location
michael@0 1315 // of the sub-doc on its parent's page frame so it can be
michael@0 1316 // printed in the correct location.
michael@0 1317 //
michael@0 1318 // This method recursvely "walks" the content for a document finding
michael@0 1319 // all the Frames and IFrames, then sets the "mFrameType" data member
michael@0 1320 // which tells us what type of PO we have
michael@0 1321 void
michael@0 1322 nsPrintEngine::MapContentForPO(nsPrintObject* aPO,
michael@0 1323 nsIContent* aContent)
michael@0 1324 {
michael@0 1325 NS_PRECONDITION(aPO && aContent, "Null argument");
michael@0 1326
michael@0 1327 nsIDocument* doc = aContent->GetDocument();
michael@0 1328
michael@0 1329 NS_ASSERTION(doc, "Content without a document from a document tree?");
michael@0 1330
michael@0 1331 nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
michael@0 1332
michael@0 1333 if (subDoc) {
michael@0 1334 nsCOMPtr<nsIDocShell> docShell(subDoc->GetDocShell());
michael@0 1335
michael@0 1336 if (docShell) {
michael@0 1337 nsPrintObject * po = nullptr;
michael@0 1338 int32_t cnt = aPO->mKids.Length();
michael@0 1339 for (int32_t i=0;i<cnt;i++) {
michael@0 1340 nsPrintObject* kid = aPO->mKids.ElementAt(i);
michael@0 1341 if (kid->mDocument == subDoc) {
michael@0 1342 po = kid;
michael@0 1343 break;
michael@0 1344 }
michael@0 1345 }
michael@0 1346
michael@0 1347 // XXX If a subdocument has no onscreen presentation, there will be no PO
michael@0 1348 // This is even if there should be a print presentation
michael@0 1349 if (po) {
michael@0 1350
michael@0 1351 nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent));
michael@0 1352 // "frame" elements not in a frameset context should be treated
michael@0 1353 // as iframes
michael@0 1354 if (frame && po->mParent->mFrameType == eFrameSet) {
michael@0 1355 po->mFrameType = eFrame;
michael@0 1356 } else {
michael@0 1357 // Assume something iframe-like, i.e. iframe, object, or embed
michael@0 1358 po->mFrameType = eIFrame;
michael@0 1359 SetPrintAsIs(po, true);
michael@0 1360 NS_ASSERTION(po->mParent, "The root must be a parent");
michael@0 1361 po->mParent->mPrintAsIs = true;
michael@0 1362 }
michael@0 1363 }
michael@0 1364 }
michael@0 1365 }
michael@0 1366
michael@0 1367 // walk children content
michael@0 1368 for (nsIContent* child = aContent->GetFirstChild();
michael@0 1369 child;
michael@0 1370 child = child->GetNextSibling()) {
michael@0 1371 MapContentForPO(aPO, child);
michael@0 1372 }
michael@0 1373 }
michael@0 1374
michael@0 1375 //---------------------------------------------------------------------
michael@0 1376 bool
michael@0 1377 nsPrintEngine::IsThereAnIFrameSelected(nsIDocShell* aDocShell,
michael@0 1378 nsIDOMWindow* aDOMWin,
michael@0 1379 bool& aIsParentFrameSet)
michael@0 1380 {
michael@0 1381 aIsParentFrameSet = IsParentAFrameSet(aDocShell);
michael@0 1382 bool iFrameIsSelected = false;
michael@0 1383 if (mPrt && mPrt->mPrintObject) {
michael@0 1384 nsPrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin);
michael@0 1385 iFrameIsSelected = po && po->mFrameType == eIFrame;
michael@0 1386 } else {
michael@0 1387 // First, check to see if we are a frameset
michael@0 1388 if (!aIsParentFrameSet) {
michael@0 1389 // Check to see if there is a currenlt focused frame
michael@0 1390 // if so, it means the selected frame is either the main docshell
michael@0 1391 // or an IFRAME
michael@0 1392 if (aDOMWin) {
michael@0 1393 // Get the main docshell's DOMWin to see if it matches
michael@0 1394 // the frame that is selected
michael@0 1395 nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(aDocShell);
michael@0 1396 if (domWin != aDOMWin) {
michael@0 1397 iFrameIsSelected = true; // we have a selected IFRAME
michael@0 1398 }
michael@0 1399 }
michael@0 1400 }
michael@0 1401 }
michael@0 1402
michael@0 1403 return iFrameIsSelected;
michael@0 1404 }
michael@0 1405
michael@0 1406 //---------------------------------------------------------------------
michael@0 1407 // Recursively sets all the PO items to be printed
michael@0 1408 // from the given item down into the tree
michael@0 1409 void
michael@0 1410 nsPrintEngine::SetPrintPO(nsPrintObject* aPO, bool aPrint)
michael@0 1411 {
michael@0 1412 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 1413
michael@0 1414 // Set whether to print flag
michael@0 1415 aPO->mDontPrint = !aPrint;
michael@0 1416
michael@0 1417 for (uint32_t i=0;i<aPO->mKids.Length();i++) {
michael@0 1418 SetPrintPO(aPO->mKids[i], aPrint);
michael@0 1419 }
michael@0 1420 }
michael@0 1421
michael@0 1422 //---------------------------------------------------------------------
michael@0 1423 // This will first use a Title and/or URL from the PrintSettings
michael@0 1424 // if one isn't set then it uses the one from the document
michael@0 1425 // then if not title is there we will make sure we send something back
michael@0 1426 // depending on the situation.
michael@0 1427 void
michael@0 1428 nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject* aPO,
michael@0 1429 nsAString& aTitle,
michael@0 1430 nsAString& aURLStr,
michael@0 1431 eDocTitleDefault aDefType)
michael@0 1432 {
michael@0 1433 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 1434
michael@0 1435 if (!mPrt)
michael@0 1436 return;
michael@0 1437
michael@0 1438 aTitle.Truncate();
michael@0 1439 aURLStr.Truncate();
michael@0 1440
michael@0 1441 // First check to see if the PrintSettings has defined an alternate title
michael@0 1442 // and use that if it did
michael@0 1443 if (mPrt->mPrintSettings) {
michael@0 1444 char16_t * docTitleStrPS = nullptr;
michael@0 1445 char16_t * docURLStrPS = nullptr;
michael@0 1446 mPrt->mPrintSettings->GetTitle(&docTitleStrPS);
michael@0 1447 mPrt->mPrintSettings->GetDocURL(&docURLStrPS);
michael@0 1448
michael@0 1449 if (docTitleStrPS) {
michael@0 1450 aTitle = docTitleStrPS;
michael@0 1451 }
michael@0 1452
michael@0 1453 if (docURLStrPS) {
michael@0 1454 aURLStr = docURLStrPS;
michael@0 1455 }
michael@0 1456
michael@0 1457 nsMemory::Free(docTitleStrPS);
michael@0 1458 nsMemory::Free(docURLStrPS);
michael@0 1459 }
michael@0 1460
michael@0 1461 nsAutoString docTitle;
michael@0 1462 nsAutoString docUrl;
michael@0 1463 GetDocumentTitleAndURL(aPO->mDocument, docTitle, docUrl);
michael@0 1464
michael@0 1465 if (aURLStr.IsEmpty() && !docUrl.IsEmpty()) {
michael@0 1466 aURLStr = docUrl;
michael@0 1467 }
michael@0 1468
michael@0 1469 if (aTitle.IsEmpty()) {
michael@0 1470 if (!docTitle.IsEmpty()) {
michael@0 1471 aTitle = docTitle;
michael@0 1472 } else {
michael@0 1473 if (aDefType == eDocTitleDefURLDoc) {
michael@0 1474 if (!aURLStr.IsEmpty()) {
michael@0 1475 aTitle = aURLStr;
michael@0 1476 } else if (mPrt->mBrandName) {
michael@0 1477 aTitle = mPrt->mBrandName;
michael@0 1478 }
michael@0 1479 }
michael@0 1480 }
michael@0 1481 }
michael@0 1482 }
michael@0 1483
michael@0 1484 //---------------------------------------------------------------------
michael@0 1485 nsresult nsPrintEngine::DocumentReadyForPrinting()
michael@0 1486 {
michael@0 1487 if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
michael@0 1488 CheckForChildFrameSets(mPrt->mPrintObject);
michael@0 1489 }
michael@0 1490
michael@0 1491 //
michael@0 1492 // Send the document to the printer...
michael@0 1493 //
michael@0 1494 nsresult rv = SetupToPrintContent();
michael@0 1495 if (NS_FAILED(rv)) {
michael@0 1496 // The print job was canceled or there was a problem
michael@0 1497 // So remove all other documents from the print list
michael@0 1498 DonePrintingPages(nullptr, rv);
michael@0 1499 }
michael@0 1500 return rv;
michael@0 1501 }
michael@0 1502
michael@0 1503 /** ---------------------------------------------------
michael@0 1504 * Cleans up when an error occurred
michael@0 1505 */
michael@0 1506 nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, bool aIsPrinting)
michael@0 1507 {
michael@0 1508 PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting?"Printing":"Print Preview", aResult));
michael@0 1509
michael@0 1510 /* cleanup... */
michael@0 1511 if (mPagePrintTimer) {
michael@0 1512 mPagePrintTimer->Stop();
michael@0 1513 NS_RELEASE(mPagePrintTimer);
michael@0 1514 }
michael@0 1515
michael@0 1516 if (aIsPrinting) {
michael@0 1517 SetIsPrinting(false);
michael@0 1518 } else {
michael@0 1519 SetIsPrintPreview(false);
michael@0 1520 SetIsCreatingPrintPreview(false);
michael@0 1521 }
michael@0 1522
michael@0 1523 /* cleanup done, let's fire-up an error dialog to notify the user
michael@0 1524 * what went wrong...
michael@0 1525 *
michael@0 1526 * When rv == NS_ERROR_ABORT, it means we want out of the
michael@0 1527 * print job without displaying any error messages
michael@0 1528 */
michael@0 1529 if (aResult != NS_ERROR_ABORT) {
michael@0 1530 ShowPrintErrorDialog(aResult, aIsPrinting);
michael@0 1531 }
michael@0 1532
michael@0 1533 FirePrintCompletionEvent();
michael@0 1534
michael@0 1535 return aResult;
michael@0 1536
michael@0 1537 }
michael@0 1538
michael@0 1539 //---------------------------------------------------------------------
michael@0 1540 void
michael@0 1541 nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, bool aIsPrinting)
michael@0 1542 {
michael@0 1543 nsAutoCString stringName;
michael@0 1544 nsXPIDLString msg, title;
michael@0 1545 nsresult rv = NS_OK;
michael@0 1546
michael@0 1547 switch(aPrintError)
michael@0 1548 {
michael@0 1549 #define ENTITY_FOR_ERROR(label) \
michael@0 1550 case NS_ERROR_##label: stringName.AssignLiteral("PERR_" #label); break
michael@0 1551
michael@0 1552 ENTITY_FOR_ERROR(GFX_PRINTER_NO_PRINTER_AVAILABLE);
michael@0 1553 ENTITY_FOR_ERROR(GFX_PRINTER_NAME_NOT_FOUND);
michael@0 1554 ENTITY_FOR_ERROR(GFX_PRINTER_COULD_NOT_OPEN_FILE);
michael@0 1555 ENTITY_FOR_ERROR(GFX_PRINTER_STARTDOC);
michael@0 1556 ENTITY_FOR_ERROR(GFX_PRINTER_ENDDOC);
michael@0 1557 ENTITY_FOR_ERROR(GFX_PRINTER_STARTPAGE);
michael@0 1558 ENTITY_FOR_ERROR(GFX_PRINTER_DOC_IS_BUSY);
michael@0 1559
michael@0 1560 ENTITY_FOR_ERROR(ABORT);
michael@0 1561 ENTITY_FOR_ERROR(NOT_AVAILABLE);
michael@0 1562 ENTITY_FOR_ERROR(NOT_IMPLEMENTED);
michael@0 1563 ENTITY_FOR_ERROR(OUT_OF_MEMORY);
michael@0 1564 ENTITY_FOR_ERROR(UNEXPECTED);
michael@0 1565
michael@0 1566 default:
michael@0 1567 ENTITY_FOR_ERROR(FAILURE);
michael@0 1568
michael@0 1569 #undef ENTITY_FOR_ERROR
michael@0 1570 }
michael@0 1571
michael@0 1572 if (!aIsPrinting) {
michael@0 1573 // Try first with _PP suffix.
michael@0 1574 stringName.AppendLiteral("_PP");
michael@0 1575 rv = nsContentUtils::GetLocalizedString(
michael@0 1576 nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg);
michael@0 1577 if (NS_FAILED(rv)) {
michael@0 1578 stringName.Truncate(stringName.Length() - 3);
michael@0 1579 }
michael@0 1580 }
michael@0 1581 if (aIsPrinting || NS_FAILED(rv)) {
michael@0 1582 rv = nsContentUtils::GetLocalizedString(
michael@0 1583 nsContentUtils::ePRINTING_PROPERTIES, stringName.get(), msg);
michael@0 1584 }
michael@0 1585 if (NS_FAILED(rv)) {
michael@0 1586 return;
michael@0 1587 }
michael@0 1588
michael@0 1589 rv = nsContentUtils::GetLocalizedString(
michael@0 1590 nsContentUtils::ePRINTING_PROPERTIES,
michael@0 1591 aIsPrinting ? "print_error_dialog_title"
michael@0 1592 : "printpreview_error_dialog_title",
michael@0 1593 title);
michael@0 1594 if (NS_FAILED(rv)) {
michael@0 1595 return;
michael@0 1596 }
michael@0 1597
michael@0 1598 nsCOMPtr<nsIWindowWatcher> wwatch =
michael@0 1599 do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
michael@0 1600 if (NS_FAILED(rv)) {
michael@0 1601 return;
michael@0 1602 }
michael@0 1603
michael@0 1604 nsCOMPtr<nsIDOMWindow> active;
michael@0 1605 wwatch->GetActiveWindow(getter_AddRefs(active));
michael@0 1606
michael@0 1607 nsCOMPtr<nsIPrompt> dialog;
michael@0 1608 /* |GetNewPrompter| allows that |active| is |nullptr|
michael@0 1609 * (see bug 234982 ("nsPrintEngine::ShowPrintErrorDialog() fails in many cases")) */
michael@0 1610 wwatch->GetNewPrompter(active, getter_AddRefs(dialog));
michael@0 1611 if (!dialog) {
michael@0 1612 return;
michael@0 1613 }
michael@0 1614
michael@0 1615 dialog->Alert(title.get(), msg.get());
michael@0 1616 }
michael@0 1617
michael@0 1618 //-----------------------------------------------------------------
michael@0 1619 //-- Section: Reflow Methods
michael@0 1620 //-----------------------------------------------------------------
michael@0 1621
michael@0 1622 nsresult
michael@0 1623 nsPrintEngine::ReconstructAndReflow(bool doSetPixelScale)
michael@0 1624 {
michael@0 1625 #if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING)
michael@0 1626 // We need to clear all the output files here
michael@0 1627 // because they will be re-created with second reflow of the docs
michael@0 1628 if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
michael@0 1629 RemoveFilesInDir(".\\");
michael@0 1630 gDumpFileNameCnt = 0;
michael@0 1631 gDumpLOFileNameCnt = 0;
michael@0 1632 }
michael@0 1633 #endif
michael@0 1634
michael@0 1635 for (uint32_t i = 0; i < mPrt->mPrintDocList.Length(); ++i) {
michael@0 1636 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 1637 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 1638
michael@0 1639 if (po->mDontPrint || po->mInvisible) {
michael@0 1640 continue;
michael@0 1641 }
michael@0 1642
michael@0 1643 UpdateZoomRatio(po, doSetPixelScale);
michael@0 1644
michael@0 1645 po->mPresContext->SetPageScale(po->mZoomRatio);
michael@0 1646
michael@0 1647 // Calculate scale factor from printer to screen
michael@0 1648 float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) /
michael@0 1649 float(mPrt->mPrintDC->AppUnitsPerDevPixel());
michael@0 1650 po->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
michael@0 1651
michael@0 1652 po->mPresShell->ReconstructFrames();
michael@0 1653
michael@0 1654 // For all views except the first one, setup the root view.
michael@0 1655 // ??? Can there be multiple po for the top-level-document?
michael@0 1656 bool documentIsTopLevel = true;
michael@0 1657 if (i != 0) {
michael@0 1658 nsSize adjSize;
michael@0 1659 bool doReturn;
michael@0 1660 nsresult rv = SetRootView(po, doReturn, documentIsTopLevel, adjSize);
michael@0 1661
michael@0 1662 MOZ_ASSERT(!documentIsTopLevel, "How could this happen?");
michael@0 1663
michael@0 1664 if (NS_FAILED(rv) || doReturn) {
michael@0 1665 return rv;
michael@0 1666 }
michael@0 1667 }
michael@0 1668
michael@0 1669 po->mPresShell->FlushPendingNotifications(Flush_Layout);
michael@0 1670
michael@0 1671 nsresult rv = UpdateSelectionAndShrinkPrintObject(po, documentIsTopLevel);
michael@0 1672 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1673 }
michael@0 1674 return NS_OK;
michael@0 1675 }
michael@0 1676
michael@0 1677 //-------------------------------------------------------
michael@0 1678 nsresult
michael@0 1679 nsPrintEngine::SetupToPrintContent()
michael@0 1680 {
michael@0 1681 nsresult rv;
michael@0 1682
michael@0 1683 bool didReconstruction = false;
michael@0 1684
michael@0 1685 // If some new content got loaded since the initial reflow rebuild
michael@0 1686 // everything.
michael@0 1687 if (mDidLoadDataForPrinting) {
michael@0 1688 rv = ReconstructAndReflow(DoSetPixelScale());
michael@0 1689 didReconstruction = true;
michael@0 1690 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1691 }
michael@0 1692
michael@0 1693 // Here is where we figure out if extra reflow for shrinking the content
michael@0 1694 // is required.
michael@0 1695 // But skip this step if we are in PrintPreview
michael@0 1696 bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
michael@0 1697 if (mPrt->mShrinkToFit && !ppIsShrinkToFit) {
michael@0 1698 // Now look for the PO that has the smallest percent for shrink to fit
michael@0 1699 if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) {
michael@0 1700 nsPrintObject* smallestPO = FindSmallestSTF();
michael@0 1701 NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
michael@0 1702 if (smallestPO) {
michael@0 1703 // Calc the shrinkage based on the entire content area
michael@0 1704 mPrt->mShrinkRatio = smallestPO->mShrinkRatio;
michael@0 1705 }
michael@0 1706 } else {
michael@0 1707 // Single document so use the Shrink as calculated for the PO
michael@0 1708 mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio;
michael@0 1709 }
michael@0 1710
michael@0 1711 if (mPrt->mShrinkRatio < 0.998f) {
michael@0 1712 rv = ReconstructAndReflow(true);
michael@0 1713 didReconstruction = true;
michael@0 1714 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1715 }
michael@0 1716
michael@0 1717 #ifdef PR_LOGGING
michael@0 1718 float calcRatio = 0.0f;
michael@0 1719 if (mPrt->mPrintDocList.Length() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) {
michael@0 1720 nsPrintObject* smallestPO = FindSmallestSTF();
michael@0 1721 NS_ASSERTION(smallestPO, "There must always be an XMost PO!");
michael@0 1722 if (smallestPO) {
michael@0 1723 // Calc the shrinkage based on the entire content area
michael@0 1724 calcRatio = smallestPO->mShrinkRatio;
michael@0 1725 }
michael@0 1726 } else {
michael@0 1727 // Single document so use the Shrink as calculated for the PO
michael@0 1728 calcRatio = mPrt->mPrintObject->mShrinkRatio;
michael@0 1729 }
michael@0 1730 PR_PL(("**************************************************************************\n"));
michael@0 1731 PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio));
michael@0 1732 PR_PL(("**************************************************************************\n"));
michael@0 1733 #endif
michael@0 1734 }
michael@0 1735
michael@0 1736 // If the frames got reconstructed and reflowed the number of pages might
michael@0 1737 // has changed.
michael@0 1738 if (didReconstruction) {
michael@0 1739 FirePrintPreviewUpdateEvent();
michael@0 1740 }
michael@0 1741
michael@0 1742 DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------"));
michael@0 1743 PR_PL(("\n"));
michael@0 1744 PR_PL(("-------------------------------------------------------\n"));
michael@0 1745 PR_PL(("\n"));
michael@0 1746
michael@0 1747 CalcNumPrintablePages(mPrt->mNumPrintablePages);
michael@0 1748
michael@0 1749 PR_PL(("--- Printing %d pages\n", mPrt->mNumPrintablePages));
michael@0 1750 DUMP_DOC_TREELAYOUT;
michael@0 1751
michael@0 1752 // Print listener setup...
michael@0 1753 if (mPrt != nullptr) {
michael@0 1754 mPrt->OnStartPrinting();
michael@0 1755 }
michael@0 1756
michael@0 1757 char16_t* fileName = nullptr;
michael@0 1758 // check to see if we are printing to a file
michael@0 1759 bool isPrintToFile = false;
michael@0 1760 mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile);
michael@0 1761 if (isPrintToFile) {
michael@0 1762 // On some platforms The BeginDocument needs to know the name of the file
michael@0 1763 // and it uses the PrintService to get it, so we need to set it into the PrintService here
michael@0 1764 mPrt->mPrintSettings->GetToFileName(&fileName);
michael@0 1765 }
michael@0 1766
michael@0 1767 nsAutoString docTitleStr;
michael@0 1768 nsAutoString docURLStr;
michael@0 1769 GetDisplayTitleAndURL(mPrt->mPrintObject, docTitleStr, docURLStr, eDocTitleDefURLDoc);
michael@0 1770
michael@0 1771 int32_t startPage = 1;
michael@0 1772 int32_t endPage = mPrt->mNumPrintablePages;
michael@0 1773
michael@0 1774 int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
michael@0 1775 mPrt->mPrintSettings->GetPrintRange(&printRangeType);
michael@0 1776 if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
michael@0 1777 mPrt->mPrintSettings->GetStartPageRange(&startPage);
michael@0 1778 mPrt->mPrintSettings->GetEndPageRange(&endPage);
michael@0 1779 if (endPage > mPrt->mNumPrintablePages) {
michael@0 1780 endPage = mPrt->mNumPrintablePages;
michael@0 1781 }
michael@0 1782 }
michael@0 1783
michael@0 1784 rv = NS_OK;
michael@0 1785 // BeginDocument may pass back a FAILURE code
michael@0 1786 // i.e. On Windows, if you are printing to a file and hit "Cancel"
michael@0 1787 // to the "File Name" dialog, this comes back as an error
michael@0 1788 // Don't start printing when regression test are executed
michael@0 1789 if (!mPrt->mDebugFilePtr && mIsDoingPrinting) {
michael@0 1790 rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage);
michael@0 1791 }
michael@0 1792
michael@0 1793 if (mIsCreatingPrintPreview) {
michael@0 1794 // Copy docTitleStr and docURLStr to the pageSequenceFrame, to be displayed
michael@0 1795 // in the header
michael@0 1796 nsIPageSequenceFrame *seqFrame = mPrt->mPrintObject->mPresShell->GetPageSequenceFrame();
michael@0 1797 if (seqFrame) {
michael@0 1798 seqFrame->StartPrint(mPrt->mPrintObject->mPresContext,
michael@0 1799 mPrt->mPrintSettings, docTitleStr, docURLStr);
michael@0 1800 }
michael@0 1801 }
michael@0 1802
michael@0 1803 PR_PL(("****************** Begin Document ************************\n"));
michael@0 1804
michael@0 1805 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1806
michael@0 1807 // This will print the docshell document
michael@0 1808 // when it completes asynchronously in the DonePrintingPages method
michael@0 1809 // it will check to see if there are more docshells to be printed and
michael@0 1810 // then PrintDocContent will be called again.
michael@0 1811
michael@0 1812 if (mIsDoingPrinting) {
michael@0 1813 PrintDocContent(mPrt->mPrintObject, rv); // ignore return value
michael@0 1814 }
michael@0 1815
michael@0 1816 return rv;
michael@0 1817 }
michael@0 1818
michael@0 1819 //-------------------------------------------------------
michael@0 1820 // Recursively reflow each sub-doc and then calc
michael@0 1821 // all the frame locations of the sub-docs
michael@0 1822 nsresult
michael@0 1823 nsPrintEngine::ReflowDocList(nsPrintObject* aPO, bool aSetPixelScale)
michael@0 1824 {
michael@0 1825 NS_ENSURE_ARG_POINTER(aPO);
michael@0 1826
michael@0 1827 // Check to see if the subdocument's element has been hidden by the parent document
michael@0 1828 if (aPO->mParent && aPO->mParent->mPresShell) {
michael@0 1829 nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
michael@0 1830 if (!frame || !frame->StyleVisibility()->IsVisible()) {
michael@0 1831 SetPrintPO(aPO, false);
michael@0 1832 aPO->mInvisible = true;
michael@0 1833 return NS_OK;
michael@0 1834 }
michael@0 1835 }
michael@0 1836
michael@0 1837 UpdateZoomRatio(aPO, aSetPixelScale);
michael@0 1838
michael@0 1839 nsresult rv;
michael@0 1840 // Reflow the PO
michael@0 1841 rv = ReflowPrintObject(aPO);
michael@0 1842 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1843
michael@0 1844 int32_t cnt = aPO->mKids.Length();
michael@0 1845 for (int32_t i=0;i<cnt;i++) {
michael@0 1846 rv = ReflowDocList(aPO->mKids[i], aSetPixelScale);
michael@0 1847 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1848 }
michael@0 1849 return NS_OK;
michael@0 1850 }
michael@0 1851
michael@0 1852 void
michael@0 1853 nsPrintEngine::FirePrintPreviewUpdateEvent()
michael@0 1854 {
michael@0 1855 // Dispatch the event only while in PrintPreview. When printing, there is no
michael@0 1856 // listener bound to this event and therefore no need to dispatch it.
michael@0 1857 if (mIsDoingPrintPreview && !mIsDoingPrinting) {
michael@0 1858 nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
michael@0 1859 (new AsyncEventDispatcher(
michael@0 1860 cv->GetDocument(), NS_LITERAL_STRING("printPreviewUpdate"), true, true)
michael@0 1861 )->RunDOMEventWhenSafe();
michael@0 1862 }
michael@0 1863 }
michael@0 1864
michael@0 1865 nsresult
michael@0 1866 nsPrintEngine::InitPrintDocConstruction(bool aHandleError)
michael@0 1867 {
michael@0 1868 nsresult rv;
michael@0 1869 rv = ReflowDocList(mPrt->mPrintObject, DoSetPixelScale());
michael@0 1870 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1871
michael@0 1872 FirePrintPreviewUpdateEvent();
michael@0 1873
michael@0 1874 if (mLoadCounter == 0) {
michael@0 1875 AfterNetworkPrint(aHandleError);
michael@0 1876 }
michael@0 1877 return rv;
michael@0 1878 }
michael@0 1879
michael@0 1880 nsresult
michael@0 1881 nsPrintEngine::AfterNetworkPrint(bool aHandleError)
michael@0 1882 {
michael@0 1883 nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(mPrt->mPrintObject->mDocShell);
michael@0 1884
michael@0 1885 webProgress->RemoveProgressListener(
michael@0 1886 static_cast<nsIWebProgressListener*>(this));
michael@0 1887
michael@0 1888 nsresult rv;
michael@0 1889 if (mIsDoingPrinting) {
michael@0 1890 rv = DocumentReadyForPrinting();
michael@0 1891 } else {
michael@0 1892 rv = FinishPrintPreview();
michael@0 1893 }
michael@0 1894
michael@0 1895 /* cleaup on failure + notify user */
michael@0 1896 if (aHandleError && NS_FAILED(rv)) {
michael@0 1897 CleanupOnFailure(rv, !mIsDoingPrinting);
michael@0 1898 }
michael@0 1899
michael@0 1900 return rv;
michael@0 1901 }
michael@0 1902
michael@0 1903 ////////////////////////////////////////////////////////////////////////////////
michael@0 1904 // nsIWebProgressListener
michael@0 1905
michael@0 1906 NS_IMETHODIMP
michael@0 1907 nsPrintEngine::OnStateChange(nsIWebProgress* aWebProgress,
michael@0 1908 nsIRequest* aRequest,
michael@0 1909 uint32_t aStateFlags,
michael@0 1910 nsresult aStatus)
michael@0 1911 {
michael@0 1912 nsAutoCString name;
michael@0 1913 aRequest->GetName(name);
michael@0 1914 if (name.Equals("about:document-onload-blocker")) {
michael@0 1915 return NS_OK;
michael@0 1916 }
michael@0 1917 if (aStateFlags & STATE_START) {
michael@0 1918 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
michael@0 1919
michael@0 1920 ++mLoadCounter;
michael@0 1921 } else if (aStateFlags & STATE_STOP) {
michael@0 1922 mDidLoadDataForPrinting = true;
michael@0 1923 --mLoadCounter;
michael@0 1924
michael@0 1925 // If all resources are loaded, then do a small timeout and if there
michael@0 1926 // are still no new requests, then another reflow.
michael@0 1927 if (mLoadCounter == 0) {
michael@0 1928 AfterNetworkPrint(true);
michael@0 1929 }
michael@0 1930 }
michael@0 1931 return NS_OK;
michael@0 1932 }
michael@0 1933
michael@0 1934
michael@0 1935
michael@0 1936 NS_IMETHODIMP
michael@0 1937 nsPrintEngine::OnProgressChange(nsIWebProgress* aWebProgress,
michael@0 1938 nsIRequest* aRequest,
michael@0 1939 int32_t aCurSelfProgress,
michael@0 1940 int32_t aMaxSelfProgress,
michael@0 1941 int32_t aCurTotalProgress,
michael@0 1942 int32_t aMaxTotalProgress)
michael@0 1943 {
michael@0 1944 NS_NOTREACHED("notification excluded in AddProgressListener(...)");
michael@0 1945 return NS_OK;
michael@0 1946 }
michael@0 1947
michael@0 1948 NS_IMETHODIMP
michael@0 1949 nsPrintEngine::OnLocationChange(nsIWebProgress* aWebProgress,
michael@0 1950 nsIRequest* aRequest,
michael@0 1951 nsIURI* aLocation,
michael@0 1952 uint32_t aFlags)
michael@0 1953 {
michael@0 1954 NS_NOTREACHED("notification excluded in AddProgressListener(...)");
michael@0 1955 return NS_OK;
michael@0 1956 }
michael@0 1957
michael@0 1958 NS_IMETHODIMP
michael@0 1959 nsPrintEngine::OnStatusChange(nsIWebProgress *aWebProgress,
michael@0 1960 nsIRequest *aRequest,
michael@0 1961 nsresult aStatus,
michael@0 1962 const char16_t *aMessage)
michael@0 1963 {
michael@0 1964 NS_NOTREACHED("notification excluded in AddProgressListener(...)");
michael@0 1965 return NS_OK;
michael@0 1966 }
michael@0 1967
michael@0 1968 NS_IMETHODIMP
michael@0 1969 nsPrintEngine::OnSecurityChange(nsIWebProgress *aWebProgress,
michael@0 1970 nsIRequest *aRequest,
michael@0 1971 uint32_t aState)
michael@0 1972 {
michael@0 1973 NS_NOTREACHED("notification excluded in AddProgressListener(...)");
michael@0 1974 return NS_OK;
michael@0 1975 }
michael@0 1976
michael@0 1977 //-------------------------------------------------------
michael@0 1978
michael@0 1979 void
michael@0 1980 nsPrintEngine::UpdateZoomRatio(nsPrintObject* aPO, bool aSetPixelScale)
michael@0 1981 {
michael@0 1982 // Here is where we set the shrinkage value into the DC
michael@0 1983 // and this is what actually makes it shrink
michael@0 1984 if (aSetPixelScale && aPO->mFrameType != eIFrame) {
michael@0 1985 float ratio;
michael@0 1986 if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) {
michael@0 1987 ratio = mPrt->mShrinkRatio - 0.005f; // round down
michael@0 1988 } else {
michael@0 1989 ratio = aPO->mShrinkRatio - 0.005f; // round down
michael@0 1990 }
michael@0 1991 aPO->mZoomRatio = ratio;
michael@0 1992 } else if (!mPrt->mShrinkToFit) {
michael@0 1993 double scaling;
michael@0 1994 mPrt->mPrintSettings->GetScaling(&scaling);
michael@0 1995 aPO->mZoomRatio = float(scaling);
michael@0 1996 }
michael@0 1997 }
michael@0 1998
michael@0 1999 nsresult
michael@0 2000 nsPrintEngine::UpdateSelectionAndShrinkPrintObject(nsPrintObject* aPO,
michael@0 2001 bool aDocumentIsTopLevel)
michael@0 2002 {
michael@0 2003 nsCOMPtr<nsIPresShell> displayShell = aPO->mDocShell->GetPresShell();
michael@0 2004 // Transfer Selection Ranges to the new Print PresShell
michael@0 2005 nsRefPtr<Selection> selection, selectionPS;
michael@0 2006 // It's okay if there is no display shell, just skip copying the selection
michael@0 2007 if (displayShell) {
michael@0 2008 selection = displayShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 2009 }
michael@0 2010 selectionPS = aPO->mPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 2011
michael@0 2012 // Reset all existing selection ranges that might have been added by calling
michael@0 2013 // this function before.
michael@0 2014 if (selectionPS) {
michael@0 2015 selectionPS->RemoveAllRanges();
michael@0 2016 }
michael@0 2017 if (selection && selectionPS) {
michael@0 2018 int32_t cnt = selection->GetRangeCount();
michael@0 2019 int32_t inx;
michael@0 2020 for (inx = 0; inx < cnt; ++inx) {
michael@0 2021 selectionPS->AddRange(selection->GetRangeAt(inx));
michael@0 2022 }
michael@0 2023 }
michael@0 2024
michael@0 2025 // If we are trying to shrink the contents to fit on the page
michael@0 2026 // we must first locate the "pageContent" frame
michael@0 2027 // Then we walk the frame tree and look for the "xmost" frame
michael@0 2028 // this is the frame where the right-hand side of the frame extends
michael@0 2029 // the furthest
michael@0 2030 if (mPrt->mShrinkToFit && aDocumentIsTopLevel) {
michael@0 2031 nsIPageSequenceFrame* pageSequence = aPO->mPresShell->GetPageSequenceFrame();
michael@0 2032 NS_ENSURE_STATE(pageSequence);
michael@0 2033 pageSequence->GetSTFPercent(aPO->mShrinkRatio);
michael@0 2034 // Limit the shrink-to-fit scaling for some text-ish type of documents.
michael@0 2035 nsAutoString contentType;
michael@0 2036 aPO->mPresShell->GetDocument()->GetContentType(contentType);
michael@0 2037 if (contentType.EqualsLiteral("application/xhtml+xml") ||
michael@0 2038 StringBeginsWith(contentType, NS_LITERAL_STRING("text/"))) {
michael@0 2039 int32_t limitPercent =
michael@0 2040 Preferences::GetInt("print.shrink-to-fit.scale-limit-percent", 20);
michael@0 2041 limitPercent = std::max(0, limitPercent);
michael@0 2042 limitPercent = std::min(100, limitPercent);
michael@0 2043 float minShrinkRatio = float(limitPercent) / 100;
michael@0 2044 aPO->mShrinkRatio = std::max(aPO->mShrinkRatio, minShrinkRatio);
michael@0 2045 }
michael@0 2046 }
michael@0 2047 return NS_OK;
michael@0 2048 }
michael@0 2049
michael@0 2050 bool
michael@0 2051 nsPrintEngine::DoSetPixelScale()
michael@0 2052 {
michael@0 2053 // This is an Optimization
michael@0 2054 // If we are in PP then we already know all the shrinkage information
michael@0 2055 // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
michael@0 2056 //
michael@0 2057 // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
michael@0 2058 // The first time we do not want to do this, the second time through we do
michael@0 2059 bool doSetPixelScale = false;
michael@0 2060 bool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit;
michael@0 2061 if (ppIsShrinkToFit) {
michael@0 2062 mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio;
michael@0 2063 doSetPixelScale = true;
michael@0 2064 }
michael@0 2065 return doSetPixelScale;
michael@0 2066 }
michael@0 2067
michael@0 2068 nsView*
michael@0 2069 nsPrintEngine::GetParentViewForRoot()
michael@0 2070 {
michael@0 2071 if (mIsCreatingPrintPreview) {
michael@0 2072 nsCOMPtr<nsIContentViewer> cv = do_QueryInterface(mDocViewerPrint);
michael@0 2073 if (cv) {
michael@0 2074 return cv->FindContainerView();
michael@0 2075 }
michael@0 2076 }
michael@0 2077 return nullptr;
michael@0 2078 }
michael@0 2079
michael@0 2080 nsresult
michael@0 2081 nsPrintEngine::SetRootView(
michael@0 2082 nsPrintObject* aPO,
michael@0 2083 bool& doReturn,
michael@0 2084 bool& documentIsTopLevel,
michael@0 2085 nsSize& adjSize
michael@0 2086 )
michael@0 2087 {
michael@0 2088 bool canCreateScrollbars = true;
michael@0 2089
michael@0 2090 nsView* rootView;
michael@0 2091 nsView* parentView = nullptr;
michael@0 2092
michael@0 2093 doReturn = false;
michael@0 2094
michael@0 2095 if (aPO->mParent && aPO->mParent->IsPrintable()) {
michael@0 2096 nsIFrame* frame = aPO->mContent ? aPO->mContent->GetPrimaryFrame() : nullptr;
michael@0 2097 // Without a frame, this document can't be displayed; therefore, there is no
michael@0 2098 // point to reflowing it
michael@0 2099 if (!frame) {
michael@0 2100 SetPrintPO(aPO, false);
michael@0 2101 doReturn = true;
michael@0 2102 return NS_OK;
michael@0 2103 }
michael@0 2104
michael@0 2105 //XXX If printing supported printing document hierarchies with non-constant
michael@0 2106 // zoom this would be wrong as we use the same mPrt->mPrintDC for all
michael@0 2107 // subdocuments.
michael@0 2108 adjSize = frame->GetContentRect().Size();
michael@0 2109 documentIsTopLevel = false;
michael@0 2110 // presshell exists because parent is printable
michael@0 2111
michael@0 2112 // the top nsPrintObject's widget will always have scrollbars
michael@0 2113 if (frame && frame->GetType() == nsGkAtoms::subDocumentFrame) {
michael@0 2114 nsView* view = frame->GetView();
michael@0 2115 NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
michael@0 2116 view = view->GetFirstChild();
michael@0 2117 NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
michael@0 2118 parentView = view;
michael@0 2119 canCreateScrollbars = false;
michael@0 2120 }
michael@0 2121 } else {
michael@0 2122 nscoord pageWidth, pageHeight;
michael@0 2123 mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
michael@0 2124 adjSize = nsSize(pageWidth, pageHeight);
michael@0 2125 documentIsTopLevel = true;
michael@0 2126 parentView = GetParentViewForRoot();
michael@0 2127 }
michael@0 2128
michael@0 2129 if (aPO->mViewManager->GetRootView()) {
michael@0 2130 // Reuse the root view that is already on the root frame.
michael@0 2131 rootView = aPO->mViewManager->GetRootView();
michael@0 2132 // Remove it from its existing parent if necessary
michael@0 2133 aPO->mViewManager->RemoveChild(rootView);
michael@0 2134 rootView->SetParent(parentView);
michael@0 2135 } else {
michael@0 2136 // Create a child window of the parent that is our "root view/window"
michael@0 2137 nsRect tbounds = nsRect(nsPoint(0, 0), adjSize);
michael@0 2138 rootView = aPO->mViewManager->CreateView(tbounds, parentView);
michael@0 2139 NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY);
michael@0 2140 }
michael@0 2141
michael@0 2142 if (mIsCreatingPrintPreview && documentIsTopLevel) {
michael@0 2143 aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars);
michael@0 2144 }
michael@0 2145
michael@0 2146 // Setup hierarchical relationship in view manager
michael@0 2147 aPO->mViewManager->SetRootView(rootView);
michael@0 2148
michael@0 2149 return NS_OK;
michael@0 2150 }
michael@0 2151
michael@0 2152 // Reflow a nsPrintObject
michael@0 2153 nsresult
michael@0 2154 nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO)
michael@0 2155 {
michael@0 2156 NS_ENSURE_STATE(aPO);
michael@0 2157
michael@0 2158 if (!aPO->IsPrintable()) {
michael@0 2159 return NS_OK;
michael@0 2160 }
michael@0 2161
michael@0 2162 NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext");
michael@0 2163
michael@0 2164 // create the PresContext
michael@0 2165 nsPresContext::nsPresContextType type =
michael@0 2166 mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
michael@0 2167 nsPresContext::eContext_Print;
michael@0 2168 nsView* parentView =
michael@0 2169 aPO->mParent && aPO->mParent->IsPrintable() ? nullptr : GetParentViewForRoot();
michael@0 2170 aPO->mPresContext = parentView ?
michael@0 2171 new nsPresContext(aPO->mDocument, type) :
michael@0 2172 new nsRootPresContext(aPO->mDocument, type);
michael@0 2173 NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY);
michael@0 2174 aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings);
michael@0 2175
michael@0 2176 // set the presentation context to the value in the print settings
michael@0 2177 bool printBGColors;
michael@0 2178 mPrt->mPrintSettings->GetPrintBGColors(&printBGColors);
michael@0 2179 aPO->mPresContext->SetBackgroundColorDraw(printBGColors);
michael@0 2180 mPrt->mPrintSettings->GetPrintBGImages(&printBGColors);
michael@0 2181 aPO->mPresContext->SetBackgroundImageDraw(printBGColors);
michael@0 2182
michael@0 2183 // init it with the DC
michael@0 2184 nsresult rv = aPO->mPresContext->Init(mPrt->mPrintDC);
michael@0 2185 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2186
michael@0 2187 aPO->mViewManager = new nsViewManager();
michael@0 2188
michael@0 2189 rv = aPO->mViewManager->Init(mPrt->mPrintDC);
michael@0 2190 NS_ENSURE_SUCCESS(rv,rv);
michael@0 2191
michael@0 2192 nsStyleSet* styleSet;
michael@0 2193 rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, &styleSet);
michael@0 2194 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2195
michael@0 2196 aPO->mPresShell = aPO->mDocument->CreateShell(aPO->mPresContext,
michael@0 2197 aPO->mViewManager, styleSet);
michael@0 2198 if (!aPO->mPresShell) {
michael@0 2199 delete styleSet;
michael@0 2200 return NS_ERROR_FAILURE;
michael@0 2201 }
michael@0 2202
michael@0 2203 styleSet->EndUpdate();
michael@0 2204
michael@0 2205 // The pres shell now owns the style set object.
michael@0 2206
michael@0 2207
michael@0 2208 bool doReturn = false;;
michael@0 2209 bool documentIsTopLevel = false;
michael@0 2210 nsSize adjSize;
michael@0 2211
michael@0 2212 rv = SetRootView(aPO, doReturn, documentIsTopLevel, adjSize);
michael@0 2213
michael@0 2214 if (NS_FAILED(rv) || doReturn) {
michael@0 2215 return rv;
michael@0 2216 }
michael@0 2217
michael@0 2218 PR_PL(("In DV::ReflowPrintObject PO: %p pS: %p (%9s) Setting w,h to %d,%d\n", aPO, aPO->mPresShell.get(),
michael@0 2219 gFrameTypesStr[aPO->mFrameType], adjSize.width, adjSize.height));
michael@0 2220
michael@0 2221
michael@0 2222 // This docshell stuff is weird; will go away when we stop having multiple
michael@0 2223 // presentations per document
michael@0 2224 aPO->mPresContext->SetContainer(aPO->mDocShell);
michael@0 2225
michael@0 2226 aPO->mPresShell->BeginObservingDocument();
michael@0 2227
michael@0 2228 aPO->mPresContext->SetPageSize(adjSize);
michael@0 2229 aPO->mPresContext->SetIsRootPaginatedDocument(documentIsTopLevel);
michael@0 2230 aPO->mPresContext->SetPageScale(aPO->mZoomRatio);
michael@0 2231 // Calculate scale factor from printer to screen
michael@0 2232 float printDPI = float(mPrt->mPrintDC->AppUnitsPerCSSInch()) /
michael@0 2233 float(mPrt->mPrintDC->AppUnitsPerDevPixel());
michael@0 2234 aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / printDPI);
michael@0 2235
michael@0 2236 if (mIsCreatingPrintPreview && documentIsTopLevel) {
michael@0 2237 mDocViewerPrint->SetPrintPreviewPresentation(aPO->mViewManager,
michael@0 2238 aPO->mPresContext,
michael@0 2239 aPO->mPresShell);
michael@0 2240 }
michael@0 2241
michael@0 2242 rv = aPO->mPresShell->Initialize(adjSize.width, adjSize.height);
michael@0 2243
michael@0 2244 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2245 NS_ASSERTION(aPO->mPresShell, "Presshell should still be here");
michael@0 2246
michael@0 2247 // Process the reflow event Initialize posted
michael@0 2248 aPO->mPresShell->FlushPendingNotifications(Flush_Layout);
michael@0 2249
michael@0 2250 rv = UpdateSelectionAndShrinkPrintObject(aPO, documentIsTopLevel);
michael@0 2251 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2252
michael@0 2253 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 2254 if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) {
michael@0 2255 nsAutoCString docStr;
michael@0 2256 nsAutoCString urlStr;
michael@0 2257 GetDocTitleAndURL(aPO, docStr, urlStr);
michael@0 2258 char filename[256];
michael@0 2259 sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++);
michael@0 2260 // Dump all the frames and view to a a file
michael@0 2261 FILE * fd = fopen(filename, "w");
michael@0 2262 if (fd) {
michael@0 2263 nsIFrame *theRootFrame =
michael@0 2264 aPO->mPresShell->FrameManager()->GetRootFrame();
michael@0 2265 fprintf(fd, "Title: %s\n", docStr.get());
michael@0 2266 fprintf(fd, "URL: %s\n", urlStr.get());
michael@0 2267 fprintf(fd, "--------------- Frames ----------------\n");
michael@0 2268 nsRefPtr<nsRenderingContext> renderingContext =
michael@0 2269 mPrt->mPrintDocDC->CreateRenderingContext();
michael@0 2270 RootFrameList(aPO->mPresContext, fd, 0);
michael@0 2271 //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0);
michael@0 2272 fprintf(fd, "---------------------------------------\n\n");
michael@0 2273 fprintf(fd, "--------------- Views From Root Frame----------------\n");
michael@0 2274 nsView* v = theRootFrame->GetView();
michael@0 2275 if (v) {
michael@0 2276 v->List(fd);
michael@0 2277 } else {
michael@0 2278 printf("View is null!\n");
michael@0 2279 }
michael@0 2280 if (docShell) {
michael@0 2281 fprintf(fd, "--------------- All Views ----------------\n");
michael@0 2282 DumpViews(docShell, fd);
michael@0 2283 fprintf(fd, "---------------------------------------\n\n");
michael@0 2284 }
michael@0 2285 fclose(fd);
michael@0 2286 }
michael@0 2287 }
michael@0 2288 #endif
michael@0 2289
michael@0 2290 return NS_OK;
michael@0 2291 }
michael@0 2292
michael@0 2293 //-------------------------------------------------------
michael@0 2294 // Figure out how many documents and how many total pages we are printing
michael@0 2295 void
michael@0 2296 nsPrintEngine::CalcNumPrintablePages(int32_t& aNumPages)
michael@0 2297 {
michael@0 2298 aNumPages = 0;
michael@0 2299 // Count the number of printable documents
michael@0 2300 // and printable pages
michael@0 2301 for (uint32_t i=0; i<mPrt->mPrintDocList.Length(); i++) {
michael@0 2302 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 2303 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 2304 if (po->mPresContext && po->mPresContext->IsRootPaginatedDocument()) {
michael@0 2305 nsIPageSequenceFrame* pageSequence = po->mPresShell->GetPageSequenceFrame();
michael@0 2306 nsIFrame * seqFrame = do_QueryFrame(pageSequence);
michael@0 2307 if (seqFrame) {
michael@0 2308 nsIFrame* frame = seqFrame->GetFirstPrincipalChild();
michael@0 2309 while (frame) {
michael@0 2310 aNumPages++;
michael@0 2311 frame = frame->GetNextSibling();
michael@0 2312 }
michael@0 2313 }
michael@0 2314 }
michael@0 2315 }
michael@0 2316 }
michael@0 2317
michael@0 2318 //-----------------------------------------------------------------
michael@0 2319 //-- Done: Reflow Methods
michael@0 2320 //-----------------------------------------------------------------
michael@0 2321
michael@0 2322 //-----------------------------------------------------------------
michael@0 2323 //-- Section: Printing Methods
michael@0 2324 //-----------------------------------------------------------------
michael@0 2325
michael@0 2326 //-------------------------------------------------------
michael@0 2327 // Called for each DocShell that needs to be printed
michael@0 2328 bool
michael@0 2329 nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus)
michael@0 2330 {
michael@0 2331 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 2332 aStatus = NS_OK;
michael@0 2333
michael@0 2334 if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) {
michael@0 2335 aStatus = DoPrint(aPO);
michael@0 2336 return true;
michael@0 2337 }
michael@0 2338
michael@0 2339 // If |aPO->mPrintAsIs| and |aPO->mHasBeenPrinted| are true,
michael@0 2340 // the kids frames are already processed in |PrintPage|.
michael@0 2341 if (!aPO->mInvisible && !(aPO->mPrintAsIs && aPO->mHasBeenPrinted)) {
michael@0 2342 for (uint32_t i=0;i<aPO->mKids.Length();i++) {
michael@0 2343 nsPrintObject* po = aPO->mKids[i];
michael@0 2344 bool printed = PrintDocContent(po, aStatus);
michael@0 2345 if (printed || NS_FAILED(aStatus)) {
michael@0 2346 return true;
michael@0 2347 }
michael@0 2348 }
michael@0 2349 }
michael@0 2350 return false;
michael@0 2351 }
michael@0 2352
michael@0 2353 static already_AddRefed<nsIDOMNode>
michael@0 2354 GetEqualNodeInCloneTree(nsIDOMNode* aNode, nsIDocument* aDoc)
michael@0 2355 {
michael@0 2356 nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
michael@0 2357 // Selections in anonymous subtrees aren't supported.
michael@0 2358 if (content && content->IsInAnonymousSubtree()) {
michael@0 2359 return nullptr;
michael@0 2360 }
michael@0 2361
michael@0 2362 nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
michael@0 2363 NS_ENSURE_TRUE(node, nullptr);
michael@0 2364
michael@0 2365 nsTArray<int32_t> indexArray;
michael@0 2366 nsINode* current = node;
michael@0 2367 NS_ENSURE_TRUE(current, nullptr);
michael@0 2368 while (current) {
michael@0 2369 nsINode* parent = current->GetParentNode();
michael@0 2370 if (!parent) {
michael@0 2371 break;
michael@0 2372 }
michael@0 2373 int32_t index = parent->IndexOf(current);
michael@0 2374 NS_ENSURE_TRUE(index >= 0, nullptr);
michael@0 2375 indexArray.AppendElement(index);
michael@0 2376 current = parent;
michael@0 2377 }
michael@0 2378 NS_ENSURE_TRUE(current->IsNodeOfType(nsINode::eDOCUMENT), nullptr);
michael@0 2379
michael@0 2380 current = aDoc;
michael@0 2381 for (int32_t i = indexArray.Length() - 1; i >= 0; --i) {
michael@0 2382 current = current->GetChildAt(indexArray[i]);
michael@0 2383 NS_ENSURE_TRUE(current, nullptr);
michael@0 2384 }
michael@0 2385 nsCOMPtr<nsIDOMNode> result = do_QueryInterface(current);
michael@0 2386 return result.forget();
michael@0 2387 }
michael@0 2388
michael@0 2389 static void
michael@0 2390 CloneRangeToSelection(nsRange* aRange, nsIDocument* aDoc,
michael@0 2391 Selection* aSelection)
michael@0 2392 {
michael@0 2393 if (aRange->Collapsed()) {
michael@0 2394 return;
michael@0 2395 }
michael@0 2396
michael@0 2397 nsCOMPtr<nsIDOMNode> startContainer, endContainer;
michael@0 2398 aRange->GetStartContainer(getter_AddRefs(startContainer));
michael@0 2399 int32_t startOffset = aRange->StartOffset();
michael@0 2400 aRange->GetEndContainer(getter_AddRefs(endContainer));
michael@0 2401 int32_t endOffset = aRange->EndOffset();
michael@0 2402 NS_ENSURE_TRUE_VOID(startContainer && endContainer);
michael@0 2403
michael@0 2404 nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
michael@0 2405 nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
michael@0 2406 NS_ENSURE_TRUE_VOID(newStart && newEnd);
michael@0 2407
michael@0 2408 nsCOMPtr<nsINode> newStartNode = do_QueryInterface(newStart);
michael@0 2409 NS_ENSURE_TRUE_VOID(newStartNode);
michael@0 2410
michael@0 2411 nsRefPtr<nsRange> range = new nsRange(newStartNode);
michael@0 2412 nsresult rv = range->SetStart(newStartNode, startOffset);
michael@0 2413 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 2414 rv = range->SetEnd(newEnd, endOffset);
michael@0 2415 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 2416
michael@0 2417 aSelection->AddRange(range);
michael@0 2418 }
michael@0 2419
michael@0 2420 static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc)
michael@0 2421 {
michael@0 2422 nsIPresShell* origShell = aOrigDoc->GetShell();
michael@0 2423 nsIPresShell* shell = aDoc->GetShell();
michael@0 2424 NS_ENSURE_STATE(origShell && shell);
michael@0 2425
michael@0 2426 nsRefPtr<Selection> origSelection =
michael@0 2427 origShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 2428 nsRefPtr<Selection> selection =
michael@0 2429 shell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 2430 NS_ENSURE_STATE(origSelection && selection);
michael@0 2431
michael@0 2432 int32_t rangeCount = origSelection->GetRangeCount();
michael@0 2433 for (int32_t i = 0; i < rangeCount; ++i) {
michael@0 2434 CloneRangeToSelection(origSelection->GetRangeAt(i), aDoc, selection);
michael@0 2435 }
michael@0 2436 return NS_OK;
michael@0 2437 }
michael@0 2438
michael@0 2439 //-------------------------------------------------------
michael@0 2440 nsresult
michael@0 2441 nsPrintEngine::DoPrint(nsPrintObject * aPO)
michael@0 2442 {
michael@0 2443 PR_PL(("\n"));
michael@0 2444 PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType]));
michael@0 2445 PR_PL(("****** In DV::DoPrint PO: %p \n", aPO));
michael@0 2446
michael@0 2447 nsIPresShell* poPresShell = aPO->mPresShell;
michael@0 2448 nsPresContext* poPresContext = aPO->mPresContext;
michael@0 2449
michael@0 2450 NS_ASSERTION(poPresContext, "PrintObject has not been reflowed");
michael@0 2451 NS_ASSERTION(poPresContext->Type() != nsPresContext::eContext_PrintPreview,
michael@0 2452 "How did this context end up here?");
michael@0 2453
michael@0 2454 if (mPrt->mPrintProgressParams) {
michael@0 2455 SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams);
michael@0 2456 }
michael@0 2457
michael@0 2458 {
michael@0 2459 int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
michael@0 2460 nsresult rv;
michael@0 2461 if (mPrt->mPrintSettings != nullptr) {
michael@0 2462 mPrt->mPrintSettings->GetPrintRange(&printRangeType);
michael@0 2463 }
michael@0 2464
michael@0 2465 // Ask the page sequence frame to print all the pages
michael@0 2466 nsIPageSequenceFrame* pageSequence = poPresShell->GetPageSequenceFrame();
michael@0 2467 NS_ASSERTION(nullptr != pageSequence, "no page sequence frame");
michael@0 2468
michael@0 2469 // We are done preparing for printing, so we can turn this off
michael@0 2470 mPrt->mPreparingForPrint = false;
michael@0 2471
michael@0 2472 // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging
michael@0 2473 if (nullptr != mPrt->mDebugFilePtr) {
michael@0 2474 #ifdef DEBUG
michael@0 2475 // output the regression test
michael@0 2476 nsIFrame* root = poPresShell->FrameManager()->GetRootFrame();
michael@0 2477 root->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0);
michael@0 2478 fclose(mPrt->mDebugFilePtr);
michael@0 2479 SetIsPrinting(false);
michael@0 2480 #endif
michael@0 2481 } else {
michael@0 2482 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 2483 nsIFrame* rootFrame = poPresShell->FrameManager()->GetRootFrame();
michael@0 2484 if (aPO->IsPrintable()) {
michael@0 2485 nsAutoCString docStr;
michael@0 2486 nsAutoCString urlStr;
michael@0 2487 GetDocTitleAndURL(aPO, docStr, urlStr);
michael@0 2488 DumpLayoutData(docStr.get(), urlStr.get(), poPresContext, mPrt->mPrintDocDC, rootFrame, docShell, nullptr);
michael@0 2489 }
michael@0 2490 #endif
michael@0 2491
michael@0 2492 if (!mPrt->mPrintSettings) {
michael@0 2493 // not sure what to do here!
michael@0 2494 SetIsPrinting(false);
michael@0 2495 return NS_ERROR_FAILURE;
michael@0 2496 }
michael@0 2497
michael@0 2498 nsAutoString docTitleStr;
michael@0 2499 nsAutoString docURLStr;
michael@0 2500 GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefBlank);
michael@0 2501
michael@0 2502 if (nsIPrintSettings::kRangeSelection == printRangeType) {
michael@0 2503 CloneSelection(aPO->mDocument->GetOriginalDocument(), aPO->mDocument);
michael@0 2504
michael@0 2505 poPresContext->SetIsRenderingOnlySelection(true);
michael@0 2506 // temporarily creating rendering context
michael@0 2507 // which is needed to find the selection frames
michael@0 2508 nsRefPtr<nsRenderingContext> rc =
michael@0 2509 mPrt->mPrintDC->CreateRenderingContext();
michael@0 2510
michael@0 2511 // find the starting and ending page numbers
michael@0 2512 // via the selection
michael@0 2513 nsIFrame* startFrame;
michael@0 2514 nsIFrame* endFrame;
michael@0 2515 int32_t startPageNum;
michael@0 2516 int32_t endPageNum;
michael@0 2517 nsRect startRect;
michael@0 2518 nsRect endRect;
michael@0 2519
michael@0 2520 nsRefPtr<Selection> selectionPS =
michael@0 2521 poPresShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
michael@0 2522
michael@0 2523 rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence,
michael@0 2524 &startFrame, startPageNum, startRect,
michael@0 2525 &endFrame, endPageNum, endRect);
michael@0 2526 if (NS_SUCCEEDED(rv)) {
michael@0 2527 mPrt->mPrintSettings->SetStartPageRange(startPageNum);
michael@0 2528 mPrt->mPrintSettings->SetEndPageRange(endPageNum);
michael@0 2529 nsIntMargin marginTwips(0,0,0,0);
michael@0 2530 nsIntMargin unwrtMarginTwips(0,0,0,0);
michael@0 2531 mPrt->mPrintSettings->GetMarginInTwips(marginTwips);
michael@0 2532 mPrt->mPrintSettings->GetUnwriteableMarginInTwips(unwrtMarginTwips);
michael@0 2533 nsMargin totalMargin = poPresContext->CSSTwipsToAppUnits(marginTwips +
michael@0 2534 unwrtMarginTwips);
michael@0 2535 if (startPageNum == endPageNum) {
michael@0 2536 startRect.y -= totalMargin.top;
michael@0 2537 endRect.y -= totalMargin.top;
michael@0 2538
michael@0 2539 // Clip out selection regions above the top of the first page
michael@0 2540 if (startRect.y < 0) {
michael@0 2541 // Reduce height to be the height of the positive-territory
michael@0 2542 // region of original rect
michael@0 2543 startRect.height = std::max(0, startRect.YMost());
michael@0 2544 startRect.y = 0;
michael@0 2545 }
michael@0 2546 if (endRect.y < 0) {
michael@0 2547 // Reduce height to be the height of the positive-territory
michael@0 2548 // region of original rect
michael@0 2549 endRect.height = std::max(0, endRect.YMost());
michael@0 2550 endRect.y = 0;
michael@0 2551 }
michael@0 2552 NS_ASSERTION(endRect.y >= startRect.y,
michael@0 2553 "Selection end point should be after start point");
michael@0 2554 NS_ASSERTION(startRect.height >= 0,
michael@0 2555 "rect should have non-negative height.");
michael@0 2556 NS_ASSERTION(endRect.height >= 0,
michael@0 2557 "rect should have non-negative height.");
michael@0 2558
michael@0 2559 nscoord selectionHgt = endRect.y + endRect.height - startRect.y;
michael@0 2560 // XXX This is temporary fix for printing more than one page of a selection
michael@0 2561 pageSequence->SetSelectionHeight(startRect.y * aPO->mZoomRatio,
michael@0 2562 selectionHgt * aPO->mZoomRatio);
michael@0 2563
michael@0 2564 // calc total pages by getting calculating the selection's height
michael@0 2565 // and then dividing it by how page content frames will fit.
michael@0 2566 nscoord pageWidth, pageHeight;
michael@0 2567 mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
michael@0 2568 pageHeight -= totalMargin.top + totalMargin.bottom;
michael@0 2569 int32_t totalPages = NSToIntCeil(float(selectionHgt) * aPO->mZoomRatio / float(pageHeight));
michael@0 2570 pageSequence->SetTotalNumPages(totalPages);
michael@0 2571 }
michael@0 2572 }
michael@0 2573 }
michael@0 2574
michael@0 2575 nsIFrame * seqFrame = do_QueryFrame(pageSequence);
michael@0 2576 if (!seqFrame) {
michael@0 2577 SetIsPrinting(false);
michael@0 2578 return NS_ERROR_FAILURE;
michael@0 2579 }
michael@0 2580
michael@0 2581 mPageSeqFrame = pageSequence;
michael@0 2582 mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr);
michael@0 2583
michael@0 2584 // Schedule Page to Print
michael@0 2585 PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]));
michael@0 2586 StartPagePrintTimer(aPO);
michael@0 2587 }
michael@0 2588 }
michael@0 2589
michael@0 2590 return NS_OK;
michael@0 2591 }
michael@0 2592
michael@0 2593 //---------------------------------------------------------------------
michael@0 2594 void
michael@0 2595 nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO,
michael@0 2596 nsIPrintProgressParams* aParams)
michael@0 2597 {
michael@0 2598 NS_ASSERTION(aPO, "Must have valid nsPrintObject");
michael@0 2599 NS_ASSERTION(aParams, "Must have valid nsIPrintProgressParams");
michael@0 2600
michael@0 2601 if (!aPO || !aPO->mDocShell || !aParams) {
michael@0 2602 return;
michael@0 2603 }
michael@0 2604 const uint32_t kTitleLength = 64;
michael@0 2605
michael@0 2606 nsAutoString docTitleStr;
michael@0 2607 nsAutoString docURLStr;
michael@0 2608 GetDisplayTitleAndURL(aPO, docTitleStr, docURLStr, eDocTitleDefURLDoc);
michael@0 2609
michael@0 2610 // Make sure the Titles & URLS don't get too long for the progress dialog
michael@0 2611 EllipseLongString(docTitleStr, kTitleLength, false);
michael@0 2612 EllipseLongString(docURLStr, kTitleLength, true);
michael@0 2613
michael@0 2614 aParams->SetDocTitle(docTitleStr.get());
michael@0 2615 aParams->SetDocURL(docURLStr.get());
michael@0 2616 }
michael@0 2617
michael@0 2618 //---------------------------------------------------------------------
michael@0 2619 void
michael@0 2620 nsPrintEngine::EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront)
michael@0 2621 {
michael@0 2622 // Make sure the URLS don't get too long for the progress dialog
michael@0 2623 if (aLen >= 3 && aStr.Length() > aLen) {
michael@0 2624 if (aDoFront) {
michael@0 2625 nsAutoString newStr;
michael@0 2626 newStr.AppendLiteral("...");
michael@0 2627 newStr += Substring(aStr, aStr.Length() - (aLen - 3), aLen - 3);
michael@0 2628 aStr = newStr;
michael@0 2629 } else {
michael@0 2630 aStr.SetLength(aLen - 3);
michael@0 2631 aStr.AppendLiteral("...");
michael@0 2632 }
michael@0 2633 }
michael@0 2634 }
michael@0 2635
michael@0 2636 static bool
michael@0 2637 DocHasPrintCallbackCanvas(nsIDocument* aDoc, void* aData)
michael@0 2638 {
michael@0 2639 if (!aDoc) {
michael@0 2640 return true;
michael@0 2641 }
michael@0 2642 Element* root = aDoc->GetRootElement();
michael@0 2643 if (!root) {
michael@0 2644 return true;
michael@0 2645 }
michael@0 2646 nsRefPtr<nsContentList> canvases = NS_GetContentList(root,
michael@0 2647 kNameSpaceID_XHTML,
michael@0 2648 NS_LITERAL_STRING("canvas"));
michael@0 2649 uint32_t canvasCount = canvases->Length(true);
michael@0 2650 for (uint32_t i = 0; i < canvasCount; ++i) {
michael@0 2651 HTMLCanvasElement* canvas = HTMLCanvasElement::FromContentOrNull(canvases->Item(i, false));
michael@0 2652 if (canvas && canvas->GetMozPrintCallback()) {
michael@0 2653 // This subdocument has a print callback. Set result and return false to
michael@0 2654 // stop iteration.
michael@0 2655 *static_cast<bool*>(aData) = true;
michael@0 2656 return false;
michael@0 2657 }
michael@0 2658 }
michael@0 2659 return true;
michael@0 2660 }
michael@0 2661
michael@0 2662 static bool
michael@0 2663 DocHasPrintCallbackCanvas(nsIDocument* aDoc)
michael@0 2664 {
michael@0 2665 bool result = false;
michael@0 2666 aDoc->EnumerateSubDocuments(&DocHasPrintCallbackCanvas, static_cast<void*>(&result));
michael@0 2667 return result;
michael@0 2668 }
michael@0 2669
michael@0 2670 /**
michael@0 2671 * Checks to see if the document this print engine is associated with has any
michael@0 2672 * canvases that have a mozPrintCallback.
michael@0 2673 */
michael@0 2674 bool
michael@0 2675 nsPrintEngine::HasPrintCallbackCanvas()
michael@0 2676 {
michael@0 2677 if (!mDocument) {
michael@0 2678 return false;
michael@0 2679 }
michael@0 2680 // First check this mDocument.
michael@0 2681 bool result = false;
michael@0 2682 DocHasPrintCallbackCanvas(mDocument, static_cast<void*>(&result));
michael@0 2683 // Also check the sub documents.
michael@0 2684 return result || DocHasPrintCallbackCanvas(mDocument);
michael@0 2685 }
michael@0 2686
michael@0 2687 //-------------------------------------------------------
michael@0 2688 bool
michael@0 2689 nsPrintEngine::PrePrintPage()
michael@0 2690 {
michael@0 2691 NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!");
michael@0 2692 NS_ASSERTION(mPrt, "mPrt is null!");
michael@0 2693
michael@0 2694 // Although these should NEVER be nullptr
michael@0 2695 // This is added insurance, to make sure we don't crash in optimized builds
michael@0 2696 if (!mPrt || !mPageSeqFrame) {
michael@0 2697 return true; // means we are done preparing the page.
michael@0 2698 }
michael@0 2699
michael@0 2700 // Check setting to see if someone request it be cancelled
michael@0 2701 bool isCancelled = false;
michael@0 2702 mPrt->mPrintSettings->GetIsCancelled(&isCancelled);
michael@0 2703 if (isCancelled)
michael@0 2704 return true;
michael@0 2705
michael@0 2706 // Ask mPageSeqFrame if the page is ready to be printed.
michael@0 2707 // If the page doesn't get printed at all, the |done| will be |true|.
michael@0 2708 bool done = false;
michael@0 2709 nsresult rv = mPageSeqFrame->PrePrintNextPage(mPagePrintTimer, &done);
michael@0 2710 if (NS_FAILED(rv)) {
michael@0 2711 // ??? ::PrintPage doesn't set |mPrt->mIsAborted = true| if rv != NS_ERROR_ABORT,
michael@0 2712 // but I don't really understand why this should be the right thing to do?
michael@0 2713 // Shouldn't |mPrt->mIsAborted| set to true all the time if something
michael@0 2714 // wents wrong?
michael@0 2715 if (rv != NS_ERROR_ABORT) {
michael@0 2716 ShowPrintErrorDialog(rv);
michael@0 2717 mPrt->mIsAborted = true;
michael@0 2718 }
michael@0 2719 done = true;
michael@0 2720 }
michael@0 2721 return done;
michael@0 2722 }
michael@0 2723
michael@0 2724 bool
michael@0 2725 nsPrintEngine::PrintPage(nsPrintObject* aPO,
michael@0 2726 bool& aInRange)
michael@0 2727 {
michael@0 2728 NS_ASSERTION(aPO, "aPO is null!");
michael@0 2729 NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!");
michael@0 2730 NS_ASSERTION(mPrt, "mPrt is null!");
michael@0 2731
michael@0 2732 // Although these should NEVER be nullptr
michael@0 2733 // This is added insurance, to make sure we don't crash in optimized builds
michael@0 2734 if (!mPrt || !aPO || !mPageSeqFrame) {
michael@0 2735 ShowPrintErrorDialog(NS_ERROR_FAILURE);
michael@0 2736 return true; // means we are done printing
michael@0 2737 }
michael@0 2738
michael@0 2739 PR_PL(("-----------------------------------\n"));
michael@0 2740 PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType]));
michael@0 2741
michael@0 2742 // Check setting to see if someone request it be cancelled
michael@0 2743 bool isCancelled = false;
michael@0 2744 mPrt->mPrintSettings->GetIsCancelled(&isCancelled);
michael@0 2745 if (isCancelled || mPrt->mIsAborted)
michael@0 2746 return true;
michael@0 2747
michael@0 2748 int32_t pageNum, numPages, endPage;
michael@0 2749 mPageSeqFrame->GetCurrentPageNum(&pageNum);
michael@0 2750 mPageSeqFrame->GetNumPages(&numPages);
michael@0 2751
michael@0 2752 bool donePrinting;
michael@0 2753 bool isDoingPrintRange;
michael@0 2754 mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange);
michael@0 2755 if (isDoingPrintRange) {
michael@0 2756 int32_t fromPage;
michael@0 2757 int32_t toPage;
michael@0 2758 mPageSeqFrame->GetPrintRange(&fromPage, &toPage);
michael@0 2759
michael@0 2760 if (fromPage > numPages) {
michael@0 2761 return true;
michael@0 2762 }
michael@0 2763 if (toPage > numPages) {
michael@0 2764 toPage = numPages;
michael@0 2765 }
michael@0 2766
michael@0 2767 PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage));
michael@0 2768
michael@0 2769 donePrinting = pageNum >= toPage;
michael@0 2770 aInRange = pageNum >= fromPage && pageNum <= toPage;
michael@0 2771 endPage = (toPage - fromPage)+1;
michael@0 2772 } else {
michael@0 2773 PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages));
michael@0 2774
michael@0 2775 donePrinting = pageNum >= numPages;
michael@0 2776 endPage = numPages;
michael@0 2777 aInRange = true;
michael@0 2778 }
michael@0 2779
michael@0 2780 // XXX This is wrong, but the actual behavior in the presence of a print
michael@0 2781 // range sucks.
michael@0 2782 if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep)
michael@0 2783 endPage = mPrt->mNumPrintablePages;
michael@0 2784
michael@0 2785 mPrt->DoOnProgressChange(++mPrt->mNumPagesPrinted, endPage, false, 0);
michael@0 2786
michael@0 2787 // Print the Page
michael@0 2788 // if a print job was cancelled externally, an EndPage or BeginPage may
michael@0 2789 // fail and the failure is passed back here.
michael@0 2790 // Returning true means we are done printing.
michael@0 2791 //
michael@0 2792 // When rv == NS_ERROR_ABORT, it means we want out of the
michael@0 2793 // print job without displaying any error messages
michael@0 2794 nsresult rv = mPageSeqFrame->PrintNextPage();
michael@0 2795 if (NS_FAILED(rv)) {
michael@0 2796 if (rv != NS_ERROR_ABORT) {
michael@0 2797 ShowPrintErrorDialog(rv);
michael@0 2798 mPrt->mIsAborted = true;
michael@0 2799 }
michael@0 2800 return true;
michael@0 2801 }
michael@0 2802
michael@0 2803 mPageSeqFrame->DoPageEnd();
michael@0 2804
michael@0 2805 return donePrinting;
michael@0 2806 }
michael@0 2807
michael@0 2808 /** ---------------------------------------------------
michael@0 2809 * Find by checking frames type
michael@0 2810 */
michael@0 2811 nsresult
michael@0 2812 nsPrintEngine::FindSelectionBoundsWithList(nsPresContext* aPresContext,
michael@0 2813 nsRenderingContext& aRC,
michael@0 2814 nsFrameList::Enumerator& aChildFrames,
michael@0 2815 nsIFrame * aParentFrame,
michael@0 2816 nsRect& aRect,
michael@0 2817 nsIFrame *& aStartFrame,
michael@0 2818 nsRect& aStartRect,
michael@0 2819 nsIFrame *& aEndFrame,
michael@0 2820 nsRect& aEndRect)
michael@0 2821 {
michael@0 2822 NS_ASSERTION(aPresContext, "Pointer is null!");
michael@0 2823 NS_ASSERTION(aParentFrame, "Pointer is null!");
michael@0 2824
michael@0 2825 aRect += aParentFrame->GetPosition();
michael@0 2826 for (; !aChildFrames.AtEnd(); aChildFrames.Next()) {
michael@0 2827 nsIFrame* child = aChildFrames.get();
michael@0 2828 if (child->IsSelected() && child->IsVisibleForPainting()) {
michael@0 2829 nsRect r = child->GetRect();
michael@0 2830 if (aStartFrame == nullptr) {
michael@0 2831 aStartFrame = child;
michael@0 2832 aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height);
michael@0 2833 } else {
michael@0 2834 aEndFrame = child;
michael@0 2835 aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height);
michael@0 2836 }
michael@0 2837 }
michael@0 2838 FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect);
michael@0 2839 child = child->GetNextSibling();
michael@0 2840 }
michael@0 2841 aRect -= aParentFrame->GetPosition();
michael@0 2842 return NS_OK;
michael@0 2843 }
michael@0 2844
michael@0 2845 //-------------------------------------------------------
michael@0 2846 // Find the Frame that is XMost
michael@0 2847 nsresult
michael@0 2848 nsPrintEngine::FindSelectionBounds(nsPresContext* aPresContext,
michael@0 2849 nsRenderingContext& aRC,
michael@0 2850 nsIFrame * aParentFrame,
michael@0 2851 nsRect& aRect,
michael@0 2852 nsIFrame *& aStartFrame,
michael@0 2853 nsRect& aStartRect,
michael@0 2854 nsIFrame *& aEndFrame,
michael@0 2855 nsRect& aEndRect)
michael@0 2856 {
michael@0 2857 NS_ASSERTION(aPresContext, "Pointer is null!");
michael@0 2858 NS_ASSERTION(aParentFrame, "Pointer is null!");
michael@0 2859
michael@0 2860 // loop through named child lists
michael@0 2861 nsIFrame::ChildListIterator lists(aParentFrame);
michael@0 2862 for (; !lists.IsDone(); lists.Next()) {
michael@0 2863 nsFrameList::Enumerator childFrames(lists.CurrentList());
michael@0 2864 nsresult rv = FindSelectionBoundsWithList(aPresContext, aRC, childFrames, aParentFrame, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect);
michael@0 2865 NS_ENSURE_SUCCESS(rv, rv);
michael@0 2866 }
michael@0 2867 return NS_OK;
michael@0 2868 }
michael@0 2869
michael@0 2870 /** ---------------------------------------------------
michael@0 2871 * This method finds the starting and ending page numbers
michael@0 2872 * of the selection and also returns rect for each where
michael@0 2873 * the x,y of the rect is relative to the very top of the
michael@0 2874 * frame tree (absolutely positioned)
michael@0 2875 */
michael@0 2876 nsresult
michael@0 2877 nsPrintEngine::GetPageRangeForSelection(nsIPresShell * aPresShell,
michael@0 2878 nsPresContext* aPresContext,
michael@0 2879 nsRenderingContext& aRC,
michael@0 2880 nsISelection* aSelection,
michael@0 2881 nsIPageSequenceFrame* aPageSeqFrame,
michael@0 2882 nsIFrame** aStartFrame,
michael@0 2883 int32_t& aStartPageNum,
michael@0 2884 nsRect& aStartRect,
michael@0 2885 nsIFrame** aEndFrame,
michael@0 2886 int32_t& aEndPageNum,
michael@0 2887 nsRect& aEndRect)
michael@0 2888 {
michael@0 2889 NS_ASSERTION(aPresShell, "Pointer is null!");
michael@0 2890 NS_ASSERTION(aPresContext, "Pointer is null!");
michael@0 2891 NS_ASSERTION(aSelection, "Pointer is null!");
michael@0 2892 NS_ASSERTION(aPageSeqFrame, "Pointer is null!");
michael@0 2893 NS_ASSERTION(aStartFrame, "Pointer is null!");
michael@0 2894 NS_ASSERTION(aEndFrame, "Pointer is null!");
michael@0 2895
michael@0 2896 nsIFrame * seqFrame = do_QueryFrame(aPageSeqFrame);
michael@0 2897 if (!seqFrame) {
michael@0 2898 return NS_ERROR_FAILURE;
michael@0 2899 }
michael@0 2900
michael@0 2901 nsIFrame * startFrame = nullptr;
michael@0 2902 nsIFrame * endFrame = nullptr;
michael@0 2903
michael@0 2904 // start out with the sequence frame and search the entire frame tree
michael@0 2905 // capturing the starting and ending child frames of the selection
michael@0 2906 // and their rects
michael@0 2907 nsRect r = seqFrame->GetRect();
michael@0 2908 FindSelectionBounds(aPresContext, aRC, seqFrame, r,
michael@0 2909 startFrame, aStartRect, endFrame, aEndRect);
michael@0 2910
michael@0 2911 #ifdef DEBUG_rodsX
michael@0 2912 printf("Start Frame: %p\n", startFrame);
michael@0 2913 printf("End Frame: %p\n", endFrame);
michael@0 2914 #endif
michael@0 2915
michael@0 2916 // initial the page numbers here
michael@0 2917 // in case we don't find and frames
michael@0 2918 aStartPageNum = -1;
michael@0 2919 aEndPageNum = -1;
michael@0 2920
michael@0 2921 nsIFrame * startPageFrame;
michael@0 2922 nsIFrame * endPageFrame;
michael@0 2923
michael@0 2924 // check to make sure we found a starting frame
michael@0 2925 if (startFrame != nullptr) {
michael@0 2926 // Now search up the tree to find what page the
michael@0 2927 // start/ending selections frames are on
michael@0 2928 //
michael@0 2929 // Check to see if start should be same as end if
michael@0 2930 // the end frame comes back null
michael@0 2931 if (endFrame == nullptr) {
michael@0 2932 // XXX the "GetPageFrame" step could be integrated into
michael@0 2933 // the FindSelectionBounds step, but walking up to find
michael@0 2934 // the parent of a child frame isn't expensive and it makes
michael@0 2935 // FindSelectionBounds a little easier to understand
michael@0 2936 startPageFrame = nsLayoutUtils::GetPageFrame(startFrame);
michael@0 2937 endPageFrame = startPageFrame;
michael@0 2938 aEndRect = aStartRect;
michael@0 2939 } else {
michael@0 2940 startPageFrame = nsLayoutUtils::GetPageFrame(startFrame);
michael@0 2941 endPageFrame = nsLayoutUtils::GetPageFrame(endFrame);
michael@0 2942 }
michael@0 2943 } else {
michael@0 2944 return NS_ERROR_FAILURE;
michael@0 2945 }
michael@0 2946
michael@0 2947 #ifdef DEBUG_rodsX
michael@0 2948 printf("Start Page: %p\n", startPageFrame);
michael@0 2949 printf("End Page: %p\n", endPageFrame);
michael@0 2950
michael@0 2951 // dump all the pages and their pointers
michael@0 2952 {
michael@0 2953 int32_t pageNum = 1;
michael@0 2954 nsIFrame* child = seqFrame->GetFirstPrincipalChild();
michael@0 2955 while (child != nullptr) {
michael@0 2956 printf("Page: %d - %p\n", pageNum, child);
michael@0 2957 pageNum++;
michael@0 2958 child = child->GetNextSibling();
michael@0 2959 }
michael@0 2960 }
michael@0 2961 #endif
michael@0 2962
michael@0 2963 // Now that we have the page frames
michael@0 2964 // find out what the page numbers are for each frame
michael@0 2965 int32_t pageNum = 1;
michael@0 2966 nsIFrame* page = seqFrame->GetFirstPrincipalChild();
michael@0 2967 while (page != nullptr) {
michael@0 2968 if (page == startPageFrame) {
michael@0 2969 aStartPageNum = pageNum;
michael@0 2970 }
michael@0 2971 if (page == endPageFrame) {
michael@0 2972 aEndPageNum = pageNum;
michael@0 2973 }
michael@0 2974 pageNum++;
michael@0 2975 page = page->GetNextSibling();
michael@0 2976 }
michael@0 2977
michael@0 2978 #ifdef DEBUG_rodsX
michael@0 2979 printf("Start Page No: %d\n", aStartPageNum);
michael@0 2980 printf("End Page No: %d\n", aEndPageNum);
michael@0 2981 #endif
michael@0 2982
michael@0 2983 *aStartFrame = startPageFrame;
michael@0 2984 *aEndFrame = endPageFrame;
michael@0 2985
michael@0 2986 return NS_OK;
michael@0 2987 }
michael@0 2988
michael@0 2989 //-----------------------------------------------------------------
michael@0 2990 //-- Done: Printing Methods
michael@0 2991 //-----------------------------------------------------------------
michael@0 2992
michael@0 2993
michael@0 2994 //-----------------------------------------------------------------
michael@0 2995 //-- Section: Misc Support Methods
michael@0 2996 //-----------------------------------------------------------------
michael@0 2997
michael@0 2998 //---------------------------------------------------------------------
michael@0 2999 void nsPrintEngine::SetIsPrinting(bool aIsPrinting)
michael@0 3000 {
michael@0 3001 mIsDoingPrinting = aIsPrinting;
michael@0 3002 // Calling SetIsPrinting while in print preview confuses the document viewer
michael@0 3003 // This is safe because we prevent exiting print preview while printing
michael@0 3004 if (!mIsDoingPrintPreview && mDocViewerPrint) {
michael@0 3005 mDocViewerPrint->SetIsPrinting(aIsPrinting);
michael@0 3006 }
michael@0 3007 if (mPrt && aIsPrinting) {
michael@0 3008 mPrt->mPreparingForPrint = true;
michael@0 3009 }
michael@0 3010 }
michael@0 3011
michael@0 3012 //---------------------------------------------------------------------
michael@0 3013 void nsPrintEngine::SetIsPrintPreview(bool aIsPrintPreview)
michael@0 3014 {
michael@0 3015 mIsDoingPrintPreview = aIsPrintPreview;
michael@0 3016
michael@0 3017 if (mDocViewerPrint) {
michael@0 3018 mDocViewerPrint->SetIsPrintPreview(aIsPrintPreview);
michael@0 3019 }
michael@0 3020 }
michael@0 3021
michael@0 3022 //---------------------------------------------------------------------
michael@0 3023 void
michael@0 3024 nsPrintEngine::CleanupDocTitleArray(char16_t**& aArray, int32_t& aCount)
michael@0 3025 {
michael@0 3026 for (int32_t i = aCount - 1; i >= 0; i--) {
michael@0 3027 nsMemory::Free(aArray[i]);
michael@0 3028 }
michael@0 3029 nsMemory::Free(aArray);
michael@0 3030 aArray = nullptr;
michael@0 3031 aCount = 0;
michael@0 3032 }
michael@0 3033
michael@0 3034 //---------------------------------------------------------------------
michael@0 3035 // static
michael@0 3036 bool nsPrintEngine::HasFramesetChild(nsIContent* aContent)
michael@0 3037 {
michael@0 3038 if (!aContent) {
michael@0 3039 return false;
michael@0 3040 }
michael@0 3041
michael@0 3042 // do a breadth search across all siblings
michael@0 3043 for (nsIContent* child = aContent->GetFirstChild();
michael@0 3044 child;
michael@0 3045 child = child->GetNextSibling()) {
michael@0 3046 if (child->IsHTML(nsGkAtoms::frameset)) {
michael@0 3047 return true;
michael@0 3048 }
michael@0 3049 }
michael@0 3050
michael@0 3051 return false;
michael@0 3052 }
michael@0 3053
michael@0 3054
michael@0 3055
michael@0 3056 /** ---------------------------------------------------
michael@0 3057 * Get the Focused Frame for a documentviewer
michael@0 3058 */
michael@0 3059 already_AddRefed<nsIDOMWindow>
michael@0 3060 nsPrintEngine::FindFocusedDOMWindow()
michael@0 3061 {
michael@0 3062 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 3063 NS_ENSURE_TRUE(fm, nullptr);
michael@0 3064
michael@0 3065 nsCOMPtr<nsPIDOMWindow> window(mDocument->GetWindow());
michael@0 3066 NS_ENSURE_TRUE(window, nullptr);
michael@0 3067
michael@0 3068 nsCOMPtr<nsPIDOMWindow> rootWindow = window->GetPrivateRoot();
michael@0 3069 NS_ENSURE_TRUE(rootWindow, nullptr);
michael@0 3070
michael@0 3071 nsCOMPtr<nsPIDOMWindow> focusedWindow;
michael@0 3072 nsFocusManager::GetFocusedDescendant(rootWindow, true,
michael@0 3073 getter_AddRefs(focusedWindow));
michael@0 3074 NS_ENSURE_TRUE(focusedWindow, nullptr);
michael@0 3075
michael@0 3076 if (IsWindowsInOurSubTree(focusedWindow)) {
michael@0 3077 return focusedWindow.forget();
michael@0 3078 }
michael@0 3079
michael@0 3080 return nullptr;
michael@0 3081 }
michael@0 3082
michael@0 3083 //---------------------------------------------------------------------
michael@0 3084 bool
michael@0 3085 nsPrintEngine::IsWindowsInOurSubTree(nsPIDOMWindow * window)
michael@0 3086 {
michael@0 3087 bool found = false;
michael@0 3088
michael@0 3089 // now check to make sure it is in "our" tree of docshells
michael@0 3090 if (window) {
michael@0 3091 nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
michael@0 3092
michael@0 3093 if (docShell) {
michael@0 3094 // get this DocViewer docshell
michael@0 3095 nsCOMPtr<nsIDocShell> thisDVDocShell(do_QueryReferent(mContainer));
michael@0 3096 while (!found) {
michael@0 3097 if (docShell) {
michael@0 3098 if (docShell == thisDVDocShell) {
michael@0 3099 found = true;
michael@0 3100 break;
michael@0 3101 }
michael@0 3102 } else {
michael@0 3103 break; // at top of tree
michael@0 3104 }
michael@0 3105 nsCOMPtr<nsIDocShellTreeItem> docShellItemParent;
michael@0 3106 docShell->GetSameTypeParent(getter_AddRefs(docShellItemParent));
michael@0 3107 docShell = do_QueryInterface(docShellItemParent);
michael@0 3108 } // while
michael@0 3109 }
michael@0 3110 } // scriptobj
michael@0 3111
michael@0 3112 return found;
michael@0 3113 }
michael@0 3114
michael@0 3115 //-------------------------------------------------------
michael@0 3116 bool
michael@0 3117 nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult)
michael@0 3118 {
michael@0 3119 //NS_ASSERTION(aPO, "Pointer is null!");
michael@0 3120 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:""));
michael@0 3121
michael@0 3122 // If there is a pageSeqFrame, make sure there are no more printCanvas active
michael@0 3123 // that might call |Notify| on the pagePrintTimer after things are cleaned up
michael@0 3124 // and printing was marked as being done.
michael@0 3125 if (mPageSeqFrame) {
michael@0 3126 mPageSeqFrame->ResetPrintCanvasList();
michael@0 3127 }
michael@0 3128
michael@0 3129 if (aPO && !mPrt->mIsAborted) {
michael@0 3130 aPO->mHasBeenPrinted = true;
michael@0 3131 nsresult rv;
michael@0 3132 bool didPrint = PrintDocContent(mPrt->mPrintObject, rv);
michael@0 3133 if (NS_SUCCEEDED(rv) && didPrint) {
michael@0 3134 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint)));
michael@0 3135 return false;
michael@0 3136 }
michael@0 3137 }
michael@0 3138
michael@0 3139 if (NS_SUCCEEDED(aResult)) {
michael@0 3140 FirePrintCompletionEvent();
michael@0 3141 }
michael@0 3142
michael@0 3143 TurnScriptingOn(true);
michael@0 3144 SetIsPrinting(false);
michael@0 3145
michael@0 3146 // Release reference to mPagePrintTimer; the timer object destroys itself
michael@0 3147 // after this returns true
michael@0 3148 NS_IF_RELEASE(mPagePrintTimer);
michael@0 3149
michael@0 3150 return true;
michael@0 3151 }
michael@0 3152
michael@0 3153 //-------------------------------------------------------
michael@0 3154 // Recursively sets the PO items to be printed "As Is"
michael@0 3155 // from the given item down into the tree
michael@0 3156 void
michael@0 3157 nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, bool aAsIs)
michael@0 3158 {
michael@0 3159 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 3160
michael@0 3161 aPO->mPrintAsIs = aAsIs;
michael@0 3162 for (uint32_t i=0;i<aPO->mKids.Length();i++) {
michael@0 3163 SetPrintAsIs(aPO->mKids[i], aAsIs);
michael@0 3164 }
michael@0 3165 }
michael@0 3166
michael@0 3167 //-------------------------------------------------------
michael@0 3168 // Given a DOMWindow it recursively finds the PO object that matches
michael@0 3169 nsPrintObject*
michael@0 3170 nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO,
michael@0 3171 nsIDOMWindow* aDOMWin)
michael@0 3172 {
michael@0 3173 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 3174
michael@0 3175 // Often the CurFocused DOMWindow is passed in
michael@0 3176 // andit is valid for it to be null, so short circut
michael@0 3177 if (!aDOMWin) {
michael@0 3178 return nullptr;
michael@0 3179 }
michael@0 3180
michael@0 3181 nsCOMPtr<nsIDOMDocument> domDoc;
michael@0 3182 aDOMWin->GetDocument(getter_AddRefs(domDoc));
michael@0 3183 nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
michael@0 3184 if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) {
michael@0 3185 return aPO;
michael@0 3186 }
michael@0 3187
michael@0 3188 int32_t cnt = aPO->mKids.Length();
michael@0 3189 for (int32_t i = 0; i < cnt; ++i) {
michael@0 3190 nsPrintObject* po = FindPrintObjectByDOMWin(aPO->mKids[i], aDOMWin);
michael@0 3191 if (po) {
michael@0 3192 return po;
michael@0 3193 }
michael@0 3194 }
michael@0 3195
michael@0 3196 return nullptr;
michael@0 3197 }
michael@0 3198
michael@0 3199 //-------------------------------------------------------
michael@0 3200 nsresult
michael@0 3201 nsPrintEngine::EnablePOsForPrinting()
michael@0 3202 {
michael@0 3203 // NOTE: All POs have been "turned off" for printing
michael@0 3204 // this is where we decided which POs get printed.
michael@0 3205 mPrt->mSelectedPO = nullptr;
michael@0 3206
michael@0 3207 if (mPrt->mPrintSettings == nullptr) {
michael@0 3208 return NS_ERROR_FAILURE;
michael@0 3209 }
michael@0 3210
michael@0 3211 mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames;
michael@0 3212 mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType);
michael@0 3213
michael@0 3214 int16_t printHowEnable = nsIPrintSettings::kFrameEnableNone;
michael@0 3215 mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable);
michael@0 3216
michael@0 3217 int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
michael@0 3218 mPrt->mPrintSettings->GetPrintRange(&printRangeType);
michael@0 3219
michael@0 3220 PR_PL(("\n"));
michael@0 3221 PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n"));
michael@0 3222 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
michael@0 3223 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
michael@0 3224 PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
michael@0 3225 PR_PL(("----\n"));
michael@0 3226
michael@0 3227 // ***** This is the ultimate override *****
michael@0 3228 // if we are printing the selection (either an IFrame or selection range)
michael@0 3229 // then set the mPrintFrameType as if it were the selected frame
michael@0 3230 if (printRangeType == nsIPrintSettings::kRangeSelection) {
michael@0 3231 mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame;
michael@0 3232 printHowEnable = nsIPrintSettings::kFrameEnableNone;
michael@0 3233 }
michael@0 3234
michael@0 3235 // This tells us that the "Frame" UI has turned off,
michael@0 3236 // so therefore there are no FrameSets/Frames/IFrames to be printed
michael@0 3237 //
michael@0 3238 // This means there are not FrameSets,
michael@0 3239 // but the document could contain an IFrame
michael@0 3240 if (printHowEnable == nsIPrintSettings::kFrameEnableNone) {
michael@0 3241
michael@0 3242 // Print all the pages or a sub range of pages
michael@0 3243 if (printRangeType == nsIPrintSettings::kRangeAllPages ||
michael@0 3244 printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) {
michael@0 3245 SetPrintPO(mPrt->mPrintObject, true);
michael@0 3246
michael@0 3247 // Set the children so they are PrinAsIs
michael@0 3248 // In this case, the children are probably IFrames
michael@0 3249 if (mPrt->mPrintObject->mKids.Length() > 0) {
michael@0 3250 for (uint32_t i=0;i<mPrt->mPrintObject->mKids.Length();i++) {
michael@0 3251 nsPrintObject* po = mPrt->mPrintObject->mKids[i];
michael@0 3252 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3253 SetPrintAsIs(po);
michael@0 3254 }
michael@0 3255
michael@0 3256 // ***** Another override *****
michael@0 3257 mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs;
michael@0 3258 }
michael@0 3259 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
michael@0 3260 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
michael@0 3261 PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
michael@0 3262 return NS_OK;
michael@0 3263 }
michael@0 3264
michael@0 3265 // This means we are either printed a selected IFrame or
michael@0 3266 // we are printing the current selection
michael@0 3267 if (printRangeType == nsIPrintSettings::kRangeSelection) {
michael@0 3268
michael@0 3269 // If the currentFocusDOMWin can'r be null if something is selected
michael@0 3270 if (mPrt->mCurrentFocusWin) {
michael@0 3271 // Find the selected IFrame
michael@0 3272 nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin);
michael@0 3273 if (po != nullptr) {
michael@0 3274 mPrt->mSelectedPO = po;
michael@0 3275 // Makes sure all of its children are be printed "AsIs"
michael@0 3276 SetPrintAsIs(po);
michael@0 3277
michael@0 3278 // Now, only enable this POs (the selected PO) and all of its children
michael@0 3279 SetPrintPO(po, true);
michael@0 3280
michael@0 3281 // check to see if we have a range selection,
michael@0 3282 // as oppose to a insert selection
michael@0 3283 // this means if the user just clicked on the IFrame then
michael@0 3284 // there will not be a selection so we want the entire page to print
michael@0 3285 //
michael@0 3286 // XXX this is sort of a hack right here to make the page
michael@0 3287 // not try to reposition itself when printing selection
michael@0 3288 nsCOMPtr<nsIDOMWindow> domWin =
michael@0 3289 do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
michael@0 3290 if (!IsThereARangeSelection(domWin)) {
michael@0 3291 printRangeType = nsIPrintSettings::kRangeAllPages;
michael@0 3292 mPrt->mPrintSettings->SetPrintRange(printRangeType);
michael@0 3293 }
michael@0 3294 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
michael@0 3295 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
michael@0 3296 PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
michael@0 3297 return NS_OK;
michael@0 3298 }
michael@0 3299 } else {
michael@0 3300 for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) {
michael@0 3301 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 3302 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3303 nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell);
michael@0 3304 if (IsThereARangeSelection(domWin)) {
michael@0 3305 mPrt->mCurrentFocusWin = domWin;
michael@0 3306 SetPrintPO(po, true);
michael@0 3307 break;
michael@0 3308 }
michael@0 3309 }
michael@0 3310 return NS_OK;
michael@0 3311 }
michael@0 3312 }
michael@0 3313 }
michael@0 3314
michael@0 3315 // check to see if there is a selection when a FrameSet is present
michael@0 3316 if (printRangeType == nsIPrintSettings::kRangeSelection) {
michael@0 3317 // If the currentFocusDOMWin can'r be null if something is selected
michael@0 3318 if (mPrt->mCurrentFocusWin) {
michael@0 3319 // Find the selected IFrame
michael@0 3320 nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin);
michael@0 3321 if (po != nullptr) {
michael@0 3322 mPrt->mSelectedPO = po;
michael@0 3323 // Makes sure all of its children are be printed "AsIs"
michael@0 3324 SetPrintAsIs(po);
michael@0 3325
michael@0 3326 // Now, only enable this POs (the selected PO) and all of its children
michael@0 3327 SetPrintPO(po, true);
michael@0 3328
michael@0 3329 // check to see if we have a range selection,
michael@0 3330 // as oppose to a insert selection
michael@0 3331 // this means if the user just clicked on the IFrame then
michael@0 3332 // there will not be a selection so we want the entire page to print
michael@0 3333 //
michael@0 3334 // XXX this is sort of a hack right here to make the page
michael@0 3335 // not try to reposition itself when printing selection
michael@0 3336 nsCOMPtr<nsIDOMWindow> domWin =
michael@0 3337 do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
michael@0 3338 if (!IsThereARangeSelection(domWin)) {
michael@0 3339 printRangeType = nsIPrintSettings::kRangeAllPages;
michael@0 3340 mPrt->mPrintSettings->SetPrintRange(printRangeType);
michael@0 3341 }
michael@0 3342 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
michael@0 3343 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
michael@0 3344 PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
michael@0 3345 return NS_OK;
michael@0 3346 }
michael@0 3347 }
michael@0 3348 }
michael@0 3349
michael@0 3350 // If we are printing "AsIs" then sets all the POs to be printed as is
michael@0 3351 if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) {
michael@0 3352 SetPrintAsIs(mPrt->mPrintObject);
michael@0 3353 SetPrintPO(mPrt->mPrintObject, true);
michael@0 3354 return NS_OK;
michael@0 3355 }
michael@0 3356
michael@0 3357 // If we are printing the selected Frame then
michael@0 3358 // find that PO for that selected DOMWin and set it all of its
michael@0 3359 // children to be printed
michael@0 3360 if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) {
michael@0 3361
michael@0 3362 if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) {
michael@0 3363 nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin);
michael@0 3364 if (po != nullptr) {
michael@0 3365 mPrt->mSelectedPO = po;
michael@0 3366 // NOTE: Calling this sets the "po" and
michael@0 3367 // we don't want to do this for documents that have no children,
michael@0 3368 // because then the "DoEndPage" gets called and it shouldn't
michael@0 3369 if (po->mKids.Length() > 0) {
michael@0 3370 // Makes sure that itself, and all of its children are printed "AsIs"
michael@0 3371 SetPrintAsIs(po);
michael@0 3372 }
michael@0 3373
michael@0 3374 // Now, only enable this POs (the selected PO) and all of its children
michael@0 3375 SetPrintPO(po, true);
michael@0 3376 }
michael@0 3377 }
michael@0 3378 return NS_OK;
michael@0 3379 }
michael@0 3380
michael@0 3381 // If we are print each subdoc separately,
michael@0 3382 // then don't print any of the FraneSet Docs
michael@0 3383 if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) {
michael@0 3384 SetPrintPO(mPrt->mPrintObject, true);
michael@0 3385 int32_t cnt = mPrt->mPrintDocList.Length();
michael@0 3386 for (int32_t i=0;i<cnt;i++) {
michael@0 3387 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 3388 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3389 if (po->mFrameType == eFrameSet) {
michael@0 3390 po->mDontPrint = true;
michael@0 3391 }
michael@0 3392 }
michael@0 3393 }
michael@0 3394
michael@0 3395 return NS_OK;
michael@0 3396 }
michael@0 3397
michael@0 3398 //-------------------------------------------------------
michael@0 3399 // Return the nsPrintObject with that is XMost (The widest frameset frame) AND
michael@0 3400 // contains the XMost (widest) layout frame
michael@0 3401 nsPrintObject*
michael@0 3402 nsPrintEngine::FindSmallestSTF()
michael@0 3403 {
michael@0 3404 float smallestRatio = 1.0f;
michael@0 3405 nsPrintObject* smallestPO = nullptr;
michael@0 3406
michael@0 3407 for (uint32_t i=0;i<mPrt->mPrintDocList.Length();i++) {
michael@0 3408 nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
michael@0 3409 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3410 if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) {
michael@0 3411 if (po->mShrinkRatio < smallestRatio) {
michael@0 3412 smallestRatio = po->mShrinkRatio;
michael@0 3413 smallestPO = po;
michael@0 3414 }
michael@0 3415 }
michael@0 3416 }
michael@0 3417
michael@0 3418 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 3419 if (smallestPO) printf("*PO: %p Type: %d %10.3f\n", smallestPO, smallestPO->mFrameType, smallestPO->mShrinkRatio);
michael@0 3420 #endif
michael@0 3421 return smallestPO;
michael@0 3422 }
michael@0 3423
michael@0 3424 //-------------------------------------------------------
michael@0 3425 void
michael@0 3426 nsPrintEngine::TurnScriptingOn(bool aDoTurnOn)
michael@0 3427 {
michael@0 3428 if (mIsDoingPrinting && aDoTurnOn && mDocViewerPrint &&
michael@0 3429 mDocViewerPrint->GetIsPrintPreview()) {
michael@0 3430 // We don't want to turn scripting on if print preview is shown still after
michael@0 3431 // printing.
michael@0 3432 return;
michael@0 3433 }
michael@0 3434
michael@0 3435 nsPrintData* prt = mPrt;
michael@0 3436 #ifdef NS_PRINT_PREVIEW
michael@0 3437 if (!prt) {
michael@0 3438 prt = mPrtPreview;
michael@0 3439 }
michael@0 3440 #endif
michael@0 3441 if (!prt) {
michael@0 3442 return;
michael@0 3443 }
michael@0 3444
michael@0 3445 NS_ASSERTION(mDocument, "We MUST have a document.");
michael@0 3446 // First, get the script global object from the document...
michael@0 3447
michael@0 3448 for (uint32_t i=0;i<prt->mPrintDocList.Length();i++) {
michael@0 3449 nsPrintObject* po = prt->mPrintDocList.ElementAt(i);
michael@0 3450 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3451
michael@0 3452 nsIDocument* doc = po->mDocument;
michael@0 3453 if (!doc) {
michael@0 3454 continue;
michael@0 3455 }
michael@0 3456
michael@0 3457 if (nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow()) {
michael@0 3458 nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
michael@0 3459 NS_WARN_IF_FALSE(go && go->GetGlobalJSObject(), "Can't get global");
michael@0 3460 nsresult propThere = NS_PROPTABLE_PROP_NOT_THERE;
michael@0 3461 doc->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview,
michael@0 3462 &propThere);
michael@0 3463 if (aDoTurnOn) {
michael@0 3464 if (propThere != NS_PROPTABLE_PROP_NOT_THERE) {
michael@0 3465 doc->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview);
michael@0 3466 if (go && go->GetGlobalJSObject()) {
michael@0 3467 xpc::Scriptability::Get(go->GetGlobalJSObject()).Unblock();
michael@0 3468 }
michael@0 3469 window->ResumeTimeouts(false);
michael@0 3470 }
michael@0 3471 } else {
michael@0 3472 // Have to be careful, because people call us over and over again with
michael@0 3473 // aDoTurnOn == false. So don't set the property if it's already
michael@0 3474 // set, since in that case we'd set it to the wrong value.
michael@0 3475 if (propThere == NS_PROPTABLE_PROP_NOT_THERE) {
michael@0 3476 // Stash the current value of IsScriptEnabled on the document, so
michael@0 3477 // that layout code running in print preview doesn't get confused.
michael@0 3478 doc->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview,
michael@0 3479 NS_INT32_TO_PTR(doc->IsScriptEnabled()));
michael@0 3480 if (go && go->GetGlobalJSObject()) {
michael@0 3481 xpc::Scriptability::Get(go->GetGlobalJSObject()).Block();
michael@0 3482 }
michael@0 3483 window->SuspendTimeouts(1, false);
michael@0 3484 }
michael@0 3485 }
michael@0 3486 }
michael@0 3487 }
michael@0 3488 }
michael@0 3489
michael@0 3490 //-----------------------------------------------------------------
michael@0 3491 //-- Done: Misc Support Methods
michael@0 3492 //-----------------------------------------------------------------
michael@0 3493
michael@0 3494
michael@0 3495 //-----------------------------------------------------------------
michael@0 3496 //-- Section: Finishing up or Cleaning up
michael@0 3497 //-----------------------------------------------------------------
michael@0 3498
michael@0 3499 //-----------------------------------------------------------------
michael@0 3500 void
michael@0 3501 nsPrintEngine::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener)
michael@0 3502 {
michael@0 3503 if (aWebProgressListener) {
michael@0 3504 aWebProgressListener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, NS_OK);
michael@0 3505 }
michael@0 3506 }
michael@0 3507
michael@0 3508 //-----------------------------------------------------------------
michael@0 3509 nsresult
michael@0 3510 nsPrintEngine::FinishPrintPreview()
michael@0 3511 {
michael@0 3512 nsresult rv = NS_OK;
michael@0 3513
michael@0 3514 #ifdef NS_PRINT_PREVIEW
michael@0 3515
michael@0 3516 if (!mPrt) {
michael@0 3517 /* we're already finished with print preview */
michael@0 3518 return rv;
michael@0 3519 }
michael@0 3520
michael@0 3521 rv = DocumentReadyForPrinting();
michael@0 3522
michael@0 3523 SetIsCreatingPrintPreview(false);
michael@0 3524
michael@0 3525 /* cleaup on failure + notify user */
michael@0 3526 if (NS_FAILED(rv)) {
michael@0 3527 /* cleanup done, let's fire-up an error dialog to notify the user
michael@0 3528 * what went wrong...
michael@0 3529 */
michael@0 3530 mPrt->OnEndPrinting();
michael@0 3531 TurnScriptingOn(true);
michael@0 3532
michael@0 3533 return rv;
michael@0 3534 }
michael@0 3535
michael@0 3536 // At this point we are done preparing everything
michael@0 3537 // before it is to be created
michael@0 3538
michael@0 3539
michael@0 3540 if (mIsDoingPrintPreview && mOldPrtPreview) {
michael@0 3541 delete mOldPrtPreview;
michael@0 3542 mOldPrtPreview = nullptr;
michael@0 3543 }
michael@0 3544
michael@0 3545
michael@0 3546 mPrt->OnEndPrinting();
michael@0 3547
michael@0 3548 // PrintPreview was built using the mPrt (code reuse)
michael@0 3549 // then we assign it over
michael@0 3550 mPrtPreview = mPrt;
michael@0 3551 mPrt = nullptr;
michael@0 3552
michael@0 3553 #endif // NS_PRINT_PREVIEW
michael@0 3554
michael@0 3555 return NS_OK;
michael@0 3556 }
michael@0 3557
michael@0 3558 //-----------------------------------------------------------------
michael@0 3559 //-- Done: Finishing up or Cleaning up
michael@0 3560 //-----------------------------------------------------------------
michael@0 3561
michael@0 3562
michael@0 3563 /*=============== Timer Related Code ======================*/
michael@0 3564 nsresult
michael@0 3565 nsPrintEngine::StartPagePrintTimer(nsPrintObject* aPO)
michael@0 3566 {
michael@0 3567 if (!mPagePrintTimer) {
michael@0 3568 // Get the delay time in between the printing of each page
michael@0 3569 // this gives the user more time to press cancel
michael@0 3570 int32_t printPageDelay = 50;
michael@0 3571 mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay);
michael@0 3572
michael@0 3573 nsRefPtr<nsPagePrintTimer> timer =
michael@0 3574 new nsPagePrintTimer(this, mDocViewerPrint, printPageDelay);
michael@0 3575 timer.forget(&mPagePrintTimer);
michael@0 3576 }
michael@0 3577
michael@0 3578 return mPagePrintTimer->Start(aPO);
michael@0 3579 }
michael@0 3580
michael@0 3581 /*=============== nsIObserver Interface ======================*/
michael@0 3582 NS_IMETHODIMP
michael@0 3583 nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
michael@0 3584 {
michael@0 3585 nsresult rv = NS_ERROR_FAILURE;
michael@0 3586
michael@0 3587 rv = InitPrintDocConstruction(true);
michael@0 3588 if (!mIsDoingPrinting && mPrtPreview) {
michael@0 3589 mPrtPreview->OnEndPrinting();
michael@0 3590 }
michael@0 3591
michael@0 3592 return rv;
michael@0 3593
michael@0 3594 }
michael@0 3595
michael@0 3596 //---------------------------------------------------------------
michael@0 3597 //-- PLEvent Notification
michael@0 3598 //---------------------------------------------------------------
michael@0 3599 class nsPrintCompletionEvent : public nsRunnable {
michael@0 3600 public:
michael@0 3601 nsPrintCompletionEvent(nsIDocumentViewerPrint *docViewerPrint)
michael@0 3602 : mDocViewerPrint(docViewerPrint) {
michael@0 3603 NS_ASSERTION(mDocViewerPrint, "mDocViewerPrint is null.");
michael@0 3604 }
michael@0 3605
michael@0 3606 NS_IMETHOD Run() MOZ_OVERRIDE {
michael@0 3607 if (mDocViewerPrint)
michael@0 3608 mDocViewerPrint->OnDonePrinting();
michael@0 3609 return NS_OK;
michael@0 3610 }
michael@0 3611
michael@0 3612 private:
michael@0 3613 nsCOMPtr<nsIDocumentViewerPrint> mDocViewerPrint;
michael@0 3614 };
michael@0 3615
michael@0 3616 //-----------------------------------------------------------
michael@0 3617 void
michael@0 3618 nsPrintEngine::FirePrintCompletionEvent()
michael@0 3619 {
michael@0 3620 nsCOMPtr<nsIRunnable> event = new nsPrintCompletionEvent(mDocViewerPrint);
michael@0 3621 if (NS_FAILED(NS_DispatchToCurrentThread(event)))
michael@0 3622 NS_WARNING("failed to dispatch print completion event");
michael@0 3623 }
michael@0 3624
michael@0 3625 //---------------------------------------------------------------
michael@0 3626 //---------------------------------------------------------------
michael@0 3627 //-- Debug helper routines
michael@0 3628 //---------------------------------------------------------------
michael@0 3629 //---------------------------------------------------------------
michael@0 3630 #if defined(XP_WIN) && defined(EXTENDED_DEBUG_PRINTING)
michael@0 3631 #include "windows.h"
michael@0 3632 #include "process.h"
michael@0 3633 #include "direct.h"
michael@0 3634
michael@0 3635 #define MY_FINDFIRST(a,b) FindFirstFile(a,b)
michael@0 3636 #define MY_FINDNEXT(a,b) FindNextFile(a,b)
michael@0 3637 #define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
michael@0 3638 #define MY_FINDCLOSE(a) FindClose(a)
michael@0 3639 #define MY_FILENAME(a) a.cFileName
michael@0 3640 #define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow
michael@0 3641
michael@0 3642 int RemoveFilesInDir(const char * aDir)
michael@0 3643 {
michael@0 3644 WIN32_FIND_DATA data_ptr;
michael@0 3645 HANDLE find_handle;
michael@0 3646
michael@0 3647 char path[MAX_PATH];
michael@0 3648
michael@0 3649 strcpy(path, aDir);
michael@0 3650
michael@0 3651 // Append slash to the end of the directory names if not there
michael@0 3652 if (path[strlen(path)-1] != '\\')
michael@0 3653 strcat(path, "\\");
michael@0 3654
michael@0 3655 char findPath[MAX_PATH];
michael@0 3656 strcpy(findPath, path);
michael@0 3657 strcat(findPath, "*.*");
michael@0 3658
michael@0 3659 find_handle = MY_FINDFIRST(findPath, &data_ptr);
michael@0 3660
michael@0 3661 if (find_handle != INVALID_HANDLE_VALUE) {
michael@0 3662 do {
michael@0 3663 if (ISDIR(data_ptr)
michael@0 3664 && (stricmp(MY_FILENAME(data_ptr),"."))
michael@0 3665 && (stricmp(MY_FILENAME(data_ptr),".."))) {
michael@0 3666 // skip
michael@0 3667 }
michael@0 3668 else if (!ISDIR(data_ptr)) {
michael@0 3669 if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) {
michael@0 3670 char fileName[MAX_PATH];
michael@0 3671 strcpy(fileName, aDir);
michael@0 3672 strcat(fileName, "\\");
michael@0 3673 strcat(fileName, MY_FILENAME(data_ptr));
michael@0 3674 printf("Removing %s\n", fileName);
michael@0 3675 remove(fileName);
michael@0 3676 }
michael@0 3677 }
michael@0 3678 } while(MY_FINDNEXT(find_handle,&data_ptr));
michael@0 3679 MY_FINDCLOSE(find_handle);
michael@0 3680 }
michael@0 3681 return TRUE;
michael@0 3682 }
michael@0 3683 #endif
michael@0 3684
michael@0 3685 #ifdef EXTENDED_DEBUG_PRINTING
michael@0 3686
michael@0 3687 /** ---------------------------------------------------
michael@0 3688 * Dumps Frames for Printing
michael@0 3689 */
michael@0 3690 static void RootFrameList(nsPresContext* aPresContext, FILE* out, int32_t aIndent)
michael@0 3691 {
michael@0 3692 if (!aPresContext || !out)
michael@0 3693 return;
michael@0 3694
michael@0 3695 nsIPresShell *shell = aPresContext->GetPresShell();
michael@0 3696 if (shell) {
michael@0 3697 nsIFrame* frame = shell->FrameManager()->GetRootFrame();
michael@0 3698 if (frame) {
michael@0 3699 frame->List(aPresContext, out, aIndent);
michael@0 3700 }
michael@0 3701 }
michael@0 3702 }
michael@0 3703
michael@0 3704 /** ---------------------------------------------------
michael@0 3705 * Dumps Frames for Printing
michael@0 3706 */
michael@0 3707 static void DumpFrames(FILE* out,
michael@0 3708 nsPresContext* aPresContext,
michael@0 3709 nsRenderingContext * aRendContext,
michael@0 3710 nsIFrame * aFrame,
michael@0 3711 int32_t aLevel)
michael@0 3712 {
michael@0 3713 NS_ASSERTION(out, "Pointer is null!");
michael@0 3714 NS_ASSERTION(aPresContext, "Pointer is null!");
michael@0 3715 NS_ASSERTION(aRendContext, "Pointer is null!");
michael@0 3716 NS_ASSERTION(aFrame, "Pointer is null!");
michael@0 3717
michael@0 3718 nsIFrame* child = aFrame->GetFirstPrincipalChild();
michael@0 3719 while (child != nullptr) {
michael@0 3720 for (int32_t i=0;i<aLevel;i++) {
michael@0 3721 fprintf(out, " ");
michael@0 3722 }
michael@0 3723 nsAutoString tmp;
michael@0 3724 child->GetFrameName(tmp);
michael@0 3725 fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
michael@0 3726 bool isSelected;
michael@0 3727 if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, true, &isSelected))) {
michael@0 3728 fprintf(out, " %p %s", child, isSelected?"VIS":"UVS");
michael@0 3729 nsRect rect = child->GetRect();
michael@0 3730 fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height);
michael@0 3731 fprintf(out, "v: %p ", (void*)child->GetView());
michael@0 3732 fprintf(out, "\n");
michael@0 3733 DumpFrames(out, aPresContext, aRendContext, child, aLevel+1);
michael@0 3734 child = child->GetNextSibling();
michael@0 3735 }
michael@0 3736 }
michael@0 3737 }
michael@0 3738
michael@0 3739
michael@0 3740 /** ---------------------------------------------------
michael@0 3741 * Dumps the Views from the DocShell
michael@0 3742 */
michael@0 3743 static void
michael@0 3744 DumpViews(nsIDocShell* aDocShell, FILE* out)
michael@0 3745 {
michael@0 3746 NS_ASSERTION(aDocShell, "Pointer is null!");
michael@0 3747 NS_ASSERTION(out, "Pointer is null!");
michael@0 3748
michael@0 3749 if (nullptr != aDocShell) {
michael@0 3750 fprintf(out, "docshell=%p \n", aDocShell);
michael@0 3751 nsIPresShell* shell = nsPrintEngine::GetPresShellFor(aDocShell);
michael@0 3752 if (shell) {
michael@0 3753 nsViewManager* vm = shell->GetViewManager();
michael@0 3754 if (vm) {
michael@0 3755 nsView* root = vm->GetRootView();
michael@0 3756 if (root) {
michael@0 3757 root->List(out);
michael@0 3758 }
michael@0 3759 }
michael@0 3760 }
michael@0 3761 else {
michael@0 3762 fputs("null pres shell\n", out);
michael@0 3763 }
michael@0 3764
michael@0 3765 // dump the views of the sub documents
michael@0 3766 int32_t i, n;
michael@0 3767 aDocShell->GetChildCount(&n);
michael@0 3768 for (i = 0; i < n; i++) {
michael@0 3769 nsCOMPtr<nsIDocShellTreeItem> child;
michael@0 3770 aDocShell->GetChildAt(i, getter_AddRefs(child));
michael@0 3771 nsCOMPtr<nsIDocShell> childAsShell(do_QueryInterface(child));
michael@0 3772 if (childAsShell) {
michael@0 3773 DumpViews(childAsShell, out);
michael@0 3774 }
michael@0 3775 }
michael@0 3776 }
michael@0 3777 }
michael@0 3778
michael@0 3779 /** ---------------------------------------------------
michael@0 3780 * Dumps the Views and Frames
michael@0 3781 */
michael@0 3782 void DumpLayoutData(char* aTitleStr,
michael@0 3783 char* aURLStr,
michael@0 3784 nsPresContext* aPresContext,
michael@0 3785 nsDeviceContext * aDC,
michael@0 3786 nsIFrame * aRootFrame,
michael@0 3787 nsIDocShekk * aDocShell,
michael@0 3788 FILE* aFD = nullptr)
michael@0 3789 {
michael@0 3790 if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
michael@0 3791
michael@0 3792 if (aPresContext == nullptr || aDC == nullptr) {
michael@0 3793 return;
michael@0 3794 }
michael@0 3795
michael@0 3796 #ifdef NS_PRINT_PREVIEW
michael@0 3797 if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) {
michael@0 3798 return;
michael@0 3799 }
michael@0 3800 #endif
michael@0 3801
michael@0 3802 NS_ASSERTION(aRootFrame, "Pointer is null!");
michael@0 3803 NS_ASSERTION(aDocShell, "Pointer is null!");
michael@0 3804
michael@0 3805 // Dump all the frames and view to a a file
michael@0 3806 char filename[256];
michael@0 3807 sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++);
michael@0 3808 FILE * fd = aFD?aFD:fopen(filename, "w");
michael@0 3809 if (fd) {
michael@0 3810 fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:"");
michael@0 3811 fprintf(fd, "URL: %s\n", aURLStr?aURLStr:"");
michael@0 3812 fprintf(fd, "--------------- Frames ----------------\n");
michael@0 3813 fprintf(fd, "--------------- Frames ----------------\n");
michael@0 3814 nsRefPtr<nsRenderingContext> renderingContext =
michael@0 3815 aDC->CreateRenderingContext();
michael@0 3816 RootFrameList(aPresContext, fd, 0);
michael@0 3817 //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0);
michael@0 3818 fprintf(fd, "---------------------------------------\n\n");
michael@0 3819 fprintf(fd, "--------------- Views From Root Frame----------------\n");
michael@0 3820 nsView* v = aRootFrame->GetView();
michael@0 3821 if (v) {
michael@0 3822 v->List(fd);
michael@0 3823 } else {
michael@0 3824 printf("View is null!\n");
michael@0 3825 }
michael@0 3826 if (aDocShell) {
michael@0 3827 fprintf(fd, "--------------- All Views ----------------\n");
michael@0 3828 DumpViews(aDocShell, fd);
michael@0 3829 fprintf(fd, "---------------------------------------\n\n");
michael@0 3830 }
michael@0 3831 if (aFD == nullptr) {
michael@0 3832 fclose(fd);
michael@0 3833 }
michael@0 3834 }
michael@0 3835 }
michael@0 3836
michael@0 3837 //-------------------------------------------------------------
michael@0 3838 static void DumpPrintObjectsList(nsTArray<nsPrintObject*> * aDocList)
michael@0 3839 {
michael@0 3840 if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
michael@0 3841
michael@0 3842 NS_ASSERTION(aDocList, "Pointer is null!");
michael@0 3843
michael@0 3844 const char types[][3] = {"DC", "FR", "IF", "FS"};
michael@0 3845 PR_PL(("Doc List\n***************************************************\n"));
michael@0 3846 PR_PL(("T P A H PO DocShell Seq Page Root Page# Rect\n"));
michael@0 3847 int32_t cnt = aDocList->Length();
michael@0 3848 for (int32_t i=0;i<cnt;i++) {
michael@0 3849 nsPrintObject* po = aDocList->ElementAt(i);
michael@0 3850 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3851 nsIFrame* rootFrame = nullptr;
michael@0 3852 if (po->mPresShell) {
michael@0 3853 rootFrame = po->mPresShell->FrameManager()->GetRootFrame();
michael@0 3854 while (rootFrame != nullptr) {
michael@0 3855 nsIPageSequenceFrame * sqf = do_QueryFrame(rootFrame);
michael@0 3856 if (sqf) {
michael@0 3857 break;
michael@0 3858 }
michael@0 3859 rootFrame = rootFrame->GetFirstPrincipalChild();
michael@0 3860 }
michael@0 3861 }
michael@0 3862
michael@0 3863 PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType],
michael@0 3864 po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mDocShell.get(), po->mSeqFrame,
michael@0 3865 po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height));
michael@0 3866 }
michael@0 3867 }
michael@0 3868
michael@0 3869 //-------------------------------------------------------------
michael@0 3870 static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel, FILE* aFD)
michael@0 3871 {
michael@0 3872 if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
michael@0 3873
michael@0 3874 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 3875
michael@0 3876 FILE * fd = aFD?aFD:stdout;
michael@0 3877 const char types[][3] = {"DC", "FR", "IF", "FS"};
michael@0 3878 if (aLevel == 0) {
michael@0 3879 fprintf(fd, "DocTree\n***************************************************\n");
michael@0 3880 fprintf(fd, "T PO DocShell Seq Page Page# Rect\n");
michael@0 3881 }
michael@0 3882 int32_t cnt = aPO->mKids.Length();
michael@0 3883 for (int32_t i=0;i<cnt;i++) {
michael@0 3884 nsPrintObject* po = aPO->mKids.ElementAt(i);
michael@0 3885 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3886 for (int32_t k=0;k<aLevel;k++) fprintf(fd, " ");
michael@0 3887 fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], po, po->mDocShell.get(), po->mSeqFrame,
michael@0 3888 po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height);
michael@0 3889 }
michael@0 3890 }
michael@0 3891
michael@0 3892 //-------------------------------------------------------------
michael@0 3893 static void GetDocTitleAndURL(nsPrintObject* aPO, nsACString& aDocStr, nsACString& aURLStr)
michael@0 3894 {
michael@0 3895 nsAutoString docTitleStr;
michael@0 3896 nsAutoString docURLStr;
michael@0 3897 nsPrintEngine::GetDisplayTitleAndURL(aPO,
michael@0 3898 docTitleStr, docURLStr,
michael@0 3899 nsPrintEngine::eDocTitleDefURLDoc);
michael@0 3900 aDocStr = NS_ConvertUTF16toUTF8(docTitleStr);
michael@0 3901 aURLStr = NS_ConvertUTF16toUTF8(docURLStr);
michael@0 3902 }
michael@0 3903
michael@0 3904 //-------------------------------------------------------------
michael@0 3905 static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,
michael@0 3906 nsDeviceContext * aDC,
michael@0 3907 int aLevel, FILE * aFD)
michael@0 3908 {
michael@0 3909 if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
michael@0 3910
michael@0 3911 NS_ASSERTION(aPO, "Pointer is null!");
michael@0 3912 NS_ASSERTION(aDC, "Pointer is null!");
michael@0 3913
michael@0 3914 const char types[][3] = {"DC", "FR", "IF", "FS"};
michael@0 3915 FILE * fd = nullptr;
michael@0 3916 if (aLevel == 0) {
michael@0 3917 fd = fopen("tree_layout.txt", "w");
michael@0 3918 fprintf(fd, "DocTree\n***************************************************\n");
michael@0 3919 fprintf(fd, "***************************************************\n");
michael@0 3920 fprintf(fd, "T PO DocShell Seq Page Page# Rect\n");
michael@0 3921 } else {
michael@0 3922 fd = aFD;
michael@0 3923 }
michael@0 3924 if (fd) {
michael@0 3925 nsIFrame* rootFrame = nullptr;
michael@0 3926 if (aPO->mPresShell) {
michael@0 3927 rootFrame = aPO->mPresShell->FrameManager()->GetRootFrame();
michael@0 3928 }
michael@0 3929 for (int32_t k=0;k<aLevel;k++) fprintf(fd, " ");
michael@0 3930 fprintf(fd, "%s %p %p %p %p %d %d,%d,%d,%d\n", types[aPO->mFrameType], aPO, aPO->mDocShell.get(), aPO->mSeqFrame,
michael@0 3931 aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height);
michael@0 3932 if (aPO->IsPrintable()) {
michael@0 3933 nsAutoCString docStr;
michael@0 3934 nsAutoCString urlStr;
michael@0 3935 GetDocTitleAndURL(aPO, docStr, urlStr);
michael@0 3936 DumpLayoutData(docStr.get(), urlStr.get(), aPO->mPresContext, aDC, rootFrame, aPO->mDocShell, fd);
michael@0 3937 }
michael@0 3938 fprintf(fd, "<***************************************************>\n");
michael@0 3939
michael@0 3940 int32_t cnt = aPO->mKids.Length();
michael@0 3941 for (int32_t i=0;i<cnt;i++) {
michael@0 3942 nsPrintObject* po = aPO->mKids.ElementAt(i);
michael@0 3943 NS_ASSERTION(po, "nsPrintObject can't be null!");
michael@0 3944 DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd);
michael@0 3945 }
michael@0 3946 }
michael@0 3947 if (aLevel == 0 && fd) {
michael@0 3948 fclose(fd);
michael@0 3949 }
michael@0 3950 }
michael@0 3951
michael@0 3952 //-------------------------------------------------------------
michael@0 3953 static void DumpPrintObjectsListStart(const char * aStr, nsTArray<nsPrintObject*> * aDocList)
michael@0 3954 {
michael@0 3955 if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return;
michael@0 3956
michael@0 3957 NS_ASSERTION(aStr, "Pointer is null!");
michael@0 3958 NS_ASSERTION(aDocList, "Pointer is null!");
michael@0 3959
michael@0 3960 PR_PL(("%s\n", aStr));
michael@0 3961 DumpPrintObjectsList(aDocList);
michael@0 3962 }
michael@0 3963
michael@0 3964 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
michael@0 3965 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
michael@0 3966 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
michael@0 3967
michael@0 3968 #else
michael@0 3969 #define DUMP_DOC_LIST(_title)
michael@0 3970 #define DUMP_DOC_TREE
michael@0 3971 #define DUMP_DOC_TREELAYOUT
michael@0 3972 #endif
michael@0 3973
michael@0 3974 //---------------------------------------------------------------
michael@0 3975 //---------------------------------------------------------------
michael@0 3976 //-- End of debug helper routines
michael@0 3977 //---------------------------------------------------------------

mercurial