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