1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsPrintEngine.h"
41 #include "nsIStringBundle.h"
42 #include "nsReadableUtils.h"
45 #include "nsISelection.h"
46 #include "nsIScriptGlobalObject.h"
47 #include "nsPIDOMWindow.h"
48 #include "nsIDocShell.h"
50 #include "nsITextToSubURI.h"
51 #include "nsContentErrors.h"
54 #include "nsIPrintSettings.h"
55 #include "nsIPrintSettingsService.h"
56 #include "nsIPrintOptions.h"
57 #include "nsIPrintSession.h"
58 #include "nsGfxCIID.h"
59 #include "nsIServiceManager.h"
60 #include "nsGkAtoms.h"
62 #include "nsISupportsPrimitives.h"
64 static const char sPrintSettingsServiceContractID
[] = "@mozilla.org/gfx/printsettings-service;1";
67 #include "nsPrintPreviewListener.h"
68 #include "nsThreadUtils.h"
71 #include "nsIWebBrowserPrint.h"
72 #include "nsIDOMHTMLFrameElement.h"
73 #include "nsIDOMHTMLFrameSetElement.h"
74 #include "nsIDOMHTMLIFrameElement.h"
75 #include "nsIDOMHTMLObjectElement.h"
76 #include "nsIDOMHTMLEmbedElement.h"
79 #include "imgIContainer.h" // image animation mode constants
80 #include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants
83 #include "nsIPrintProgress.h"
84 #include "nsIPrintProgressParams.h"
85 #include "nsIObserver.h"
88 #include "nsIPrompt.h"
89 #include "nsIWindowWatcher.h"
90 #include "nsIStringBundle.h"
93 #include "nsIPrintingPromptService.h"
94 static const char kPrintingPromptService
[] = "@mozilla.org/embedcomp/printingprompt-service;1";
97 #include "nsPagePrintTimer.h"
100 #include "nsIDocument.h"
103 #include "nsIDOMEventTarget.h"
104 #include "nsIDOMFocusListener.h"
105 #include "nsISelectionController.h"
108 #include "nsISupportsUtils.h"
109 #include "nsIFrame.h"
110 #include "nsIScriptContext.h"
111 #include "nsILinkHandler.h"
112 #include "nsIDOMDocument.h"
113 #include "nsISelectionListener.h"
114 #include "nsISelectionPrivate.h"
115 #include "nsIDOMHTMLDocument.h"
116 #include "nsIDOMNSDocument.h"
117 #include "nsIDOMNSHTMLDocument.h"
118 #include "nsIDOMHTMLCollection.h"
119 #include "nsIDOMHTMLElement.h"
120 #include "nsIDOMRange.h"
121 #include "nsContentCID.h"
122 #include "nsLayoutCID.h"
123 #include "nsContentUtils.h"
124 #include "nsIPresShell.h"
125 #include "nsLayoutUtils.h"
127 #include "nsViewsCID.h"
128 #include "nsWidgetsCID.h"
129 #include "nsIDeviceContext.h"
130 #include "nsIDeviceContextSpec.h"
131 #include "nsIViewManager.h"
134 #include "nsIPageSequenceFrame.h"
136 #include "nsIContentViewerEdit.h"
137 #include "nsIContentViewerFile.h"
138 #include "nsIMarkupDocumentViewer.h"
139 #include "nsIInterfaceRequestor.h"
140 #include "nsIInterfaceRequestorUtils.h"
141 #include "nsIDocShellTreeItem.h"
142 #include "nsIDocShellTreeNode.h"
143 #include "nsIDocShellTreeOwner.h"
144 #include "nsIWebBrowserChrome.h"
145 #include "nsIDocShell.h"
146 #include "nsIBaseWindow.h"
147 #include "nsILayoutHistoryState.h"
148 #include "nsFrameManager.h"
149 #include "nsIParser.h"
150 #include "nsGUIEvent.h"
151 #include "nsHTMLReflowState.h"
152 #include "nsIDOMHTMLAnchorElement.h"
153 #include "nsIDOMHTMLAreaElement.h"
154 #include "nsIDOMHTMLLinkElement.h"
155 #include "nsIDOMHTMLImageElement.h"
156 #include "nsIContentViewerContainer.h"
157 #include "nsIContentViewer.h"
158 #include "nsIDocumentViewerPrint.h"
160 #include "nsPIDOMWindow.h"
161 #include "nsFocusManager.h"
163 #include "nsCDefaultURIFixup.h"
164 #include "nsIURIFixup.h"
165 #include "mozilla/dom/Element.h"
167 using namespace mozilla::dom
;
169 //-----------------------------------------------------
172 #define FORCE_PR_LOG /* Allow logging in the release build */
180 // PR_LOGGING is force to always be on (even in release builds)
181 // but we only want some of it on,
182 //#define EXTENDED_DEBUG_PRINTING
185 #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
187 static PRLogModuleInfo
* kPrintingLogMod
= PR_NewLogModule("printing");
188 #define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
190 #ifdef EXTENDED_DEBUG_PRINTING
191 static PRUint32 gDumpFileNameCnt
= 0;
192 static PRUint32 gDumpLOFileNameCnt
= 0;
195 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
196 static const char * gFrameTypesStr
[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"};
197 static const char * gPrintFrameTypeStr
[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"};
198 static const char * gFrameHowToEnableStr
[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"};
199 static const char * gPrintRangeStr
[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"};
201 #define PRT_YESNO(_p)
205 #ifdef EXTENDED_DEBUG_PRINTING
206 // Forward Declarations
207 static void DumpPrintObjectsListStart(const char * aStr
, nsTArray
<nsPrintObject
*> * aDocList
);
208 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
= 0, FILE* aFD
= nsnull
);
209 static void DumpPrintObjectsTreeLayout(nsPrintObject
* aPO
,nsIDeviceContext
* aDC
, int aLevel
= 0, FILE * aFD
= nsnull
);
211 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
212 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
213 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
215 #define DUMP_DOC_LIST(_title)
216 #define DUMP_DOC_TREE
217 #define DUMP_DOC_TREELAYOUT
220 class nsScriptSuppressor
223 nsScriptSuppressor(nsPrintEngine
* aPrintEngine
)
224 : mPrintEngine(aPrintEngine
), mSuppressed(PR_FALSE
) {}
226 ~nsScriptSuppressor() { Unsuppress(); }
231 mSuppressed
= PR_TRUE
;
232 mPrintEngine
->TurnScriptingOn(PR_FALSE
);
238 if (mPrintEngine
&& mSuppressed
) {
239 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
241 mSuppressed
= PR_FALSE
;
244 void Disconnect() { mPrintEngine
= nsnull
; }
246 nsRefPtr
<nsPrintEngine
> mPrintEngine
;
251 static NS_DEFINE_CID(kViewManagerCID
, NS_VIEW_MANAGER_CID
);
252 static NS_DEFINE_CID(kWidgetCID
, NS_CHILD_CID
);
254 NS_IMPL_ISUPPORTS1(nsPrintEngine
, nsIObserver
)
256 //---------------------------------------------------
257 //-- nsPrintEngine Class Impl
258 //---------------------------------------------------
259 nsPrintEngine::nsPrintEngine() :
260 mIsCreatingPrintPreview(PR_FALSE
),
261 mIsDoingPrinting(PR_FALSE
),
262 mIsDoingPrintPreview(PR_FALSE
),
263 mProgressDialogIsShown(PR_FALSE
),
267 mPagePrintTimer(nsnull
),
268 mPageSeqFrame(nsnull
),
269 mParentWidget(nsnull
),
271 mOldPrtPreview(nsnull
),
276 //-------------------------------------------------------
277 nsPrintEngine::~nsPrintEngine()
279 Destroy(); // for insurance
282 //-------------------------------------------------------
283 void nsPrintEngine::Destroy()
290 #ifdef NS_PRINT_PREVIEW
293 mPrtPreview
= nsnull
;
297 if (mOldPrtPreview
) {
298 delete mOldPrtPreview
;
299 mOldPrtPreview
= nsnull
;
303 mDocViewerPrint
= nsnull
;
306 //-------------------------------------------------------
307 void nsPrintEngine::DestroyPrintingData()
315 //---------------------------------------------------------------------------------
316 //-- Section: Methods needed by the DocViewer
317 //---------------------------------------------------------------------------------
319 //--------------------------------------------------------
320 nsresult
nsPrintEngine::Initialize(nsIDocumentViewerPrint
* aDocViewerPrint
,
321 nsISupports
* aContainer
,
322 nsIDocument
* aDocument
,
324 nsIWidget
* aParentWidget
,
327 NS_ENSURE_ARG_POINTER(aDocViewerPrint
);
328 NS_ENSURE_ARG_POINTER(aContainer
);
329 NS_ENSURE_ARG_POINTER(aDocument
);
331 mDocViewerPrint
= aDocViewerPrint
;
332 mContainer
= aContainer
; // weak reference
333 mDocument
= aDocument
;
334 mScreenDPI
= aScreenDPI
;
335 mParentWidget
= aParentWidget
;
337 mDebugFile
= aDebugFile
; // ok to be NULL
342 //-------------------------------------------------------
344 nsPrintEngine::CheckBeforeDestroy()
346 if (mPrt
&& mPrt
->mPreparingForPrint
) {
347 mPrt
->mDocWasToBeDestroyed
= PR_TRUE
;
353 //-------------------------------------------------------
355 nsPrintEngine::Cancelled()
357 if (mPrt
&& mPrt
->mPrintSettings
) {
358 return mPrt
->mPrintSettings
->SetIsCancelled(PR_TRUE
);
360 return NS_ERROR_FAILURE
;
363 //-------------------------------------------------------
364 // Install our event listeners on the document to prevent
365 // some events from being processed while in PrintPreview
367 // No return code - if this fails, there isn't much we can do
369 nsPrintEngine::InstallPrintPreviewListener()
371 if (!mPrt
->mPPEventListeners
) {
372 nsCOMPtr
<nsPIDOMWindow
> win(do_GetInterface(mContainer
));
373 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(win
->GetFrameElementInternal()));
374 mPrt
->mPPEventListeners
= new nsPrintPreviewListener(target
);
376 if (mPrt
->mPPEventListeners
) {
377 mPrt
->mPPEventListeners
->AddListeners();
382 //----------------------------------------------------------------------
384 nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject
* aPO
,
385 nsIFrame
*& aSeqFrame
,
388 NS_ENSURE_ARG_POINTER(aPO
);
390 // Finds the SimplePageSequencer frame
391 nsIPageSequenceFrame
* seqFrame
= aPO
->mPresShell
->GetPageSequenceFrame();
393 aSeqFrame
= do_QueryFrame(seqFrame
);
397 if (aSeqFrame
== nsnull
) return NS_ERROR_FAILURE
;
399 // first count the total number of pages
401 nsIFrame
* pageFrame
= aSeqFrame
->GetFirstChild(nsnull
);
402 while (pageFrame
!= nsnull
) {
404 pageFrame
= pageFrame
->GetNextSibling();
411 //-----------------------------------------------------------------
412 nsresult
nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame
*& aSeqFrame
, PRInt32
& aCount
)
414 NS_ASSERTION(mPrtPreview
, "mPrtPreview can't be null!");
415 return GetSeqFrameAndCountPagesInternal(mPrtPreview
->mPrintObject
, aSeqFrame
, aCount
);
417 //---------------------------------------------------------------------------------
418 //-- Done: Methods needed by the DocViewer
419 //---------------------------------------------------------------------------------
422 //---------------------------------------------------------------------------------
423 //-- Section: nsIWebBrowserPrint
424 //---------------------------------------------------------------------------------
426 // Foward decl for Debug Helper Functions
427 #ifdef EXTENDED_DEBUG_PRINTING
428 static int RemoveFilesInDir(const char * aDir
);
429 static void GetDocTitleAndURL(nsPrintObject
* aPO
, char *& aDocStr
, char *& aURLStr
);
430 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
, FILE* aFD
);
431 static void DumpPrintObjectsList(nsTArray
<nsPrintObject
*> * aDocList
);
432 static void RootFrameList(nsPresContext
* aPresContext
, FILE* out
, PRInt32 aIndent
);
433 static void DumpViews(nsIDocShell
* aDocShell
, FILE* out
);
434 static void DumpLayoutData(char* aTitleStr
, char* aURLStr
,
435 nsPresContext
* aPresContext
,
436 nsIDeviceContext
* aDC
, nsIFrame
* aRootFrame
,
437 nsIDocShell
* aDocShell
, FILE* aFD
);
440 //--------------------------------------------------------------------------------
443 nsPrintEngine::CommonPrint(PRBool aIsPrintPreview
,
444 nsIPrintSettings
* aPrintSettings
,
445 nsIWebProgressListener
* aWebProgressListener
,
446 nsIDOMDocument
* aDoc
) {
447 nsresult rv
= DoCommonPrint(aIsPrintPreview
, aPrintSettings
,
448 aWebProgressListener
, aDoc
);
450 if (aIsPrintPreview
) {
451 SetIsCreatingPrintPreview(PR_FALSE
);
452 SetIsPrintPreview(PR_FALSE
);
454 SetIsPrinting(PR_FALSE
);
456 if (mProgressDialogIsShown
)
457 CloseProgressDialog(aWebProgressListener
);
458 if (rv
!= NS_ERROR_ABORT
&& rv
!= NS_ERROR_OUT_OF_MEMORY
)
459 ShowPrintErrorDialog(rv
, !aIsPrintPreview
);
468 nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview
,
469 nsIPrintSettings
* aPrintSettings
,
470 nsIWebProgressListener
* aWebProgressListener
,
471 nsIDOMDocument
* aDoc
)
475 if (aIsPrintPreview
) {
476 // The WebProgressListener can be QI'ed to nsIPrintingPromptService
477 // then that means the progress dialog is already being shown.
478 nsCOMPtr
<nsIPrintingPromptService
> pps(do_QueryInterface(aWebProgressListener
));
479 mProgressDialogIsShown
= pps
!= nsnull
;
481 if (mIsDoingPrintPreview
) {
482 mOldPrtPreview
= mPrtPreview
;
483 mPrtPreview
= nsnull
;
486 mProgressDialogIsShown
= PR_FALSE
;
489 mPrt
= new nsPrintData(aIsPrintPreview
? nsPrintData::eIsPrintPreview
:
490 nsPrintData::eIsPrinting
);
491 NS_ENSURE_TRUE(mPrt
, NS_ERROR_OUT_OF_MEMORY
);
493 // if they don't pass in a PrintSettings, then get the Global PS
494 mPrt
->mPrintSettings
= aPrintSettings
;
495 if (!mPrt
->mPrintSettings
) {
496 rv
= GetGlobalPrintSettings(getter_AddRefs(mPrt
->mPrintSettings
));
497 NS_ENSURE_SUCCESS(rv
, rv
);
500 rv
= CheckForPrinters(mPrt
->mPrintSettings
);
501 NS_ENSURE_SUCCESS(rv
, rv
);
503 mPrt
->mPrintSettings
->SetIsCancelled(PR_FALSE
);
504 mPrt
->mPrintSettings
->GetShrinkToFit(&mPrt
->mShrinkToFit
);
506 if (aIsPrintPreview
) {
507 SetIsCreatingPrintPreview(PR_TRUE
);
508 SetIsPrintPreview(PR_TRUE
);
509 nsCOMPtr
<nsIMarkupDocumentViewer
> viewer
=
510 do_QueryInterface(mDocViewerPrint
);
512 viewer
->SetTextZoom(1.0f
);
513 viewer
->SetFullZoom(1.0f
);
516 SetIsPrinting(PR_TRUE
);
519 // Create a print session and let the print settings know about it.
520 // The print settings hold an nsWeakPtr to the session so it does not
521 // need to be cleared from the settings at the end of the job.
522 // XXX What lifetime does the printSession need to have?
523 nsCOMPtr
<nsIPrintSession
> printSession
;
524 if (!aIsPrintPreview
) {
525 printSession
= do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv
);
526 NS_ENSURE_SUCCESS(rv
, rv
);
527 mPrt
->mPrintSettings
->SetPrintSession(printSession
);
530 if (aWebProgressListener
!= nsnull
) {
531 mPrt
->mPrintProgressListeners
.AppendObject(aWebProgressListener
);
534 // Get the currently focused window and cache it
535 // because the Print Dialog will "steal" focus and later when you try
536 // to get the currently focused windows it will be NULL
537 mPrt
->mCurrentFocusWin
= FindFocusedDOMWindow();
539 // Check to see if there is a "regular" selection
540 PRBool isSelection
= IsThereARangeSelection(mPrt
->mCurrentFocusWin
);
542 // Get the docshell for this documentviewer
543 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
, &rv
));
544 NS_ENSURE_SUCCESS(rv
, rv
);
546 mPrt
->mPrintObject
= new nsPrintObject();
547 NS_ENSURE_TRUE(mPrt
->mPrintObject
, NS_ERROR_OUT_OF_MEMORY
);
548 rv
= mPrt
->mPrintObject
->Init(webContainer
, aDoc
, aIsPrintPreview
);
549 NS_ENSURE_SUCCESS(rv
, rv
);
551 NS_ENSURE_TRUE(mPrt
->mPrintDocList
.AppendElement(mPrt
->mPrintObject
),
552 NS_ERROR_OUT_OF_MEMORY
);
554 mPrt
->mIsParentAFrameSet
= IsParentAFrameSet(webContainer
);
555 mPrt
->mPrintObject
->mFrameType
= mPrt
->mIsParentAFrameSet
? eFrameSet
: eDoc
;
557 // Build the "tree" of PrintObjects
558 nsCOMPtr
<nsIDocShellTreeNode
> parentAsNode
=
559 do_QueryInterface(mPrt
->mPrintObject
->mDocShell
);
560 BuildDocTree(parentAsNode
, &mPrt
->mPrintDocList
, mPrt
->mPrintObject
);
562 // XXX This isn't really correct...
563 if (!mPrt
->mPrintObject
->mDocument
||
564 !mPrt
->mPrintObject
->mDocument
->GetRootElement())
565 return NS_ERROR_GFX_PRINTER_STARTDOC
;
567 // Create the linkage from the sub-docs back to the content element
568 // in the parent document
569 MapContentToWebShells(mPrt
->mPrintObject
, mPrt
->mPrintObject
);
571 mPrt
->mIsIFrameSelected
= IsThereAnIFrameSelected(webContainer
, mPrt
->mCurrentFocusWin
, mPrt
->mIsParentAFrameSet
);
573 // Setup print options for UI
574 if (mPrt
->mIsParentAFrameSet
) {
575 if (mPrt
->mCurrentFocusWin
) {
576 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll
);
578 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach
);
581 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone
);
583 // Now determine how to set up the Frame print UI
584 mPrt
->mPrintSettings
->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB
, isSelection
|| mPrt
->mIsIFrameSelected
);
586 nsCOMPtr
<nsIDeviceContextSpec
> devspec
587 (do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv
));
588 NS_ENSURE_SUCCESS(rv
, rv
);
590 nsScriptSuppressor
scriptSuppressor(this);
591 if (!aIsPrintPreview
) {
593 mPrt
->mDebugFilePtr
= mDebugFile
;
596 scriptSuppressor
.Suppress();
597 PRBool printSilently
;
598 mPrt
->mPrintSettings
->GetPrintSilent(&printSilently
);
600 // Check prefs for a default setting as to whether we should print silently
601 printSilently
= nsContentUtils::GetBoolPref("print.always_print_silent",
604 // Ask dialog to be Print Shown via the Plugable Printing Dialog Service
605 // This service is for the Print Dialog and the Print Progress Dialog
606 // If printing silently or you can't get the service continue on
607 if (!printSilently
) {
608 nsCOMPtr
<nsIPrintingPromptService
> printPromptService(do_GetService(kPrintingPromptService
));
609 if (printPromptService
) {
610 nsIDOMWindow
*domWin
= mDocument
->GetWindow();
611 NS_ENSURE_TRUE(domWin
, NS_ERROR_FAILURE
);
613 // Platforms not implementing a given dialog for the service may
614 // return NS_ERROR_NOT_IMPLEMENTED or an error code.
616 // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior
617 // Any other error code means we must bail out
619 nsCOMPtr
<nsIWebBrowserPrint
> wbp(do_QueryInterface(mDocViewerPrint
));
620 rv
= printPromptService
->ShowPrintDialog(domWin
, wbp
,
621 mPrt
->mPrintSettings
);
622 if (rv
== NS_ERROR_NOT_IMPLEMENTED
) {
623 // This means the Dialog service was there,
624 // but they choose not to implement this dialog and
625 // are looking for default behavior from the toolkit
627 } else if (NS_SUCCEEDED(rv
)) {
628 // since we got the dialog and it worked then make sure we
629 // are telling GFX we want to print silent
630 printSilently
= PR_TRUE
;
632 // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
633 mPrt
->mPrintSettings
->GetShrinkToFit(&mPrt
->mShrinkToFit
);
635 rv
= NS_ERROR_GFX_NO_PRINTROMPTSERVICE
;
638 // Call any code that requires a run of the event loop.
639 rv
= mPrt
->mPrintSettings
->SetupSilentPrinting();
641 // Check explicitly for abort because it's expected
642 if (rv
== NS_ERROR_ABORT
)
644 NS_ENSURE_SUCCESS(rv
, rv
);
647 rv
= devspec
->Init(nsnull
, mPrt
->mPrintSettings
, aIsPrintPreview
);
648 NS_ENSURE_SUCCESS(rv
, rv
);
650 mPrt
->mPrintDC
= do_CreateInstance("@mozilla.org/gfx/devicecontext;1", &rv
);
651 NS_ENSURE_SUCCESS(rv
, rv
);
652 rv
= mPrt
->mPrintDC
->InitForPrinting(devspec
);
653 NS_ENSURE_SUCCESS(rv
, rv
);
655 if (aIsPrintPreview
) {
656 mPrt
->mPrintSettings
->SetPrintFrameType(nsIPrintSettings::kFramesAsIs
);
658 // override any UI that wants to PrintPreview any selection or page range
659 // we want to view every page in PrintPreview each time
660 mPrt
->mPrintSettings
->SetPrintRange(nsIPrintSettings::kRangeAllPages
);
662 // Always check and set the print settings first and then fall back
663 // onto the PrintService if there isn't a PrintSettings
665 // Posiible Usage values:
666 // nsIPrintSettings::kUseInternalDefault
667 // nsIPrintSettings::kUseSettingWhenPossible
669 // NOTE: The consts are the same for PrintSettings and PrintSettings
670 PRInt16 printFrameTypeUsage
= nsIPrintSettings::kUseSettingWhenPossible
;
671 mPrt
->mPrintSettings
->GetPrintFrameTypeUsage(&printFrameTypeUsage
);
673 // Ok, see if we are going to use our value and override the default
674 if (printFrameTypeUsage
== nsIPrintSettings::kUseSettingWhenPossible
) {
675 // Get the Print Options/Settings PrintFrameType to see what is preferred
676 PRInt16 printFrameType
= nsIPrintSettings::kEachFrameSep
;
677 mPrt
->mPrintSettings
->GetPrintFrameType(&printFrameType
);
679 // Don't let anybody do something stupid like try to set it to
680 // kNoFrames when we are printing a FrameSet
681 if (printFrameType
== nsIPrintSettings::kNoFrames
) {
682 mPrt
->mPrintFrameType
= nsIPrintSettings::kEachFrameSep
;
683 mPrt
->mPrintSettings
->SetPrintFrameType(mPrt
->mPrintFrameType
);
685 // First find out from the PrinService what options are available
686 // to us for Printing FrameSets
687 PRInt16 howToEnableFrameUI
;
688 mPrt
->mPrintSettings
->GetHowToEnableFrameUI(&howToEnableFrameUI
);
689 if (howToEnableFrameUI
!= nsIPrintSettings::kFrameEnableNone
) {
690 switch (howToEnableFrameUI
) {
691 case nsIPrintSettings::kFrameEnableAll
:
692 mPrt
->mPrintFrameType
= printFrameType
;
695 case nsIPrintSettings::kFrameEnableAsIsAndEach
:
696 if (printFrameType
!= nsIPrintSettings::kSelectedFrame
) {
697 mPrt
->mPrintFrameType
= printFrameType
;
698 } else { // revert back to a good value
699 mPrt
->mPrintFrameType
= nsIPrintSettings::kEachFrameSep
;
703 mPrt
->mPrintSettings
->SetPrintFrameType(mPrt
->mPrintFrameType
);
707 mPrt
->mPrintSettings
->GetPrintFrameType(&mPrt
->mPrintFrameType
);
711 if (aIsPrintPreview
) {
712 PRBool notifyOnInit
= PR_FALSE
;
713 ShowPrintProgress(PR_FALSE
, notifyOnInit
);
715 // Very important! Turn Off scripting
716 TurnScriptingOn(PR_FALSE
);
719 rv
= FinishPrintPreview();
723 NS_ENSURE_SUCCESS(rv
, rv
);
725 PRUnichar
* docTitleStr
;
726 PRUnichar
* docURLStr
;
728 GetDisplayTitleAndURL(mPrt
->mPrintObject
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
730 // Nobody ever cared about the file name passed in, as far as I can tell
731 rv
= mPrt
->mPrintDC
->PrepareDocument(docTitleStr
, nsnull
);
733 if (docTitleStr
) nsMemory::Free(docTitleStr
);
734 if (docURLStr
) nsMemory::Free(docURLStr
);
736 NS_ENSURE_SUCCESS(rv
, rv
);
739 ShowPrintProgress(PR_TRUE
, doNotify
);
741 // Print listener setup...
742 mPrt
->OnStartPrinting();
743 rv
= DocumentReadyForPrinting();
744 NS_ENSURE_SUCCESS(rv
, rv
);
748 // We will enable scripting later after printing has finished.
749 scriptSuppressor
.Disconnect();
754 //---------------------------------------------------------------------------------
756 nsPrintEngine::Print(nsIPrintSettings
* aPrintSettings
,
757 nsIWebProgressListener
* aWebProgressListener
)
759 // If we have a print preview document, use that instead of the original
760 // mDocument. That way animated images etc. get printed using the same state
761 // as in print preview.
762 nsCOMPtr
<nsIDOMDocument
> doc
=
763 do_QueryInterface(mPrtPreview
&& mPrtPreview
->mPrintObject
?
764 mPrtPreview
->mPrintObject
->mDocument
: mDocument
);
766 return CommonPrint(PR_FALSE
, aPrintSettings
, aWebProgressListener
, doc
);
770 nsPrintEngine::PrintPreview(nsIPrintSettings
* aPrintSettings
,
771 nsIDOMWindow
*aChildDOMWin
,
772 nsIWebProgressListener
* aWebProgressListener
)
774 // Get the DocShell and see if it is busy
775 // (We can't Print Preview this document if it is still busy)
776 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(mContainer
));
777 NS_ASSERTION(docShell
, "This has to be a docshell");
779 PRUint32 busyFlags
= nsIDocShell::BUSY_FLAGS_NONE
;
780 if (NS_FAILED(docShell
->GetBusyFlags(&busyFlags
)) ||
781 busyFlags
!= nsIDocShell::BUSY_FLAGS_NONE
) {
782 CloseProgressDialog(aWebProgressListener
);
783 ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP
, PR_FALSE
);
784 return NS_ERROR_FAILURE
;
787 NS_ENSURE_STATE(aChildDOMWin
);
788 nsCOMPtr
<nsIDOMDocument
> doc
;
789 aChildDOMWin
->GetDocument(getter_AddRefs(doc
));
790 NS_ENSURE_STATE(doc
);
792 // Document is not busy -- go ahead with the Print Preview
793 return CommonPrint(PR_TRUE
, aPrintSettings
, aWebProgressListener
, doc
);
796 //----------------------------------------------------------------------------------
797 /* readonly attribute boolean isFramesetDocument; */
799 nsPrintEngine::GetIsFramesetDocument(PRBool
*aIsFramesetDocument
)
801 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
));
802 *aIsFramesetDocument
= IsParentAFrameSet(webContainer
);
806 //----------------------------------------------------------------------------------
807 /* readonly attribute boolean isIFrameSelected; */
809 nsPrintEngine::GetIsIFrameSelected(PRBool
*aIsIFrameSelected
)
811 *aIsIFrameSelected
= PR_FALSE
;
813 // Get the docshell for this documentviewer
814 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
));
815 // Get the currently focused window
816 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
817 if (currentFocusWin
&& webContainer
) {
818 // Get whether the doc contains a frameset
819 // Also, check to see if the currently focus docshell
820 // is a child of this docshell
821 PRPackedBool isParentFrameSet
;
822 *aIsIFrameSelected
= IsThereAnIFrameSelected(webContainer
, currentFocusWin
, isParentFrameSet
);
827 //----------------------------------------------------------------------------------
828 /* readonly attribute boolean isRangeSelection; */
830 nsPrintEngine::GetIsRangeSelection(PRBool
*aIsRangeSelection
)
832 // Get the currently focused window
833 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
834 *aIsRangeSelection
= IsThereARangeSelection(currentFocusWin
);
838 //----------------------------------------------------------------------------------
839 /* readonly attribute boolean isFramesetFrameSelected; */
841 nsPrintEngine::GetIsFramesetFrameSelected(PRBool
*aIsFramesetFrameSelected
)
843 // Get the currently focused window
844 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
845 *aIsFramesetFrameSelected
= currentFocusWin
!= nsnull
;
849 //----------------------------------------------------------------------------------
850 /* readonly attribute long printPreviewNumPages; */
852 nsPrintEngine::GetPrintPreviewNumPages(PRInt32
*aPrintPreviewNumPages
)
854 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages
);
856 nsIFrame
* seqFrame
= nsnull
;
857 *aPrintPreviewNumPages
= 0;
859 NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview
->mPrintObject
, seqFrame
, *aPrintPreviewNumPages
))) {
860 return NS_ERROR_FAILURE
;
865 //----------------------------------------------------------------------------------
866 // Enumerate all the documents for their titles
868 nsPrintEngine::EnumerateDocumentNames(PRUint32
* aCount
,
869 PRUnichar
*** aResult
)
871 NS_ENSURE_ARG(aCount
);
872 NS_ENSURE_ARG_POINTER(aResult
);
877 PRInt32 numDocs
= mPrt
->mPrintDocList
.Length();
878 PRUnichar
** array
= (PRUnichar
**) nsMemory::Alloc(numDocs
* sizeof(PRUnichar
*));
880 return NS_ERROR_OUT_OF_MEMORY
;
882 for (PRInt32 i
=0;i
<numDocs
;i
++) {
883 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
884 NS_ASSERTION(po
, "nsPrintObject can't be null!");
885 PRUnichar
* docTitleStr
;
886 PRUnichar
* docURLStr
;
887 GetDocumentTitleAndURL(po
->mDocument
, &docTitleStr
, &docURLStr
);
889 // Use the URL if the doc is empty
890 if (!docTitleStr
|| !*docTitleStr
) {
891 if (docURLStr
&& *docURLStr
) {
892 nsMemory::Free(docTitleStr
);
893 docTitleStr
= docURLStr
;
895 nsMemory::Free(docURLStr
);
898 if (!docTitleStr
|| !*docTitleStr
) {
899 CleanupDocTitleArray(array
, i
);
900 return NS_ERROR_OUT_OF_MEMORY
;
903 array
[i
] = docTitleStr
;
904 if (docURLStr
) nsMemory::Free(docURLStr
);
913 //----------------------------------------------------------------------------------
914 /* readonly attribute nsIPrintSettings globalPrintSettings; */
916 nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings
**aGlobalPrintSettings
)
918 NS_ENSURE_ARG_POINTER(aGlobalPrintSettings
);
920 nsresult rv
= NS_ERROR_FAILURE
;
921 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
922 do_GetService(sPrintSettingsServiceContractID
, &rv
);
923 if (NS_SUCCEEDED(rv
)) {
924 rv
= printSettingsService
->GetGlobalPrintSettings(aGlobalPrintSettings
);
929 //----------------------------------------------------------------------------------
930 /* readonly attribute boolean doingPrint; */
932 nsPrintEngine::GetDoingPrint(PRBool
*aDoingPrint
)
934 NS_ENSURE_ARG_POINTER(aDoingPrint
);
935 *aDoingPrint
= mIsDoingPrinting
;
939 //----------------------------------------------------------------------------------
940 /* readonly attribute boolean doingPrintPreview; */
942 nsPrintEngine::GetDoingPrintPreview(PRBool
*aDoingPrintPreview
)
944 NS_ENSURE_ARG_POINTER(aDoingPrintPreview
);
945 *aDoingPrintPreview
= mIsDoingPrintPreview
;
949 //----------------------------------------------------------------------------------
950 /* readonly attribute nsIPrintSettings currentPrintSettings; */
952 nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings
* *aCurrentPrintSettings
)
954 NS_ENSURE_ARG_POINTER(aCurrentPrintSettings
);
957 *aCurrentPrintSettings
= mPrt
->mPrintSettings
;
959 } else if (mPrtPreview
) {
960 *aCurrentPrintSettings
= mPrtPreview
->mPrintSettings
;
963 *aCurrentPrintSettings
= nsnull
;
965 NS_IF_ADDREF(*aCurrentPrintSettings
);
969 //-----------------------------------------------------------------
970 //-- Section: Pre-Reflow Methods
971 //-----------------------------------------------------------------
973 //---------------------------------------------------------------------
974 // This method checks to see if there is at least one printer defined
975 // and if so, it sets the first printer in the list as the default name
976 // in the PrintSettings which is then used for Printer Preview
978 nsPrintEngine::CheckForPrinters(nsIPrintSettings
* aPrintSettings
)
981 // Mac doesn't support retrieving a printer list.
984 NS_ENSURE_ARG_POINTER(aPrintSettings
);
986 // See if aPrintSettings already has a printer
987 nsXPIDLString printerName
;
988 nsresult rv
= aPrintSettings
->GetPrinterName(getter_Copies(printerName
));
989 if (NS_SUCCEEDED(rv
) && !printerName
.IsEmpty()) {
993 // aPrintSettings doesn't have a printer set. Try to fetch the default.
994 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
995 do_GetService(sPrintSettingsServiceContractID
, &rv
);
996 NS_ENSURE_SUCCESS(rv
, rv
);
998 rv
= printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
999 if (NS_SUCCEEDED(rv
) && !printerName
.IsEmpty()) {
1000 rv
= aPrintSettings
->SetPrinterName(printerName
.get());
1006 //----------------------------------------------------------------------
1007 // Set up to use the "pluggable" Print Progress Dialog
1009 nsPrintEngine::ShowPrintProgress(PRBool aIsForPrinting
, PRBool
& aDoNotify
)
1011 // default to not notifying, that if something here goes wrong
1012 // or we aren't going to show the progress dialog we can straight into
1013 // reflowing the doc for printing.
1014 aDoNotify
= PR_FALSE
;
1016 // Assume we can't do progress and then see if we can
1017 PRBool showProgresssDialog
= PR_FALSE
;
1019 // if it is already being shown then don't bother to find out if it should be
1020 // so skip this and leave mShowProgressDialog set to FALSE
1021 if (!mProgressDialogIsShown
) {
1022 showProgresssDialog
=
1023 nsContentUtils::GetBoolPref("print.show_print_progress");
1026 // Turning off the showing of Print Progress in Prefs overrides
1027 // whether the calling PS desire to have it on or off, so only check PS if
1028 // prefs says it's ok to be on.
1029 if (showProgresssDialog
) {
1030 mPrt
->mPrintSettings
->GetShowPrintProgress(&showProgresssDialog
);
1033 // Now open the service to get the progress dialog
1034 // If we don't get a service, that's ok, then just don't show progress
1035 if (showProgresssDialog
) {
1036 nsCOMPtr
<nsIPrintingPromptService
> printPromptService(do_GetService(kPrintingPromptService
));
1037 if (printPromptService
) {
1038 nsPIDOMWindow
*domWin
= mDocument
->GetWindow();
1039 if (!domWin
) return;
1041 nsCOMPtr
<nsIDocShellTreeItem
> docShellItem
=
1042 do_QueryInterface(domWin
->GetDocShell());
1043 if (!docShellItem
) return;
1044 nsCOMPtr
<nsIDocShellTreeOwner
> owner
;
1045 docShellItem
->GetTreeOwner(getter_AddRefs(owner
));
1046 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
= do_GetInterface(owner
);
1047 if (!browserChrome
) return;
1048 PRBool isModal
= PR_TRUE
;
1049 browserChrome
->IsWindowModal(&isModal
);
1051 // Showing a print progress dialog when printing a modal window
1052 // isn't supported. See bug 301560.
1056 nsCOMPtr
<nsIWebProgressListener
> printProgressListener
;
1058 nsCOMPtr
<nsIWebBrowserPrint
> wbp(do_QueryInterface(mDocViewerPrint
));
1059 nsresult rv
= printPromptService
->ShowProgress(domWin
, wbp
, mPrt
->mPrintSettings
, this, aIsForPrinting
,
1060 getter_AddRefs(printProgressListener
),
1061 getter_AddRefs(mPrt
->mPrintProgressParams
),
1063 if (NS_SUCCEEDED(rv
)) {
1064 if (printProgressListener
&& mPrt
->mPrintProgressParams
) {
1065 mPrt
->mPrintProgressListeners
.AppendObject(printProgressListener
);
1066 SetDocAndURLIntoProgress(mPrt
->mPrintObject
, mPrt
->mPrintProgressParams
);
1073 //---------------------------------------------------------------------
1075 nsPrintEngine::IsThereARangeSelection(nsIDOMWindow
* aDOMWin
)
1077 nsCOMPtr
<nsIPresShell
> presShell
;
1079 nsCOMPtr
<nsPIDOMWindow
> window(do_QueryInterface(aDOMWin
));
1080 window
->GetDocShell()->GetPresShell(getter_AddRefs(presShell
));
1086 // check here to see if there is a range selection
1087 // so we know whether to turn on the "Selection" radio button
1088 nsCOMPtr
<nsISelection
> selection
;
1089 selection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
1092 selection
->GetRangeCount(&count
);
1094 nsCOMPtr
<nsIDOMRange
> range
;
1095 if (NS_SUCCEEDED(selection
->GetRangeAt(0, getter_AddRefs(range
)))) {
1096 // check to make sure it isn't an insertion selection
1098 selection
->GetIsCollapsed(&isCollapsed
);
1099 return !isCollapsed
;
1102 if (count
> 1) return PR_TRUE
;
1107 //---------------------------------------------------------------------
1109 nsPrintEngine::IsParentAFrameSet(nsIDocShell
* aParent
)
1111 // See if the incoming doc is the root document
1112 nsCOMPtr
<nsIDocShellTreeItem
> parentAsItem(do_QueryInterface(aParent
));
1113 if (!parentAsItem
) return PR_FALSE
;
1115 // When it is the top level document we need to check
1116 // to see if it contains a frameset. If it does, then
1117 // we only want to print the doc's children and not the document itself
1118 // For anything else we always print all the children and the document
1119 // for example, if the doc contains an IFRAME we eant to print the child
1120 // document (the IFRAME) and then the rest of the document.
1122 // XXX we really need to search the frame tree, and not the content
1123 // but there is no way to distinguish between IFRAMEs and FRAMEs
1124 // with the GetFrameType call.
1125 // Bug 53459 has been files so we can eventually distinguish
1126 // between IFRAME frames and FRAME frames
1127 PRBool isFrameSet
= PR_FALSE
;
1128 // only check to see if there is a frameset if there is
1129 // NO parent doc for this doc. meaning this parent is the root doc
1130 nsCOMPtr
<nsIDOMDocument
> domDoc
= do_GetInterface(aParent
);
1131 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
1133 nsIContent
*rootElement
= doc
->GetRootElement();
1135 isFrameSet
= HasFramesetChild(rootElement
);
1142 //---------------------------------------------------------------------
1143 // Recursively build a list of sub documents to be printed
1144 // that mirrors the document tree
1146 nsPrintEngine::BuildDocTree(nsIDocShellTreeNode
* aParentNode
,
1147 nsTArray
<nsPrintObject
*> * aDocList
,
1148 nsPrintObject
* aPO
)
1150 NS_ASSERTION(aParentNode
, "Pointer is null!");
1151 NS_ASSERTION(aDocList
, "Pointer is null!");
1152 NS_ASSERTION(aPO
, "Pointer is null!");
1154 PRInt32 childWebshellCount
;
1155 aParentNode
->GetChildCount(&childWebshellCount
);
1156 if (childWebshellCount
> 0) {
1157 for (PRInt32 i
=0;i
<childWebshellCount
;i
++) {
1158 nsCOMPtr
<nsIDocShellTreeItem
> child
;
1159 aParentNode
->GetChildAt(i
, getter_AddRefs(child
));
1160 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
1162 nsCOMPtr
<nsIContentViewer
> viewer
;
1163 childAsShell
->GetContentViewer(getter_AddRefs(viewer
));
1165 nsCOMPtr
<nsIContentViewerFile
> viewerFile(do_QueryInterface(viewer
));
1167 nsCOMPtr
<nsIDocShell
> childDocShell(do_QueryInterface(child
));
1168 nsCOMPtr
<nsIDocShellTreeNode
> childNode(do_QueryInterface(child
));
1169 nsCOMPtr
<nsIDOMDocument
> doc
= do_GetInterface(childDocShell
);
1170 nsPrintObject
* po
= new nsPrintObject();
1172 nsresult rv
= po
->Init(childDocShell
, doc
, aPO
->mPrintPreview
);
1174 NS_NOTREACHED("Init failed?");
1175 aPO
->mKids
.AppendElement(po
);
1176 aDocList
->AppendElement(po
);
1177 BuildDocTree(childNode
, aDocList
, po
);
1184 //---------------------------------------------------------------------
1186 nsPrintEngine::GetDocumentTitleAndURL(nsIDocument
* aDoc
,
1188 PRUnichar
** aURLStr
)
1190 NS_ASSERTION(aDoc
, "Pointer is null!");
1191 NS_ASSERTION(aTitle
, "Pointer is null!");
1192 NS_ASSERTION(aURLStr
, "Pointer is null!");
1197 nsAutoString docTitle
;
1198 nsCOMPtr
<nsIDOMNSDocument
> doc
= do_QueryInterface(aDoc
);
1199 doc
->GetTitle(docTitle
);
1200 if (!docTitle
.IsEmpty()) {
1201 *aTitle
= ToNewUnicode(docTitle
);
1204 nsIURI
* url
= aDoc
->GetDocumentURI();
1207 nsCOMPtr
<nsIURIFixup
> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
1208 if (!urifixup
) return;
1210 nsCOMPtr
<nsIURI
> exposableURI
;
1211 urifixup
->CreateExposableURI(url
, getter_AddRefs(exposableURI
));
1213 if (!exposableURI
) return;
1215 nsCAutoString urlCStr
;
1216 exposableURI
->GetSpec(urlCStr
);
1219 nsCOMPtr
<nsITextToSubURI
> textToSubURI
=
1220 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID
, &rv
);
1221 if (NS_FAILED(rv
)) return;
1223 nsAutoString unescapedURI
;
1224 rv
= textToSubURI
->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
1225 urlCStr
, unescapedURI
);
1226 if (NS_FAILED(rv
)) return;
1228 *aURLStr
= ToNewUnicode(unescapedURI
);
1231 //---------------------------------------------------------------------
1232 // The walks the PO tree and for each document it walks the content
1233 // tree looking for any content that are sub-shells
1235 // It then sets the mContent pointer in the "found" PO object back to the
1236 // the document that contained it.
1238 nsPrintEngine::MapContentToWebShells(nsPrintObject
* aRootPO
,
1241 NS_ASSERTION(aRootPO
, "Pointer is null!");
1242 NS_ASSERTION(aPO
, "Pointer is null!");
1244 // Recursively walk the content from the root item
1245 // XXX Would be faster to enumerate the subdocuments, although right now
1246 // nsIDocument doesn't expose quite what would be needed.
1247 nsCOMPtr
<nsIContentViewer
> viewer
;
1248 aPO
->mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
1249 if (!viewer
) return;
1251 nsCOMPtr
<nsIDOMDocument
> domDoc
;
1252 viewer
->GetDOMDocument(getter_AddRefs(domDoc
));
1253 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
1256 Element
* rootElement
= doc
->GetRootElement();
1258 MapContentForPO(aPO
, rootElement
);
1260 NS_WARNING("Null root content on (sub)document.");
1263 // Continue recursively walking the chilren of this PO
1264 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1265 MapContentToWebShells(aRootPO
, aPO
->mKids
[i
]);
1270 //-------------------------------------------------------
1271 // A Frame's sub-doc may contain content or a FrameSet
1272 // When it contains a FrameSet the mFrameType for the PrintObject
1273 // is always set to an eFrame. Which is fine when printing "AsIs"
1274 // but is incorrect when when printing "Each Frame Separately".
1275 // When printing "Each Frame Separately" the Frame really acts like
1278 // This method walks the PO tree and checks to see if the PrintObject is
1279 // an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet)
1280 // If so, then the mFrameType need to be changed to eFrameSet
1282 // Also note: We only want to call this we are printing "Each Frame Separately"
1283 // when printing "As Is" leave it as an eFrame
1285 nsPrintEngine::CheckForChildFrameSets(nsPrintObject
* aPO
)
1287 NS_ASSERTION(aPO
, "Pointer is null!");
1289 // Continue recursively walking the chilren of this PO
1290 PRBool hasChildFrames
= PR_FALSE
;
1291 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1292 nsPrintObject
* po
= aPO
->mKids
[i
];
1293 if (po
->mFrameType
== eFrame
) {
1294 hasChildFrames
= PR_TRUE
;
1295 CheckForChildFrameSets(po
);
1299 if (hasChildFrames
&& aPO
->mFrameType
== eFrame
) {
1300 aPO
->mFrameType
= eFrameSet
;
1304 //---------------------------------------------------------------------
1305 // This method is key to the entire print mechanism.
1307 // This "maps" or figures out which sub-doc represents a
1308 // given Frame or IFrame in its parent sub-doc.
1310 // So the Mcontent pointer in the child sub-doc points to the
1311 // content in the its parent document, that caused it to be printed.
1312 // This is used later to (after reflow) to find the absolute location
1313 // of the sub-doc on its parent's page frame so it can be
1314 // printed in the correct location.
1316 // This method recursvely "walks" the content for a document finding
1317 // all the Frames and IFrames, then sets the "mFrameType" data member
1318 // which tells us what type of PO we have
1320 nsPrintEngine::MapContentForPO(nsPrintObject
* aPO
,
1321 nsIContent
* aContent
)
1323 NS_PRECONDITION(aPO
&& aContent
, "Null argument");
1325 nsIDocument
* doc
= aContent
->GetDocument();
1327 NS_ASSERTION(doc
, "Content without a document from a document tree?");
1329 nsIDocument
* subDoc
= doc
->GetSubDocumentFor(aContent
);
1332 nsCOMPtr
<nsISupports
> container
= subDoc
->GetContainer();
1333 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(container
));
1336 nsPrintObject
* po
= nsnull
;
1337 PRInt32 cnt
= aPO
->mKids
.Length();
1338 for (PRInt32 i
=0;i
<cnt
;i
++) {
1339 nsPrintObject
* kid
= aPO
->mKids
.ElementAt(i
);
1340 if (kid
->mDocument
== subDoc
) {
1346 // XXX If a subdocument has no onscreen presentation, there will be no PO
1347 // This is even if there should be a print presentation
1350 nsCOMPtr
<nsIDOMHTMLFrameElement
> frame(do_QueryInterface(aContent
));
1351 // "frame" elements not in a frameset context should be treated
1353 if (frame
&& po
->mParent
->mFrameType
== eFrameSet
) {
1354 po
->mFrameType
= eFrame
;
1356 // Assume something iframe-like, i.e. iframe, object, or embed
1357 po
->mFrameType
= eIFrame
;
1358 SetPrintAsIs(po
, PR_TRUE
);
1359 NS_ASSERTION(po
->mParent
, "The root must be a parent");
1360 po
->mParent
->mPrintAsIs
= PR_TRUE
;
1366 // walk children content
1367 PRUint32 count
= aContent
->GetChildCount();
1368 for (PRUint32 i
= 0; i
< count
; ++i
) {
1369 nsIContent
*child
= aContent
->GetChildAt(i
);
1370 MapContentForPO(aPO
, child
);
1374 //---------------------------------------------------------------------
1376 nsPrintEngine::IsThereAnIFrameSelected(nsIDocShell
* aDocShell
,
1377 nsIDOMWindow
* aDOMWin
,
1378 PRPackedBool
& aIsParentFrameSet
)
1380 aIsParentFrameSet
= IsParentAFrameSet(aDocShell
);
1381 PRBool iFrameIsSelected
= PR_FALSE
;
1382 if (mPrt
&& mPrt
->mPrintObject
) {
1383 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, aDOMWin
);
1384 iFrameIsSelected
= po
&& po
->mFrameType
== eIFrame
;
1386 // First, check to see if we are a frameset
1387 if (!aIsParentFrameSet
) {
1388 // Check to see if there is a currenlt focused frame
1389 // if so, it means the selected frame is either the main docshell
1392 // Get the main docshell's DOMWin to see if it matches
1393 // the frame that is selected
1394 nsCOMPtr
<nsIDOMWindow
> domWin
= do_GetInterface(aDocShell
);
1395 if (domWin
!= aDOMWin
) {
1396 iFrameIsSelected
= PR_TRUE
; // we have a selected IFRAME
1402 return iFrameIsSelected
;
1405 //---------------------------------------------------------------------
1406 // Recursively sets all the PO items to be printed
1407 // from the given item down into the tree
1409 nsPrintEngine::SetPrintPO(nsPrintObject
* aPO
, PRBool aPrint
)
1411 NS_ASSERTION(aPO
, "Pointer is null!");
1413 // Set whether to print flag
1414 aPO
->mDontPrint
= !aPrint
;
1416 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1417 SetPrintPO(aPO
->mKids
[i
], aPrint
);
1421 //---------------------------------------------------------------------
1422 // This will first use a Title and/or URL from the PrintSettings
1423 // if one isn't set then it uses the one from the document
1424 // then if not title is there we will make sure we send something back
1425 // depending on the situation.
1427 nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject
* aPO
,
1429 PRUnichar
** aURLStr
,
1430 eDocTitleDefault aDefType
)
1432 NS_ASSERTION(aPO
, "Pointer is null!");
1433 NS_ASSERTION(aTitle
, "Pointer is null!");
1434 NS_ASSERTION(aURLStr
, "Pointer is null!");
1442 // First check to see if the PrintSettings has defined an alternate title
1443 // and use that if it did
1444 PRUnichar
* docTitleStrPS
= nsnull
;
1445 PRUnichar
* docURLStrPS
= nsnull
;
1446 if (mPrt
->mPrintSettings
) {
1447 mPrt
->mPrintSettings
->GetTitle(&docTitleStrPS
);
1448 mPrt
->mPrintSettings
->GetDocURL(&docURLStrPS
);
1450 if (docTitleStrPS
&& *docTitleStrPS
) {
1451 *aTitle
= docTitleStrPS
;
1454 if (docURLStrPS
&& *docURLStrPS
) {
1455 *aURLStr
= docURLStrPS
;
1459 if (docTitleStrPS
&& docURLStrPS
) {
1464 PRUnichar
* docTitle
;
1466 GetDocumentTitleAndURL(aPO
->mDocument
, &docTitle
, &docUrl
);
1472 nsMemory::Free(docUrl
);
1479 nsMemory::Free(docTitle
);
1480 } else if (!docTitleStrPS
) {
1482 case eDocTitleDefBlank
: *aTitle
= ToNewUnicode(EmptyString());
1485 case eDocTitleDefURLDoc
:
1487 *aTitle
= NS_strdup(*aURLStr
);
1488 } else if (mPrt
->mBrandName
) {
1489 *aTitle
= NS_strdup(mPrt
->mBrandName
);
1492 case eDocTitleDefNone
:
1493 // *aTitle defaults to nsnull
1499 //---------------------------------------------------------------------
1500 nsresult
nsPrintEngine::DocumentReadyForPrinting()
1502 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
) {
1503 CheckForChildFrameSets(mPrt
->mPrintObject
);
1507 // Send the document to the printer...
1509 nsresult rv
= SetupToPrintContent();
1510 if (NS_FAILED(rv
)) {
1511 // The print job was canceled or there was a problem
1512 // So remove all other documents from the print list
1513 DonePrintingPages(nsnull
, rv
);
1518 /** ---------------------------------------------------
1519 * Cleans up when an error occurred
1521 nsresult
nsPrintEngine::CleanupOnFailure(nsresult aResult
, PRBool aIsPrinting
)
1523 PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting
?"Printing":"Print Preview", aResult
));
1526 if (mPagePrintTimer
) {
1527 mPagePrintTimer
->Stop();
1528 NS_RELEASE(mPagePrintTimer
);
1532 SetIsPrinting(PR_FALSE
);
1534 SetIsPrintPreview(PR_FALSE
);
1535 SetIsCreatingPrintPreview(PR_FALSE
);
1538 /* cleanup done, let's fire-up an error dialog to notify the user
1539 * what went wrong...
1541 * When rv == NS_ERROR_ABORT, it means we want out of the
1542 * print job without displaying any error messages
1544 if (aResult
!= NS_ERROR_ABORT
) {
1545 ShowPrintErrorDialog(aResult
, aIsPrinting
);
1548 FirePrintCompletionEvent();
1554 //---------------------------------------------------------------------
1556 nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError
, PRBool aIsPrinting
)
1559 PR_PL(("nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError=%lx, PRBool aIsPrinting=%d)\n", (long)aPrintError
, (int)aIsPrinting
));
1561 nsCAutoString stringName
;
1565 #define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName.AssignLiteral(#nserr); break;
1566 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND
)
1567 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE
)
1568 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE
)
1569 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND
)
1570 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED
)
1571 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE
)
1572 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY
)
1573 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER
)
1574 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR
)
1575 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE
)
1576 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR
)
1577 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW
)
1578 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED
)
1579 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY
)
1580 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED
)
1581 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE
)
1582 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT
)
1583 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC
)
1584 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC
)
1585 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE
)
1586 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE
)
1587 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW
)
1588 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED
)
1589 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED
)
1590 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED
)
1591 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES
)
1592 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR
)
1593 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP
)
1594 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED
)
1595 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT
)
1596 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE
)
1597 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL
) // Temporary code for Bug 136185 / bug 240490
1598 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PLEX_NOT_SUPPORTED
)
1599 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY
)
1600 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED
)
1601 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE
)
1602 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_RESOLUTION_NOT_SUPPORTED
)
1605 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE
)
1606 #undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG
1609 PR_PL(("ShowPrintErrorDialog: stringName='%s'\n", stringName
.get()));
1611 nsXPIDLString msg
, title
;
1613 nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
1614 stringName
.get(), msg
);
1615 if (NS_FAILED(rv
)) {
1616 PR_PL(("GetLocalizedString failed\n"));
1620 rv
= nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
1621 aIsPrinting
? "print_error_dialog_title"
1622 : "printpreview_error_dialog_title",
1625 nsCOMPtr
<nsIWindowWatcher
> wwatch
= do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
1626 if (NS_FAILED(rv
)) {
1627 PR_PL(("ShowPrintErrorDialog(): wwatch==nsnull\n"));
1631 nsCOMPtr
<nsIDOMWindow
> active
;
1632 wwatch
->GetActiveWindow(getter_AddRefs(active
));
1634 nsCOMPtr
<nsIPrompt
> dialog
;
1635 /* |GetNewPrompter| allows that |active| is |nsnull|
1636 * (see bug 234982 ("nsPrintEngine::ShowPrintErrorDialog() fails in many cases")) */
1637 wwatch
->GetNewPrompter(active
, getter_AddRefs(dialog
));
1639 PR_PL(("ShowPrintErrorDialog(): dialog==nsnull\n"));
1643 dialog
->Alert(title
.get(), msg
.get());
1644 PR_PL(("ShowPrintErrorDialog(): alert displayed successfully.\n"));
1647 //-----------------------------------------------------------------
1648 //-- Section: Reflow Methods
1649 //-----------------------------------------------------------------
1651 //-------------------------------------------------------
1653 nsPrintEngine::SetupToPrintContent()
1655 // In this step we figure out which documents should be printed
1656 // i.e. if we are printing the selection then only enable that nsPrintObject
1658 if (NS_FAILED(EnablePOsForPrinting())) {
1659 return NS_ERROR_FAILURE
;
1661 DUMP_DOC_LIST("\nAfter Enable------------------------------------------");
1663 // This is an Optimization
1664 // If we are in PP then we already know all the shrinkage information
1665 // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
1667 // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
1668 // The first time we do not want to do this, the second time through we do
1669 PRBool doSetPixelScale
= PR_FALSE
;
1670 PRBool ppIsShrinkToFit
= mPrtPreview
&& mPrtPreview
->mShrinkToFit
;
1671 if (ppIsShrinkToFit
) {
1672 mPrt
->mShrinkRatio
= mPrtPreview
->mShrinkRatio
;
1673 doSetPixelScale
= PR_TRUE
;
1676 // Here we reflow all the PrintObjects
1677 nsresult rv
= ReflowDocList(mPrt
->mPrintObject
, doSetPixelScale
);
1678 if (NS_FAILED(rv
)) {
1679 return NS_ERROR_FAILURE
;
1682 // Here is where we do the extra reflow for shrinking the content
1683 // But skip this step if we are in PrintPreview
1684 if (mPrt
->mShrinkToFit
&& !ppIsShrinkToFit
) {
1685 // Now look for the PO that has the smallest percent for shrink to fit
1686 if (mPrt
->mPrintDocList
.Length() > 1 && mPrt
->mPrintObject
->mFrameType
== eFrameSet
) {
1687 nsPrintObject
* smallestPO
= FindSmallestSTF();
1688 NS_ASSERTION(smallestPO
, "There must always be an XMost PO!");
1690 // Calc the shrinkage based on the entire content area
1691 mPrt
->mShrinkRatio
= smallestPO
->mShrinkRatio
;
1694 // Single document so use the Shrink as calculated for the PO
1695 mPrt
->mShrinkRatio
= mPrt
->mPrintObject
->mShrinkRatio
;
1698 // Only Shrink if we are smaller
1699 if (mPrt
->mShrinkRatio
< 0.998f
) {
1700 // Clamp Shrink to Fit to 60%
1701 mPrt
->mShrinkRatio
= NS_MAX(mPrt
->mShrinkRatio
, 0.60f
);
1703 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
1704 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
1705 NS_ASSERTION(po
, "nsPrintObject can't be null!");
1706 // Wipe out the presentation before we reflow
1707 po
->DestroyPresentation();
1710 #if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
1711 // We need to clear all the output files here
1712 // because they will be re-created with second reflow of the docs
1713 if (kPrintingLogMod
&& kPrintingLogMod
->level
== DUMP_LAYOUT_LEVEL
) {
1714 RemoveFilesInDir(".\\");
1715 gDumpFileNameCnt
= 0;
1716 gDumpLOFileNameCnt
= 0;
1720 // Here we reflow all the PrintObjects a second time
1721 // this time using the shrinkage values
1722 // The last param here tells reflow to NOT calc the shrinkage values
1723 if (NS_FAILED(ReflowDocList(mPrt
->mPrintObject
, PR_TRUE
))) {
1724 return NS_ERROR_FAILURE
;
1730 float calcRatio
= 0.0f
;
1731 if (mPrt
->mPrintDocList
.Length() > 1 && mPrt
->mPrintObject
->mFrameType
== eFrameSet
) {
1732 nsPrintObject
* smallestPO
= FindSmallestSTF();
1733 NS_ASSERTION(smallestPO
, "There must always be an XMost PO!");
1735 // Calc the shrinkage based on the entire content area
1736 calcRatio
= smallestPO
->mShrinkRatio
;
1739 // Single document so use the Shrink as calculated for the PO
1740 calcRatio
= mPrt
->mPrintObject
->mShrinkRatio
;
1742 PR_PL(("**************************************************************************\n"));
1743 PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt
->mShrinkRatio
, calcRatio
, mPrt
->mShrinkRatio
-calcRatio
));
1744 PR_PL(("**************************************************************************\n"));
1749 DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------"));
1751 PR_PL(("-------------------------------------------------------\n"));
1754 CalcNumPrintablePages(mPrt
->mNumPrintablePages
);
1756 PR_PL(("--- Printing %d pages\n", mPrt
->mNumPrintablePages
));
1757 DUMP_DOC_TREELAYOUT
;
1759 // Print listener setup...
1760 if (mPrt
!= nsnull
) {
1761 mPrt
->OnStartPrinting();
1764 PRUnichar
* fileName
= nsnull
;
1765 // check to see if we are printing to a file
1766 PRBool isPrintToFile
= PR_FALSE
;
1767 mPrt
->mPrintSettings
->GetPrintToFile(&isPrintToFile
);
1768 if (isPrintToFile
) {
1769 // On some platforms The BeginDocument needs to know the name of the file
1770 // and it uses the PrintService to get it, so we need to set it into the PrintService here
1771 mPrt
->mPrintSettings
->GetToFileName(&fileName
);
1774 PRUnichar
* docTitleStr
;
1775 PRUnichar
* docURLStr
;
1776 GetDisplayTitleAndURL(mPrt
->mPrintObject
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
1778 PRInt32 startPage
= 1;
1779 PRInt32 endPage
= mPrt
->mNumPrintablePages
;
1781 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
1782 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
1783 if (printRangeType
== nsIPrintSettings::kRangeSpecifiedPageRange
) {
1784 mPrt
->mPrintSettings
->GetStartPageRange(&startPage
);
1785 mPrt
->mPrintSettings
->GetEndPageRange(&endPage
);
1786 if (endPage
> mPrt
->mNumPrintablePages
) {
1787 endPage
= mPrt
->mNumPrintablePages
;
1792 // BeginDocument may pass back a FAILURE code
1793 // i.e. On Windows, if you are printing to a file and hit "Cancel"
1794 // to the "File Name" dialog, this comes back as an error
1795 // Don't start printing when regression test are executed
1796 if (!mPrt
->mDebugFilePtr
&& mIsDoingPrinting
) {
1797 rv
= mPrt
->mPrintDC
->BeginDocument(docTitleStr
, fileName
, startPage
, endPage
);
1800 if (mIsCreatingPrintPreview
) {
1801 // Print Preview -- Pass ownership of docTitleStr and docURLStr
1802 // to the pageSequenceFrame, to be displayed in the header
1803 nsIPageSequenceFrame
*seqFrame
= mPrt
->mPrintObject
->mPresShell
->GetPageSequenceFrame();
1805 seqFrame
->StartPrint(mPrt
->mPrintObject
->mPresContext
,
1806 mPrt
->mPrintSettings
, docTitleStr
, docURLStr
);
1809 if (docTitleStr
) nsMemory::Free(docTitleStr
);
1810 if (docURLStr
) nsMemory::Free(docURLStr
);
1813 PR_PL(("****************** Begin Document ************************\n"));
1815 NS_ENSURE_SUCCESS(rv
, rv
);
1817 // This will print the docshell document
1818 // when it completes asynchronously in the DonePrintingPages method
1819 // it will check to see if there are more docshells to be printed and
1820 // then PrintDocContent will be called again.
1822 if (mIsDoingPrinting
) {
1823 PrintDocContent(mPrt
->mPrintObject
, rv
); // ignore return value
1829 //-------------------------------------------------------
1830 // Recursively reflow each sub-doc and then calc
1831 // all the frame locations of the sub-docs
1833 nsPrintEngine::ReflowDocList(nsPrintObject
* aPO
, PRBool aSetPixelScale
)
1835 NS_ENSURE_ARG_POINTER(aPO
);
1837 // Check to see if the subdocument's element has been hidden by the parent document
1838 if (aPO
->mParent
&& aPO
->mParent
->mPresShell
) {
1839 nsIFrame
* frame
= aPO
->mContent
->GetPrimaryFrame();
1841 if (!frame
->GetStyleVisibility()->IsVisible()) {
1842 aPO
->mDontPrint
= PR_TRUE
;
1843 aPO
->mInvisible
= PR_TRUE
;
1849 // Here is where we set the shrinkage value into the DC
1850 // and this is what actually makes it shrink
1851 if (aSetPixelScale
&& aPO
->mFrameType
!= eIFrame
) {
1853 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kFramesAsIs
|| mPrt
->mPrintFrameType
== nsIPrintSettings::kNoFrames
) {
1854 ratio
= mPrt
->mShrinkRatio
- 0.005f
; // round down
1856 ratio
= aPO
->mShrinkRatio
- 0.005f
; // round down
1858 aPO
->mZoomRatio
= ratio
;
1859 } else if (!mPrt
->mShrinkToFit
) {
1861 mPrt
->mPrintSettings
->GetScaling(&scaling
);
1862 aPO
->mZoomRatio
= float(scaling
);
1867 rv
= ReflowPrintObject(aPO
);
1868 NS_ENSURE_SUCCESS(rv
, rv
);
1870 PRInt32 cnt
= aPO
->mKids
.Length();
1871 for (PRInt32 i
=0;i
<cnt
;i
++) {
1872 rv
= ReflowDocList(aPO
->mKids
[i
], aSetPixelScale
);
1873 NS_ENSURE_SUCCESS(rv
, rv
);
1878 //-------------------------------------------------------
1879 // Reflow a nsPrintObject
1881 nsPrintEngine::ReflowPrintObject(nsPrintObject
* aPO
)
1883 NS_ASSERTION(aPO
, "Pointer is null!");
1884 if (!aPO
) return NS_ERROR_FAILURE
;
1887 PRBool documentIsTopLevel
;
1888 nsIFrame
* frame
= nsnull
;
1889 if (!aPO
->IsPrintable())
1892 if (aPO
->mParent
&& aPO
->mParent
->IsPrintable()) {
1893 frame
= aPO
->mContent
->GetPrimaryFrame();
1894 // Without a frame, this document can't be displayed; therefore, there is no
1895 // point to reflowing it
1897 SetPrintPO(aPO
, PR_FALSE
);
1901 adjSize
= frame
->GetContentRect().Size();
1902 documentIsTopLevel
= PR_FALSE
;
1903 // presshell exists because parent is printable
1905 nscoord pageWidth
, pageHeight
;
1906 mPrt
->mPrintDC
->GetDeviceSurfaceDimensions(pageWidth
, pageHeight
);
1907 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1908 // If we're in landscape mode on Linux, the device surface will have
1909 // been rotated, so for the purposes of reflowing content, we'll
1910 // treat device's height as our width and its width as our height,
1911 PRInt32 orientation
;
1912 mPrt
->mPrintSettings
->GetOrientation(&orientation
);
1913 if (nsIPrintSettings::kLandscapeOrientation
== orientation
) {
1914 adjSize
= nsSize(pageHeight
, pageWidth
);
1916 adjSize
= nsSize(pageWidth
, pageHeight
);
1919 adjSize
= nsSize(pageWidth
, pageHeight
);
1920 #endif // XP_UNIX && !XP_MACOSX
1921 documentIsTopLevel
= PR_TRUE
;
1924 // Here we decide whether we need scrollbars and
1925 // what the parent will be of the widget
1926 // How this logic presently works: Print Preview is always as-is (as far
1927 // as I can tell; not sure how it would work in other cases); only the root
1928 // is not eIFrame or eFrame. The child documents get a parent widget from
1929 // logic in nsFrameFrame. In any case, a child widget is created for the root
1930 // view of the document.
1931 PRBool canCreateScrollbars
= PR_TRUE
;
1932 nsIView
* parentView
= nsnull
;
1933 // the top nsPrintObject's widget will always have scrollbars
1934 if (frame
&& frame
->GetType() == nsGkAtoms::subDocumentFrame
) {
1935 nsIView
* view
= frame
->GetView();
1936 NS_ENSURE_TRUE(view
, NS_ERROR_FAILURE
);
1937 view
= view
->GetFirstChild();
1938 NS_ENSURE_TRUE(view
, NS_ERROR_FAILURE
);
1940 canCreateScrollbars
= PR_FALSE
;
1943 NS_ASSERTION(!aPO
->mPresContext
, "Recreating prescontext");
1945 // create the PresContext
1946 aPO
->mPresContext
= new nsRootPresContext(aPO
->mDocument
,
1947 mIsCreatingPrintPreview
? nsPresContext::eContext_PrintPreview
:
1948 nsPresContext::eContext_Print
);
1949 NS_ENSURE_TRUE(aPO
->mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
1950 aPO
->mPresContext
->SetPrintSettings(mPrt
->mPrintSettings
);
1952 // set the presentation context to the value in the print settings
1953 PRBool printBGColors
;
1954 mPrt
->mPrintSettings
->GetPrintBGColors(&printBGColors
);
1955 aPO
->mPresContext
->SetBackgroundColorDraw(printBGColors
);
1956 mPrt
->mPrintSettings
->GetPrintBGImages(&printBGColors
);
1957 aPO
->mPresContext
->SetBackgroundImageDraw(printBGColors
);
1959 // init it with the DC
1960 nsresult rv
= aPO
->mPresContext
->Init(mPrt
->mPrintDC
);
1961 NS_ENSURE_SUCCESS(rv
, rv
);
1963 aPO
->mViewManager
= do_CreateInstance(kViewManagerCID
, &rv
);
1964 NS_ENSURE_SUCCESS(rv
,rv
);
1966 rv
= aPO
->mViewManager
->Init(mPrt
->mPrintDC
);
1967 NS_ENSURE_SUCCESS(rv
,rv
);
1969 nsStyleSet
* styleSet
;
1970 rv
= mDocViewerPrint
->CreateStyleSet(aPO
->mDocument
, &styleSet
);
1971 NS_ENSURE_SUCCESS(rv
, rv
);
1973 rv
= aPO
->mDocument
->CreateShell(aPO
->mPresContext
, aPO
->mViewManager
,
1974 styleSet
, getter_AddRefs(aPO
->mPresShell
));
1975 if (NS_FAILED(rv
)) {
1980 styleSet
->EndUpdate();
1982 // The pres shell now owns the style set object.
1984 PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO
,
1985 gFrameTypesStr
[aPO
->mFrameType
], adjSize
.width
, adjSize
.height
));
1987 // Create a child window of the parent that is our "root view/window"
1988 nsRect tbounds
= nsRect(nsPoint(0, 0), adjSize
);
1989 nsIView
* rootView
= aPO
->mViewManager
->CreateView(tbounds
, parentView
);
1990 NS_ENSURE_TRUE(rootView
, NS_ERROR_OUT_OF_MEMORY
);
1992 // Only create a widget for print preview; when printing, a widget is
1993 // unnecessary and unexpected
1994 // Also, no widget should be needed except for the top-level document
1995 if (mIsCreatingPrintPreview
&& documentIsTopLevel
) {
1996 nsNativeWidget widget
= nsnull
;
1998 widget
= mParentWidget
->GetNativeData(NS_NATIVE_WIDGET
);
1999 rv
= rootView
->CreateWidget(kWidgetCID
, nsnull
,
2000 widget
, PR_TRUE
, PR_TRUE
,
2001 eContentTypeContent
);
2002 NS_ENSURE_SUCCESS(rv
, rv
);
2003 aPO
->mWindow
= rootView
->GetWidget();
2004 aPO
->mPresContext
->SetPaginatedScrolling(canCreateScrollbars
);
2007 // Setup hierarchical relationship in view manager
2008 aPO
->mViewManager
->SetRootView(rootView
);
2010 // This docshell stuff is weird; will go away when we stop having multiple
2011 // presentations per document
2012 nsCOMPtr
<nsISupports
> supps(do_QueryInterface(aPO
->mDocShell
));
2013 aPO
->mPresContext
->SetContainer(supps
);
2015 aPO
->mPresShell
->BeginObservingDocument();
2017 aPO
->mPresContext
->SetPageSize(adjSize
);
2018 aPO
->mPresContext
->SetIsRootPaginatedDocument(documentIsTopLevel
);
2019 aPO
->mPresContext
->SetPageScale(aPO
->mZoomRatio
);
2020 // Calculate scale factor from printer to screen
2021 float printDPI
= float(mPrt
->mPrintDC
->AppUnitsPerInch()) /
2022 float(mPrt
->mPrintDC
->AppUnitsPerDevPixel());
2023 aPO
->mPresContext
->SetPrintPreviewScale(mScreenDPI
/ printDPI
);
2025 if (mIsCreatingPrintPreview
&& documentIsTopLevel
) {
2026 mDocViewerPrint
->SetPrintPreviewPresentation(aPO
->mWindow
,
2032 rv
= aPO
->mPresShell
->InitialReflow(adjSize
.width
, adjSize
.height
);
2034 NS_ENSURE_SUCCESS(rv
, rv
);
2035 NS_ASSERTION(aPO
->mPresShell
, "Presshell should still be here");
2037 // Process the reflow event InitialReflow posted
2038 aPO
->mPresShell
->FlushPendingNotifications(Flush_Layout
);
2040 nsCOMPtr
<nsIPresShell
> displayShell
;
2041 aPO
->mDocShell
->GetPresShell(getter_AddRefs(displayShell
));
2042 // Transfer Selection Ranges to the new Print PresShell
2043 nsCOMPtr
<nsISelection
> selection
, selectionPS
;
2044 // It's okay if there is no display shell, just skip copying the selection
2046 selection
= displayShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2048 selectionPS
= aPO
->mPresShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2049 if (selection
&& selectionPS
) {
2051 selection
->GetRangeCount(&cnt
);
2053 for (inx
=0;inx
<cnt
;inx
++) {
2054 nsCOMPtr
<nsIDOMRange
> range
;
2055 if (NS_SUCCEEDED(selection
->GetRangeAt(inx
, getter_AddRefs(range
))))
2056 selectionPS
->AddRange(range
);
2060 // If we are trying to shrink the contents to fit on the page
2061 // we must first locate the "pageContent" frame
2062 // Then we walk the frame tree and look for the "xmost" frame
2063 // this is the frame where the right-hand side of the frame extends
2065 if (mPrt
->mShrinkToFit
&& documentIsTopLevel
) {
2066 nsIPageSequenceFrame
* pageSequence
= aPO
->mPresShell
->GetPageSequenceFrame();
2067 NS_ENSURE_STATE(pageSequence
);
2068 pageSequence
->GetSTFPercent(aPO
->mShrinkRatio
);
2071 #ifdef EXTENDED_DEBUG_PRINTING
2072 if (kPrintingLogMod
&& kPrintingLogMod
->level
== DUMP_LAYOUT_LEVEL
) {
2075 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
2077 sprintf(filename
, "print_dump_%d.txt", gDumpFileNameCnt
++);
2078 // Dump all the frames and view to a a file
2079 FILE * fd
= fopen(filename
, "w");
2081 nsIFrame
*theRootFrame
=
2082 aPO
->mPresShell
->FrameManager()->GetRootFrame();
2083 fprintf(fd
, "Title: %s\n", docStr
?docStr
:"");
2084 fprintf(fd
, "URL: %s\n", urlStr
?urlStr
:"");
2085 fprintf(fd
, "--------------- Frames ----------------\n");
2086 nsCOMPtr
<nsIRenderingContext
> renderingContext
;
2087 mPrt
->mPrintDocDC
->CreateRenderingContext(*getter_AddRefs(renderingContext
));
2088 RootFrameList(aPO
->mPresContext
, fd
, 0);
2089 //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0);
2090 fprintf(fd
, "---------------------------------------\n\n");
2091 fprintf(fd
, "--------------- Views From Root Frame----------------\n");
2092 nsIView
* v
= theRootFrame
->GetView();
2096 printf("View is null!\n");
2099 fprintf(fd
, "--------------- All Views ----------------\n");
2100 DumpViews(docShell
, fd
);
2101 fprintf(fd
, "---------------------------------------\n\n");
2105 if (docStr
) nsMemory::Free(docStr
);
2106 if (urlStr
) nsMemory::Free(urlStr
);
2113 //-------------------------------------------------------
2114 // Figure out how many documents and how many total pages we are printing
2116 nsPrintEngine::CalcNumPrintablePages(PRInt32
& aNumPages
)
2119 // Count the number of printable documents
2120 // and printable pages
2121 for (PRUint32 i
=0; i
<mPrt
->mPrintDocList
.Length(); i
++) {
2122 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
2123 NS_ASSERTION(po
, "nsPrintObject can't be null!");
2124 if (po
->mPresContext
&& po
->mPresContext
->IsRootPaginatedDocument()) {
2125 nsIPageSequenceFrame
* pageSequence
= po
->mPresShell
->GetPageSequenceFrame();
2126 nsIFrame
* seqFrame
= do_QueryFrame(pageSequence
);
2128 nsIFrame
* frame
= seqFrame
->GetFirstChild(nsnull
);
2131 frame
= frame
->GetNextSibling();
2137 //-----------------------------------------------------------------
2138 //-- Done: Reflow Methods
2139 //-----------------------------------------------------------------
2141 //-----------------------------------------------------------------
2142 //-- Section: Printing Methods
2143 //-----------------------------------------------------------------
2145 //-------------------------------------------------------
2146 // Called for each DocShell that needs to be printed
2148 nsPrintEngine::PrintDocContent(nsPrintObject
* aPO
, nsresult
& aStatus
)
2150 NS_ASSERTION(aPO
, "Pointer is null!");
2153 if (!aPO
->mHasBeenPrinted
&& aPO
->IsPrintable()) {
2154 aStatus
= DoPrint(aPO
);
2158 // If |aPO->mPrintAsIs| and |aPO->mHasBeenPrinted| are true,
2159 // the kids frames are already processed in |PrintPage|.
2160 if (!aPO
->mInvisible
&& !(aPO
->mPrintAsIs
&& aPO
->mHasBeenPrinted
)) {
2161 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
2162 nsPrintObject
* po
= aPO
->mKids
[i
];
2163 PRBool printed
= PrintDocContent(po
, aStatus
);
2164 if (printed
|| NS_FAILED(aStatus
)) {
2172 static already_AddRefed
<nsIDOMNode
>
2173 GetEqualNodeInCloneTree(nsIDOMNode
* aNode
, nsIDocument
* aDoc
)
2175 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aNode
);
2176 // Selections in anonymous subtrees aren't supported.
2177 if (content
&& content
->IsInAnonymousSubtree()) {
2181 nsCOMPtr
<nsINode
> node
= do_QueryInterface(aNode
);
2182 NS_ENSURE_TRUE(node
, nsnull
);
2184 nsTArray
<PRInt32
> indexArray
;
2185 nsINode
* current
= node
;
2186 NS_ENSURE_TRUE(current
, nsnull
);
2188 nsINode
* parent
= current
->GetNodeParent();
2192 PRInt32 index
= parent
->IndexOf(current
);
2193 NS_ENSURE_TRUE(index
>= 0, nsnull
);
2194 indexArray
.AppendElement(index
);
2197 NS_ENSURE_TRUE(current
->IsNodeOfType(nsINode::eDOCUMENT
), nsnull
);
2200 for (PRInt32 i
= indexArray
.Length() - 1; i
>= 0; --i
) {
2201 current
= current
->GetChildAt(indexArray
[i
]);
2202 NS_ENSURE_TRUE(current
, nsnull
);
2204 nsCOMPtr
<nsIDOMNode
> result
= do_QueryInterface(current
);
2205 return result
.forget();
2208 static nsresult
CloneRangeToSelection(nsIDOMRange
* aRange
,
2210 nsISelection
* aSelection
)
2212 PRBool collapsed
= PR_FALSE
;
2213 aRange
->GetCollapsed(&collapsed
);
2218 nsCOMPtr
<nsIDOMNode
> startContainer
, endContainer
;
2219 PRInt32 startOffset
= -1, endOffset
= -1;
2220 aRange
->GetStartContainer(getter_AddRefs(startContainer
));
2221 aRange
->GetStartOffset(&startOffset
);
2222 aRange
->GetEndContainer(getter_AddRefs(endContainer
));
2223 aRange
->GetEndOffset(&endOffset
);
2224 NS_ENSURE_STATE(startContainer
&& endContainer
);
2226 nsCOMPtr
<nsIDOMNode
> newStart
= GetEqualNodeInCloneTree(startContainer
, aDoc
);
2227 nsCOMPtr
<nsIDOMNode
> newEnd
= GetEqualNodeInCloneTree(endContainer
, aDoc
);
2228 NS_ENSURE_STATE(newStart
&& newEnd
);
2230 nsCOMPtr
<nsIDOMRange
> range
;
2231 NS_NewRange(getter_AddRefs(range
));
2232 NS_ENSURE_TRUE(range
, NS_ERROR_OUT_OF_MEMORY
);
2234 nsresult rv
= range
->SetStart(newStart
, startOffset
);
2235 NS_ENSURE_SUCCESS(rv
, rv
);
2236 rv
= range
->SetEnd(newEnd
, endOffset
);
2237 NS_ENSURE_SUCCESS(rv
, rv
);
2239 return aSelection
->AddRange(range
);
2242 static nsresult
CloneSelection(nsIDocument
* aOrigDoc
, nsIDocument
* aDoc
)
2244 nsIPresShell
* origShell
= aOrigDoc
->GetPrimaryShell();
2245 nsIPresShell
* shell
= aDoc
->GetPrimaryShell();
2246 NS_ENSURE_STATE(origShell
&& shell
);
2248 nsCOMPtr
<nsISelection
> origSelection
=
2249 origShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2250 nsCOMPtr
<nsISelection
> selection
=
2251 shell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2252 NS_ENSURE_STATE(origSelection
&& selection
);
2254 PRInt32 rangeCount
= 0;
2255 origSelection
->GetRangeCount(&rangeCount
);
2256 for (PRInt32 i
= 0; i
< rangeCount
; ++i
) {
2257 nsCOMPtr
<nsIDOMRange
> range
;
2258 origSelection
->GetRangeAt(i
, getter_AddRefs(range
));
2260 CloneRangeToSelection(range
, aDoc
, selection
);
2266 //-------------------------------------------------------
2268 nsPrintEngine::DoPrint(nsPrintObject
* aPO
)
2271 PR_PL(("**************************** %s ****************************\n", gFrameTypesStr
[aPO
->mFrameType
]));
2272 PR_PL(("****** In DV::DoPrint PO: %p \n", aPO
));
2274 nsIPresShell
* poPresShell
= aPO
->mPresShell
;
2275 nsPresContext
* poPresContext
= aPO
->mPresContext
;
2277 NS_ASSERTION(poPresContext
, "PrintObject has not been reflowed");
2278 NS_ASSERTION(poPresContext
->Type() != nsPresContext::eContext_PrintPreview
,
2279 "How did this context end up here?");
2281 if (mPrt
->mPrintProgressParams
) {
2282 SetDocAndURLIntoProgress(aPO
, mPrt
->mPrintProgressParams
);
2286 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
2288 if (mPrt
->mPrintSettings
!= nsnull
) {
2289 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
2292 // Ask the page sequence frame to print all the pages
2293 nsIPageSequenceFrame
* pageSequence
= poPresShell
->GetPageSequenceFrame();
2294 NS_ASSERTION(nsnull
!= pageSequence
, "no page sequence frame");
2296 // We are done preparing for printing, so we can turn this off
2297 mPrt
->mPreparingForPrint
= PR_FALSE
;
2299 // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging
2300 if (nsnull
!= mPrt
->mDebugFilePtr
) {
2302 // output the regression test
2303 nsIFrame
* root
= poPresShell
->FrameManager()->GetRootFrame();
2304 root
->DumpRegressionData(poPresContext
, mPrt
->mDebugFilePtr
, 0);
2305 fclose(mPrt
->mDebugFilePtr
);
2306 SetIsPrinting(PR_FALSE
);
2309 #ifdef EXTENDED_DEBUG_PRINTING
2310 nsIFrame
* rootFrame
= poPresShell
->FrameManager()->GetRootFrame();
2311 if (aPO
->IsPrintable()) {
2314 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
2315 DumpLayoutData(docStr
, urlStr
, poPresContext
, mPrt
->mPrintDocDC
, rootFrame
, docShell
, nsnull
);
2316 if (docStr
) nsMemory::Free(docStr
);
2317 if (urlStr
) nsMemory::Free(urlStr
);
2321 if (mPrt
->mPrintSettings
) {
2322 PRUnichar
* docTitleStr
= nsnull
;
2323 PRUnichar
* docURLStr
= nsnull
;
2325 GetDisplayTitleAndURL(aPO
, &docTitleStr
, &docURLStr
, eDocTitleDefBlank
);
2327 if (nsIPrintSettings::kRangeSelection
== printRangeType
) {
2328 CloneSelection(aPO
->mDocument
->GetOriginalDocument(), aPO
->mDocument
);
2330 poPresContext
->SetIsRenderingOnlySelection(PR_TRUE
);
2331 // temporarily creating rendering context
2332 // which is needed to dinf the selection frames
2333 nsCOMPtr
<nsIRenderingContext
> rc
;
2334 mPrt
->mPrintDC
->CreateRenderingContext(*getter_AddRefs(rc
));
2336 // find the starting and ending page numbers
2337 // via the selection
2338 nsIFrame
* startFrame
;
2340 PRInt32 startPageNum
;
2345 nsCOMPtr
<nsISelection
> selectionPS
;
2346 selectionPS
= poPresShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2348 rv
= GetPageRangeForSelection(poPresShell
, poPresContext
, *rc
, selectionPS
, pageSequence
,
2349 &startFrame
, startPageNum
, startRect
,
2350 &endFrame
, endPageNum
, endRect
);
2351 if (NS_SUCCEEDED(rv
)) {
2352 mPrt
->mPrintSettings
->SetStartPageRange(startPageNum
);
2353 mPrt
->mPrintSettings
->SetEndPageRange(endPageNum
);
2354 nsIntMargin
marginTwips(0,0,0,0);
2355 nsIntMargin
unwrtMarginTwips(0,0,0,0);
2356 mPrt
->mPrintSettings
->GetMarginInTwips(marginTwips
);
2357 mPrt
->mPrintSettings
->GetUnwriteableMarginInTwips(unwrtMarginTwips
);
2358 nsMargin totalMargin
= poPresContext
->TwipsToAppUnits(marginTwips
+
2360 if (startPageNum
== endPageNum
) {
2362 startRect
.y
-= totalMargin
.top
;
2363 endRect
.y
-= totalMargin
.top
;
2365 // Clip out selection regions above the top of the first page
2366 if (startRect
.y
< 0) {
2367 // Reduce height to be the height of the positive-territory
2368 // region of original rect
2369 startRect
.height
= NS_MAX(0, startRect
.YMost());
2372 if (endRect
.y
< 0) {
2373 // Reduce height to be the height of the positive-territory
2374 // region of original rect
2375 endRect
.height
= NS_MAX(0, endRect
.YMost());
2378 NS_ASSERTION(endRect
.y
>= startRect
.y
,
2379 "Selection end point should be after start point");
2380 NS_ASSERTION(startRect
.height
>= 0,
2381 "rect should have non-negative height.");
2382 NS_ASSERTION(endRect
.height
>= 0,
2383 "rect should have non-negative height.");
2385 nscoord selectionHgt
= endRect
.y
+ endRect
.height
- startRect
.y
;
2386 // XXX This is temporary fix for printing more than one page of a selection
2387 pageSequence
->SetSelectionHeight(startRect
.y
* aPO
->mZoomRatio
,
2388 selectionHgt
* aPO
->mZoomRatio
);
2390 // calc total pages by getting calculating the selection's height
2391 // and then dividing it by how page content frames will fit.
2392 nscoord pageWidth
, pageHeight
;
2393 mPrt
->mPrintDC
->GetDeviceSurfaceDimensions(pageWidth
, pageHeight
);
2394 pageHeight
-= totalMargin
.top
+ totalMargin
.bottom
;
2395 PRInt32 totalPages
= NSToIntCeil(float(selectionHgt
) * aPO
->mZoomRatio
/ float(pageHeight
));
2396 pageSequence
->SetTotalNumPages(totalPages
);
2402 nsIFrame
* seqFrame
= do_QueryFrame(pageSequence
);
2404 SetIsPrinting(PR_FALSE
);
2405 return NS_ERROR_FAILURE
;
2408 mPageSeqFrame
= pageSequence
;
2409 mPageSeqFrame
->StartPrint(poPresContext
, mPrt
->mPrintSettings
, docTitleStr
, docURLStr
);
2411 // Schedule Page to Print
2412 PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO
, gFrameTypesStr
[aPO
->mFrameType
]));
2413 StartPagePrintTimer(aPO
);
2415 // not sure what to do here!
2416 SetIsPrinting(PR_FALSE
);
2417 return NS_ERROR_FAILURE
;
2425 //---------------------------------------------------------------------
2427 nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject
* aPO
,
2428 nsIPrintProgressParams
* aParams
)
2430 NS_ASSERTION(aPO
, "Must have vaild nsPrintObject");
2431 NS_ASSERTION(aParams
, "Must have vaild nsIPrintProgressParams");
2433 if (!aPO
|| !aPO
->mDocShell
|| !aParams
) {
2436 const PRUint32 kTitleLength
= 64;
2438 PRUnichar
* docTitleStr
;
2439 PRUnichar
* docURLStr
;
2440 GetDisplayTitleAndURL(aPO
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
2442 // Make sure the Titles & URLS don't get too long for the progress dialog
2443 ElipseLongString(docTitleStr
, kTitleLength
, PR_FALSE
);
2444 ElipseLongString(docURLStr
, kTitleLength
, PR_TRUE
);
2446 aParams
->SetDocTitle(docTitleStr
);
2447 aParams
->SetDocURL(docURLStr
);
2449 if (docTitleStr
!= nsnull
) nsMemory::Free(docTitleStr
);
2450 if (docURLStr
!= nsnull
) nsMemory::Free(docURLStr
);
2453 //---------------------------------------------------------------------
2455 nsPrintEngine::ElipseLongString(PRUnichar
*& aStr
, const PRUint32 aLen
, PRBool aDoFront
)
2457 // Make sure the URLS don't get too long for the progress dialog
2458 if (aStr
&& nsCRT::strlen(aStr
) > aLen
) {
2460 PRUnichar
* ptr
= &aStr
[nsCRT::strlen(aStr
)-aLen
+3];
2461 nsAutoString newStr
;
2462 newStr
.AppendLiteral("...");
2464 nsMemory::Free(aStr
);
2465 aStr
= ToNewUnicode(newStr
);
2467 nsAutoString
newStr(aStr
);
2468 newStr
.SetLength(aLen
-3);
2469 newStr
.AppendLiteral("...");
2470 nsMemory::Free(aStr
);
2471 aStr
= ToNewUnicode(newStr
);
2476 //-------------------------------------------------------
2478 nsPrintEngine::PrintPage(nsPrintObject
* aPO
,
2481 NS_ASSERTION(aPO
, "aPO is null!");
2482 NS_ASSERTION(mPageSeqFrame
, "mPageSeqFrame is null!");
2483 NS_ASSERTION(mPrt
, "mPrt is null!");
2485 // Although these should NEVER be NULL
2486 // This is added insurance, to make sure we don't crash in optimized builds
2487 if (!mPrt
|| !aPO
|| !mPageSeqFrame
) {
2488 ShowPrintErrorDialog(NS_ERROR_FAILURE
);
2489 return PR_TRUE
; // means we are done printing
2492 PR_PL(("-----------------------------------\n"));
2493 PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO
, gFrameTypesStr
[aPO
->mFrameType
]));
2495 // Check setting to see if someone request it be cancelled
2496 PRBool isCancelled
= PR_FALSE
;
2497 mPrt
->mPrintSettings
->GetIsCancelled(&isCancelled
);
2501 PRInt32 pageNum
, numPages
, endPage
;
2502 mPageSeqFrame
->GetCurrentPageNum(&pageNum
);
2503 mPageSeqFrame
->GetNumPages(&numPages
);
2505 PRBool donePrinting
;
2506 PRBool isDoingPrintRange
;
2507 mPageSeqFrame
->IsDoingPrintRange(&isDoingPrintRange
);
2508 if (isDoingPrintRange
) {
2511 mPageSeqFrame
->GetPrintRange(&fromPage
, &toPage
);
2513 if (fromPage
> numPages
) {
2516 if (toPage
> numPages
) {
2520 PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum
, fromPage
, toPage
));
2522 donePrinting
= pageNum
>= toPage
;
2523 aInRange
= pageNum
>= fromPage
&& pageNum
<= toPage
;
2524 endPage
= (toPage
- fromPage
)+1;
2526 PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum
, numPages
));
2528 donePrinting
= pageNum
>= numPages
;
2533 // XXX This is wrong, but the actual behavior in the presence of a print
2535 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
)
2536 endPage
= mPrt
->mNumPrintablePages
;
2538 mPrt
->DoOnProgressChange(++mPrt
->mNumPagesPrinted
, endPage
, PR_FALSE
, 0);
2541 // if a print job was cancelled externally, an EndPage or BeginPage may
2542 // fail and the failure is passed back here.
2543 // Returning PR_TRUE means we are done printing.
2545 // When rv == NS_ERROR_ABORT, it means we want out of the
2546 // print job without displaying any error messages
2547 nsresult rv
= mPageSeqFrame
->PrintNextPage();
2548 if (NS_FAILED(rv
)) {
2549 if (rv
!= NS_ERROR_ABORT
) {
2550 ShowPrintErrorDialog(rv
);
2551 mPrt
->mIsAborted
= PR_TRUE
;
2556 mPageSeqFrame
->DoPageEnd();
2558 return donePrinting
;
2561 /** ---------------------------------------------------
2562 * Find by checking frames type
2565 nsPrintEngine::FindSelectionBoundsWithList(nsPresContext
* aPresContext
,
2566 nsIRenderingContext
& aRC
,
2568 nsIFrame
* aParentFrame
,
2570 nsIFrame
*& aStartFrame
,
2572 nsIFrame
*& aEndFrame
,
2575 NS_ASSERTION(aPresContext
, "Pointer is null!");
2576 NS_ASSERTION(aParentFrame
, "Pointer is null!");
2578 nsIFrame
* child
= aParentFrame
->GetFirstChild(aList
);
2579 aRect
+= aParentFrame
->GetPosition();
2581 // only leaf frames have this bit flipped
2582 // then check the hard way
2583 PRBool isSelected
= (child
->GetStateBits() & NS_FRAME_SELECTED_CONTENT
)
2584 == NS_FRAME_SELECTED_CONTENT
;
2586 isSelected
= child
->IsVisibleForPainting();
2590 nsRect r
= child
->GetRect();
2591 if (aStartFrame
== nsnull
) {
2592 aStartFrame
= child
;
2593 aStartRect
.SetRect(aRect
.x
+ r
.x
, aRect
.y
+ r
.y
, r
.width
, r
.height
);
2596 aEndRect
.SetRect(aRect
.x
+ r
.x
, aRect
.y
+ r
.y
, r
.width
, r
.height
);
2599 FindSelectionBounds(aPresContext
, aRC
, child
, aRect
, aStartFrame
, aStartRect
, aEndFrame
, aEndRect
);
2600 child
= child
->GetNextSibling();
2602 aRect
-= aParentFrame
->GetPosition();
2606 //-------------------------------------------------------
2607 // Find the Frame that is XMost
2609 nsPrintEngine::FindSelectionBounds(nsPresContext
* aPresContext
,
2610 nsIRenderingContext
& aRC
,
2611 nsIFrame
* aParentFrame
,
2613 nsIFrame
*& aStartFrame
,
2615 nsIFrame
*& aEndFrame
,
2618 NS_ASSERTION(aPresContext
, "Pointer is null!");
2619 NS_ASSERTION(aParentFrame
, "Pointer is null!");
2621 // loop through named child lists
2622 nsIAtom
* childListName
= nsnull
;
2623 PRInt32 childListIndex
= 0;
2625 nsresult rv
= FindSelectionBoundsWithList(aPresContext
, aRC
, childListName
, aParentFrame
, aRect
, aStartFrame
, aStartRect
, aEndFrame
, aEndRect
);
2626 NS_ENSURE_SUCCESS(rv
, rv
);
2627 childListName
= aParentFrame
->GetAdditionalChildListName(childListIndex
++);
2628 } while (childListName
);
2632 /** ---------------------------------------------------
2633 * This method finds the starting and ending page numbers
2634 * of the selection and also returns rect for each where
2635 * the x,y of the rect is relative to the very top of the
2636 * frame tree (absolutely positioned)
2639 nsPrintEngine::GetPageRangeForSelection(nsIPresShell
* aPresShell
,
2640 nsPresContext
* aPresContext
,
2641 nsIRenderingContext
& aRC
,
2642 nsISelection
* aSelection
,
2643 nsIPageSequenceFrame
* aPageSeqFrame
,
2644 nsIFrame
** aStartFrame
,
2645 PRInt32
& aStartPageNum
,
2647 nsIFrame
** aEndFrame
,
2648 PRInt32
& aEndPageNum
,
2651 NS_ASSERTION(aPresShell
, "Pointer is null!");
2652 NS_ASSERTION(aPresContext
, "Pointer is null!");
2653 NS_ASSERTION(aSelection
, "Pointer is null!");
2654 NS_ASSERTION(aPageSeqFrame
, "Pointer is null!");
2655 NS_ASSERTION(aStartFrame
, "Pointer is null!");
2656 NS_ASSERTION(aEndFrame
, "Pointer is null!");
2658 nsIFrame
* seqFrame
= do_QueryFrame(aPageSeqFrame
);
2660 return NS_ERROR_FAILURE
;
2663 nsIFrame
* startFrame
= nsnull
;
2664 nsIFrame
* endFrame
= nsnull
;
2666 // start out with the sequence frame and search the entire frame tree
2667 // capturing the starting and ending child frames of the selection
2669 nsRect r
= seqFrame
->GetRect();
2670 FindSelectionBounds(aPresContext
, aRC
, seqFrame
, r
,
2671 startFrame
, aStartRect
, endFrame
, aEndRect
);
2674 printf("Start Frame: %p\n", startFrame
);
2675 printf("End Frame: %p\n", endFrame
);
2678 // initial the page numbers here
2679 // in case we don't find and frames
2683 nsIFrame
* startPageFrame
;
2684 nsIFrame
* endPageFrame
;
2686 // check to make sure we found a starting frame
2687 if (startFrame
!= nsnull
) {
2688 // Now search up the tree to find what page the
2689 // start/ending selections frames are on
2691 // Check to see if start should be same as end if
2692 // the end frame comes back null
2693 if (endFrame
== nsnull
) {
2694 // XXX the "GetPageFrame" step could be integrated into
2695 // the FindSelectionBounds step, but walking up to find
2696 // the parent of a child frame isn't expensive and it makes
2697 // FindSelectionBounds a little easier to understand
2698 startPageFrame
= nsLayoutUtils::GetPageFrame(startFrame
);
2699 endPageFrame
= startPageFrame
;
2700 aEndRect
= aStartRect
;
2702 startPageFrame
= nsLayoutUtils::GetPageFrame(startFrame
);
2703 endPageFrame
= nsLayoutUtils::GetPageFrame(endFrame
);
2706 return NS_ERROR_FAILURE
;
2710 printf("Start Page: %p\n", startPageFrame
);
2711 printf("End Page: %p\n", endPageFrame
);
2713 // dump all the pages and their pointers
2715 PRInt32 pageNum
= 1;
2716 nsIFrame
* child
= seqFrame
->GetFirstChild(nsnull
);
2717 while (child
!= nsnull
) {
2718 printf("Page: %d - %p\n", pageNum
, child
);
2720 child
= child
->GetNextSibling();
2725 // Now that we have the page frames
2726 // find out what the page numbers are for each frame
2727 PRInt32 pageNum
= 1;
2728 nsIFrame
* page
= seqFrame
->GetFirstChild(nsnull
);
2729 while (page
!= nsnull
) {
2730 if (page
== startPageFrame
) {
2731 aStartPageNum
= pageNum
;
2733 if (page
== endPageFrame
) {
2734 aEndPageNum
= pageNum
;
2737 page
= page
->GetNextSibling();
2741 printf("Start Page No: %d\n", aStartPageNum
);
2742 printf("End Page No: %d\n", aEndPageNum
);
2745 *aStartFrame
= startPageFrame
;
2746 *aEndFrame
= endPageFrame
;
2751 //-----------------------------------------------------------------
2752 //-- Done: Printing Methods
2753 //-----------------------------------------------------------------
2756 //-----------------------------------------------------------------
2757 //-- Section: Misc Support Methods
2758 //-----------------------------------------------------------------
2760 //---------------------------------------------------------------------
2761 void nsPrintEngine::SetIsPrinting(PRBool aIsPrinting
)
2763 mIsDoingPrinting
= aIsPrinting
;
2764 // Calling SetIsPrinting while in print preview confuses the document viewer
2765 // This is safe because we prevent exiting print preview while printing
2766 if (mDocViewerPrint
&& !mIsDoingPrintPreview
) {
2767 mDocViewerPrint
->SetIsPrinting(aIsPrinting
);
2769 if (mPrt
&& aIsPrinting
) {
2770 mPrt
->mPreparingForPrint
= PR_TRUE
;
2774 //---------------------------------------------------------------------
2775 void nsPrintEngine::SetIsPrintPreview(PRBool aIsPrintPreview
)
2777 mIsDoingPrintPreview
= aIsPrintPreview
;
2779 if (mDocViewerPrint
) {
2780 mDocViewerPrint
->SetIsPrintPreview(aIsPrintPreview
);
2784 //---------------------------------------------------------------------
2786 nsPrintEngine::CleanupDocTitleArray(PRUnichar
**& aArray
, PRInt32
& aCount
)
2788 for (PRInt32 i
= aCount
- 1; i
>= 0; i
--) {
2789 nsMemory::Free(aArray
[i
]);
2791 nsMemory::Free(aArray
);
2796 //---------------------------------------------------------------------
2798 PRBool
nsPrintEngine::HasFramesetChild(nsIContent
* aContent
)
2804 PRUint32 numChildren
= aContent
->GetChildCount();
2806 // do a breadth search across all siblings
2807 for (PRUint32 i
= 0; i
< numChildren
; ++i
) {
2808 nsIContent
*child
= aContent
->GetChildAt(i
);
2809 if (child
->Tag() == nsGkAtoms::frameset
&&
2820 /** ---------------------------------------------------
2821 * Get the Focused Frame for a documentviewer
2823 already_AddRefed
<nsIDOMWindow
>
2824 nsPrintEngine::FindFocusedDOMWindow()
2826 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
2827 NS_ENSURE_TRUE(fm
, nsnull
);
2829 nsCOMPtr
<nsPIDOMWindow
> window(mDocument
->GetWindow());
2830 NS_ENSURE_TRUE(window
, nsnull
);
2832 nsCOMPtr
<nsPIDOMWindow
> rootWindow
= window
->GetPrivateRoot();
2833 NS_ENSURE_TRUE(rootWindow
, nsnull
);
2835 nsPIDOMWindow
* focusedWindow
;
2836 nsFocusManager::GetFocusedDescendant(rootWindow
, PR_TRUE
, &focusedWindow
);
2837 NS_ENSURE_TRUE(focusedWindow
, nsnull
);
2839 if (IsWindowsInOurSubTree(focusedWindow
)) {
2840 return focusedWindow
;
2843 NS_IF_RELEASE(focusedWindow
);
2847 //---------------------------------------------------------------------
2849 nsPrintEngine::IsWindowsInOurSubTree(nsPIDOMWindow
* window
)
2851 PRBool found
= PR_FALSE
;
2853 // now check to make sure it is in "our" tree of docshells
2855 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
2856 do_QueryInterface(window
->GetDocShell());
2858 if (docShellAsItem
) {
2859 // get this DocViewer docshell
2860 nsCOMPtr
<nsIDocShell
> thisDVDocShell(do_QueryInterface(mContainer
));
2862 nsCOMPtr
<nsIDocShell
> parentDocshell(do_QueryInterface(docShellAsItem
));
2863 if (parentDocshell
) {
2864 if (parentDocshell
== thisDVDocShell
) {
2869 break; // at top of tree
2871 nsCOMPtr
<nsIDocShellTreeItem
> docShellParent
;
2872 docShellAsItem
->GetSameTypeParent(getter_AddRefs(docShellParent
));
2873 docShellAsItem
= docShellParent
;
2881 //-------------------------------------------------------
2883 nsPrintEngine::DonePrintingPages(nsPrintObject
* aPO
, nsresult aResult
)
2885 //NS_ASSERTION(aPO, "Pointer is null!");
2886 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO
, aPO
?gFrameTypesStr
[aPO
->mFrameType
]:""));
2888 if (aPO
!= nsnull
) {
2889 aPO
->mHasBeenPrinted
= PR_TRUE
;
2891 PRBool didPrint
= PrintDocContent(mPrt
->mPrintObject
, rv
);
2892 if (NS_SUCCEEDED(rv
) && didPrint
) {
2893 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO
, gFrameTypesStr
[aPO
->mFrameType
], PRT_YESNO(didPrint
)));
2898 if (NS_SUCCEEDED(aResult
)) {
2899 FirePrintCompletionEvent();
2902 TurnScriptingOn(PR_TRUE
);
2903 SetIsPrinting(PR_FALSE
);
2905 // Release reference to mPagePrintTimer; the timer object destroys itself
2906 // after this returns true
2907 NS_IF_RELEASE(mPagePrintTimer
);
2912 //-------------------------------------------------------
2913 // Recursively sets the PO items to be printed "As Is"
2914 // from the given item down into the tree
2916 nsPrintEngine::SetPrintAsIs(nsPrintObject
* aPO
, PRBool aAsIs
)
2918 NS_ASSERTION(aPO
, "Pointer is null!");
2920 aPO
->mPrintAsIs
= aAsIs
;
2921 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
2922 SetPrintAsIs(aPO
->mKids
[i
], aAsIs
);
2926 //-------------------------------------------------------
2927 // Given a DOMWindow it recursively finds the PO object that matches
2929 nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject
* aPO
,
2930 nsIDOMWindow
* aDOMWin
)
2932 NS_ASSERTION(aPO
, "Pointer is null!");
2934 // Often the CurFocused DOMWindow is passed in
2935 // andit is valid for it to be null, so short circut
2940 nsCOMPtr
<nsIDOMDocument
> domDoc
;
2941 aDOMWin
->GetDocument(getter_AddRefs(domDoc
));
2942 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
2943 if (aPO
->mDocument
&& aPO
->mDocument
->GetOriginalDocument() == doc
) {
2947 PRInt32 cnt
= aPO
->mKids
.Length();
2948 for (PRInt32 i
= 0; i
< cnt
; ++i
) {
2949 nsPrintObject
* po
= FindPrintObjectByDOMWin(aPO
->mKids
[i
], aDOMWin
);
2958 //-------------------------------------------------------
2960 nsPrintEngine::EnablePOsForPrinting()
2962 // NOTE: All POs have been "turned off" for printing
2963 // this is where we decided which POs get printed.
2964 mPrt
->mSelectedPO
= nsnull
;
2966 if (mPrt
->mPrintSettings
== nsnull
) {
2967 return NS_ERROR_FAILURE
;
2970 mPrt
->mPrintFrameType
= nsIPrintSettings::kNoFrames
;
2971 mPrt
->mPrintSettings
->GetPrintFrameType(&mPrt
->mPrintFrameType
);
2973 PRInt16 printHowEnable
= nsIPrintSettings::kFrameEnableNone
;
2974 mPrt
->mPrintSettings
->GetHowToEnableFrameUI(&printHowEnable
);
2976 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
2977 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
2980 PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n"));
2981 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
2982 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
2983 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
2986 // ***** This is the ultimate override *****
2987 // if we are printing the selection (either an IFrame or selection range)
2988 // then set the mPrintFrameType as if it were the selected frame
2989 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
2990 mPrt
->mPrintFrameType
= nsIPrintSettings::kSelectedFrame
;
2991 printHowEnable
= nsIPrintSettings::kFrameEnableNone
;
2994 // This tells us that the "Frame" UI has turned off,
2995 // so therefore there are no FrameSets/Frames/IFrames to be printed
2997 // This means there are not FrameSets,
2998 // but the document could contain an IFrame
2999 if (printHowEnable
== nsIPrintSettings::kFrameEnableNone
) {
3001 // Print all the pages or a sub range of pages
3002 if (printRangeType
== nsIPrintSettings::kRangeAllPages
||
3003 printRangeType
== nsIPrintSettings::kRangeSpecifiedPageRange
) {
3004 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3006 // Set the children so they are PrinAsIs
3007 // In this case, the children are probably IFrames
3008 if (mPrt
->mPrintObject
->mKids
.Length() > 0) {
3009 for (PRUint32 i
=0;i
<mPrt
->mPrintObject
->mKids
.Length();i
++) {
3010 nsPrintObject
* po
= mPrt
->mPrintObject
->mKids
[i
];
3011 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3015 // ***** Another override *****
3016 mPrt
->mPrintFrameType
= nsIPrintSettings::kFramesAsIs
;
3018 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3019 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3020 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3024 // This means we are either printed a selected IFrame or
3025 // we are printing the current selection
3026 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
3028 // If the currentFocusDOMWin can'r be null if something is selected
3029 if (mPrt
->mCurrentFocusWin
) {
3030 // Find the selected IFrame
3031 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3033 mPrt
->mSelectedPO
= po
;
3034 // Makes sure all of its children are be printed "AsIs"
3037 // Now, only enable this POs (the selected PO) and all of its children
3038 SetPrintPO(po
, PR_TRUE
);
3040 // check to see if we have a range selection,
3041 // as oppose to a insert selection
3042 // this means if the user just clicked on the IFrame then
3043 // there will not be a selection so we want the entire page to print
3045 // XXX this is sort of a hack right here to make the page
3046 // not try to reposition itself when printing selection
3047 nsCOMPtr
<nsIDOMWindow
> domWin
=
3048 do_QueryInterface(po
->mDocument
->GetOriginalDocument()->GetWindow());
3049 if (!IsThereARangeSelection(domWin
)) {
3050 printRangeType
= nsIPrintSettings::kRangeAllPages
;
3051 mPrt
->mPrintSettings
->SetPrintRange(printRangeType
);
3053 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3054 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3055 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3059 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
3060 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3061 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3062 nsCOMPtr
<nsIDOMWindow
> domWin
= do_GetInterface(po
->mDocShell
);
3063 if (IsThereARangeSelection(domWin
)) {
3064 mPrt
->mCurrentFocusWin
= domWin
;
3065 SetPrintPO(po
, PR_TRUE
);
3074 // check to see if there is a selection when a FrameSet is present
3075 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
3076 // If the currentFocusDOMWin can'r be null if something is selected
3077 if (mPrt
->mCurrentFocusWin
) {
3078 // Find the selected IFrame
3079 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3081 mPrt
->mSelectedPO
= po
;
3082 // Makes sure all of its children are be printed "AsIs"
3085 // Now, only enable this POs (the selected PO) and all of its children
3086 SetPrintPO(po
, PR_TRUE
);
3088 // check to see if we have a range selection,
3089 // as oppose to a insert selection
3090 // this means if the user just clicked on the IFrame then
3091 // there will not be a selection so we want the entire page to print
3093 // XXX this is sort of a hack right here to make the page
3094 // not try to reposition itself when printing selection
3095 nsCOMPtr
<nsIDOMWindow
> domWin
=
3096 do_QueryInterface(po
->mDocument
->GetOriginalDocument()->GetWindow());
3097 if (!IsThereARangeSelection(domWin
)) {
3098 printRangeType
= nsIPrintSettings::kRangeAllPages
;
3099 mPrt
->mPrintSettings
->SetPrintRange(printRangeType
);
3101 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3102 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3103 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3109 // If we are printing "AsIs" then sets all the POs to be printed as is
3110 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kFramesAsIs
) {
3111 SetPrintAsIs(mPrt
->mPrintObject
);
3112 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3116 // If we are printing the selected Frame then
3117 // find that PO for that selected DOMWin and set it all of its
3118 // children to be printed
3119 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kSelectedFrame
) {
3121 if ((mPrt
->mIsParentAFrameSet
&& mPrt
->mCurrentFocusWin
) || mPrt
->mIsIFrameSelected
) {
3122 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3124 mPrt
->mSelectedPO
= po
;
3125 // NOTE: Calling this sets the "po" and
3126 // we don't want to do this for documents that have no children,
3127 // because then the "DoEndPage" gets called and it shouldn't
3128 if (po
->mKids
.Length() > 0) {
3129 // Makes sure that itself, and all of its children are printed "AsIs"
3133 // Now, only enable this POs (the selected PO) and all of its children
3134 SetPrintPO(po
, PR_TRUE
);
3140 // If we are print each subdoc separately,
3141 // then don't print any of the FraneSet Docs
3142 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
) {
3143 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3144 PRInt32 cnt
= mPrt
->mPrintDocList
.Length();
3145 for (PRInt32 i
=0;i
<cnt
;i
++) {
3146 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3147 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3148 if (po
->mFrameType
== eFrameSet
) {
3149 po
->mDontPrint
= PR_TRUE
;
3157 //-------------------------------------------------------
3158 // Return the nsPrintObject with that is XMost (The widest frameset frame) AND
3159 // contains the XMost (widest) layout frame
3161 nsPrintEngine::FindSmallestSTF()
3163 float smallestRatio
= 1.0f
;
3164 nsPrintObject
* smallestPO
= nsnull
;
3166 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
3167 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3168 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3169 if (po
->mFrameType
!= eFrameSet
&& po
->mFrameType
!= eIFrame
) {
3170 if (po
->mShrinkRatio
< smallestRatio
) {
3171 smallestRatio
= po
->mShrinkRatio
;
3177 #ifdef EXTENDED_DEBUG_PRINTING
3178 if (smallestPO
) printf("*PO: %p Type: %d %10.3f\n", smallestPO
, smallestPO
->mFrameType
, smallestPO
->mShrinkRatio
);
3183 //-------------------------------------------------------
3185 nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn
)
3187 if (mIsDoingPrinting
&& aDoTurnOn
&& mDocViewerPrint
&&
3188 mDocViewerPrint
->GetIsPrintPreview()) {
3189 // We don't want to turn scripting on if print preview is shown still after
3194 nsPrintData
* prt
= mPrt
;
3195 #ifdef NS_PRINT_PREVIEW
3204 NS_ASSERTION(mDocument
, "We MUST have a document.");
3205 // First, get the script global object from the document...
3207 for (PRUint32 i
=0;i
<prt
->mPrintDocList
.Length();i
++) {
3208 nsPrintObject
* po
= prt
->mPrintDocList
.ElementAt(i
);
3209 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3211 nsIDocument
* doc
= po
->mDocument
;
3216 // get the script global object
3217 nsIScriptGlobalObject
*scriptGlobalObj
= doc
->GetScriptGlobalObject();
3219 if (scriptGlobalObj
) {
3220 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(scriptGlobalObj
);
3221 NS_ASSERTION(window
, "Can't get nsPIDOMWindow");
3222 nsIScriptContext
*scx
= scriptGlobalObj
->GetContext();
3223 NS_WARN_IF_FALSE(scx
, "Can't get nsIScriptContext");
3224 nsresult propThere
= NS_PROPTABLE_PROP_NOT_THERE
;
3225 doc
->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
,
3228 if (propThere
!= NS_PROPTABLE_PROP_NOT_THERE
) {
3229 doc
->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
);
3231 scx
->SetScriptsEnabled(PR_TRUE
, PR_FALSE
);
3233 window
->ResumeTimeouts(PR_FALSE
);
3236 // Have to be careful, because people call us over and over again with
3237 // aDoTurnOn == PR_FALSE. So don't set the property if it's already
3238 // set, since in that case we'd set it to the wrong value.
3239 if (propThere
== NS_PROPTABLE_PROP_NOT_THERE
) {
3240 // Stash the current value of IsScriptEnabled on the document, so
3241 // that layout code running in print preview doesn't get confused.
3242 doc
->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
,
3243 NS_INT32_TO_PTR(doc
->IsScriptEnabled()));
3245 scx
->SetScriptsEnabled(PR_FALSE
, PR_FALSE
);
3247 window
->SuspendTimeouts(1, PR_FALSE
);
3254 //-----------------------------------------------------------------
3255 //-- Done: Misc Support Methods
3256 //-----------------------------------------------------------------
3259 //-----------------------------------------------------------------
3260 //-- Section: Finishing up or Cleaning up
3261 //-----------------------------------------------------------------
3263 //-----------------------------------------------------------------
3265 nsPrintEngine::CloseProgressDialog(nsIWebProgressListener
* aWebProgressListener
)
3267 if (aWebProgressListener
) {
3268 aWebProgressListener
->OnStateChange(nsnull
, nsnull
, nsIWebProgressListener::STATE_STOP
|nsIWebProgressListener::STATE_IS_DOCUMENT
, nsnull
);
3272 //-----------------------------------------------------------------
3274 nsPrintEngine::FinishPrintPreview()
3276 nsresult rv
= NS_OK
;
3278 #ifdef NS_PRINT_PREVIEW
3281 /* we're already finished with print preview */
3285 rv
= DocumentReadyForPrinting();
3287 SetIsCreatingPrintPreview(PR_FALSE
);
3289 /* cleaup on failure + notify user */
3290 if (NS_FAILED(rv
)) {
3291 /* cleanup done, let's fire-up an error dialog to notify the user
3292 * what went wrong...
3294 mPrt
->OnEndPrinting();
3295 TurnScriptingOn(PR_TRUE
);
3300 // At this point we are done preparing everything
3301 // before it is to be created
3304 if (mIsDoingPrintPreview
&& mOldPrtPreview
) {
3305 delete mOldPrtPreview
;
3306 mOldPrtPreview
= nsnull
;
3309 InstallPrintPreviewListener();
3311 mPrt
->OnEndPrinting();
3313 // PrintPreview was built using the mPrt (code reuse)
3314 // then we assign it over
3318 #endif // NS_PRINT_PREVIEW
3323 //-----------------------------------------------------------------
3324 //-- Done: Finishing up or Cleaning up
3325 //-----------------------------------------------------------------
3328 /*=============== Timer Related Code ======================*/
3330 nsPrintEngine::StartPagePrintTimer(nsPrintObject
* aPO
)
3332 if (!mPagePrintTimer
) {
3333 nsresult rv
= NS_NewPagePrintTimer(&mPagePrintTimer
);
3334 NS_ENSURE_SUCCESS(rv
, rv
);
3336 // Get the delay time in between the printing of each page
3337 // this gives the user more time to press cancel
3338 PRInt32 printPageDelay
= 50;
3339 mPrt
->mPrintSettings
->GetPrintPageDelay(&printPageDelay
);
3341 mPagePrintTimer
->Init(this, mDocViewerPrint
, printPageDelay
);
3344 return mPagePrintTimer
->Start(aPO
);
3347 /*=============== nsIObserver Interface ======================*/
3349 nsPrintEngine::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*aData
)
3351 nsresult rv
= NS_ERROR_FAILURE
;
3353 if (mIsDoingPrinting
) {
3354 rv
= DocumentReadyForPrinting();
3356 /* cleaup on failure + notify user */
3357 if (NS_FAILED(rv
)) {
3358 CleanupOnFailure(rv
, PR_TRUE
);
3361 rv
= FinishPrintPreview();
3362 if (NS_FAILED(rv
)) {
3363 CleanupOnFailure(rv
, PR_FALSE
);
3366 mPrtPreview
->OnEndPrinting();
3375 //---------------------------------------------------------------
3376 //-- PLEvent Notification
3377 //---------------------------------------------------------------
3378 class nsPrintCompletionEvent
: public nsRunnable
{
3380 nsPrintCompletionEvent(nsIDocumentViewerPrint
*docViewerPrint
)
3381 : mDocViewerPrint(docViewerPrint
) {
3382 NS_ASSERTION(mDocViewerPrint
, "mDocViewerPrint is null.");
3386 if (mDocViewerPrint
)
3387 mDocViewerPrint
->OnDonePrinting();
3392 nsCOMPtr
<nsIDocumentViewerPrint
> mDocViewerPrint
;
3395 //-----------------------------------------------------------
3397 nsPrintEngine::FirePrintCompletionEvent()
3399 nsCOMPtr
<nsIRunnable
> event
= new nsPrintCompletionEvent(mDocViewerPrint
);
3400 if (NS_FAILED(NS_DispatchToCurrentThread(event
)))
3401 NS_WARNING("failed to dispatch print completion event");
3404 //---------------------------------------------------------------
3405 //---------------------------------------------------------------
3406 //-- Debug helper routines
3407 //---------------------------------------------------------------
3408 //---------------------------------------------------------------
3409 #if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
3410 #include "windows.h"
3411 #include "process.h"
3414 #define MY_FINDFIRST(a,b) FindFirstFile(a,b)
3415 #define MY_FINDNEXT(a,b) FindNextFile(a,b)
3416 #define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
3417 #define MY_FINDCLOSE(a) FindClose(a)
3418 #define MY_FILENAME(a) a.cFileName
3419 #define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow
3421 int RemoveFilesInDir(const char * aDir
)
3423 WIN32_FIND_DATA data_ptr
;
3426 char path
[MAX_PATH
];
3430 // Append slash to the end of the directory names if not there
3431 if (path
[strlen(path
)-1] != '\\')
3434 char findPath
[MAX_PATH
];
3435 strcpy(findPath
, path
);
3436 strcat(findPath
, "*.*");
3438 find_handle
= MY_FINDFIRST(findPath
, &data_ptr
);
3440 if (find_handle
!= INVALID_HANDLE_VALUE
) {
3443 && (stricmp(MY_FILENAME(data_ptr
),"."))
3444 && (stricmp(MY_FILENAME(data_ptr
),".."))) {
3447 else if (!ISDIR(data_ptr
)) {
3448 if (!strncmp(MY_FILENAME(data_ptr
), "print_dump", 10)) {
3449 char fileName
[MAX_PATH
];
3450 strcpy(fileName
, aDir
);
3451 strcat(fileName
, "\\");
3452 strcat(fileName
, MY_FILENAME(data_ptr
));
3453 printf("Removing %s\n", fileName
);
3457 } while(MY_FINDNEXT(find_handle
,&data_ptr
));
3458 MY_FINDCLOSE(find_handle
);
3464 #ifdef EXTENDED_DEBUG_PRINTING
3466 /** ---------------------------------------------------
3467 * Dumps Frames for Printing
3469 static void RootFrameList(nsPresContext
* aPresContext
, FILE* out
, PRInt32 aIndent
)
3471 if (!aPresContext
|| !out
)
3474 nsIPresShell
*shell
= aPresContext
->GetPresShell();
3476 nsIFrame
* frame
= shell
->FrameManager()->GetRootFrame();
3478 frame
->List(aPresContext
, out
, aIndent
);
3483 /** ---------------------------------------------------
3484 * Dumps Frames for Printing
3486 static void DumpFrames(FILE* out
,
3487 nsPresContext
* aPresContext
,
3488 nsIRenderingContext
* aRendContext
,
3492 NS_ASSERTION(out
, "Pointer is null!");
3493 NS_ASSERTION(aPresContext
, "Pointer is null!");
3494 NS_ASSERTION(aRendContext
, "Pointer is null!");
3495 NS_ASSERTION(aFrame
, "Pointer is null!");
3497 nsIFrame
* child
= aFrame
->GetFirstChild(nsnull
);
3498 while (child
!= nsnull
) {
3499 for (PRInt32 i
=0;i
<aLevel
;i
++) {
3503 child
->GetFrameName(tmp
);
3504 fputs(NS_LossyConvertUTF16toASCII(tmp
).get(), out
);
3506 if (NS_SUCCEEDED(child
->IsVisibleForPainting(aPresContext
, *aRendContext
, PR_TRUE
, &isSelected
))) {
3507 fprintf(out
, " %p %s", child
, isSelected
?"VIS":"UVS");
3508 nsRect rect
= child
->GetRect();
3509 fprintf(out
, "[%d,%d,%d,%d] ", rect
.x
, rect
.y
, rect
.width
, rect
.height
);
3510 fprintf(out
, "v: %p ", (void*)child
->GetView());
3512 DumpFrames(out
, aPresContext
, aRendContext
, child
, aLevel
+1);
3513 child
= child
->GetNextSibling();
3519 /** ---------------------------------------------------
3520 * Dumps the Views from the DocShell
3523 DumpViews(nsIDocShell
* aDocShell
, FILE* out
)
3525 NS_ASSERTION(aDocShell
, "Pointer is null!");
3526 NS_ASSERTION(out
, "Pointer is null!");
3528 if (nsnull
!= aDocShell
) {
3529 fprintf(out
, "docshell=%p \n", aDocShell
);
3530 nsIPresShell
* shell
= nsPrintEngine::GetPresShellFor(aDocShell
);
3532 nsIViewManager
* vm
= shell
->GetViewManager();
3535 vm
->GetRootView(root
);
3536 if (nsnull
!= root
) {
3542 fputs("null pres shell\n", out
);
3545 // dump the views of the sub documents
3547 nsCOMPtr
<nsIDocShellTreeNode
> docShellAsNode(do_QueryInterface(aDocShell
));
3548 docShellAsNode
->GetChildCount(&n
);
3549 for (i
= 0; i
< n
; i
++) {
3550 nsCOMPtr
<nsIDocShellTreeItem
> child
;
3551 docShellAsNode
->GetChildAt(i
, getter_AddRefs(child
));
3552 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
3554 DumpViews(childAsShell
, out
);
3560 /** ---------------------------------------------------
3561 * Dumps the Views and Frames
3563 void DumpLayoutData(char* aTitleStr
,
3565 nsPresContext
* aPresContext
,
3566 nsIDeviceContext
* aDC
,
3567 nsIFrame
* aRootFrame
,
3568 nsIDocShekk
* aDocShell
,
3571 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3573 if (aPresContext
== nsnull
|| aDC
== nsnull
) {
3577 #ifdef NS_PRINT_PREVIEW
3578 if (aPresContext
->Type() == nsPresContext::eContext_PrintPreview
) {
3583 NS_ASSERTION(aRootFrame
, "Pointer is null!");
3584 NS_ASSERTION(aDocShell
, "Pointer is null!");
3586 // Dump all the frames and view to a a file
3588 sprintf(filename
, "print_dump_layout_%d.txt", gDumpLOFileNameCnt
++);
3589 FILE * fd
= aFD
?aFD
:fopen(filename
, "w");
3591 fprintf(fd
, "Title: %s\n", aTitleStr
?aTitleStr
:"");
3592 fprintf(fd
, "URL: %s\n", aURLStr
?aURLStr
:"");
3593 fprintf(fd
, "--------------- Frames ----------------\n");
3594 fprintf(fd
, "--------------- Frames ----------------\n");
3595 nsCOMPtr
<nsIRenderingContext
> renderingContext
;
3596 aDC
->CreateRenderingContext(*getter_AddRefs(renderingContext
));
3597 RootFrameList(aPresContext
, fd
, 0);
3598 //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0);
3599 fprintf(fd
, "---------------------------------------\n\n");
3600 fprintf(fd
, "--------------- Views From Root Frame----------------\n");
3601 nsIView
* v
= aRootFrame
->GetView();
3605 printf("View is null!\n");
3608 fprintf(fd
, "--------------- All Views ----------------\n");
3609 DumpViews(aDocShell
, fd
);
3610 fprintf(fd
, "---------------------------------------\n\n");
3612 if (aFD
== nsnull
) {
3618 //-------------------------------------------------------------
3619 static void DumpPrintObjectsList(nsTArray
<nsPrintObject
*> * aDocList
)
3621 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3623 NS_ASSERTION(aDocList
, "Pointer is null!");
3625 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3626 PR_PL(("Doc List\n***************************************************\n"));
3627 PR_PL(("T P A H PO DocShell Seq Page Root Page# Rect\n"));
3628 PRInt32 cnt
= aDocList
->Length();
3629 for (PRInt32 i
=0;i
<cnt
;i
++) {
3630 nsPrintObject
* po
= aDocList
->ElementAt(i
);
3631 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3632 nsIFrame
* rootFrame
= nsnull
;
3633 if (po
->mPresShell
) {
3634 rootFrame
= po
->mPresShell
->FrameManager()->GetRootFrame();
3635 while (rootFrame
!= nsnull
) {
3636 nsIPageSequenceFrame
* sqf
= do_QueryFrame(rootFrame
);
3640 rootFrame
= rootFrame
->GetFirstChild(nsnull
);
3644 PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types
[po
->mFrameType
],
3645 po
->IsPrintable(), po
->mPrintAsIs
, po
->mHasBeenPrinted
, po
, po
->mDocShell
.get(), po
->mSeqFrame
,
3646 po
->mPageFrame
, rootFrame
, po
->mPageNum
, po
->mRect
.x
, po
->mRect
.y
, po
->mRect
.width
, po
->mRect
.height
));
3650 //-------------------------------------------------------------
3651 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
, FILE* aFD
)
3653 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3655 NS_ASSERTION(aPO
, "Pointer is null!");
3657 FILE * fd
= aFD
?aFD
:stdout
;
3658 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3660 fprintf(fd
, "DocTree\n***************************************************\n");
3661 fprintf(fd
, "T PO DocShell Seq Page Page# Rect\n");
3663 PRInt32 cnt
= aPO
->mKids
.Length();
3664 for (PRInt32 i
=0;i
<cnt
;i
++) {
3665 nsPrintObject
* po
= aPO
->mKids
.ElementAt(i
);
3666 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3667 for (PRInt32 k
=0;k
<aLevel
;k
++) fprintf(fd
, " ");
3668 fprintf(fd
, "%s %p %p %p %p %d %d,%d,%d,%d\n", types
[po
->mFrameType
], po
, po
->mDocShell
.get(), po
->mSeqFrame
,
3669 po
->mPageFrame
, po
->mPageNum
, po
->mRect
.x
, po
->mRect
.y
, po
->mRect
.width
, po
->mRect
.height
);
3673 //-------------------------------------------------------------
3674 static void GetDocTitleAndURL(nsPrintObject
* aPO
, char *& aDocStr
, char *& aURLStr
)
3679 PRUnichar
* docTitleStr
;
3680 PRUnichar
* docURLStr
;
3681 nsPrintEngine::GetDisplayTitleAndURL(aPO
,
3682 &docTitleStr
, &docURLStr
,
3683 nsPrintEngine::eDocTitleDefURLDoc
);
3686 nsAutoString
strDocTitle(docTitleStr
);
3687 aDocStr
= ToNewCString(strDocTitle
);
3688 nsMemory::Free(docTitleStr
);
3692 nsAutoString
strURL(docURLStr
);
3693 aURLStr
= ToNewCString(strURL
);
3694 nsMemory::Free(docURLStr
);
3698 //-------------------------------------------------------------
3699 static void DumpPrintObjectsTreeLayout(nsPrintObject
* aPO
,
3700 nsIDeviceContext
* aDC
,
3701 int aLevel
, FILE * aFD
)
3703 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3705 NS_ASSERTION(aPO
, "Pointer is null!");
3706 NS_ASSERTION(aDC
, "Pointer is null!");
3708 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3711 fd
= fopen("tree_layout.txt", "w");
3712 fprintf(fd
, "DocTree\n***************************************************\n");
3713 fprintf(fd
, "***************************************************\n");
3714 fprintf(fd
, "T PO DocShell Seq Page Page# Rect\n");
3719 nsIFrame
* rootFrame
= nsnull
;
3720 if (aPO
->mPresShell
) {
3721 rootFrame
= aPO
->mPresShell
->FrameManager()->GetRootFrame();
3723 for (PRInt32 k
=0;k
<aLevel
;k
++) fprintf(fd
, " ");
3724 fprintf(fd
, "%s %p %p %p %p %d %d,%d,%d,%d\n", types
[aPO
->mFrameType
], aPO
, aPO
->mDocShell
.get(), aPO
->mSeqFrame
,
3725 aPO
->mPageFrame
, aPO
->mPageNum
, aPO
->mRect
.x
, aPO
->mRect
.y
, aPO
->mRect
.width
, aPO
->mRect
.height
);
3726 if (aPO
->IsPrintable()) {
3729 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
3730 DumpLayoutData(docStr
, urlStr
, aPO
->mPresContext
, aDC
, rootFrame
, aPO
->mDocShell
, fd
);
3731 if (docStr
) nsMemory::Free(docStr
);
3732 if (urlStr
) nsMemory::Free(urlStr
);
3734 fprintf(fd
, "<***************************************************>\n");
3736 PRInt32 cnt
= aPO
->mKids
.Length();
3737 for (PRInt32 i
=0;i
<cnt
;i
++) {
3738 nsPrintObject
* po
= aPO
->mKids
.ElementAt(i
);
3739 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3740 DumpPrintObjectsTreeLayout(po
, aDC
, aLevel
+1, fd
);
3743 if (aLevel
== 0 && fd
) {
3748 //-------------------------------------------------------------
3749 static void DumpPrintObjectsListStart(const char * aStr
, nsTArray
<nsPrintObject
*> * aDocList
)
3751 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3753 NS_ASSERTION(aStr
, "Pointer is null!");
3754 NS_ASSERTION(aDocList
, "Pointer is null!");
3756 PR_PL(("%s\n", aStr
));
3757 DumpPrintObjectsList(aDocList
);
3760 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
3761 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
3762 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
3765 #define DUMP_DOC_LIST(_title)
3766 #define DUMP_DOC_TREE
3767 #define DUMP_DOC_TREELAYOUT
3770 //---------------------------------------------------------------
3771 //---------------------------------------------------------------
3772 //-- End of debug helper routines
3773 //---------------------------------------------------------------