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 "nsIDocumentViewer.h"
159 #include "nsIDocumentViewerPrint.h"
161 #include "nsPIDOMWindow.h"
162 #include "nsFocusManager.h"
164 #include "nsCDefaultURIFixup.h"
165 #include "nsIURIFixup.h"
166 #include "mozilla/dom/Element.h"
168 using namespace mozilla::dom
;
170 //-----------------------------------------------------
173 #define FORCE_PR_LOG /* Allow logging in the release build */
181 // PR_LOGGING is force to always be on (even in release builds)
182 // but we only want some of it on,
183 //#define EXTENDED_DEBUG_PRINTING
186 #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
188 static PRLogModuleInfo
* kPrintingLogMod
= PR_NewLogModule("printing");
189 #define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
191 #ifdef EXTENDED_DEBUG_PRINTING
192 static PRUint32 gDumpFileNameCnt
= 0;
193 static PRUint32 gDumpLOFileNameCnt
= 0;
196 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
197 static const char * gFrameTypesStr
[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"};
198 static const char * gPrintFrameTypeStr
[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"};
199 static const char * gFrameHowToEnableStr
[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"};
200 static const char * gPrintRangeStr
[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"};
202 #define PRT_YESNO(_p)
206 #ifdef EXTENDED_DEBUG_PRINTING
207 // Forward Declarations
208 static void DumpPrintObjectsListStart(const char * aStr
, nsTArray
<nsPrintObject
*> * aDocList
);
209 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
= 0, FILE* aFD
= nsnull
);
210 static void DumpPrintObjectsTreeLayout(nsPrintObject
* aPO
,nsIDeviceContext
* aDC
, int aLevel
= 0, FILE * aFD
= nsnull
);
212 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
213 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
214 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
216 #define DUMP_DOC_LIST(_title)
217 #define DUMP_DOC_TREE
218 #define DUMP_DOC_TREELAYOUT
221 class nsScriptSuppressor
224 nsScriptSuppressor(nsPrintEngine
* aPrintEngine
)
225 : mPrintEngine(aPrintEngine
), mSuppressed(PR_FALSE
) {}
227 ~nsScriptSuppressor() { Unsuppress(); }
232 mSuppressed
= PR_TRUE
;
233 mPrintEngine
->TurnScriptingOn(PR_FALSE
);
239 if (mPrintEngine
&& mSuppressed
) {
240 mPrintEngine
->TurnScriptingOn(PR_TRUE
);
242 mSuppressed
= PR_FALSE
;
245 void Disconnect() { mPrintEngine
= nsnull
; }
247 nsRefPtr
<nsPrintEngine
> mPrintEngine
;
252 static NS_DEFINE_CID(kViewManagerCID
, NS_VIEW_MANAGER_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
),
270 mOldPrtPreview(nsnull
),
275 //-------------------------------------------------------
276 nsPrintEngine::~nsPrintEngine()
278 Destroy(); // for insurance
281 //-------------------------------------------------------
282 void nsPrintEngine::Destroy()
289 #ifdef NS_PRINT_PREVIEW
292 mPrtPreview
= nsnull
;
296 if (mOldPrtPreview
) {
297 delete mOldPrtPreview
;
298 mOldPrtPreview
= nsnull
;
302 mDocViewerPrint
= nsnull
;
305 //-------------------------------------------------------
306 void nsPrintEngine::DestroyPrintingData()
314 //---------------------------------------------------------------------------------
315 //-- Section: Methods needed by the DocViewer
316 //---------------------------------------------------------------------------------
318 //--------------------------------------------------------
319 nsresult
nsPrintEngine::Initialize(nsIDocumentViewerPrint
* aDocViewerPrint
,
320 nsISupports
* aContainer
,
321 nsIDocument
* aDocument
,
325 NS_ENSURE_ARG_POINTER(aDocViewerPrint
);
326 NS_ENSURE_ARG_POINTER(aContainer
);
327 NS_ENSURE_ARG_POINTER(aDocument
);
329 mDocViewerPrint
= aDocViewerPrint
;
330 mContainer
= aContainer
; // weak reference
331 mDocument
= aDocument
;
332 mScreenDPI
= aScreenDPI
;
334 mDebugFile
= aDebugFile
; // ok to be NULL
339 //-------------------------------------------------------
341 nsPrintEngine::CheckBeforeDestroy()
343 if (mPrt
&& mPrt
->mPreparingForPrint
) {
344 mPrt
->mDocWasToBeDestroyed
= PR_TRUE
;
350 //-------------------------------------------------------
352 nsPrintEngine::Cancelled()
354 if (mPrt
&& mPrt
->mPrintSettings
) {
355 return mPrt
->mPrintSettings
->SetIsCancelled(PR_TRUE
);
357 return NS_ERROR_FAILURE
;
360 //-------------------------------------------------------
361 // Install our event listeners on the document to prevent
362 // some events from being processed while in PrintPreview
364 // No return code - if this fails, there isn't much we can do
366 nsPrintEngine::InstallPrintPreviewListener()
368 if (!mPrt
->mPPEventListeners
) {
369 nsCOMPtr
<nsPIDOMWindow
> win(do_GetInterface(mContainer
));
370 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(win
->GetFrameElementInternal()));
371 mPrt
->mPPEventListeners
= new nsPrintPreviewListener(target
);
373 if (mPrt
->mPPEventListeners
) {
374 mPrt
->mPPEventListeners
->AddListeners();
379 //----------------------------------------------------------------------
381 nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject
* aPO
,
382 nsIFrame
*& aSeqFrame
,
385 NS_ENSURE_ARG_POINTER(aPO
);
387 // Finds the SimplePageSequencer frame
388 nsIPageSequenceFrame
* seqFrame
= aPO
->mPresShell
->GetPageSequenceFrame();
390 aSeqFrame
= do_QueryFrame(seqFrame
);
394 if (aSeqFrame
== nsnull
) return NS_ERROR_FAILURE
;
396 // first count the total number of pages
398 nsIFrame
* pageFrame
= aSeqFrame
->GetFirstChild(nsnull
);
399 while (pageFrame
!= nsnull
) {
401 pageFrame
= pageFrame
->GetNextSibling();
408 //-----------------------------------------------------------------
409 nsresult
nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame
*& aSeqFrame
, PRInt32
& aCount
)
411 NS_ASSERTION(mPrtPreview
, "mPrtPreview can't be null!");
412 return GetSeqFrameAndCountPagesInternal(mPrtPreview
->mPrintObject
, aSeqFrame
, aCount
);
414 //---------------------------------------------------------------------------------
415 //-- Done: Methods needed by the DocViewer
416 //---------------------------------------------------------------------------------
419 //---------------------------------------------------------------------------------
420 //-- Section: nsIWebBrowserPrint
421 //---------------------------------------------------------------------------------
423 // Foward decl for Debug Helper Functions
424 #ifdef EXTENDED_DEBUG_PRINTING
425 static int RemoveFilesInDir(const char * aDir
);
426 static void GetDocTitleAndURL(nsPrintObject
* aPO
, char *& aDocStr
, char *& aURLStr
);
427 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
, FILE* aFD
);
428 static void DumpPrintObjectsList(nsTArray
<nsPrintObject
*> * aDocList
);
429 static void RootFrameList(nsPresContext
* aPresContext
, FILE* out
, PRInt32 aIndent
);
430 static void DumpViews(nsIDocShell
* aDocShell
, FILE* out
);
431 static void DumpLayoutData(char* aTitleStr
, char* aURLStr
,
432 nsPresContext
* aPresContext
,
433 nsIDeviceContext
* aDC
, nsIFrame
* aRootFrame
,
434 nsIDocShell
* aDocShell
, FILE* aFD
);
437 //--------------------------------------------------------------------------------
440 nsPrintEngine::CommonPrint(PRBool aIsPrintPreview
,
441 nsIPrintSettings
* aPrintSettings
,
442 nsIWebProgressListener
* aWebProgressListener
,
443 nsIDOMDocument
* aDoc
) {
444 nsresult rv
= DoCommonPrint(aIsPrintPreview
, aPrintSettings
,
445 aWebProgressListener
, aDoc
);
447 if (aIsPrintPreview
) {
448 SetIsCreatingPrintPreview(PR_FALSE
);
449 SetIsPrintPreview(PR_FALSE
);
451 SetIsPrinting(PR_FALSE
);
453 if (mProgressDialogIsShown
)
454 CloseProgressDialog(aWebProgressListener
);
455 if (rv
!= NS_ERROR_ABORT
&& rv
!= NS_ERROR_OUT_OF_MEMORY
)
456 ShowPrintErrorDialog(rv
, !aIsPrintPreview
);
465 nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview
,
466 nsIPrintSettings
* aPrintSettings
,
467 nsIWebProgressListener
* aWebProgressListener
,
468 nsIDOMDocument
* aDoc
)
472 if (aIsPrintPreview
) {
473 // The WebProgressListener can be QI'ed to nsIPrintingPromptService
474 // then that means the progress dialog is already being shown.
475 nsCOMPtr
<nsIPrintingPromptService
> pps(do_QueryInterface(aWebProgressListener
));
476 mProgressDialogIsShown
= pps
!= nsnull
;
478 if (mIsDoingPrintPreview
) {
479 mOldPrtPreview
= mPrtPreview
;
480 mPrtPreview
= nsnull
;
483 mProgressDialogIsShown
= PR_FALSE
;
486 mPrt
= new nsPrintData(aIsPrintPreview
? nsPrintData::eIsPrintPreview
:
487 nsPrintData::eIsPrinting
);
488 NS_ENSURE_TRUE(mPrt
, NS_ERROR_OUT_OF_MEMORY
);
490 // if they don't pass in a PrintSettings, then get the Global PS
491 mPrt
->mPrintSettings
= aPrintSettings
;
492 if (!mPrt
->mPrintSettings
) {
493 rv
= GetGlobalPrintSettings(getter_AddRefs(mPrt
->mPrintSettings
));
494 NS_ENSURE_SUCCESS(rv
, rv
);
497 rv
= CheckForPrinters(mPrt
->mPrintSettings
);
498 NS_ENSURE_SUCCESS(rv
, rv
);
500 mPrt
->mPrintSettings
->SetIsCancelled(PR_FALSE
);
501 mPrt
->mPrintSettings
->GetShrinkToFit(&mPrt
->mShrinkToFit
);
503 if (aIsPrintPreview
) {
504 SetIsCreatingPrintPreview(PR_TRUE
);
505 SetIsPrintPreview(PR_TRUE
);
506 nsCOMPtr
<nsIMarkupDocumentViewer
> viewer
=
507 do_QueryInterface(mDocViewerPrint
);
509 viewer
->SetTextZoom(1.0f
);
510 viewer
->SetFullZoom(1.0f
);
513 SetIsPrinting(PR_TRUE
);
516 // Create a print session and let the print settings know about it.
517 // The print settings hold an nsWeakPtr to the session so it does not
518 // need to be cleared from the settings at the end of the job.
519 // XXX What lifetime does the printSession need to have?
520 nsCOMPtr
<nsIPrintSession
> printSession
;
521 if (!aIsPrintPreview
) {
522 printSession
= do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv
);
523 NS_ENSURE_SUCCESS(rv
, rv
);
524 mPrt
->mPrintSettings
->SetPrintSession(printSession
);
527 if (aWebProgressListener
!= nsnull
) {
528 mPrt
->mPrintProgressListeners
.AppendObject(aWebProgressListener
);
531 // Get the currently focused window and cache it
532 // because the Print Dialog will "steal" focus and later when you try
533 // to get the currently focused windows it will be NULL
534 mPrt
->mCurrentFocusWin
= FindFocusedDOMWindow();
536 // Check to see if there is a "regular" selection
537 PRBool isSelection
= IsThereARangeSelection(mPrt
->mCurrentFocusWin
);
539 // Get the docshell for this documentviewer
540 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
, &rv
));
541 NS_ENSURE_SUCCESS(rv
, rv
);
543 mPrt
->mPrintObject
= new nsPrintObject();
544 NS_ENSURE_TRUE(mPrt
->mPrintObject
, NS_ERROR_OUT_OF_MEMORY
);
545 rv
= mPrt
->mPrintObject
->Init(webContainer
, aDoc
, aIsPrintPreview
);
546 NS_ENSURE_SUCCESS(rv
, rv
);
548 NS_ENSURE_TRUE(mPrt
->mPrintDocList
.AppendElement(mPrt
->mPrintObject
),
549 NS_ERROR_OUT_OF_MEMORY
);
551 mPrt
->mIsParentAFrameSet
= IsParentAFrameSet(webContainer
);
552 mPrt
->mPrintObject
->mFrameType
= mPrt
->mIsParentAFrameSet
? eFrameSet
: eDoc
;
554 // Build the "tree" of PrintObjects
555 nsCOMPtr
<nsIDocShellTreeNode
> parentAsNode
=
556 do_QueryInterface(mPrt
->mPrintObject
->mDocShell
);
557 BuildDocTree(parentAsNode
, &mPrt
->mPrintDocList
, mPrt
->mPrintObject
);
559 // XXX This isn't really correct...
560 if (!mPrt
->mPrintObject
->mDocument
||
561 !mPrt
->mPrintObject
->mDocument
->GetRootElement())
562 return NS_ERROR_GFX_PRINTER_STARTDOC
;
564 // Create the linkage from the sub-docs back to the content element
565 // in the parent document
566 MapContentToWebShells(mPrt
->mPrintObject
, mPrt
->mPrintObject
);
568 mPrt
->mIsIFrameSelected
= IsThereAnIFrameSelected(webContainer
, mPrt
->mCurrentFocusWin
, mPrt
->mIsParentAFrameSet
);
570 // Setup print options for UI
571 if (mPrt
->mIsParentAFrameSet
) {
572 if (mPrt
->mCurrentFocusWin
) {
573 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll
);
575 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach
);
578 mPrt
->mPrintSettings
->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone
);
580 // Now determine how to set up the Frame print UI
581 mPrt
->mPrintSettings
->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB
, isSelection
|| mPrt
->mIsIFrameSelected
);
583 nsCOMPtr
<nsIDeviceContextSpec
> devspec
584 (do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv
));
585 NS_ENSURE_SUCCESS(rv
, rv
);
587 nsScriptSuppressor
scriptSuppressor(this);
588 if (!aIsPrintPreview
) {
590 mPrt
->mDebugFilePtr
= mDebugFile
;
593 scriptSuppressor
.Suppress();
594 PRBool printSilently
;
595 mPrt
->mPrintSettings
->GetPrintSilent(&printSilently
);
597 // Check prefs for a default setting as to whether we should print silently
598 printSilently
= nsContentUtils::GetBoolPref("print.always_print_silent",
601 // Ask dialog to be Print Shown via the Plugable Printing Dialog Service
602 // This service is for the Print Dialog and the Print Progress Dialog
603 // If printing silently or you can't get the service continue on
604 if (!printSilently
) {
605 nsCOMPtr
<nsIPrintingPromptService
> printPromptService(do_GetService(kPrintingPromptService
));
606 if (printPromptService
) {
607 nsIDOMWindow
*domWin
= mDocument
->GetWindow();
608 NS_ENSURE_TRUE(domWin
, NS_ERROR_FAILURE
);
610 // Platforms not implementing a given dialog for the service may
611 // return NS_ERROR_NOT_IMPLEMENTED or an error code.
613 // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior
614 // Any other error code means we must bail out
616 nsCOMPtr
<nsIWebBrowserPrint
> wbp(do_QueryInterface(mDocViewerPrint
));
617 rv
= printPromptService
->ShowPrintDialog(domWin
, wbp
,
618 mPrt
->mPrintSettings
);
620 // ShowPrintDialog triggers an event loop which means we can't assume
621 // that the state of this->{anything} matches the state we've checked
622 // above. Including that a given {thing} is non null.
624 if (NS_SUCCEEDED(rv
)) {
625 // since we got the dialog and it worked then make sure we
626 // are telling GFX we want to print silent
627 printSilently
= PR_TRUE
;
629 if (mPrt
&& mPrt
->mPrintSettings
) {
630 // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
631 mPrt
->mPrintSettings
->GetShrinkToFit(&mPrt
->mShrinkToFit
);
633 } else if (rv
== NS_ERROR_NOT_IMPLEMENTED
) {
634 // This means the Dialog service was there,
635 // but they choose not to implement this dialog and
636 // are looking for default behavior from the toolkit
640 rv
= NS_ERROR_GFX_NO_PRINTROMPTSERVICE
;
643 // Call any code that requires a run of the event loop.
644 rv
= mPrt
->mPrintSettings
->SetupSilentPrinting();
646 // Check explicitly for abort because it's expected
647 if (rv
== NS_ERROR_ABORT
)
649 NS_ENSURE_SUCCESS(rv
, rv
);
652 rv
= devspec
->Init(nsnull
, mPrt
->mPrintSettings
, aIsPrintPreview
);
653 NS_ENSURE_SUCCESS(rv
, rv
);
655 mPrt
->mPrintDC
= do_CreateInstance("@mozilla.org/gfx/devicecontext;1", &rv
);
656 NS_ENSURE_SUCCESS(rv
, rv
);
657 rv
= mPrt
->mPrintDC
->InitForPrinting(devspec
);
658 NS_ENSURE_SUCCESS(rv
, rv
);
660 if (aIsPrintPreview
) {
661 mPrt
->mPrintSettings
->SetPrintFrameType(nsIPrintSettings::kFramesAsIs
);
663 // override any UI that wants to PrintPreview any selection or page range
664 // we want to view every page in PrintPreview each time
665 mPrt
->mPrintSettings
->SetPrintRange(nsIPrintSettings::kRangeAllPages
);
667 // Always check and set the print settings first and then fall back
668 // onto the PrintService if there isn't a PrintSettings
670 // Posiible Usage values:
671 // nsIPrintSettings::kUseInternalDefault
672 // nsIPrintSettings::kUseSettingWhenPossible
674 // NOTE: The consts are the same for PrintSettings and PrintSettings
675 PRInt16 printFrameTypeUsage
= nsIPrintSettings::kUseSettingWhenPossible
;
676 mPrt
->mPrintSettings
->GetPrintFrameTypeUsage(&printFrameTypeUsage
);
678 // Ok, see if we are going to use our value and override the default
679 if (printFrameTypeUsage
== nsIPrintSettings::kUseSettingWhenPossible
) {
680 // Get the Print Options/Settings PrintFrameType to see what is preferred
681 PRInt16 printFrameType
= nsIPrintSettings::kEachFrameSep
;
682 mPrt
->mPrintSettings
->GetPrintFrameType(&printFrameType
);
684 // Don't let anybody do something stupid like try to set it to
685 // kNoFrames when we are printing a FrameSet
686 if (printFrameType
== nsIPrintSettings::kNoFrames
) {
687 mPrt
->mPrintFrameType
= nsIPrintSettings::kEachFrameSep
;
688 mPrt
->mPrintSettings
->SetPrintFrameType(mPrt
->mPrintFrameType
);
690 // First find out from the PrinService what options are available
691 // to us for Printing FrameSets
692 PRInt16 howToEnableFrameUI
;
693 mPrt
->mPrintSettings
->GetHowToEnableFrameUI(&howToEnableFrameUI
);
694 if (howToEnableFrameUI
!= nsIPrintSettings::kFrameEnableNone
) {
695 switch (howToEnableFrameUI
) {
696 case nsIPrintSettings::kFrameEnableAll
:
697 mPrt
->mPrintFrameType
= printFrameType
;
700 case nsIPrintSettings::kFrameEnableAsIsAndEach
:
701 if (printFrameType
!= nsIPrintSettings::kSelectedFrame
) {
702 mPrt
->mPrintFrameType
= printFrameType
;
703 } else { // revert back to a good value
704 mPrt
->mPrintFrameType
= nsIPrintSettings::kEachFrameSep
;
708 mPrt
->mPrintSettings
->SetPrintFrameType(mPrt
->mPrintFrameType
);
712 mPrt
->mPrintSettings
->GetPrintFrameType(&mPrt
->mPrintFrameType
);
716 if (aIsPrintPreview
) {
717 PRBool notifyOnInit
= PR_FALSE
;
718 ShowPrintProgress(PR_FALSE
, notifyOnInit
);
720 // Very important! Turn Off scripting
721 TurnScriptingOn(PR_FALSE
);
724 rv
= FinishPrintPreview();
728 NS_ENSURE_SUCCESS(rv
, rv
);
730 PRUnichar
* docTitleStr
;
731 PRUnichar
* docURLStr
;
733 GetDisplayTitleAndURL(mPrt
->mPrintObject
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
735 // Nobody ever cared about the file name passed in, as far as I can tell
736 rv
= mPrt
->mPrintDC
->PrepareDocument(docTitleStr
, nsnull
);
738 if (docTitleStr
) nsMemory::Free(docTitleStr
);
739 if (docURLStr
) nsMemory::Free(docURLStr
);
741 NS_ENSURE_SUCCESS(rv
, rv
);
744 ShowPrintProgress(PR_TRUE
, doNotify
);
746 // Print listener setup...
747 mPrt
->OnStartPrinting();
748 rv
= DocumentReadyForPrinting();
749 NS_ENSURE_SUCCESS(rv
, rv
);
753 // We will enable scripting later after printing has finished.
754 scriptSuppressor
.Disconnect();
759 //---------------------------------------------------------------------------------
761 nsPrintEngine::Print(nsIPrintSettings
* aPrintSettings
,
762 nsIWebProgressListener
* aWebProgressListener
)
764 // If we have a print preview document, use that instead of the original
765 // mDocument. That way animated images etc. get printed using the same state
766 // as in print preview.
767 nsCOMPtr
<nsIDOMDocument
> doc
=
768 do_QueryInterface(mPrtPreview
&& mPrtPreview
->mPrintObject
?
769 mPrtPreview
->mPrintObject
->mDocument
: mDocument
);
771 return CommonPrint(PR_FALSE
, aPrintSettings
, aWebProgressListener
, doc
);
775 nsPrintEngine::PrintPreview(nsIPrintSettings
* aPrintSettings
,
776 nsIDOMWindow
*aChildDOMWin
,
777 nsIWebProgressListener
* aWebProgressListener
)
779 // Get the DocShell and see if it is busy
780 // (We can't Print Preview this document if it is still busy)
781 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(mContainer
));
782 NS_ASSERTION(docShell
, "This has to be a docshell");
784 PRUint32 busyFlags
= nsIDocShell::BUSY_FLAGS_NONE
;
785 if (NS_FAILED(docShell
->GetBusyFlags(&busyFlags
)) ||
786 busyFlags
!= nsIDocShell::BUSY_FLAGS_NONE
) {
787 CloseProgressDialog(aWebProgressListener
);
788 ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP
, PR_FALSE
);
789 return NS_ERROR_FAILURE
;
792 NS_ENSURE_STATE(aChildDOMWin
);
793 nsCOMPtr
<nsIDOMDocument
> doc
;
794 aChildDOMWin
->GetDocument(getter_AddRefs(doc
));
795 NS_ENSURE_STATE(doc
);
797 // Document is not busy -- go ahead with the Print Preview
798 return CommonPrint(PR_TRUE
, aPrintSettings
, aWebProgressListener
, doc
);
801 //----------------------------------------------------------------------------------
802 /* readonly attribute boolean isFramesetDocument; */
804 nsPrintEngine::GetIsFramesetDocument(PRBool
*aIsFramesetDocument
)
806 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
));
807 *aIsFramesetDocument
= IsParentAFrameSet(webContainer
);
811 //----------------------------------------------------------------------------------
812 /* readonly attribute boolean isIFrameSelected; */
814 nsPrintEngine::GetIsIFrameSelected(PRBool
*aIsIFrameSelected
)
816 *aIsIFrameSelected
= PR_FALSE
;
818 // Get the docshell for this documentviewer
819 nsCOMPtr
<nsIDocShell
> webContainer(do_QueryInterface(mContainer
));
820 // Get the currently focused window
821 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
822 if (currentFocusWin
&& webContainer
) {
823 // Get whether the doc contains a frameset
824 // Also, check to see if the currently focus docshell
825 // is a child of this docshell
826 PRPackedBool isParentFrameSet
;
827 *aIsIFrameSelected
= IsThereAnIFrameSelected(webContainer
, currentFocusWin
, isParentFrameSet
);
832 //----------------------------------------------------------------------------------
833 /* readonly attribute boolean isRangeSelection; */
835 nsPrintEngine::GetIsRangeSelection(PRBool
*aIsRangeSelection
)
837 // Get the currently focused window
838 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
839 *aIsRangeSelection
= IsThereARangeSelection(currentFocusWin
);
843 //----------------------------------------------------------------------------------
844 /* readonly attribute boolean isFramesetFrameSelected; */
846 nsPrintEngine::GetIsFramesetFrameSelected(PRBool
*aIsFramesetFrameSelected
)
848 // Get the currently focused window
849 nsCOMPtr
<nsIDOMWindow
> currentFocusWin
= FindFocusedDOMWindow();
850 *aIsFramesetFrameSelected
= currentFocusWin
!= nsnull
;
854 //----------------------------------------------------------------------------------
855 /* readonly attribute long printPreviewNumPages; */
857 nsPrintEngine::GetPrintPreviewNumPages(PRInt32
*aPrintPreviewNumPages
)
859 NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages
);
861 nsIFrame
* seqFrame
= nsnull
;
862 *aPrintPreviewNumPages
= 0;
864 NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview
->mPrintObject
, seqFrame
, *aPrintPreviewNumPages
))) {
865 return NS_ERROR_FAILURE
;
870 //----------------------------------------------------------------------------------
871 // Enumerate all the documents for their titles
873 nsPrintEngine::EnumerateDocumentNames(PRUint32
* aCount
,
874 PRUnichar
*** aResult
)
876 NS_ENSURE_ARG(aCount
);
877 NS_ENSURE_ARG_POINTER(aResult
);
882 PRInt32 numDocs
= mPrt
->mPrintDocList
.Length();
883 PRUnichar
** array
= (PRUnichar
**) nsMemory::Alloc(numDocs
* sizeof(PRUnichar
*));
885 return NS_ERROR_OUT_OF_MEMORY
;
887 for (PRInt32 i
=0;i
<numDocs
;i
++) {
888 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
889 NS_ASSERTION(po
, "nsPrintObject can't be null!");
890 PRUnichar
* docTitleStr
;
891 PRUnichar
* docURLStr
;
892 GetDocumentTitleAndURL(po
->mDocument
, &docTitleStr
, &docURLStr
);
894 // Use the URL if the doc is empty
895 if (!docTitleStr
|| !*docTitleStr
) {
896 if (docURLStr
&& *docURLStr
) {
897 nsMemory::Free(docTitleStr
);
898 docTitleStr
= docURLStr
;
900 nsMemory::Free(docURLStr
);
903 if (!docTitleStr
|| !*docTitleStr
) {
904 CleanupDocTitleArray(array
, i
);
905 return NS_ERROR_OUT_OF_MEMORY
;
908 array
[i
] = docTitleStr
;
909 if (docURLStr
) nsMemory::Free(docURLStr
);
918 //----------------------------------------------------------------------------------
919 /* readonly attribute nsIPrintSettings globalPrintSettings; */
921 nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings
**aGlobalPrintSettings
)
923 NS_ENSURE_ARG_POINTER(aGlobalPrintSettings
);
925 nsresult rv
= NS_ERROR_FAILURE
;
926 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
927 do_GetService(sPrintSettingsServiceContractID
, &rv
);
928 if (NS_SUCCEEDED(rv
)) {
929 rv
= printSettingsService
->GetGlobalPrintSettings(aGlobalPrintSettings
);
934 //----------------------------------------------------------------------------------
935 /* readonly attribute boolean doingPrint; */
937 nsPrintEngine::GetDoingPrint(PRBool
*aDoingPrint
)
939 NS_ENSURE_ARG_POINTER(aDoingPrint
);
940 *aDoingPrint
= mIsDoingPrinting
;
944 //----------------------------------------------------------------------------------
945 /* readonly attribute boolean doingPrintPreview; */
947 nsPrintEngine::GetDoingPrintPreview(PRBool
*aDoingPrintPreview
)
949 NS_ENSURE_ARG_POINTER(aDoingPrintPreview
);
950 *aDoingPrintPreview
= mIsDoingPrintPreview
;
954 //----------------------------------------------------------------------------------
955 /* readonly attribute nsIPrintSettings currentPrintSettings; */
957 nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings
* *aCurrentPrintSettings
)
959 NS_ENSURE_ARG_POINTER(aCurrentPrintSettings
);
962 *aCurrentPrintSettings
= mPrt
->mPrintSettings
;
964 } else if (mPrtPreview
) {
965 *aCurrentPrintSettings
= mPrtPreview
->mPrintSettings
;
968 *aCurrentPrintSettings
= nsnull
;
970 NS_IF_ADDREF(*aCurrentPrintSettings
);
974 //-----------------------------------------------------------------
975 //-- Section: Pre-Reflow Methods
976 //-----------------------------------------------------------------
978 //---------------------------------------------------------------------
979 // This method checks to see if there is at least one printer defined
980 // and if so, it sets the first printer in the list as the default name
981 // in the PrintSettings which is then used for Printer Preview
983 nsPrintEngine::CheckForPrinters(nsIPrintSettings
* aPrintSettings
)
985 #if defined(XP_MACOSX) || defined(ANDROID)
986 // Mac doesn't support retrieving a printer list.
989 NS_ENSURE_ARG_POINTER(aPrintSettings
);
991 // See if aPrintSettings already has a printer
992 nsXPIDLString printerName
;
993 nsresult rv
= aPrintSettings
->GetPrinterName(getter_Copies(printerName
));
994 if (NS_SUCCEEDED(rv
) && !printerName
.IsEmpty()) {
998 // aPrintSettings doesn't have a printer set. Try to fetch the default.
999 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
1000 do_GetService(sPrintSettingsServiceContractID
, &rv
);
1001 NS_ENSURE_SUCCESS(rv
, rv
);
1003 rv
= printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
1004 if (NS_SUCCEEDED(rv
) && !printerName
.IsEmpty()) {
1005 rv
= aPrintSettings
->SetPrinterName(printerName
.get());
1011 //----------------------------------------------------------------------
1012 // Set up to use the "pluggable" Print Progress Dialog
1014 nsPrintEngine::ShowPrintProgress(PRBool aIsForPrinting
, PRBool
& aDoNotify
)
1016 // default to not notifying, that if something here goes wrong
1017 // or we aren't going to show the progress dialog we can straight into
1018 // reflowing the doc for printing.
1019 aDoNotify
= PR_FALSE
;
1021 // Assume we can't do progress and then see if we can
1022 PRBool showProgresssDialog
= PR_FALSE
;
1024 // if it is already being shown then don't bother to find out if it should be
1025 // so skip this and leave mShowProgressDialog set to FALSE
1026 if (!mProgressDialogIsShown
) {
1027 showProgresssDialog
=
1028 nsContentUtils::GetBoolPref("print.show_print_progress");
1031 // Turning off the showing of Print Progress in Prefs overrides
1032 // whether the calling PS desire to have it on or off, so only check PS if
1033 // prefs says it's ok to be on.
1034 if (showProgresssDialog
) {
1035 mPrt
->mPrintSettings
->GetShowPrintProgress(&showProgresssDialog
);
1038 // Now open the service to get the progress dialog
1039 // If we don't get a service, that's ok, then just don't show progress
1040 if (showProgresssDialog
) {
1041 nsCOMPtr
<nsIPrintingPromptService
> printPromptService(do_GetService(kPrintingPromptService
));
1042 if (printPromptService
) {
1043 nsPIDOMWindow
*domWin
= mDocument
->GetWindow();
1044 if (!domWin
) return;
1046 nsCOMPtr
<nsIDocShellTreeItem
> docShellItem
=
1047 do_QueryInterface(domWin
->GetDocShell());
1048 if (!docShellItem
) return;
1049 nsCOMPtr
<nsIDocShellTreeOwner
> owner
;
1050 docShellItem
->GetTreeOwner(getter_AddRefs(owner
));
1051 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
= do_GetInterface(owner
);
1052 if (!browserChrome
) return;
1053 PRBool isModal
= PR_TRUE
;
1054 browserChrome
->IsWindowModal(&isModal
);
1056 // Showing a print progress dialog when printing a modal window
1057 // isn't supported. See bug 301560.
1061 nsCOMPtr
<nsIWebProgressListener
> printProgressListener
;
1063 nsCOMPtr
<nsIWebBrowserPrint
> wbp(do_QueryInterface(mDocViewerPrint
));
1064 nsresult rv
= printPromptService
->ShowProgress(domWin
, wbp
, mPrt
->mPrintSettings
, this, aIsForPrinting
,
1065 getter_AddRefs(printProgressListener
),
1066 getter_AddRefs(mPrt
->mPrintProgressParams
),
1068 if (NS_SUCCEEDED(rv
)) {
1069 if (printProgressListener
&& mPrt
->mPrintProgressParams
) {
1070 mPrt
->mPrintProgressListeners
.AppendObject(printProgressListener
);
1071 SetDocAndURLIntoProgress(mPrt
->mPrintObject
, mPrt
->mPrintProgressParams
);
1078 //---------------------------------------------------------------------
1080 nsPrintEngine::IsThereARangeSelection(nsIDOMWindow
* aDOMWin
)
1082 nsCOMPtr
<nsIPresShell
> presShell
;
1084 nsCOMPtr
<nsPIDOMWindow
> window(do_QueryInterface(aDOMWin
));
1085 window
->GetDocShell()->GetPresShell(getter_AddRefs(presShell
));
1091 // check here to see if there is a range selection
1092 // so we know whether to turn on the "Selection" radio button
1093 nsCOMPtr
<nsISelection
> selection
;
1094 selection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
1097 selection
->GetRangeCount(&count
);
1099 nsCOMPtr
<nsIDOMRange
> range
;
1100 if (NS_SUCCEEDED(selection
->GetRangeAt(0, getter_AddRefs(range
)))) {
1101 // check to make sure it isn't an insertion selection
1103 selection
->GetIsCollapsed(&isCollapsed
);
1104 return !isCollapsed
;
1107 if (count
> 1) return PR_TRUE
;
1112 //---------------------------------------------------------------------
1114 nsPrintEngine::IsParentAFrameSet(nsIDocShell
* aParent
)
1116 // See if the incoming doc is the root document
1117 nsCOMPtr
<nsIDocShellTreeItem
> parentAsItem(do_QueryInterface(aParent
));
1118 if (!parentAsItem
) return PR_FALSE
;
1120 // When it is the top level document we need to check
1121 // to see if it contains a frameset. If it does, then
1122 // we only want to print the doc's children and not the document itself
1123 // For anything else we always print all the children and the document
1124 // for example, if the doc contains an IFRAME we eant to print the child
1125 // document (the IFRAME) and then the rest of the document.
1127 // XXX we really need to search the frame tree, and not the content
1128 // but there is no way to distinguish between IFRAMEs and FRAMEs
1129 // with the GetFrameType call.
1130 // Bug 53459 has been files so we can eventually distinguish
1131 // between IFRAME frames and FRAME frames
1132 PRBool isFrameSet
= PR_FALSE
;
1133 // only check to see if there is a frameset if there is
1134 // NO parent doc for this doc. meaning this parent is the root doc
1135 nsCOMPtr
<nsIDOMDocument
> domDoc
= do_GetInterface(aParent
);
1136 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
1138 nsIContent
*rootElement
= doc
->GetRootElement();
1140 isFrameSet
= HasFramesetChild(rootElement
);
1147 //---------------------------------------------------------------------
1148 // Recursively build a list of sub documents to be printed
1149 // that mirrors the document tree
1151 nsPrintEngine::BuildDocTree(nsIDocShellTreeNode
* aParentNode
,
1152 nsTArray
<nsPrintObject
*> * aDocList
,
1153 nsPrintObject
* aPO
)
1155 NS_ASSERTION(aParentNode
, "Pointer is null!");
1156 NS_ASSERTION(aDocList
, "Pointer is null!");
1157 NS_ASSERTION(aPO
, "Pointer is null!");
1159 PRInt32 childWebshellCount
;
1160 aParentNode
->GetChildCount(&childWebshellCount
);
1161 if (childWebshellCount
> 0) {
1162 for (PRInt32 i
=0;i
<childWebshellCount
;i
++) {
1163 nsCOMPtr
<nsIDocShellTreeItem
> child
;
1164 aParentNode
->GetChildAt(i
, getter_AddRefs(child
));
1165 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
1167 nsCOMPtr
<nsIContentViewer
> viewer
;
1168 childAsShell
->GetContentViewer(getter_AddRefs(viewer
));
1170 nsCOMPtr
<nsIContentViewerFile
> viewerFile(do_QueryInterface(viewer
));
1172 nsCOMPtr
<nsIDocShell
> childDocShell(do_QueryInterface(child
));
1173 nsCOMPtr
<nsIDocShellTreeNode
> childNode(do_QueryInterface(child
));
1174 nsCOMPtr
<nsIDOMDocument
> doc
= do_GetInterface(childDocShell
);
1175 nsPrintObject
* po
= new nsPrintObject();
1177 nsresult rv
= po
->Init(childDocShell
, doc
, aPO
->mPrintPreview
);
1179 NS_NOTREACHED("Init failed?");
1180 aPO
->mKids
.AppendElement(po
);
1181 aDocList
->AppendElement(po
);
1182 BuildDocTree(childNode
, aDocList
, po
);
1189 //---------------------------------------------------------------------
1191 nsPrintEngine::GetDocumentTitleAndURL(nsIDocument
* aDoc
,
1193 PRUnichar
** aURLStr
)
1195 NS_ASSERTION(aDoc
, "Pointer is null!");
1196 NS_ASSERTION(aTitle
, "Pointer is null!");
1197 NS_ASSERTION(aURLStr
, "Pointer is null!");
1202 nsAutoString docTitle
;
1203 nsCOMPtr
<nsIDOMNSDocument
> doc
= do_QueryInterface(aDoc
);
1204 doc
->GetTitle(docTitle
);
1205 if (!docTitle
.IsEmpty()) {
1206 *aTitle
= ToNewUnicode(docTitle
);
1209 nsIURI
* url
= aDoc
->GetDocumentURI();
1212 nsCOMPtr
<nsIURIFixup
> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
1213 if (!urifixup
) return;
1215 nsCOMPtr
<nsIURI
> exposableURI
;
1216 urifixup
->CreateExposableURI(url
, getter_AddRefs(exposableURI
));
1218 if (!exposableURI
) return;
1220 nsCAutoString urlCStr
;
1221 exposableURI
->GetSpec(urlCStr
);
1224 nsCOMPtr
<nsITextToSubURI
> textToSubURI
=
1225 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID
, &rv
);
1226 if (NS_FAILED(rv
)) return;
1228 nsAutoString unescapedURI
;
1229 rv
= textToSubURI
->UnEscapeURIForUI(NS_LITERAL_CSTRING("UTF-8"),
1230 urlCStr
, unescapedURI
);
1231 if (NS_FAILED(rv
)) return;
1233 *aURLStr
= ToNewUnicode(unescapedURI
);
1236 //---------------------------------------------------------------------
1237 // The walks the PO tree and for each document it walks the content
1238 // tree looking for any content that are sub-shells
1240 // It then sets the mContent pointer in the "found" PO object back to the
1241 // the document that contained it.
1243 nsPrintEngine::MapContentToWebShells(nsPrintObject
* aRootPO
,
1246 NS_ASSERTION(aRootPO
, "Pointer is null!");
1247 NS_ASSERTION(aPO
, "Pointer is null!");
1249 // Recursively walk the content from the root item
1250 // XXX Would be faster to enumerate the subdocuments, although right now
1251 // nsIDocument doesn't expose quite what would be needed.
1252 nsCOMPtr
<nsIContentViewer
> viewer
;
1253 aPO
->mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
1254 if (!viewer
) return;
1256 nsCOMPtr
<nsIDOMDocument
> domDoc
;
1257 viewer
->GetDOMDocument(getter_AddRefs(domDoc
));
1258 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
1261 Element
* rootElement
= doc
->GetRootElement();
1263 MapContentForPO(aPO
, rootElement
);
1265 NS_WARNING("Null root content on (sub)document.");
1268 // Continue recursively walking the chilren of this PO
1269 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1270 MapContentToWebShells(aRootPO
, aPO
->mKids
[i
]);
1275 //-------------------------------------------------------
1276 // A Frame's sub-doc may contain content or a FrameSet
1277 // When it contains a FrameSet the mFrameType for the PrintObject
1278 // is always set to an eFrame. Which is fine when printing "AsIs"
1279 // but is incorrect when when printing "Each Frame Separately".
1280 // When printing "Each Frame Separately" the Frame really acts like
1283 // This method walks the PO tree and checks to see if the PrintObject is
1284 // an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet)
1285 // If so, then the mFrameType need to be changed to eFrameSet
1287 // Also note: We only want to call this we are printing "Each Frame Separately"
1288 // when printing "As Is" leave it as an eFrame
1290 nsPrintEngine::CheckForChildFrameSets(nsPrintObject
* aPO
)
1292 NS_ASSERTION(aPO
, "Pointer is null!");
1294 // Continue recursively walking the chilren of this PO
1295 PRBool hasChildFrames
= PR_FALSE
;
1296 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1297 nsPrintObject
* po
= aPO
->mKids
[i
];
1298 if (po
->mFrameType
== eFrame
) {
1299 hasChildFrames
= PR_TRUE
;
1300 CheckForChildFrameSets(po
);
1304 if (hasChildFrames
&& aPO
->mFrameType
== eFrame
) {
1305 aPO
->mFrameType
= eFrameSet
;
1309 //---------------------------------------------------------------------
1310 // This method is key to the entire print mechanism.
1312 // This "maps" or figures out which sub-doc represents a
1313 // given Frame or IFrame in its parent sub-doc.
1315 // So the Mcontent pointer in the child sub-doc points to the
1316 // content in the its parent document, that caused it to be printed.
1317 // This is used later to (after reflow) to find the absolute location
1318 // of the sub-doc on its parent's page frame so it can be
1319 // printed in the correct location.
1321 // This method recursvely "walks" the content for a document finding
1322 // all the Frames and IFrames, then sets the "mFrameType" data member
1323 // which tells us what type of PO we have
1325 nsPrintEngine::MapContentForPO(nsPrintObject
* aPO
,
1326 nsIContent
* aContent
)
1328 NS_PRECONDITION(aPO
&& aContent
, "Null argument");
1330 nsIDocument
* doc
= aContent
->GetDocument();
1332 NS_ASSERTION(doc
, "Content without a document from a document tree?");
1334 nsIDocument
* subDoc
= doc
->GetSubDocumentFor(aContent
);
1337 nsCOMPtr
<nsISupports
> container
= subDoc
->GetContainer();
1338 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(container
));
1341 nsPrintObject
* po
= nsnull
;
1342 PRInt32 cnt
= aPO
->mKids
.Length();
1343 for (PRInt32 i
=0;i
<cnt
;i
++) {
1344 nsPrintObject
* kid
= aPO
->mKids
.ElementAt(i
);
1345 if (kid
->mDocument
== subDoc
) {
1351 // XXX If a subdocument has no onscreen presentation, there will be no PO
1352 // This is even if there should be a print presentation
1355 nsCOMPtr
<nsIDOMHTMLFrameElement
> frame(do_QueryInterface(aContent
));
1356 // "frame" elements not in a frameset context should be treated
1358 if (frame
&& po
->mParent
->mFrameType
== eFrameSet
) {
1359 po
->mFrameType
= eFrame
;
1361 // Assume something iframe-like, i.e. iframe, object, or embed
1362 po
->mFrameType
= eIFrame
;
1363 SetPrintAsIs(po
, PR_TRUE
);
1364 NS_ASSERTION(po
->mParent
, "The root must be a parent");
1365 po
->mParent
->mPrintAsIs
= PR_TRUE
;
1371 // walk children content
1372 PRUint32 count
= aContent
->GetChildCount();
1373 for (PRUint32 i
= 0; i
< count
; ++i
) {
1374 nsIContent
*child
= aContent
->GetChildAt(i
);
1375 MapContentForPO(aPO
, child
);
1379 //---------------------------------------------------------------------
1381 nsPrintEngine::IsThereAnIFrameSelected(nsIDocShell
* aDocShell
,
1382 nsIDOMWindow
* aDOMWin
,
1383 PRPackedBool
& aIsParentFrameSet
)
1385 aIsParentFrameSet
= IsParentAFrameSet(aDocShell
);
1386 PRBool iFrameIsSelected
= PR_FALSE
;
1387 if (mPrt
&& mPrt
->mPrintObject
) {
1388 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, aDOMWin
);
1389 iFrameIsSelected
= po
&& po
->mFrameType
== eIFrame
;
1391 // First, check to see if we are a frameset
1392 if (!aIsParentFrameSet
) {
1393 // Check to see if there is a currenlt focused frame
1394 // if so, it means the selected frame is either the main docshell
1397 // Get the main docshell's DOMWin to see if it matches
1398 // the frame that is selected
1399 nsCOMPtr
<nsIDOMWindow
> domWin
= do_GetInterface(aDocShell
);
1400 if (domWin
!= aDOMWin
) {
1401 iFrameIsSelected
= PR_TRUE
; // we have a selected IFRAME
1407 return iFrameIsSelected
;
1410 //---------------------------------------------------------------------
1411 // Recursively sets all the PO items to be printed
1412 // from the given item down into the tree
1414 nsPrintEngine::SetPrintPO(nsPrintObject
* aPO
, PRBool aPrint
)
1416 NS_ASSERTION(aPO
, "Pointer is null!");
1418 // Set whether to print flag
1419 aPO
->mDontPrint
= !aPrint
;
1421 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
1422 SetPrintPO(aPO
->mKids
[i
], aPrint
);
1426 //---------------------------------------------------------------------
1427 // This will first use a Title and/or URL from the PrintSettings
1428 // if one isn't set then it uses the one from the document
1429 // then if not title is there we will make sure we send something back
1430 // depending on the situation.
1432 nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject
* aPO
,
1434 PRUnichar
** aURLStr
,
1435 eDocTitleDefault aDefType
)
1437 NS_ASSERTION(aPO
, "Pointer is null!");
1438 NS_ASSERTION(aTitle
, "Pointer is null!");
1439 NS_ASSERTION(aURLStr
, "Pointer is null!");
1447 // First check to see if the PrintSettings has defined an alternate title
1448 // and use that if it did
1449 PRUnichar
* docTitleStrPS
= nsnull
;
1450 PRUnichar
* docURLStrPS
= nsnull
;
1451 if (mPrt
->mPrintSettings
) {
1452 mPrt
->mPrintSettings
->GetTitle(&docTitleStrPS
);
1453 mPrt
->mPrintSettings
->GetDocURL(&docURLStrPS
);
1455 if (docTitleStrPS
&& *docTitleStrPS
) {
1456 *aTitle
= docTitleStrPS
;
1459 if (docURLStrPS
&& *docURLStrPS
) {
1460 *aURLStr
= docURLStrPS
;
1464 if (docTitleStrPS
&& docURLStrPS
) {
1469 PRUnichar
* docTitle
;
1471 GetDocumentTitleAndURL(aPO
->mDocument
, &docTitle
, &docUrl
);
1477 nsMemory::Free(docUrl
);
1484 nsMemory::Free(docTitle
);
1485 } else if (!docTitleStrPS
) {
1487 case eDocTitleDefBlank
: *aTitle
= ToNewUnicode(EmptyString());
1490 case eDocTitleDefURLDoc
:
1492 *aTitle
= NS_strdup(*aURLStr
);
1493 } else if (mPrt
->mBrandName
) {
1494 *aTitle
= NS_strdup(mPrt
->mBrandName
);
1497 case eDocTitleDefNone
:
1498 // *aTitle defaults to nsnull
1504 //---------------------------------------------------------------------
1505 nsresult
nsPrintEngine::DocumentReadyForPrinting()
1507 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
) {
1508 CheckForChildFrameSets(mPrt
->mPrintObject
);
1512 // Send the document to the printer...
1514 nsresult rv
= SetupToPrintContent();
1515 if (NS_FAILED(rv
)) {
1516 // The print job was canceled or there was a problem
1517 // So remove all other documents from the print list
1518 DonePrintingPages(nsnull
, rv
);
1523 /** ---------------------------------------------------
1524 * Cleans up when an error occurred
1526 nsresult
nsPrintEngine::CleanupOnFailure(nsresult aResult
, PRBool aIsPrinting
)
1528 PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting
?"Printing":"Print Preview", aResult
));
1531 if (mPagePrintTimer
) {
1532 mPagePrintTimer
->Stop();
1533 NS_RELEASE(mPagePrintTimer
);
1537 SetIsPrinting(PR_FALSE
);
1539 SetIsPrintPreview(PR_FALSE
);
1540 SetIsCreatingPrintPreview(PR_FALSE
);
1543 /* cleanup done, let's fire-up an error dialog to notify the user
1544 * what went wrong...
1546 * When rv == NS_ERROR_ABORT, it means we want out of the
1547 * print job without displaying any error messages
1549 if (aResult
!= NS_ERROR_ABORT
) {
1550 ShowPrintErrorDialog(aResult
, aIsPrinting
);
1553 FirePrintCompletionEvent();
1559 //---------------------------------------------------------------------
1561 nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError
, PRBool aIsPrinting
)
1564 PR_PL(("nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError=%lx, PRBool aIsPrinting=%d)\n", (long)aPrintError
, (int)aIsPrinting
));
1566 nsCAutoString stringName
;
1570 #define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName.AssignLiteral(#nserr); break;
1571 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND
)
1572 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE
)
1573 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE
)
1574 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND
)
1575 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED
)
1576 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE
)
1577 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY
)
1578 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER
)
1579 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR
)
1580 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE
)
1581 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR
)
1582 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW
)
1583 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED
)
1584 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY
)
1585 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED
)
1586 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE
)
1587 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT
)
1588 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC
)
1589 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC
)
1590 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE
)
1591 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE
)
1592 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW
)
1593 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED
)
1594 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED
)
1595 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED
)
1596 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES
)
1597 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR
)
1598 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP
)
1599 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED
)
1600 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT
)
1601 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE
)
1602 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL
) // Temporary code for Bug 136185 / bug 240490
1603 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PLEX_NOT_SUPPORTED
)
1604 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY
)
1605 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED
)
1606 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE
)
1607 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_RESOLUTION_NOT_SUPPORTED
)
1610 NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE
)
1611 #undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG
1614 PR_PL(("ShowPrintErrorDialog: stringName='%s'\n", stringName
.get()));
1616 nsXPIDLString msg
, title
;
1618 nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
1619 stringName
.get(), msg
);
1620 if (NS_FAILED(rv
)) {
1621 PR_PL(("GetLocalizedString failed\n"));
1625 rv
= nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
1626 aIsPrinting
? "print_error_dialog_title"
1627 : "printpreview_error_dialog_title",
1630 nsCOMPtr
<nsIWindowWatcher
> wwatch
= do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
1631 if (NS_FAILED(rv
)) {
1632 PR_PL(("ShowPrintErrorDialog(): wwatch==nsnull\n"));
1636 nsCOMPtr
<nsIDOMWindow
> active
;
1637 wwatch
->GetActiveWindow(getter_AddRefs(active
));
1639 nsCOMPtr
<nsIPrompt
> dialog
;
1640 /* |GetNewPrompter| allows that |active| is |nsnull|
1641 * (see bug 234982 ("nsPrintEngine::ShowPrintErrorDialog() fails in many cases")) */
1642 wwatch
->GetNewPrompter(active
, getter_AddRefs(dialog
));
1644 PR_PL(("ShowPrintErrorDialog(): dialog==nsnull\n"));
1648 dialog
->Alert(title
.get(), msg
.get());
1649 PR_PL(("ShowPrintErrorDialog(): alert displayed successfully.\n"));
1652 //-----------------------------------------------------------------
1653 //-- Section: Reflow Methods
1654 //-----------------------------------------------------------------
1656 //-------------------------------------------------------
1658 nsPrintEngine::SetupToPrintContent()
1660 // In this step we figure out which documents should be printed
1661 // i.e. if we are printing the selection then only enable that nsPrintObject
1663 if (NS_FAILED(EnablePOsForPrinting())) {
1664 return NS_ERROR_FAILURE
;
1666 DUMP_DOC_LIST("\nAfter Enable------------------------------------------");
1668 // This is an Optimization
1669 // If we are in PP then we already know all the shrinkage information
1670 // so just transfer it to the PrintData and we will skip the extra shrinkage reflow
1672 // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC
1673 // The first time we do not want to do this, the second time through we do
1674 PRBool doSetPixelScale
= PR_FALSE
;
1675 PRBool ppIsShrinkToFit
= mPrtPreview
&& mPrtPreview
->mShrinkToFit
;
1676 if (ppIsShrinkToFit
) {
1677 mPrt
->mShrinkRatio
= mPrtPreview
->mShrinkRatio
;
1678 doSetPixelScale
= PR_TRUE
;
1681 // Here we reflow all the PrintObjects
1682 nsresult rv
= ReflowDocList(mPrt
->mPrintObject
, doSetPixelScale
);
1683 if (NS_FAILED(rv
)) {
1684 return NS_ERROR_FAILURE
;
1687 // Here is where we do the extra reflow for shrinking the content
1688 // But skip this step if we are in PrintPreview
1689 if (mPrt
->mShrinkToFit
&& !ppIsShrinkToFit
) {
1690 // Now look for the PO that has the smallest percent for shrink to fit
1691 if (mPrt
->mPrintDocList
.Length() > 1 && mPrt
->mPrintObject
->mFrameType
== eFrameSet
) {
1692 nsPrintObject
* smallestPO
= FindSmallestSTF();
1693 NS_ASSERTION(smallestPO
, "There must always be an XMost PO!");
1695 // Calc the shrinkage based on the entire content area
1696 mPrt
->mShrinkRatio
= smallestPO
->mShrinkRatio
;
1699 // Single document so use the Shrink as calculated for the PO
1700 mPrt
->mShrinkRatio
= mPrt
->mPrintObject
->mShrinkRatio
;
1703 // Only Shrink if we are smaller
1704 if (mPrt
->mShrinkRatio
< 0.998f
) {
1705 // Clamp Shrink to Fit to 60%
1706 mPrt
->mShrinkRatio
= NS_MAX(mPrt
->mShrinkRatio
, 0.60f
);
1708 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
1709 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
1710 NS_ASSERTION(po
, "nsPrintObject can't be null!");
1711 // Wipe out the presentation before we reflow
1712 po
->DestroyPresentation();
1715 #if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
1716 // We need to clear all the output files here
1717 // because they will be re-created with second reflow of the docs
1718 if (kPrintingLogMod
&& kPrintingLogMod
->level
== DUMP_LAYOUT_LEVEL
) {
1719 RemoveFilesInDir(".\\");
1720 gDumpFileNameCnt
= 0;
1721 gDumpLOFileNameCnt
= 0;
1725 // Here we reflow all the PrintObjects a second time
1726 // this time using the shrinkage values
1727 // The last param here tells reflow to NOT calc the shrinkage values
1728 if (NS_FAILED(ReflowDocList(mPrt
->mPrintObject
, PR_TRUE
))) {
1729 return NS_ERROR_FAILURE
;
1735 float calcRatio
= 0.0f
;
1736 if (mPrt
->mPrintDocList
.Length() > 1 && mPrt
->mPrintObject
->mFrameType
== eFrameSet
) {
1737 nsPrintObject
* smallestPO
= FindSmallestSTF();
1738 NS_ASSERTION(smallestPO
, "There must always be an XMost PO!");
1740 // Calc the shrinkage based on the entire content area
1741 calcRatio
= smallestPO
->mShrinkRatio
;
1744 // Single document so use the Shrink as calculated for the PO
1745 calcRatio
= mPrt
->mPrintObject
->mShrinkRatio
;
1747 PR_PL(("**************************************************************************\n"));
1748 PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt
->mShrinkRatio
, calcRatio
, mPrt
->mShrinkRatio
-calcRatio
));
1749 PR_PL(("**************************************************************************\n"));
1754 DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------"));
1756 PR_PL(("-------------------------------------------------------\n"));
1759 CalcNumPrintablePages(mPrt
->mNumPrintablePages
);
1761 PR_PL(("--- Printing %d pages\n", mPrt
->mNumPrintablePages
));
1762 DUMP_DOC_TREELAYOUT
;
1764 // Print listener setup...
1765 if (mPrt
!= nsnull
) {
1766 mPrt
->OnStartPrinting();
1769 PRUnichar
* fileName
= nsnull
;
1770 // check to see if we are printing to a file
1771 PRBool isPrintToFile
= PR_FALSE
;
1772 mPrt
->mPrintSettings
->GetPrintToFile(&isPrintToFile
);
1773 if (isPrintToFile
) {
1774 // On some platforms The BeginDocument needs to know the name of the file
1775 // and it uses the PrintService to get it, so we need to set it into the PrintService here
1776 mPrt
->mPrintSettings
->GetToFileName(&fileName
);
1779 PRUnichar
* docTitleStr
;
1780 PRUnichar
* docURLStr
;
1781 GetDisplayTitleAndURL(mPrt
->mPrintObject
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
1783 PRInt32 startPage
= 1;
1784 PRInt32 endPage
= mPrt
->mNumPrintablePages
;
1786 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
1787 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
1788 if (printRangeType
== nsIPrintSettings::kRangeSpecifiedPageRange
) {
1789 mPrt
->mPrintSettings
->GetStartPageRange(&startPage
);
1790 mPrt
->mPrintSettings
->GetEndPageRange(&endPage
);
1791 if (endPage
> mPrt
->mNumPrintablePages
) {
1792 endPage
= mPrt
->mNumPrintablePages
;
1797 // BeginDocument may pass back a FAILURE code
1798 // i.e. On Windows, if you are printing to a file and hit "Cancel"
1799 // to the "File Name" dialog, this comes back as an error
1800 // Don't start printing when regression test are executed
1801 if (!mPrt
->mDebugFilePtr
&& mIsDoingPrinting
) {
1802 rv
= mPrt
->mPrintDC
->BeginDocument(docTitleStr
, fileName
, startPage
, endPage
);
1805 if (mIsCreatingPrintPreview
) {
1806 // Print Preview -- Pass ownership of docTitleStr and docURLStr
1807 // to the pageSequenceFrame, to be displayed in the header
1808 nsIPageSequenceFrame
*seqFrame
= mPrt
->mPrintObject
->mPresShell
->GetPageSequenceFrame();
1810 seqFrame
->StartPrint(mPrt
->mPrintObject
->mPresContext
,
1811 mPrt
->mPrintSettings
, docTitleStr
, docURLStr
);
1812 docTitleStr
= nsnull
;
1816 if (docTitleStr
) nsMemory::Free(docTitleStr
);
1817 if (docURLStr
) nsMemory::Free(docURLStr
);
1819 PR_PL(("****************** Begin Document ************************\n"));
1821 NS_ENSURE_SUCCESS(rv
, rv
);
1823 // This will print the docshell document
1824 // when it completes asynchronously in the DonePrintingPages method
1825 // it will check to see if there are more docshells to be printed and
1826 // then PrintDocContent will be called again.
1828 if (mIsDoingPrinting
) {
1829 PrintDocContent(mPrt
->mPrintObject
, rv
); // ignore return value
1835 //-------------------------------------------------------
1836 // Recursively reflow each sub-doc and then calc
1837 // all the frame locations of the sub-docs
1839 nsPrintEngine::ReflowDocList(nsPrintObject
* aPO
, PRBool aSetPixelScale
)
1841 NS_ENSURE_ARG_POINTER(aPO
);
1843 // Check to see if the subdocument's element has been hidden by the parent document
1844 if (aPO
->mParent
&& aPO
->mParent
->mPresShell
) {
1845 nsIFrame
* frame
= aPO
->mContent
->GetPrimaryFrame();
1847 if (!frame
->GetStyleVisibility()->IsVisible()) {
1848 aPO
->mDontPrint
= PR_TRUE
;
1849 aPO
->mInvisible
= PR_TRUE
;
1855 // Here is where we set the shrinkage value into the DC
1856 // and this is what actually makes it shrink
1857 if (aSetPixelScale
&& aPO
->mFrameType
!= eIFrame
) {
1859 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kFramesAsIs
|| mPrt
->mPrintFrameType
== nsIPrintSettings::kNoFrames
) {
1860 ratio
= mPrt
->mShrinkRatio
- 0.005f
; // round down
1862 ratio
= aPO
->mShrinkRatio
- 0.005f
; // round down
1864 aPO
->mZoomRatio
= ratio
;
1865 } else if (!mPrt
->mShrinkToFit
) {
1867 mPrt
->mPrintSettings
->GetScaling(&scaling
);
1868 aPO
->mZoomRatio
= float(scaling
);
1873 rv
= ReflowPrintObject(aPO
);
1874 NS_ENSURE_SUCCESS(rv
, rv
);
1876 PRInt32 cnt
= aPO
->mKids
.Length();
1877 for (PRInt32 i
=0;i
<cnt
;i
++) {
1878 rv
= ReflowDocList(aPO
->mKids
[i
], aSetPixelScale
);
1879 NS_ENSURE_SUCCESS(rv
, rv
);
1884 //-------------------------------------------------------
1885 // Reflow a nsPrintObject
1887 nsPrintEngine::ReflowPrintObject(nsPrintObject
* aPO
)
1889 NS_ASSERTION(aPO
, "Pointer is null!");
1890 if (!aPO
) return NS_ERROR_FAILURE
;
1893 PRBool documentIsTopLevel
;
1894 if (!aPO
->IsPrintable())
1897 PRBool canCreateScrollbars
= PR_TRUE
;
1898 nsIView
* parentView
= nsnull
;
1900 if (aPO
->mParent
&& aPO
->mParent
->IsPrintable()) {
1901 nsIFrame
* frame
= aPO
->mContent
->GetPrimaryFrame();
1902 // Without a frame, this document can't be displayed; therefore, there is no
1903 // point to reflowing it
1905 SetPrintPO(aPO
, PR_FALSE
);
1909 //XXX If printing supported printing document hierarchies with non-constant
1910 // zoom this would be wrong as we use the same mPrt->mPrintDC for all
1912 adjSize
= frame
->GetContentRect().Size();
1913 documentIsTopLevel
= PR_FALSE
;
1914 // presshell exists because parent is printable
1916 // the top nsPrintObject's widget will always have scrollbars
1917 if (frame
&& frame
->GetType() == nsGkAtoms::subDocumentFrame
) {
1918 nsIView
* view
= frame
->GetView();
1919 NS_ENSURE_TRUE(view
, NS_ERROR_FAILURE
);
1920 view
= view
->GetFirstChild();
1921 NS_ENSURE_TRUE(view
, NS_ERROR_FAILURE
);
1923 canCreateScrollbars
= PR_FALSE
;
1926 nscoord pageWidth
, pageHeight
;
1927 mPrt
->mPrintDC
->GetDeviceSurfaceDimensions(pageWidth
, pageHeight
);
1928 #if defined(XP_UNIX) && !defined(XP_MACOSX)
1929 // If we're in landscape mode on Linux, the device surface will have
1930 // been rotated, so for the purposes of reflowing content, we'll
1931 // treat device's height as our width and its width as our height,
1932 PRInt32 orientation
;
1933 mPrt
->mPrintSettings
->GetOrientation(&orientation
);
1934 if (nsIPrintSettings::kLandscapeOrientation
== orientation
) {
1935 adjSize
= nsSize(pageHeight
, pageWidth
);
1937 adjSize
= nsSize(pageWidth
, pageHeight
);
1940 adjSize
= nsSize(pageWidth
, pageHeight
);
1941 #endif // XP_UNIX && !XP_MACOSX
1942 documentIsTopLevel
= PR_TRUE
;
1944 if (mIsCreatingPrintPreview
) {
1945 nsCOMPtr
<nsIDocumentViewer
> dv
= do_QueryInterface(mDocViewerPrint
);
1947 parentView
= dv
->FindContainerView();
1952 NS_ASSERTION(!aPO
->mPresContext
, "Recreating prescontext");
1954 // create the PresContext
1955 aPO
->mPresContext
= new nsPresContext(aPO
->mDocument
,
1956 mIsCreatingPrintPreview
? nsPresContext::eContext_PrintPreview
:
1957 nsPresContext::eContext_Print
);
1958 NS_ENSURE_TRUE(aPO
->mPresContext
, NS_ERROR_OUT_OF_MEMORY
);
1959 aPO
->mPresContext
->SetPrintSettings(mPrt
->mPrintSettings
);
1961 // set the presentation context to the value in the print settings
1962 PRBool printBGColors
;
1963 mPrt
->mPrintSettings
->GetPrintBGColors(&printBGColors
);
1964 aPO
->mPresContext
->SetBackgroundColorDraw(printBGColors
);
1965 mPrt
->mPrintSettings
->GetPrintBGImages(&printBGColors
);
1966 aPO
->mPresContext
->SetBackgroundImageDraw(printBGColors
);
1968 // init it with the DC
1969 nsresult rv
= aPO
->mPresContext
->Init(mPrt
->mPrintDC
);
1970 NS_ENSURE_SUCCESS(rv
, rv
);
1972 aPO
->mViewManager
= do_CreateInstance(kViewManagerCID
, &rv
);
1973 NS_ENSURE_SUCCESS(rv
,rv
);
1975 rv
= aPO
->mViewManager
->Init(mPrt
->mPrintDC
);
1976 NS_ENSURE_SUCCESS(rv
,rv
);
1978 nsStyleSet
* styleSet
;
1979 rv
= mDocViewerPrint
->CreateStyleSet(aPO
->mDocument
, &styleSet
);
1980 NS_ENSURE_SUCCESS(rv
, rv
);
1982 rv
= aPO
->mDocument
->CreateShell(aPO
->mPresContext
, aPO
->mViewManager
,
1983 styleSet
, getter_AddRefs(aPO
->mPresShell
));
1984 if (NS_FAILED(rv
)) {
1989 styleSet
->EndUpdate();
1991 // The pres shell now owns the style set object.
1993 PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO
,
1994 gFrameTypesStr
[aPO
->mFrameType
], adjSize
.width
, adjSize
.height
));
1996 // Create a child window of the parent that is our "root view/window"
1997 nsRect tbounds
= nsRect(nsPoint(0, 0), adjSize
);
1998 nsIView
* rootView
= aPO
->mViewManager
->CreateView(tbounds
, parentView
);
1999 NS_ENSURE_TRUE(rootView
, NS_ERROR_OUT_OF_MEMORY
);
2001 if (mIsCreatingPrintPreview
&& documentIsTopLevel
) {
2002 aPO
->mPresContext
->SetPaginatedScrolling(canCreateScrollbars
);
2005 // Setup hierarchical relationship in view manager
2006 aPO
->mViewManager
->SetRootView(rootView
);
2008 // This docshell stuff is weird; will go away when we stop having multiple
2009 // presentations per document
2010 nsCOMPtr
<nsISupports
> supps(do_QueryInterface(aPO
->mDocShell
));
2011 aPO
->mPresContext
->SetContainer(supps
);
2013 aPO
->mPresShell
->BeginObservingDocument();
2015 aPO
->mPresContext
->SetPageSize(adjSize
);
2016 aPO
->mPresContext
->SetIsRootPaginatedDocument(documentIsTopLevel
);
2017 aPO
->mPresContext
->SetPageScale(aPO
->mZoomRatio
);
2018 // Calculate scale factor from printer to screen
2019 float printDPI
= float(mPrt
->mPrintDC
->AppUnitsPerCSSInch()) /
2020 float(mPrt
->mPrintDC
->AppUnitsPerDevPixel());
2021 aPO
->mPresContext
->SetPrintPreviewScale(mScreenDPI
/ printDPI
);
2023 if (mIsCreatingPrintPreview
&& documentIsTopLevel
) {
2024 mDocViewerPrint
->SetPrintPreviewPresentation(aPO
->mViewManager
,
2029 rv
= aPO
->mPresShell
->InitialReflow(adjSize
.width
, adjSize
.height
);
2031 NS_ENSURE_SUCCESS(rv
, rv
);
2032 NS_ASSERTION(aPO
->mPresShell
, "Presshell should still be here");
2034 // Process the reflow event InitialReflow posted
2035 aPO
->mPresShell
->FlushPendingNotifications(Flush_Layout
);
2037 nsCOMPtr
<nsIPresShell
> displayShell
;
2038 aPO
->mDocShell
->GetPresShell(getter_AddRefs(displayShell
));
2039 // Transfer Selection Ranges to the new Print PresShell
2040 nsCOMPtr
<nsISelection
> selection
, selectionPS
;
2041 // It's okay if there is no display shell, just skip copying the selection
2043 selection
= displayShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2045 selectionPS
= aPO
->mPresShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2046 if (selection
&& selectionPS
) {
2048 selection
->GetRangeCount(&cnt
);
2050 for (inx
=0;inx
<cnt
;inx
++) {
2051 nsCOMPtr
<nsIDOMRange
> range
;
2052 if (NS_SUCCEEDED(selection
->GetRangeAt(inx
, getter_AddRefs(range
))))
2053 selectionPS
->AddRange(range
);
2057 // If we are trying to shrink the contents to fit on the page
2058 // we must first locate the "pageContent" frame
2059 // Then we walk the frame tree and look for the "xmost" frame
2060 // this is the frame where the right-hand side of the frame extends
2062 if (mPrt
->mShrinkToFit
&& documentIsTopLevel
) {
2063 nsIPageSequenceFrame
* pageSequence
= aPO
->mPresShell
->GetPageSequenceFrame();
2064 NS_ENSURE_STATE(pageSequence
);
2065 pageSequence
->GetSTFPercent(aPO
->mShrinkRatio
);
2068 #ifdef EXTENDED_DEBUG_PRINTING
2069 if (kPrintingLogMod
&& kPrintingLogMod
->level
== DUMP_LAYOUT_LEVEL
) {
2072 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
2074 sprintf(filename
, "print_dump_%d.txt", gDumpFileNameCnt
++);
2075 // Dump all the frames and view to a a file
2076 FILE * fd
= fopen(filename
, "w");
2078 nsIFrame
*theRootFrame
=
2079 aPO
->mPresShell
->FrameManager()->GetRootFrame();
2080 fprintf(fd
, "Title: %s\n", docStr
?docStr
:"");
2081 fprintf(fd
, "URL: %s\n", urlStr
?urlStr
:"");
2082 fprintf(fd
, "--------------- Frames ----------------\n");
2083 nsCOMPtr
<nsIRenderingContext
> renderingContext
;
2084 mPrt
->mPrintDocDC
->CreateRenderingContext(*getter_AddRefs(renderingContext
));
2085 RootFrameList(aPO
->mPresContext
, fd
, 0);
2086 //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0);
2087 fprintf(fd
, "---------------------------------------\n\n");
2088 fprintf(fd
, "--------------- Views From Root Frame----------------\n");
2089 nsIView
* v
= theRootFrame
->GetView();
2093 printf("View is null!\n");
2096 fprintf(fd
, "--------------- All Views ----------------\n");
2097 DumpViews(docShell
, fd
);
2098 fprintf(fd
, "---------------------------------------\n\n");
2102 if (docStr
) nsMemory::Free(docStr
);
2103 if (urlStr
) nsMemory::Free(urlStr
);
2110 //-------------------------------------------------------
2111 // Figure out how many documents and how many total pages we are printing
2113 nsPrintEngine::CalcNumPrintablePages(PRInt32
& aNumPages
)
2116 // Count the number of printable documents
2117 // and printable pages
2118 for (PRUint32 i
=0; i
<mPrt
->mPrintDocList
.Length(); i
++) {
2119 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
2120 NS_ASSERTION(po
, "nsPrintObject can't be null!");
2121 if (po
->mPresContext
&& po
->mPresContext
->IsRootPaginatedDocument()) {
2122 nsIPageSequenceFrame
* pageSequence
= po
->mPresShell
->GetPageSequenceFrame();
2123 nsIFrame
* seqFrame
= do_QueryFrame(pageSequence
);
2125 nsIFrame
* frame
= seqFrame
->GetFirstChild(nsnull
);
2128 frame
= frame
->GetNextSibling();
2134 //-----------------------------------------------------------------
2135 //-- Done: Reflow Methods
2136 //-----------------------------------------------------------------
2138 //-----------------------------------------------------------------
2139 //-- Section: Printing Methods
2140 //-----------------------------------------------------------------
2142 //-------------------------------------------------------
2143 // Called for each DocShell that needs to be printed
2145 nsPrintEngine::PrintDocContent(nsPrintObject
* aPO
, nsresult
& aStatus
)
2147 NS_ASSERTION(aPO
, "Pointer is null!");
2150 if (!aPO
->mHasBeenPrinted
&& aPO
->IsPrintable()) {
2151 aStatus
= DoPrint(aPO
);
2155 // If |aPO->mPrintAsIs| and |aPO->mHasBeenPrinted| are true,
2156 // the kids frames are already processed in |PrintPage|.
2157 if (!aPO
->mInvisible
&& !(aPO
->mPrintAsIs
&& aPO
->mHasBeenPrinted
)) {
2158 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
2159 nsPrintObject
* po
= aPO
->mKids
[i
];
2160 PRBool printed
= PrintDocContent(po
, aStatus
);
2161 if (printed
|| NS_FAILED(aStatus
)) {
2169 static already_AddRefed
<nsIDOMNode
>
2170 GetEqualNodeInCloneTree(nsIDOMNode
* aNode
, nsIDocument
* aDoc
)
2172 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aNode
);
2173 // Selections in anonymous subtrees aren't supported.
2174 if (content
&& content
->IsInAnonymousSubtree()) {
2178 nsCOMPtr
<nsINode
> node
= do_QueryInterface(aNode
);
2179 NS_ENSURE_TRUE(node
, nsnull
);
2181 nsTArray
<PRInt32
> indexArray
;
2182 nsINode
* current
= node
;
2183 NS_ENSURE_TRUE(current
, nsnull
);
2185 nsINode
* parent
= current
->GetNodeParent();
2189 PRInt32 index
= parent
->IndexOf(current
);
2190 NS_ENSURE_TRUE(index
>= 0, nsnull
);
2191 indexArray
.AppendElement(index
);
2194 NS_ENSURE_TRUE(current
->IsNodeOfType(nsINode::eDOCUMENT
), nsnull
);
2197 for (PRInt32 i
= indexArray
.Length() - 1; i
>= 0; --i
) {
2198 current
= current
->GetChildAt(indexArray
[i
]);
2199 NS_ENSURE_TRUE(current
, nsnull
);
2201 nsCOMPtr
<nsIDOMNode
> result
= do_QueryInterface(current
);
2202 return result
.forget();
2205 static nsresult
CloneRangeToSelection(nsIDOMRange
* aRange
,
2207 nsISelection
* aSelection
)
2209 PRBool collapsed
= PR_FALSE
;
2210 aRange
->GetCollapsed(&collapsed
);
2215 nsCOMPtr
<nsIDOMNode
> startContainer
, endContainer
;
2216 PRInt32 startOffset
= -1, endOffset
= -1;
2217 aRange
->GetStartContainer(getter_AddRefs(startContainer
));
2218 aRange
->GetStartOffset(&startOffset
);
2219 aRange
->GetEndContainer(getter_AddRefs(endContainer
));
2220 aRange
->GetEndOffset(&endOffset
);
2221 NS_ENSURE_STATE(startContainer
&& endContainer
);
2223 nsCOMPtr
<nsIDOMNode
> newStart
= GetEqualNodeInCloneTree(startContainer
, aDoc
);
2224 nsCOMPtr
<nsIDOMNode
> newEnd
= GetEqualNodeInCloneTree(endContainer
, aDoc
);
2225 NS_ENSURE_STATE(newStart
&& newEnd
);
2227 nsCOMPtr
<nsIDOMRange
> range
;
2228 NS_NewRange(getter_AddRefs(range
));
2229 NS_ENSURE_TRUE(range
, NS_ERROR_OUT_OF_MEMORY
);
2231 nsresult rv
= range
->SetStart(newStart
, startOffset
);
2232 NS_ENSURE_SUCCESS(rv
, rv
);
2233 rv
= range
->SetEnd(newEnd
, endOffset
);
2234 NS_ENSURE_SUCCESS(rv
, rv
);
2236 return aSelection
->AddRange(range
);
2239 static nsresult
CloneSelection(nsIDocument
* aOrigDoc
, nsIDocument
* aDoc
)
2241 nsIPresShell
* origShell
= aOrigDoc
->GetShell();
2242 nsIPresShell
* shell
= aDoc
->GetShell();
2243 NS_ENSURE_STATE(origShell
&& shell
);
2245 nsCOMPtr
<nsISelection
> origSelection
=
2246 origShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2247 nsCOMPtr
<nsISelection
> selection
=
2248 shell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2249 NS_ENSURE_STATE(origSelection
&& selection
);
2251 PRInt32 rangeCount
= 0;
2252 origSelection
->GetRangeCount(&rangeCount
);
2253 for (PRInt32 i
= 0; i
< rangeCount
; ++i
) {
2254 nsCOMPtr
<nsIDOMRange
> range
;
2255 origSelection
->GetRangeAt(i
, getter_AddRefs(range
));
2257 CloneRangeToSelection(range
, aDoc
, selection
);
2263 //-------------------------------------------------------
2265 nsPrintEngine::DoPrint(nsPrintObject
* aPO
)
2268 PR_PL(("**************************** %s ****************************\n", gFrameTypesStr
[aPO
->mFrameType
]));
2269 PR_PL(("****** In DV::DoPrint PO: %p \n", aPO
));
2271 nsIPresShell
* poPresShell
= aPO
->mPresShell
;
2272 nsPresContext
* poPresContext
= aPO
->mPresContext
;
2274 NS_ASSERTION(poPresContext
, "PrintObject has not been reflowed");
2275 NS_ASSERTION(poPresContext
->Type() != nsPresContext::eContext_PrintPreview
,
2276 "How did this context end up here?");
2278 if (mPrt
->mPrintProgressParams
) {
2279 SetDocAndURLIntoProgress(aPO
, mPrt
->mPrintProgressParams
);
2283 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
2285 if (mPrt
->mPrintSettings
!= nsnull
) {
2286 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
2289 // Ask the page sequence frame to print all the pages
2290 nsIPageSequenceFrame
* pageSequence
= poPresShell
->GetPageSequenceFrame();
2291 NS_ASSERTION(nsnull
!= pageSequence
, "no page sequence frame");
2293 // We are done preparing for printing, so we can turn this off
2294 mPrt
->mPreparingForPrint
= PR_FALSE
;
2296 // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging
2297 if (nsnull
!= mPrt
->mDebugFilePtr
) {
2299 // output the regression test
2300 nsIFrame
* root
= poPresShell
->FrameManager()->GetRootFrame();
2301 root
->DumpRegressionData(poPresContext
, mPrt
->mDebugFilePtr
, 0);
2302 fclose(mPrt
->mDebugFilePtr
);
2303 SetIsPrinting(PR_FALSE
);
2306 #ifdef EXTENDED_DEBUG_PRINTING
2307 nsIFrame
* rootFrame
= poPresShell
->FrameManager()->GetRootFrame();
2308 if (aPO
->IsPrintable()) {
2311 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
2312 DumpLayoutData(docStr
, urlStr
, poPresContext
, mPrt
->mPrintDocDC
, rootFrame
, docShell
, nsnull
);
2313 if (docStr
) nsMemory::Free(docStr
);
2314 if (urlStr
) nsMemory::Free(urlStr
);
2318 if (!mPrt
->mPrintSettings
) {
2319 // not sure what to do here!
2320 SetIsPrinting(PR_FALSE
);
2321 return NS_ERROR_FAILURE
;
2324 PRUnichar
* docTitleStr
= nsnull
;
2325 PRUnichar
* docURLStr
= nsnull
;
2327 GetDisplayTitleAndURL(aPO
, &docTitleStr
, &docURLStr
, eDocTitleDefBlank
);
2329 if (nsIPrintSettings::kRangeSelection
== printRangeType
) {
2330 CloneSelection(aPO
->mDocument
->GetOriginalDocument(), aPO
->mDocument
);
2332 poPresContext
->SetIsRenderingOnlySelection(PR_TRUE
);
2333 // temporarily creating rendering context
2334 // which is needed to dinf the selection frames
2335 nsCOMPtr
<nsIRenderingContext
> rc
;
2336 mPrt
->mPrintDC
->CreateRenderingContext(*getter_AddRefs(rc
));
2338 // find the starting and ending page numbers
2339 // via the selection
2340 nsIFrame
* startFrame
;
2342 PRInt32 startPageNum
;
2347 nsCOMPtr
<nsISelection
> selectionPS
;
2348 selectionPS
= poPresShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
2350 rv
= GetPageRangeForSelection(poPresShell
, poPresContext
, *rc
, selectionPS
, pageSequence
,
2351 &startFrame
, startPageNum
, startRect
,
2352 &endFrame
, endPageNum
, endRect
);
2353 if (NS_SUCCEEDED(rv
)) {
2354 mPrt
->mPrintSettings
->SetStartPageRange(startPageNum
);
2355 mPrt
->mPrintSettings
->SetEndPageRange(endPageNum
);
2356 nsIntMargin
marginTwips(0,0,0,0);
2357 nsIntMargin
unwrtMarginTwips(0,0,0,0);
2358 mPrt
->mPrintSettings
->GetMarginInTwips(marginTwips
);
2359 mPrt
->mPrintSettings
->GetUnwriteableMarginInTwips(unwrtMarginTwips
);
2360 nsMargin totalMargin
= poPresContext
->CSSTwipsToAppUnits(marginTwips
+
2362 if (startPageNum
== endPageNum
) {
2363 startRect
.y
-= totalMargin
.top
;
2364 endRect
.y
-= totalMargin
.top
;
2366 // Clip out selection regions above the top of the first page
2367 if (startRect
.y
< 0) {
2368 // Reduce height to be the height of the positive-territory
2369 // region of original rect
2370 startRect
.height
= NS_MAX(0, startRect
.YMost());
2373 if (endRect
.y
< 0) {
2374 // Reduce height to be the height of the positive-territory
2375 // region of original rect
2376 endRect
.height
= NS_MAX(0, endRect
.YMost());
2379 NS_ASSERTION(endRect
.y
>= startRect
.y
,
2380 "Selection end point should be after start point");
2381 NS_ASSERTION(startRect
.height
>= 0,
2382 "rect should have non-negative height.");
2383 NS_ASSERTION(endRect
.height
>= 0,
2384 "rect should have non-negative height.");
2386 nscoord selectionHgt
= endRect
.y
+ endRect
.height
- startRect
.y
;
2387 // XXX This is temporary fix for printing more than one page of a selection
2388 pageSequence
->SetSelectionHeight(startRect
.y
* aPO
->mZoomRatio
,
2389 selectionHgt
* aPO
->mZoomRatio
);
2391 // calc total pages by getting calculating the selection's height
2392 // and then dividing it by how page content frames will fit.
2393 nscoord pageWidth
, pageHeight
;
2394 mPrt
->mPrintDC
->GetDeviceSurfaceDimensions(pageWidth
, pageHeight
);
2395 pageHeight
-= totalMargin
.top
+ totalMargin
.bottom
;
2396 PRInt32 totalPages
= NSToIntCeil(float(selectionHgt
) * aPO
->mZoomRatio
/ float(pageHeight
));
2397 pageSequence
->SetTotalNumPages(totalPages
);
2402 nsIFrame
* seqFrame
= do_QueryFrame(pageSequence
);
2404 SetIsPrinting(PR_FALSE
);
2405 if (docTitleStr
) nsMemory::Free(docTitleStr
);
2406 if (docURLStr
) nsMemory::Free(docURLStr
);
2407 return NS_ERROR_FAILURE
;
2410 mPageSeqFrame
= pageSequence
;
2411 mPageSeqFrame
->StartPrint(poPresContext
, mPrt
->mPrintSettings
, docTitleStr
, docURLStr
);
2413 // Schedule Page to Print
2414 PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO
, gFrameTypesStr
[aPO
->mFrameType
]));
2415 StartPagePrintTimer(aPO
);
2422 //---------------------------------------------------------------------
2424 nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject
* aPO
,
2425 nsIPrintProgressParams
* aParams
)
2427 NS_ASSERTION(aPO
, "Must have vaild nsPrintObject");
2428 NS_ASSERTION(aParams
, "Must have vaild nsIPrintProgressParams");
2430 if (!aPO
|| !aPO
->mDocShell
|| !aParams
) {
2433 const PRUint32 kTitleLength
= 64;
2435 PRUnichar
* docTitleStr
;
2436 PRUnichar
* docURLStr
;
2437 GetDisplayTitleAndURL(aPO
, &docTitleStr
, &docURLStr
, eDocTitleDefURLDoc
);
2439 // Make sure the Titles & URLS don't get too long for the progress dialog
2440 ElipseLongString(docTitleStr
, kTitleLength
, PR_FALSE
);
2441 ElipseLongString(docURLStr
, kTitleLength
, PR_TRUE
);
2443 aParams
->SetDocTitle(docTitleStr
);
2444 aParams
->SetDocURL(docURLStr
);
2446 if (docTitleStr
!= nsnull
) nsMemory::Free(docTitleStr
);
2447 if (docURLStr
!= nsnull
) nsMemory::Free(docURLStr
);
2450 //---------------------------------------------------------------------
2452 nsPrintEngine::ElipseLongString(PRUnichar
*& aStr
, const PRUint32 aLen
, PRBool aDoFront
)
2454 // Make sure the URLS don't get too long for the progress dialog
2455 if (aStr
&& nsCRT::strlen(aStr
) > aLen
) {
2457 PRUnichar
* ptr
= &aStr
[nsCRT::strlen(aStr
)-aLen
+3];
2458 nsAutoString newStr
;
2459 newStr
.AppendLiteral("...");
2461 nsMemory::Free(aStr
);
2462 aStr
= ToNewUnicode(newStr
);
2464 nsAutoString
newStr(aStr
);
2465 newStr
.SetLength(aLen
-3);
2466 newStr
.AppendLiteral("...");
2467 nsMemory::Free(aStr
);
2468 aStr
= ToNewUnicode(newStr
);
2473 //-------------------------------------------------------
2475 nsPrintEngine::PrintPage(nsPrintObject
* aPO
,
2478 NS_ASSERTION(aPO
, "aPO is null!");
2479 NS_ASSERTION(mPageSeqFrame
, "mPageSeqFrame is null!");
2480 NS_ASSERTION(mPrt
, "mPrt is null!");
2482 // Although these should NEVER be NULL
2483 // This is added insurance, to make sure we don't crash in optimized builds
2484 if (!mPrt
|| !aPO
|| !mPageSeqFrame
) {
2485 ShowPrintErrorDialog(NS_ERROR_FAILURE
);
2486 return PR_TRUE
; // means we are done printing
2489 PR_PL(("-----------------------------------\n"));
2490 PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO
, gFrameTypesStr
[aPO
->mFrameType
]));
2492 // Check setting to see if someone request it be cancelled
2493 PRBool isCancelled
= PR_FALSE
;
2494 mPrt
->mPrintSettings
->GetIsCancelled(&isCancelled
);
2498 PRInt32 pageNum
, numPages
, endPage
;
2499 mPageSeqFrame
->GetCurrentPageNum(&pageNum
);
2500 mPageSeqFrame
->GetNumPages(&numPages
);
2502 PRBool donePrinting
;
2503 PRBool isDoingPrintRange
;
2504 mPageSeqFrame
->IsDoingPrintRange(&isDoingPrintRange
);
2505 if (isDoingPrintRange
) {
2508 mPageSeqFrame
->GetPrintRange(&fromPage
, &toPage
);
2510 if (fromPage
> numPages
) {
2513 if (toPage
> numPages
) {
2517 PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum
, fromPage
, toPage
));
2519 donePrinting
= pageNum
>= toPage
;
2520 aInRange
= pageNum
>= fromPage
&& pageNum
<= toPage
;
2521 endPage
= (toPage
- fromPage
)+1;
2523 PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum
, numPages
));
2525 donePrinting
= pageNum
>= numPages
;
2530 // XXX This is wrong, but the actual behavior in the presence of a print
2532 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
)
2533 endPage
= mPrt
->mNumPrintablePages
;
2535 mPrt
->DoOnProgressChange(++mPrt
->mNumPagesPrinted
, endPage
, PR_FALSE
, 0);
2538 // if a print job was cancelled externally, an EndPage or BeginPage may
2539 // fail and the failure is passed back here.
2540 // Returning PR_TRUE means we are done printing.
2542 // When rv == NS_ERROR_ABORT, it means we want out of the
2543 // print job without displaying any error messages
2544 nsresult rv
= mPageSeqFrame
->PrintNextPage();
2545 if (NS_FAILED(rv
)) {
2546 if (rv
!= NS_ERROR_ABORT
) {
2547 ShowPrintErrorDialog(rv
);
2548 mPrt
->mIsAborted
= PR_TRUE
;
2553 mPageSeqFrame
->DoPageEnd();
2555 return donePrinting
;
2558 /** ---------------------------------------------------
2559 * Find by checking frames type
2562 nsPrintEngine::FindSelectionBoundsWithList(nsPresContext
* aPresContext
,
2563 nsIRenderingContext
& aRC
,
2565 nsIFrame
* aParentFrame
,
2567 nsIFrame
*& aStartFrame
,
2569 nsIFrame
*& aEndFrame
,
2572 NS_ASSERTION(aPresContext
, "Pointer is null!");
2573 NS_ASSERTION(aParentFrame
, "Pointer is null!");
2575 nsIFrame
* child
= aParentFrame
->GetFirstChild(aList
);
2576 aRect
+= aParentFrame
->GetPosition();
2578 // only leaf frames have this bit flipped
2579 // then check the hard way
2580 PRBool isSelected
= (child
->GetStateBits() & NS_FRAME_SELECTED_CONTENT
)
2581 == NS_FRAME_SELECTED_CONTENT
;
2583 isSelected
= child
->IsVisibleForPainting();
2587 nsRect r
= child
->GetRect();
2588 if (aStartFrame
== nsnull
) {
2589 aStartFrame
= child
;
2590 aStartRect
.SetRect(aRect
.x
+ r
.x
, aRect
.y
+ r
.y
, r
.width
, r
.height
);
2593 aEndRect
.SetRect(aRect
.x
+ r
.x
, aRect
.y
+ r
.y
, r
.width
, r
.height
);
2596 FindSelectionBounds(aPresContext
, aRC
, child
, aRect
, aStartFrame
, aStartRect
, aEndFrame
, aEndRect
);
2597 child
= child
->GetNextSibling();
2599 aRect
-= aParentFrame
->GetPosition();
2603 //-------------------------------------------------------
2604 // Find the Frame that is XMost
2606 nsPrintEngine::FindSelectionBounds(nsPresContext
* aPresContext
,
2607 nsIRenderingContext
& aRC
,
2608 nsIFrame
* aParentFrame
,
2610 nsIFrame
*& aStartFrame
,
2612 nsIFrame
*& aEndFrame
,
2615 NS_ASSERTION(aPresContext
, "Pointer is null!");
2616 NS_ASSERTION(aParentFrame
, "Pointer is null!");
2618 // loop through named child lists
2619 nsIAtom
* childListName
= nsnull
;
2620 PRInt32 childListIndex
= 0;
2622 nsresult rv
= FindSelectionBoundsWithList(aPresContext
, aRC
, childListName
, aParentFrame
, aRect
, aStartFrame
, aStartRect
, aEndFrame
, aEndRect
);
2623 NS_ENSURE_SUCCESS(rv
, rv
);
2624 childListName
= aParentFrame
->GetAdditionalChildListName(childListIndex
++);
2625 } while (childListName
);
2629 /** ---------------------------------------------------
2630 * This method finds the starting and ending page numbers
2631 * of the selection and also returns rect for each where
2632 * the x,y of the rect is relative to the very top of the
2633 * frame tree (absolutely positioned)
2636 nsPrintEngine::GetPageRangeForSelection(nsIPresShell
* aPresShell
,
2637 nsPresContext
* aPresContext
,
2638 nsIRenderingContext
& aRC
,
2639 nsISelection
* aSelection
,
2640 nsIPageSequenceFrame
* aPageSeqFrame
,
2641 nsIFrame
** aStartFrame
,
2642 PRInt32
& aStartPageNum
,
2644 nsIFrame
** aEndFrame
,
2645 PRInt32
& aEndPageNum
,
2648 NS_ASSERTION(aPresShell
, "Pointer is null!");
2649 NS_ASSERTION(aPresContext
, "Pointer is null!");
2650 NS_ASSERTION(aSelection
, "Pointer is null!");
2651 NS_ASSERTION(aPageSeqFrame
, "Pointer is null!");
2652 NS_ASSERTION(aStartFrame
, "Pointer is null!");
2653 NS_ASSERTION(aEndFrame
, "Pointer is null!");
2655 nsIFrame
* seqFrame
= do_QueryFrame(aPageSeqFrame
);
2657 return NS_ERROR_FAILURE
;
2660 nsIFrame
* startFrame
= nsnull
;
2661 nsIFrame
* endFrame
= nsnull
;
2663 // start out with the sequence frame and search the entire frame tree
2664 // capturing the starting and ending child frames of the selection
2666 nsRect r
= seqFrame
->GetRect();
2667 FindSelectionBounds(aPresContext
, aRC
, seqFrame
, r
,
2668 startFrame
, aStartRect
, endFrame
, aEndRect
);
2671 printf("Start Frame: %p\n", startFrame
);
2672 printf("End Frame: %p\n", endFrame
);
2675 // initial the page numbers here
2676 // in case we don't find and frames
2680 nsIFrame
* startPageFrame
;
2681 nsIFrame
* endPageFrame
;
2683 // check to make sure we found a starting frame
2684 if (startFrame
!= nsnull
) {
2685 // Now search up the tree to find what page the
2686 // start/ending selections frames are on
2688 // Check to see if start should be same as end if
2689 // the end frame comes back null
2690 if (endFrame
== nsnull
) {
2691 // XXX the "GetPageFrame" step could be integrated into
2692 // the FindSelectionBounds step, but walking up to find
2693 // the parent of a child frame isn't expensive and it makes
2694 // FindSelectionBounds a little easier to understand
2695 startPageFrame
= nsLayoutUtils::GetPageFrame(startFrame
);
2696 endPageFrame
= startPageFrame
;
2697 aEndRect
= aStartRect
;
2699 startPageFrame
= nsLayoutUtils::GetPageFrame(startFrame
);
2700 endPageFrame
= nsLayoutUtils::GetPageFrame(endFrame
);
2703 return NS_ERROR_FAILURE
;
2707 printf("Start Page: %p\n", startPageFrame
);
2708 printf("End Page: %p\n", endPageFrame
);
2710 // dump all the pages and their pointers
2712 PRInt32 pageNum
= 1;
2713 nsIFrame
* child
= seqFrame
->GetFirstChild(nsnull
);
2714 while (child
!= nsnull
) {
2715 printf("Page: %d - %p\n", pageNum
, child
);
2717 child
= child
->GetNextSibling();
2722 // Now that we have the page frames
2723 // find out what the page numbers are for each frame
2724 PRInt32 pageNum
= 1;
2725 nsIFrame
* page
= seqFrame
->GetFirstChild(nsnull
);
2726 while (page
!= nsnull
) {
2727 if (page
== startPageFrame
) {
2728 aStartPageNum
= pageNum
;
2730 if (page
== endPageFrame
) {
2731 aEndPageNum
= pageNum
;
2734 page
= page
->GetNextSibling();
2738 printf("Start Page No: %d\n", aStartPageNum
);
2739 printf("End Page No: %d\n", aEndPageNum
);
2742 *aStartFrame
= startPageFrame
;
2743 *aEndFrame
= endPageFrame
;
2748 //-----------------------------------------------------------------
2749 //-- Done: Printing Methods
2750 //-----------------------------------------------------------------
2753 //-----------------------------------------------------------------
2754 //-- Section: Misc Support Methods
2755 //-----------------------------------------------------------------
2757 //---------------------------------------------------------------------
2758 void nsPrintEngine::SetIsPrinting(PRBool aIsPrinting
)
2760 mIsDoingPrinting
= aIsPrinting
;
2761 // Calling SetIsPrinting while in print preview confuses the document viewer
2762 // This is safe because we prevent exiting print preview while printing
2763 if (mDocViewerPrint
&& !mIsDoingPrintPreview
) {
2764 mDocViewerPrint
->SetIsPrinting(aIsPrinting
);
2766 if (mPrt
&& aIsPrinting
) {
2767 mPrt
->mPreparingForPrint
= PR_TRUE
;
2771 //---------------------------------------------------------------------
2772 void nsPrintEngine::SetIsPrintPreview(PRBool aIsPrintPreview
)
2774 mIsDoingPrintPreview
= aIsPrintPreview
;
2776 if (mDocViewerPrint
) {
2777 mDocViewerPrint
->SetIsPrintPreview(aIsPrintPreview
);
2781 //---------------------------------------------------------------------
2783 nsPrintEngine::CleanupDocTitleArray(PRUnichar
**& aArray
, PRInt32
& aCount
)
2785 for (PRInt32 i
= aCount
- 1; i
>= 0; i
--) {
2786 nsMemory::Free(aArray
[i
]);
2788 nsMemory::Free(aArray
);
2793 //---------------------------------------------------------------------
2795 PRBool
nsPrintEngine::HasFramesetChild(nsIContent
* aContent
)
2801 PRUint32 numChildren
= aContent
->GetChildCount();
2803 // do a breadth search across all siblings
2804 for (PRUint32 i
= 0; i
< numChildren
; ++i
) {
2805 nsIContent
*child
= aContent
->GetChildAt(i
);
2806 if (child
->Tag() == nsGkAtoms::frameset
&&
2817 /** ---------------------------------------------------
2818 * Get the Focused Frame for a documentviewer
2820 already_AddRefed
<nsIDOMWindow
>
2821 nsPrintEngine::FindFocusedDOMWindow()
2823 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
2824 NS_ENSURE_TRUE(fm
, nsnull
);
2826 nsCOMPtr
<nsPIDOMWindow
> window(mDocument
->GetWindow());
2827 NS_ENSURE_TRUE(window
, nsnull
);
2829 nsCOMPtr
<nsPIDOMWindow
> rootWindow
= window
->GetPrivateRoot();
2830 NS_ENSURE_TRUE(rootWindow
, nsnull
);
2832 nsPIDOMWindow
* focusedWindow
;
2833 nsFocusManager::GetFocusedDescendant(rootWindow
, PR_TRUE
, &focusedWindow
);
2834 NS_ENSURE_TRUE(focusedWindow
, nsnull
);
2836 if (IsWindowsInOurSubTree(focusedWindow
)) {
2837 return focusedWindow
;
2840 NS_IF_RELEASE(focusedWindow
);
2844 //---------------------------------------------------------------------
2846 nsPrintEngine::IsWindowsInOurSubTree(nsPIDOMWindow
* window
)
2848 PRBool found
= PR_FALSE
;
2850 // now check to make sure it is in "our" tree of docshells
2852 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
2853 do_QueryInterface(window
->GetDocShell());
2855 if (docShellAsItem
) {
2856 // get this DocViewer docshell
2857 nsCOMPtr
<nsIDocShell
> thisDVDocShell(do_QueryInterface(mContainer
));
2859 nsCOMPtr
<nsIDocShell
> parentDocshell(do_QueryInterface(docShellAsItem
));
2860 if (parentDocshell
) {
2861 if (parentDocshell
== thisDVDocShell
) {
2866 break; // at top of tree
2868 nsCOMPtr
<nsIDocShellTreeItem
> docShellParent
;
2869 docShellAsItem
->GetSameTypeParent(getter_AddRefs(docShellParent
));
2870 docShellAsItem
= docShellParent
;
2878 //-------------------------------------------------------
2880 nsPrintEngine::DonePrintingPages(nsPrintObject
* aPO
, nsresult aResult
)
2882 //NS_ASSERTION(aPO, "Pointer is null!");
2883 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO
, aPO
?gFrameTypesStr
[aPO
->mFrameType
]:""));
2885 if (aPO
!= nsnull
) {
2886 aPO
->mHasBeenPrinted
= PR_TRUE
;
2888 PRBool didPrint
= PrintDocContent(mPrt
->mPrintObject
, rv
);
2889 if (NS_SUCCEEDED(rv
) && didPrint
) {
2890 PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO
, gFrameTypesStr
[aPO
->mFrameType
], PRT_YESNO(didPrint
)));
2895 if (NS_SUCCEEDED(aResult
)) {
2896 FirePrintCompletionEvent();
2899 TurnScriptingOn(PR_TRUE
);
2900 SetIsPrinting(PR_FALSE
);
2902 // Release reference to mPagePrintTimer; the timer object destroys itself
2903 // after this returns true
2904 NS_IF_RELEASE(mPagePrintTimer
);
2909 //-------------------------------------------------------
2910 // Recursively sets the PO items to be printed "As Is"
2911 // from the given item down into the tree
2913 nsPrintEngine::SetPrintAsIs(nsPrintObject
* aPO
, PRBool aAsIs
)
2915 NS_ASSERTION(aPO
, "Pointer is null!");
2917 aPO
->mPrintAsIs
= aAsIs
;
2918 for (PRUint32 i
=0;i
<aPO
->mKids
.Length();i
++) {
2919 SetPrintAsIs(aPO
->mKids
[i
], aAsIs
);
2923 //-------------------------------------------------------
2924 // Given a DOMWindow it recursively finds the PO object that matches
2926 nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject
* aPO
,
2927 nsIDOMWindow
* aDOMWin
)
2929 NS_ASSERTION(aPO
, "Pointer is null!");
2931 // Often the CurFocused DOMWindow is passed in
2932 // andit is valid for it to be null, so short circut
2937 nsCOMPtr
<nsIDOMDocument
> domDoc
;
2938 aDOMWin
->GetDocument(getter_AddRefs(domDoc
));
2939 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
2940 if (aPO
->mDocument
&& aPO
->mDocument
->GetOriginalDocument() == doc
) {
2944 PRInt32 cnt
= aPO
->mKids
.Length();
2945 for (PRInt32 i
= 0; i
< cnt
; ++i
) {
2946 nsPrintObject
* po
= FindPrintObjectByDOMWin(aPO
->mKids
[i
], aDOMWin
);
2955 //-------------------------------------------------------
2957 nsPrintEngine::EnablePOsForPrinting()
2959 // NOTE: All POs have been "turned off" for printing
2960 // this is where we decided which POs get printed.
2961 mPrt
->mSelectedPO
= nsnull
;
2963 if (mPrt
->mPrintSettings
== nsnull
) {
2964 return NS_ERROR_FAILURE
;
2967 mPrt
->mPrintFrameType
= nsIPrintSettings::kNoFrames
;
2968 mPrt
->mPrintSettings
->GetPrintFrameType(&mPrt
->mPrintFrameType
);
2970 PRInt16 printHowEnable
= nsIPrintSettings::kFrameEnableNone
;
2971 mPrt
->mPrintSettings
->GetHowToEnableFrameUI(&printHowEnable
);
2973 PRInt16 printRangeType
= nsIPrintSettings::kRangeAllPages
;
2974 mPrt
->mPrintSettings
->GetPrintRange(&printRangeType
);
2977 PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n"));
2978 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
2979 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
2980 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
2983 // ***** This is the ultimate override *****
2984 // if we are printing the selection (either an IFrame or selection range)
2985 // then set the mPrintFrameType as if it were the selected frame
2986 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
2987 mPrt
->mPrintFrameType
= nsIPrintSettings::kSelectedFrame
;
2988 printHowEnable
= nsIPrintSettings::kFrameEnableNone
;
2991 // This tells us that the "Frame" UI has turned off,
2992 // so therefore there are no FrameSets/Frames/IFrames to be printed
2994 // This means there are not FrameSets,
2995 // but the document could contain an IFrame
2996 if (printHowEnable
== nsIPrintSettings::kFrameEnableNone
) {
2998 // Print all the pages or a sub range of pages
2999 if (printRangeType
== nsIPrintSettings::kRangeAllPages
||
3000 printRangeType
== nsIPrintSettings::kRangeSpecifiedPageRange
) {
3001 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3003 // Set the children so they are PrinAsIs
3004 // In this case, the children are probably IFrames
3005 if (mPrt
->mPrintObject
->mKids
.Length() > 0) {
3006 for (PRUint32 i
=0;i
<mPrt
->mPrintObject
->mKids
.Length();i
++) {
3007 nsPrintObject
* po
= mPrt
->mPrintObject
->mKids
[i
];
3008 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3012 // ***** Another override *****
3013 mPrt
->mPrintFrameType
= nsIPrintSettings::kFramesAsIs
;
3015 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3016 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3017 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3021 // This means we are either printed a selected IFrame or
3022 // we are printing the current selection
3023 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
3025 // If the currentFocusDOMWin can'r be null if something is selected
3026 if (mPrt
->mCurrentFocusWin
) {
3027 // Find the selected IFrame
3028 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3030 mPrt
->mSelectedPO
= po
;
3031 // Makes sure all of its children are be printed "AsIs"
3034 // Now, only enable this POs (the selected PO) and all of its children
3035 SetPrintPO(po
, PR_TRUE
);
3037 // check to see if we have a range selection,
3038 // as oppose to a insert selection
3039 // this means if the user just clicked on the IFrame then
3040 // there will not be a selection so we want the entire page to print
3042 // XXX this is sort of a hack right here to make the page
3043 // not try to reposition itself when printing selection
3044 nsCOMPtr
<nsIDOMWindow
> domWin
=
3045 do_QueryInterface(po
->mDocument
->GetOriginalDocument()->GetWindow());
3046 if (!IsThereARangeSelection(domWin
)) {
3047 printRangeType
= nsIPrintSettings::kRangeAllPages
;
3048 mPrt
->mPrintSettings
->SetPrintRange(printRangeType
);
3050 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3051 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3052 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3056 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
3057 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3058 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3059 nsCOMPtr
<nsIDOMWindow
> domWin
= do_GetInterface(po
->mDocShell
);
3060 if (IsThereARangeSelection(domWin
)) {
3061 mPrt
->mCurrentFocusWin
= domWin
;
3062 SetPrintPO(po
, PR_TRUE
);
3071 // check to see if there is a selection when a FrameSet is present
3072 if (printRangeType
== nsIPrintSettings::kRangeSelection
) {
3073 // If the currentFocusDOMWin can'r be null if something is selected
3074 if (mPrt
->mCurrentFocusWin
) {
3075 // Find the selected IFrame
3076 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3078 mPrt
->mSelectedPO
= po
;
3079 // Makes sure all of its children are be printed "AsIs"
3082 // Now, only enable this POs (the selected PO) and all of its children
3083 SetPrintPO(po
, PR_TRUE
);
3085 // check to see if we have a range selection,
3086 // as oppose to a insert selection
3087 // this means if the user just clicked on the IFrame then
3088 // there will not be a selection so we want the entire page to print
3090 // XXX this is sort of a hack right here to make the page
3091 // not try to reposition itself when printing selection
3092 nsCOMPtr
<nsIDOMWindow
> domWin
=
3093 do_QueryInterface(po
->mDocument
->GetOriginalDocument()->GetWindow());
3094 if (!IsThereARangeSelection(domWin
)) {
3095 printRangeType
= nsIPrintSettings::kRangeAllPages
;
3096 mPrt
->mPrintSettings
->SetPrintRange(printRangeType
);
3098 PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr
[mPrt
->mPrintFrameType
]));
3099 PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr
[printHowEnable
]));
3100 PR_PL(("PrintRange: %s \n", gPrintRangeStr
[printRangeType
]));
3106 // If we are printing "AsIs" then sets all the POs to be printed as is
3107 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kFramesAsIs
) {
3108 SetPrintAsIs(mPrt
->mPrintObject
);
3109 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3113 // If we are printing the selected Frame then
3114 // find that PO for that selected DOMWin and set it all of its
3115 // children to be printed
3116 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kSelectedFrame
) {
3118 if ((mPrt
->mIsParentAFrameSet
&& mPrt
->mCurrentFocusWin
) || mPrt
->mIsIFrameSelected
) {
3119 nsPrintObject
* po
= FindPrintObjectByDOMWin(mPrt
->mPrintObject
, mPrt
->mCurrentFocusWin
);
3121 mPrt
->mSelectedPO
= po
;
3122 // NOTE: Calling this sets the "po" and
3123 // we don't want to do this for documents that have no children,
3124 // because then the "DoEndPage" gets called and it shouldn't
3125 if (po
->mKids
.Length() > 0) {
3126 // Makes sure that itself, and all of its children are printed "AsIs"
3130 // Now, only enable this POs (the selected PO) and all of its children
3131 SetPrintPO(po
, PR_TRUE
);
3137 // If we are print each subdoc separately,
3138 // then don't print any of the FraneSet Docs
3139 if (mPrt
->mPrintFrameType
== nsIPrintSettings::kEachFrameSep
) {
3140 SetPrintPO(mPrt
->mPrintObject
, PR_TRUE
);
3141 PRInt32 cnt
= mPrt
->mPrintDocList
.Length();
3142 for (PRInt32 i
=0;i
<cnt
;i
++) {
3143 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3144 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3145 if (po
->mFrameType
== eFrameSet
) {
3146 po
->mDontPrint
= PR_TRUE
;
3154 //-------------------------------------------------------
3155 // Return the nsPrintObject with that is XMost (The widest frameset frame) AND
3156 // contains the XMost (widest) layout frame
3158 nsPrintEngine::FindSmallestSTF()
3160 float smallestRatio
= 1.0f
;
3161 nsPrintObject
* smallestPO
= nsnull
;
3163 for (PRUint32 i
=0;i
<mPrt
->mPrintDocList
.Length();i
++) {
3164 nsPrintObject
* po
= mPrt
->mPrintDocList
.ElementAt(i
);
3165 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3166 if (po
->mFrameType
!= eFrameSet
&& po
->mFrameType
!= eIFrame
) {
3167 if (po
->mShrinkRatio
< smallestRatio
) {
3168 smallestRatio
= po
->mShrinkRatio
;
3174 #ifdef EXTENDED_DEBUG_PRINTING
3175 if (smallestPO
) printf("*PO: %p Type: %d %10.3f\n", smallestPO
, smallestPO
->mFrameType
, smallestPO
->mShrinkRatio
);
3180 //-------------------------------------------------------
3182 nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn
)
3184 if (mIsDoingPrinting
&& aDoTurnOn
&& mDocViewerPrint
&&
3185 mDocViewerPrint
->GetIsPrintPreview()) {
3186 // We don't want to turn scripting on if print preview is shown still after
3191 nsPrintData
* prt
= mPrt
;
3192 #ifdef NS_PRINT_PREVIEW
3201 NS_ASSERTION(mDocument
, "We MUST have a document.");
3202 // First, get the script global object from the document...
3204 for (PRUint32 i
=0;i
<prt
->mPrintDocList
.Length();i
++) {
3205 nsPrintObject
* po
= prt
->mPrintDocList
.ElementAt(i
);
3206 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3208 nsIDocument
* doc
= po
->mDocument
;
3213 // get the script global object
3214 nsIScriptGlobalObject
*scriptGlobalObj
= doc
->GetScriptGlobalObject();
3216 if (scriptGlobalObj
) {
3217 nsCOMPtr
<nsPIDOMWindow
> window
= do_QueryInterface(scriptGlobalObj
);
3218 NS_ASSERTION(window
, "Can't get nsPIDOMWindow");
3219 nsIScriptContext
*scx
= scriptGlobalObj
->GetContext();
3220 NS_WARN_IF_FALSE(scx
, "Can't get nsIScriptContext");
3221 nsresult propThere
= NS_PROPTABLE_PROP_NOT_THERE
;
3222 doc
->GetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
,
3225 if (propThere
!= NS_PROPTABLE_PROP_NOT_THERE
) {
3226 doc
->DeleteProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
);
3228 scx
->SetScriptsEnabled(PR_TRUE
, PR_FALSE
);
3230 window
->ResumeTimeouts(PR_FALSE
);
3233 // Have to be careful, because people call us over and over again with
3234 // aDoTurnOn == PR_FALSE. So don't set the property if it's already
3235 // set, since in that case we'd set it to the wrong value.
3236 if (propThere
== NS_PROPTABLE_PROP_NOT_THERE
) {
3237 // Stash the current value of IsScriptEnabled on the document, so
3238 // that layout code running in print preview doesn't get confused.
3239 doc
->SetProperty(nsGkAtoms::scriptEnabledBeforePrintOrPreview
,
3240 NS_INT32_TO_PTR(doc
->IsScriptEnabled()));
3242 scx
->SetScriptsEnabled(PR_FALSE
, PR_FALSE
);
3244 window
->SuspendTimeouts(1, PR_FALSE
);
3251 //-----------------------------------------------------------------
3252 //-- Done: Misc Support Methods
3253 //-----------------------------------------------------------------
3256 //-----------------------------------------------------------------
3257 //-- Section: Finishing up or Cleaning up
3258 //-----------------------------------------------------------------
3260 //-----------------------------------------------------------------
3262 nsPrintEngine::CloseProgressDialog(nsIWebProgressListener
* aWebProgressListener
)
3264 if (aWebProgressListener
) {
3265 aWebProgressListener
->OnStateChange(nsnull
, nsnull
, nsIWebProgressListener::STATE_STOP
|nsIWebProgressListener::STATE_IS_DOCUMENT
, nsnull
);
3269 //-----------------------------------------------------------------
3271 nsPrintEngine::FinishPrintPreview()
3273 nsresult rv
= NS_OK
;
3275 #ifdef NS_PRINT_PREVIEW
3278 /* we're already finished with print preview */
3282 rv
= DocumentReadyForPrinting();
3284 SetIsCreatingPrintPreview(PR_FALSE
);
3286 /* cleaup on failure + notify user */
3287 if (NS_FAILED(rv
)) {
3288 /* cleanup done, let's fire-up an error dialog to notify the user
3289 * what went wrong...
3291 mPrt
->OnEndPrinting();
3292 TurnScriptingOn(PR_TRUE
);
3297 // At this point we are done preparing everything
3298 // before it is to be created
3301 if (mIsDoingPrintPreview
&& mOldPrtPreview
) {
3302 delete mOldPrtPreview
;
3303 mOldPrtPreview
= nsnull
;
3306 InstallPrintPreviewListener();
3308 mPrt
->OnEndPrinting();
3310 // PrintPreview was built using the mPrt (code reuse)
3311 // then we assign it over
3315 #endif // NS_PRINT_PREVIEW
3320 //-----------------------------------------------------------------
3321 //-- Done: Finishing up or Cleaning up
3322 //-----------------------------------------------------------------
3325 /*=============== Timer Related Code ======================*/
3327 nsPrintEngine::StartPagePrintTimer(nsPrintObject
* aPO
)
3329 if (!mPagePrintTimer
) {
3330 nsresult rv
= NS_NewPagePrintTimer(&mPagePrintTimer
);
3331 NS_ENSURE_SUCCESS(rv
, rv
);
3333 // Get the delay time in between the printing of each page
3334 // this gives the user more time to press cancel
3335 PRInt32 printPageDelay
= 50;
3336 mPrt
->mPrintSettings
->GetPrintPageDelay(&printPageDelay
);
3338 mPagePrintTimer
->Init(this, mDocViewerPrint
, printPageDelay
);
3341 return mPagePrintTimer
->Start(aPO
);
3344 /*=============== nsIObserver Interface ======================*/
3346 nsPrintEngine::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*aData
)
3348 nsresult rv
= NS_ERROR_FAILURE
;
3350 if (mIsDoingPrinting
) {
3351 rv
= DocumentReadyForPrinting();
3353 /* cleaup on failure + notify user */
3354 if (NS_FAILED(rv
)) {
3355 CleanupOnFailure(rv
, PR_TRUE
);
3358 rv
= FinishPrintPreview();
3359 if (NS_FAILED(rv
)) {
3360 CleanupOnFailure(rv
, PR_FALSE
);
3363 mPrtPreview
->OnEndPrinting();
3372 //---------------------------------------------------------------
3373 //-- PLEvent Notification
3374 //---------------------------------------------------------------
3375 class nsPrintCompletionEvent
: public nsRunnable
{
3377 nsPrintCompletionEvent(nsIDocumentViewerPrint
*docViewerPrint
)
3378 : mDocViewerPrint(docViewerPrint
) {
3379 NS_ASSERTION(mDocViewerPrint
, "mDocViewerPrint is null.");
3383 if (mDocViewerPrint
)
3384 mDocViewerPrint
->OnDonePrinting();
3389 nsCOMPtr
<nsIDocumentViewerPrint
> mDocViewerPrint
;
3392 //-----------------------------------------------------------
3394 nsPrintEngine::FirePrintCompletionEvent()
3396 nsCOMPtr
<nsIRunnable
> event
= new nsPrintCompletionEvent(mDocViewerPrint
);
3397 if (NS_FAILED(NS_DispatchToCurrentThread(event
)))
3398 NS_WARNING("failed to dispatch print completion event");
3401 //---------------------------------------------------------------
3402 //---------------------------------------------------------------
3403 //-- Debug helper routines
3404 //---------------------------------------------------------------
3405 //---------------------------------------------------------------
3406 #if (defined(XP_WIN) || defined(XP_OS2)) && defined(EXTENDED_DEBUG_PRINTING)
3407 #include "windows.h"
3408 #include "process.h"
3411 #define MY_FINDFIRST(a,b) FindFirstFile(a,b)
3412 #define MY_FINDNEXT(a,b) FindNextFile(a,b)
3413 #define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
3414 #define MY_FINDCLOSE(a) FindClose(a)
3415 #define MY_FILENAME(a) a.cFileName
3416 #define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow
3418 int RemoveFilesInDir(const char * aDir
)
3420 WIN32_FIND_DATA data_ptr
;
3423 char path
[MAX_PATH
];
3427 // Append slash to the end of the directory names if not there
3428 if (path
[strlen(path
)-1] != '\\')
3431 char findPath
[MAX_PATH
];
3432 strcpy(findPath
, path
);
3433 strcat(findPath
, "*.*");
3435 find_handle
= MY_FINDFIRST(findPath
, &data_ptr
);
3437 if (find_handle
!= INVALID_HANDLE_VALUE
) {
3440 && (stricmp(MY_FILENAME(data_ptr
),"."))
3441 && (stricmp(MY_FILENAME(data_ptr
),".."))) {
3444 else if (!ISDIR(data_ptr
)) {
3445 if (!strncmp(MY_FILENAME(data_ptr
), "print_dump", 10)) {
3446 char fileName
[MAX_PATH
];
3447 strcpy(fileName
, aDir
);
3448 strcat(fileName
, "\\");
3449 strcat(fileName
, MY_FILENAME(data_ptr
));
3450 printf("Removing %s\n", fileName
);
3454 } while(MY_FINDNEXT(find_handle
,&data_ptr
));
3455 MY_FINDCLOSE(find_handle
);
3461 #ifdef EXTENDED_DEBUG_PRINTING
3463 /** ---------------------------------------------------
3464 * Dumps Frames for Printing
3466 static void RootFrameList(nsPresContext
* aPresContext
, FILE* out
, PRInt32 aIndent
)
3468 if (!aPresContext
|| !out
)
3471 nsIPresShell
*shell
= aPresContext
->GetPresShell();
3473 nsIFrame
* frame
= shell
->FrameManager()->GetRootFrame();
3475 frame
->List(aPresContext
, out
, aIndent
);
3480 /** ---------------------------------------------------
3481 * Dumps Frames for Printing
3483 static void DumpFrames(FILE* out
,
3484 nsPresContext
* aPresContext
,
3485 nsIRenderingContext
* aRendContext
,
3489 NS_ASSERTION(out
, "Pointer is null!");
3490 NS_ASSERTION(aPresContext
, "Pointer is null!");
3491 NS_ASSERTION(aRendContext
, "Pointer is null!");
3492 NS_ASSERTION(aFrame
, "Pointer is null!");
3494 nsIFrame
* child
= aFrame
->GetFirstChild(nsnull
);
3495 while (child
!= nsnull
) {
3496 for (PRInt32 i
=0;i
<aLevel
;i
++) {
3500 child
->GetFrameName(tmp
);
3501 fputs(NS_LossyConvertUTF16toASCII(tmp
).get(), out
);
3503 if (NS_SUCCEEDED(child
->IsVisibleForPainting(aPresContext
, *aRendContext
, PR_TRUE
, &isSelected
))) {
3504 fprintf(out
, " %p %s", child
, isSelected
?"VIS":"UVS");
3505 nsRect rect
= child
->GetRect();
3506 fprintf(out
, "[%d,%d,%d,%d] ", rect
.x
, rect
.y
, rect
.width
, rect
.height
);
3507 fprintf(out
, "v: %p ", (void*)child
->GetView());
3509 DumpFrames(out
, aPresContext
, aRendContext
, child
, aLevel
+1);
3510 child
= child
->GetNextSibling();
3516 /** ---------------------------------------------------
3517 * Dumps the Views from the DocShell
3520 DumpViews(nsIDocShell
* aDocShell
, FILE* out
)
3522 NS_ASSERTION(aDocShell
, "Pointer is null!");
3523 NS_ASSERTION(out
, "Pointer is null!");
3525 if (nsnull
!= aDocShell
) {
3526 fprintf(out
, "docshell=%p \n", aDocShell
);
3527 nsIPresShell
* shell
= nsPrintEngine::GetPresShellFor(aDocShell
);
3529 nsIViewManager
* vm
= shell
->GetViewManager();
3532 vm
->GetRootView(root
);
3533 if (nsnull
!= root
) {
3539 fputs("null pres shell\n", out
);
3542 // dump the views of the sub documents
3544 nsCOMPtr
<nsIDocShellTreeNode
> docShellAsNode(do_QueryInterface(aDocShell
));
3545 docShellAsNode
->GetChildCount(&n
);
3546 for (i
= 0; i
< n
; i
++) {
3547 nsCOMPtr
<nsIDocShellTreeItem
> child
;
3548 docShellAsNode
->GetChildAt(i
, getter_AddRefs(child
));
3549 nsCOMPtr
<nsIDocShell
> childAsShell(do_QueryInterface(child
));
3551 DumpViews(childAsShell
, out
);
3557 /** ---------------------------------------------------
3558 * Dumps the Views and Frames
3560 void DumpLayoutData(char* aTitleStr
,
3562 nsPresContext
* aPresContext
,
3563 nsIDeviceContext
* aDC
,
3564 nsIFrame
* aRootFrame
,
3565 nsIDocShekk
* aDocShell
,
3568 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3570 if (aPresContext
== nsnull
|| aDC
== nsnull
) {
3574 #ifdef NS_PRINT_PREVIEW
3575 if (aPresContext
->Type() == nsPresContext::eContext_PrintPreview
) {
3580 NS_ASSERTION(aRootFrame
, "Pointer is null!");
3581 NS_ASSERTION(aDocShell
, "Pointer is null!");
3583 // Dump all the frames and view to a a file
3585 sprintf(filename
, "print_dump_layout_%d.txt", gDumpLOFileNameCnt
++);
3586 FILE * fd
= aFD
?aFD
:fopen(filename
, "w");
3588 fprintf(fd
, "Title: %s\n", aTitleStr
?aTitleStr
:"");
3589 fprintf(fd
, "URL: %s\n", aURLStr
?aURLStr
:"");
3590 fprintf(fd
, "--------------- Frames ----------------\n");
3591 fprintf(fd
, "--------------- Frames ----------------\n");
3592 nsCOMPtr
<nsIRenderingContext
> renderingContext
;
3593 aDC
->CreateRenderingContext(*getter_AddRefs(renderingContext
));
3594 RootFrameList(aPresContext
, fd
, 0);
3595 //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0);
3596 fprintf(fd
, "---------------------------------------\n\n");
3597 fprintf(fd
, "--------------- Views From Root Frame----------------\n");
3598 nsIView
* v
= aRootFrame
->GetView();
3602 printf("View is null!\n");
3605 fprintf(fd
, "--------------- All Views ----------------\n");
3606 DumpViews(aDocShell
, fd
);
3607 fprintf(fd
, "---------------------------------------\n\n");
3609 if (aFD
== nsnull
) {
3615 //-------------------------------------------------------------
3616 static void DumpPrintObjectsList(nsTArray
<nsPrintObject
*> * aDocList
)
3618 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3620 NS_ASSERTION(aDocList
, "Pointer is null!");
3622 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3623 PR_PL(("Doc List\n***************************************************\n"));
3624 PR_PL(("T P A H PO DocShell Seq Page Root Page# Rect\n"));
3625 PRInt32 cnt
= aDocList
->Length();
3626 for (PRInt32 i
=0;i
<cnt
;i
++) {
3627 nsPrintObject
* po
= aDocList
->ElementAt(i
);
3628 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3629 nsIFrame
* rootFrame
= nsnull
;
3630 if (po
->mPresShell
) {
3631 rootFrame
= po
->mPresShell
->FrameManager()->GetRootFrame();
3632 while (rootFrame
!= nsnull
) {
3633 nsIPageSequenceFrame
* sqf
= do_QueryFrame(rootFrame
);
3637 rootFrame
= rootFrame
->GetFirstChild(nsnull
);
3641 PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types
[po
->mFrameType
],
3642 po
->IsPrintable(), po
->mPrintAsIs
, po
->mHasBeenPrinted
, po
, po
->mDocShell
.get(), po
->mSeqFrame
,
3643 po
->mPageFrame
, rootFrame
, po
->mPageNum
, po
->mRect
.x
, po
->mRect
.y
, po
->mRect
.width
, po
->mRect
.height
));
3647 //-------------------------------------------------------------
3648 static void DumpPrintObjectsTree(nsPrintObject
* aPO
, int aLevel
, FILE* aFD
)
3650 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3652 NS_ASSERTION(aPO
, "Pointer is null!");
3654 FILE * fd
= aFD
?aFD
:stdout
;
3655 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3657 fprintf(fd
, "DocTree\n***************************************************\n");
3658 fprintf(fd
, "T PO DocShell Seq Page Page# Rect\n");
3660 PRInt32 cnt
= aPO
->mKids
.Length();
3661 for (PRInt32 i
=0;i
<cnt
;i
++) {
3662 nsPrintObject
* po
= aPO
->mKids
.ElementAt(i
);
3663 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3664 for (PRInt32 k
=0;k
<aLevel
;k
++) fprintf(fd
, " ");
3665 fprintf(fd
, "%s %p %p %p %p %d %d,%d,%d,%d\n", types
[po
->mFrameType
], po
, po
->mDocShell
.get(), po
->mSeqFrame
,
3666 po
->mPageFrame
, po
->mPageNum
, po
->mRect
.x
, po
->mRect
.y
, po
->mRect
.width
, po
->mRect
.height
);
3670 //-------------------------------------------------------------
3671 static void GetDocTitleAndURL(nsPrintObject
* aPO
, char *& aDocStr
, char *& aURLStr
)
3676 PRUnichar
* docTitleStr
;
3677 PRUnichar
* docURLStr
;
3678 nsPrintEngine::GetDisplayTitleAndURL(aPO
,
3679 &docTitleStr
, &docURLStr
,
3680 nsPrintEngine::eDocTitleDefURLDoc
);
3683 nsAutoString
strDocTitle(docTitleStr
);
3684 aDocStr
= ToNewCString(strDocTitle
);
3685 nsMemory::Free(docTitleStr
);
3689 nsAutoString
strURL(docURLStr
);
3690 aURLStr
= ToNewCString(strURL
);
3691 nsMemory::Free(docURLStr
);
3695 //-------------------------------------------------------------
3696 static void DumpPrintObjectsTreeLayout(nsPrintObject
* aPO
,
3697 nsIDeviceContext
* aDC
,
3698 int aLevel
, FILE * aFD
)
3700 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3702 NS_ASSERTION(aPO
, "Pointer is null!");
3703 NS_ASSERTION(aDC
, "Pointer is null!");
3705 const char types
[][3] = {"DC", "FR", "IF", "FS"};
3708 fd
= fopen("tree_layout.txt", "w");
3709 fprintf(fd
, "DocTree\n***************************************************\n");
3710 fprintf(fd
, "***************************************************\n");
3711 fprintf(fd
, "T PO DocShell Seq Page Page# Rect\n");
3716 nsIFrame
* rootFrame
= nsnull
;
3717 if (aPO
->mPresShell
) {
3718 rootFrame
= aPO
->mPresShell
->FrameManager()->GetRootFrame();
3720 for (PRInt32 k
=0;k
<aLevel
;k
++) fprintf(fd
, " ");
3721 fprintf(fd
, "%s %p %p %p %p %d %d,%d,%d,%d\n", types
[aPO
->mFrameType
], aPO
, aPO
->mDocShell
.get(), aPO
->mSeqFrame
,
3722 aPO
->mPageFrame
, aPO
->mPageNum
, aPO
->mRect
.x
, aPO
->mRect
.y
, aPO
->mRect
.width
, aPO
->mRect
.height
);
3723 if (aPO
->IsPrintable()) {
3726 GetDocTitleAndURL(aPO
, docStr
, urlStr
);
3727 DumpLayoutData(docStr
, urlStr
, aPO
->mPresContext
, aDC
, rootFrame
, aPO
->mDocShell
, fd
);
3728 if (docStr
) nsMemory::Free(docStr
);
3729 if (urlStr
) nsMemory::Free(urlStr
);
3731 fprintf(fd
, "<***************************************************>\n");
3733 PRInt32 cnt
= aPO
->mKids
.Length();
3734 for (PRInt32 i
=0;i
<cnt
;i
++) {
3735 nsPrintObject
* po
= aPO
->mKids
.ElementAt(i
);
3736 NS_ASSERTION(po
, "nsPrintObject can't be null!");
3737 DumpPrintObjectsTreeLayout(po
, aDC
, aLevel
+1, fd
);
3740 if (aLevel
== 0 && fd
) {
3745 //-------------------------------------------------------------
3746 static void DumpPrintObjectsListStart(const char * aStr
, nsTArray
<nsPrintObject
*> * aDocList
)
3748 if (!kPrintingLogMod
|| kPrintingLogMod
->level
!= DUMP_LAYOUT_LEVEL
) return;
3750 NS_ASSERTION(aStr
, "Pointer is null!");
3751 NS_ASSERTION(aDocList
, "Pointer is null!");
3753 PR_PL(("%s\n", aStr
));
3754 DumpPrintObjectsList(aDocList
);
3757 #define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList);
3758 #define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject);
3759 #define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC);
3762 #define DUMP_DOC_LIST(_title)
3763 #define DUMP_DOC_TREE
3764 #define DUMP_DOC_TREELAYOUT
3767 //---------------------------------------------------------------
3768 //---------------------------------------------------------------
3769 //-- End of debug helper routines
3770 //---------------------------------------------------------------